蓝牙及蓝牙通讯Bluetooth概述
生活随笔
收集整理的這篇文章主要介紹了
蓝牙及蓝牙通讯Bluetooth概述
小編覺得挺不錯(cuò)的,現(xiàn)在分享給大家,幫大家做個(gè)參考.
藍(lán)牙及藍(lán)牙通訊Bluetooth概述
一、藍(lán)牙介紹:
(一)、Bluetooth的由來及現(xiàn)狀
藍(lán)牙一詞源于公元十世紀(jì)丹麥國王HaraldBlatand名字中的Blatand。Blatand的英文之意就是Blue tooth。這是因?yàn)檫@位讓丹麥人引以為傲的國王酷愛吃藍(lán)莓以至于牙齦都被染成藍(lán)色。由于Blatand統(tǒng)一了丹麥和挪威,所以,作為無線通信技術(shù)的一種,藍(lán)牙技術(shù)之所以取名Bluetooth可謂志向遠(yuǎn)大。
不過,在以Android為代表的智能機(jī)出現(xiàn)以前,藍(lán)牙在早期智能機(jī)甚至功能機(jī)中一直扮演著“雞肋”的角色。那么,隨著無線通信技術(shù)的快速發(fā)展以及Android的普及,藍(lán)牙技術(shù)在我們生活中的應(yīng)用也越來越多,包括藍(lán)牙耳機(jī)和鼠標(biāo),及藍(lán)牙局域網(wǎng)應(yīng)用(聊天、游戲等)。
(二)、藍(lán)牙規(guī)范介紹
Core Specification(核心規(guī)范)
作用:用于規(guī)定藍(lán)牙設(shè)備必須實(shí)現(xiàn)的通用功能和協(xié)議層次。它由軟件和硬件模塊組成,兩個(gè)模塊之間的信息和數(shù)據(jù)通過主機(jī)控制接口(HCI)的解釋才能進(jìn)行傳遞
核心規(guī)范是藍(lán)牙協(xié)議家族的基礎(chǔ),自藍(lán)牙技術(shù)聯(lián)盟(Bluetooth SIG,Special Interest Group)在1999年頒布藍(lán)牙核心規(guī)范1.0版本以來,到目前為止藍(lán)牙SIG一共發(fā)布了七個(gè)重要版本。每一個(gè)版本都促使藍(lán)牙技術(shù)朝著更快、更安全、更省電的方向發(fā)展。
二、藍(lán)牙的用法
(一)、藍(lán)牙API
Android所有關(guān)于藍(lán)牙開發(fā)的類都在android.bluetooth包下,只有8個(gè)類:
BluetoothAdapter 本地藍(lán)牙適配器
BluetoothClass 藍(lán)牙類(主要包括服務(wù)和設(shè)備)
BluetoothClass.Device 藍(lán)牙設(shè)備類
BluetoothClass.Device.Major 藍(lán)牙設(shè)備管理
BluetoothClass.Service 藍(lán)牙服務(wù)類
BluetoothDevice 藍(lán)牙設(shè)備(遠(yuǎn)程藍(lán)牙設(shè)備)
BluetoothServiceSocket 監(jiān)聽藍(lán)牙連接的類
BluetoothSocket 藍(lán)牙連接類
1、BluetoothAdapter :
表示本地的藍(lán)牙適配器 (藍(lán)牙射頻)。BluetoothAdapter 是為所有藍(lán)牙交互的入口點(diǎn)。它可以發(fā)現(xiàn)其他藍(lán)牙設(shè)備、 查詢綁定 (配對) 設(shè)備的列表、 實(shí)例化已知的 MAC 地址的BluetoothDevice(藍(lán)牙設(shè)備) 和創(chuàng)建 BluetoothServerSocket 用于偵聽來自其他設(shè)備的通信。直到我們建立bluetoothSocket連接之前,都要不斷操作它 。BluetoothAdapter里的方法很多,常用的有以下幾個(gè):
cancelDiscovery() 根據(jù)字面意思,是取消發(fā)現(xiàn),也就是說當(dāng)我們正在搜索設(shè)備的時(shí)候調(diào)用這個(gè)方法將不再繼續(xù)搜索;
disable()關(guān)閉藍(lán)牙;
enable()打開藍(lán)牙;這個(gè)方法打開藍(lán)牙不會彈出提示,更多的時(shí)候我們需要問下用戶是否打開,以下兩行代碼同樣是打開藍(lán)牙,不過會提示用戶:
Intemtenabler=new Intent(BluetoothAdapter.ACTION_REQUEST_ENABLE);
startActivityForResult(enabler,reCode);//同startActivity(enabler);
getAddress()獲取本地藍(lán)牙地址
getDefaultAdapter()獲取默認(rèn)BluetoothAdapter,實(shí)際上,也只有這一種方法獲取BluetoothAdapter
getName()獲取本地藍(lán)牙名稱
getRemoteDevice(String address)根據(jù)藍(lán)牙地址獲取遠(yuǎn)程藍(lán)牙設(shè)備
getState()獲取本地藍(lán)牙適配器當(dāng)前狀態(tài)(感覺可能調(diào)試的時(shí)候更需要)
isDiscovering()判斷當(dāng)前是否正在查找設(shè)備,是返回true
isEnabled()判斷藍(lán)牙是否打開,已打開返回true,否則,返回false
listenUsingRfcommWithServiceRecord(String name,UUID uuid)根據(jù)名稱,UUID創(chuàng)建并返回BluetoothServerSocket對象,這是創(chuàng)建BluetoothSocket服務(wù)器端的第一步 。第一個(gè)參數(shù)表示藍(lán)牙服務(wù)的名稱,可以是任意字符串,第二個(gè)參數(shù)是UUID。
startDiscovery()開始搜索,這是搜索的第一步
2、BluetoothDevice
表示遠(yuǎn)程藍(lán)牙設(shè)備。使用此類并通過BluetoothSocket類可以請求連接遠(yuǎn)程設(shè)備,或查詢這臺設(shè)備的信息如其名稱、 地址、 類和綁定狀態(tài)。
createRfcommSocketToServiceRecord(UUIDuuid)
根據(jù)UUID創(chuàng)建并返回一個(gè)BluetoothSocket,這個(gè)方法也是我們獲取BluetoothDevice的目的——創(chuàng)建BluetoothSocket。這個(gè)類其他的方法,如getAddress()、getName(),同BluetoothAdapter。
【備注:】藍(lán)牙—RFCOMM協(xié)議
串口仿真協(xié)議(RFCOMM),RFCOMM是一個(gè)簡單的協(xié)議,其中針對9針RS-232串口仿真附加了部分條款.可支持在兩個(gè)藍(lán)牙設(shè)備之間同時(shí)保持高達(dá)60路的通信連接.RFCOMM的目的是針對如何在兩個(gè)不同設(shè)備上的應(yīng)用之間保證一條完整的通信路徑。
3、BluetoothServerSocket
表示打開服務(wù)器套接字偵聽傳入的請求 (類似于 TCP ServerSocket)。為了連接兩臺 Android 設(shè)備,一臺設(shè)備必須用此類打開一個(gè)服務(wù)器套接字。當(dāng)遠(yuǎn)程藍(lán)牙設(shè)備向此設(shè)備發(fā)出連接請求時(shí),而且當(dāng)連接被接收時(shí),BluetoothServerSocket 將返回連接的 BluetoothSocket。這個(gè)類有三個(gè)方法。
accept()
accept(inttimeout): 兩者的區(qū)別在于后者指定了過時(shí)時(shí)間,需要注意的是,執(zhí)行這兩個(gè)方法的時(shí)候,直到接收到了客戶端的請求(或是過期之后),都會阻塞線程,應(yīng)該放在新線程里運(yùn)行! 還需要注意,這兩個(gè)方法都返回一個(gè)BluetoothSocket,最后的連接也是服務(wù)器端與客戶端這兩個(gè)BluetoothSocket的連接。
close():關(guān)閉
4、BluetoothSocket
跟BluetoothServerSocket相對,是客戶端。表示一個(gè)藍(lán)牙套接字 (類似于 TCP Socket) 的接口。這是一個(gè)允許應(yīng)用程序與另一臺藍(lán)牙設(shè)備通過InputStream和OutputStream來交換數(shù)據(jù)的連接點(diǎn)。其一共5個(gè)方法,一般都會用到。
close():關(guān)閉
connect():連接
getInptuStream():獲取輸入流
getOutputStream():獲取輸出流
getRemoteDevice():獲取遠(yuǎn)程設(shè)備,這里指的是獲取bluetoothSocket指定連接的那個(gè)遠(yuǎn)程藍(lán)牙設(shè)備
5、BluetoothClass
描述的一般特征和藍(lán)牙設(shè)備的功能。這是一整套只讀的屬性用于定義設(shè)備的主要和次要設(shè)備類和它的服務(wù)。然而,這并不是支持所有藍(lán)牙配置文件和服務(wù)的設(shè)備,但很適用于獲取設(shè)備類型
6、BluetoothProfile
表示一個(gè)藍(lán)牙配置文件。藍(lán)牙配置文件是基于藍(lán)牙通信設(shè)備之間的無線接口規(guī)范。如免提規(guī)范(Hands-Free profile)
7、BluetoothHeadset
藍(lán)牙耳機(jī)與手機(jī)一起使用配置文件 ,這包括藍(lán)牙耳機(jī)和免提(v1.5) 的配置文件
8、BluetoothA2dp
定義了如何高質(zhì)量的音頻可以進(jìn)行流式處理從一個(gè)設(shè)備到另一個(gè)通過藍(lán)牙連接。"A2DP"代表先進(jìn)音頻分配協(xié)議
9、BluetoothHealth
表示控制藍(lán)牙服務(wù)健康設(shè)備協(xié)議
10、BluetoothHealthCallback
BluetoothHealthCallback 一個(gè)抽象類,您使用來實(shí)現(xiàn) BluetoothHealth 回調(diào),你必須擴(kuò)展此類并實(shí)現(xiàn)回調(diào)方法以接收有關(guān)更改的更新應(yīng)用程序的注冊和藍(lán)牙通道狀態(tài)。BluetoothHealthAppConfiguration 表示一個(gè)藍(lán)牙健康第三方應(yīng)用程序注冊與遠(yuǎn)程藍(lán)牙健康設(shè)備進(jìn)行通信的應(yīng)用程
11、BluetoothHealthAppConfiguration
表示一個(gè)藍(lán)牙健康第三方應(yīng)用程序注冊與遠(yuǎn)程藍(lán)牙健康設(shè)備進(jìn)行通信的應(yīng)用程序配置
12、BluetoothProfile.ServiceListener
通知 BluetoothProfile IPC 客戶端界面時(shí)已被連接或斷開服務(wù) (即運(yùn)行一個(gè)特定的配置文件內(nèi)部服務(wù))
(二)、使用藍(lán)牙的權(quán)限
<uses-permission android:name="android.permission.BLUETOOTH"/>
<uses-permission android:name="android.permission.BLUETOOTH_ADMIN"/>
(三)、 UUID(universal unique identifier , 全局唯一標(biāo)識符)
格式如下:UUID格式一般是"xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx",可到http://www.uuidgenerator.com 申請。UUID分為5段,是一個(gè)8-4-4-4-12的字符串,這個(gè)字符串要求永不重復(fù)。
String uuid = java.util.UUID.randomUUID().toString();
一般在創(chuàng)建Socket時(shí)需要UUID作為端口的唯一性,如果兩臺Android設(shè)備互聯(lián),則沒有什么特殊的,如果讓非Android的藍(lán)牙設(shè)備連接Android藍(lán)牙設(shè)備,則UUID必須使用某個(gè)固定保留的UUID
Android中創(chuàng)建UUID:
UUID uuid = UUID.fromString("00001101-0000-1000-8000-00805F9B34FB")
常用固定的UUID
藍(lán)牙串口服務(wù)(SPP)
SerialPortServiceClass_UUID = '{00001101-0000-1000-8000-00805F9B34FB}'
LANAccessUsingPPPServiceClass_UUID = '{00001102-0000-1000-8000-00805F9B34FB}'
撥號網(wǎng)絡(luò)服務(wù)
DialupNetworkingServiceClass_UUID = '{00001103-0000-1000-8000-00805F9B34FB}'
信息同步服務(wù)
IrMCSyncServiceClass_UUID = '{00001104-0000-1000-8000-00805F9B34FB}'
SDP_OBEXObjectPushServiceClass_UUID = '{00001105-0000-1000-8000-00805F9B34FB}'
文件傳輸服務(wù)
OBEXFileTransferServiceClass_UUID = '{00001106-0000-1000-8000-00805F9B34FB}'
IrMCSyncCommandServiceClass_UUID = '{00001107-0000-1000-8000-00805F9B34FB}'
SDP_HeadsetServiceClass_UUID = '{00001108-0000-1000-8000-00805F9B34FB}'
CordlessTelephonyServiceClass_UUID = '{00001109-0000-1000-8000-00805F9B34FB}'
SDP_AudioSourceServiceClass_UUID = '{0000110A-0000-1000-8000-00805F9B34FB}'
SDP_AudioSinkServiceClass_UUID = '{0000110B-0000-1000-8000-00805F9B34FB}'
SDP_AVRemoteControlTargetServiceClass_UUID = '{0000110C-0000-1000-8000-00805F9B34FB}'
SDP_AdvancedAudioDistributionServiceClass_UUID = '{0000110D-0000-1000-8000-00805F9B34FB}'
SDP_AVRemoteControlServiceClass_UUID = '{0000110E-0000-1000-8000-00805F9B34FB}'
VideoConferencingServiceClass_UUID = '{0000110F-0000-1000-8000-00805F9B34FB}'
IntercomServiceClass_UUID = '{00001110-0000-1000-8000-00805F9B34FB}'
藍(lán)牙傳真服務(wù)
FaxServiceClass_UUID = '{00001111-0000-1000-8000-00805F9B34FB}'
HeadsetAudioGatewayServiceClass_UUID = '{00001112-0000-1000-8000-00805F9B34FB}'
WAPServiceClass_UUID = '{00001113-0000-1000-8000-00805F9B34FB}'
WAPClientServiceClass_UUID = '{00001114-0000-1000-8000-00805F9B34FB}'
藍(lán)牙打印服務(wù)
HCRPrintServiceClass_UUID = '{00001126-0000-1000-8000-00805F9B34FB}'
HCRScanServiceClass_UUID = '{00001127-0000-1000-8000-00805F9B34FB}'
CommonISDNAccessServiceClass_UUID = '{00001128-0000-1000-8000-00805F9B34FB}'
VideoConferencingGWServiceClass_UUID = '{00001129-0000-1000-8000-00805F9B34FB}'
UDIMTServiceClass_UUID = '{0000112A-0000-1000-8000-00805F9B34FB}'
UDITAServiceClass_UUID = '{0000112B-0000-1000-8000-00805F9B34FB}'
AudioVideoServiceClass_UUID = '{0000112C-0000-1000-8000-00805F9B34FB}'
SIMAccessServiceClass_UUID = '{0000112D-0000-1000-8000-00805F9B34FB}'
PnPInformationServiceClass_UUID = '{00001200-0000-1000-8000-00805F9B34FB}'
GenericNetworkingServiceClass_UUID = '{00001201-0000-1000-8000-00805F9B34FB}'
GenericFileTransferServiceClass_UUID = '{00001202-0000-1000-8000-00805F9B34FB}'
GenericAudioServiceClass_UUID = '{00001203-0000-1000-8000-00805F9B34FB}'
GenericTelephonyServiceClass_UUID = '{00001204-0000-1000-8000-00805F9B34FB}'
個(gè)人局域網(wǎng)服務(wù)
PANUServiceClass_UUID = '{00001115-0000-1000-8000-00805F9B34FB}'
NAPServiceClass_UUID = '{00001116-0000-1000-8000-00805F9B34FB}'
GNServiceClass_UUID = '{00001117-0000-1000-8000-00805F9B34FB}'
DirectPrintingServiceClass_UUID = '{00001118-0000-1000-8000-00805F9B34FB}'
ReferencePrintingServiceClass_UUID = '{00001119-0000-1000-8000-00805F9B34FB}'
ImagingServiceClass_UUID = '{0000111A-0000-1000-8000-00805F9B34FB}'
ImagingResponderServiceClass_UUID = '{0000111B-0000-1000-8000-00805F9B34FB}'
ImagingAutomaticArchiveServiceClass_UUID = '{0000111C-0000-1000-8000-00805F9B34FB}'
ImagingReferenceObjectsServiceClass_UUID = '{0000111D-0000-1000-8000-00805F9B34FB}'
SDP_HandsfreeServiceClass_UUID = '{0000111E-0000-1000-8000-00805F9B34FB}'
HandsfreeAudioGatewayServiceClass_UUID = '{0000111F-0000-1000-8000-00805F9B34FB}'
DirectPrintingReferenceObjectsServiceClass_UUID = '{00001120-0000-1000-8000-00805F9B34FB}'
ReflectedUIServiceClass_UUID = '{00001121-0000-1000-8000-00805F9B34FB}'
BasicPringingServiceClass_UUID = '{00001122-0000-1000-8000-00805F9B34FB}'
PrintingStatusServiceClass_UUID = '{00001123-0000-1000-8000-00805F9B34FB}'
人機(jī)輸入服務(wù)
HumanInterfaceDeviceServiceClass_UUID = '{00001124-0000-1000-8000-00805F9B34FB}'
HardcopyCableReplacementServiceClass_UUID = '{00001125-0000-1000-8000-00805F9B34FB}'
(四)、使用藍(lán)牙的步驟:【五步曲】
1、獲取本地藍(lán)牙適配器
BluetoothAdapter mAdapter= BluetoothAdapter.getDefaultAdapter();
2、打開藍(lán)牙
if(!mAdapter.isEnabled()){
//彈出對話框提示用戶是否打開
Intent enabler = new Intent(BluetoothAdapter.ACTION_REQUEST_ENABLE);
startActivityForResult(enabler, REQUEST_ENABLE);
//不做提示,強(qiáng)行打開
// mAdapter.enable();
}
補(bǔ)充一下,使設(shè)備能夠被搜索
Intent enabler = new Intent(BluetoothAdapter.ACTION_REQUEST_DISCOVERABLE);
startActivityForResult(enabler,REQUEST_DISCOVERABLE);
3、搜索設(shè)備
1)mAdapter.startDiscovery()是第一步,可是你會發(fā)現(xiàn)沒有返回的藍(lán)牙設(shè)備,怎么知道查找到了呢?
2)定義BroadcastReceiver,代碼如下
BroadcastReceiver mReceiver = new BroadcastReceiver() {
public void onReceive(Context context, Intent intent) {
String action = intent.getAction();
//找到設(shè)備
if (BluetoothDevice.ACTION_FOUND.equals(action)) {
BluetoothDevice device = intent.getParcelableExtra(BluetoothDevice.EXTRA_DEVICE);
if (device.getBondState() != BluetoothDevice.BOND_BONDED) {
Log.v(TAG, "find device:" + device.getName()+ device.getAddress());
}
//搜索完成
}else if (BluetoothAdapter.ACTION_DISCOVERY_FINISHED.equals(action)) {
setTitle("搜索完成");
if (mNewDevicesAdapter.getCount() == 0) {
Log.v(TAG,"find over");
}
}
//執(zhí)行更新列表的代碼
}
};
這樣,沒查找到新設(shè)備或是搜索完成,相應(yīng)的操作都在上段代碼的兩個(gè)if里執(zhí)行了,不過前提是你要先注冊
BroadcastReceiver,具體代碼如下,該段代碼,一般寫在onCreate()里.
IntentFilter filter = new IntentFilter(BluetoothDevice.ACTION_FOUND);
registerReceiver(mReceiver, filter);
filter = new IntentFilter(BluetoothAdapter.ACTION_DISCOVERY_FINISHED);
registerReceiver(mReceiver, filter);
4、建立連接
首先Android sdk(2.0以上版本)支持的藍(lán)牙連接是通過BluetoothSocket建立連接,服務(wù)器端(BluetoothServerSocket)和客戶端(BluetoothSocket)需指定同樣的UUID,才能建立連接,因?yàn)榻⑦B接的方法會阻塞線程,所以服務(wù)器端和客戶端都應(yīng)啟動新線程連接
1)服務(wù)器端:
BluetoothServerSocket serverSocket = mAdapter. listenUsingRfcommWithServiceRecord(serverSocketName,UUID);
serverSocket.accept();
2)客戶端:
還記得剛才在BroadcastReceiver獲取了BLuetoothDevice么?
BluetoothSocket clienSocket=dcvice. createRfcommSocketToServiceRecord(UUID);
clienSocket.connect();
5、數(shù)據(jù)傳遞
通過以上操作,就已經(jīng)建立的BluetoothSocket連接了,數(shù)據(jù)傳遞無非是通過流的形式
1)獲取流
inputStream = socket.getInputStream();
outputStream = socket.getOutputStream();
2)寫出、讀入
BluetoothServerSocket
BluetoothServerSocket BluetoothAdapter.listenUsingRfcommWithServiceRecord(String name, UUID)
通過此方法監(jiān)聽BluetoothSocket的連接
BluetoothServerSocket.accept() 開始接收BluetoothSocket
BluetoothServerSocket.close() 關(guān)閉服務(wù)
BluetoothSocket
BluetoothSocket BluetoothDevice.createInsecureRfcommSocketToServiceRecord(UUID uuid)
通過此方法向指定的BluetoothDevice發(fā)送Socket連接
UUID:00001101-0000-1000-8000-00805F9B34FB
connect() 嘗試連接
boolean isConnected() 是否已連接,要求最低sdk 14+
BluetoothDevice getRemoteDevice() 獲取當(dāng)前正在或已連接的設(shè)備
InputStream getInputStream() 獲取輸入流
OutputStream getOutputStream() 獲取輸出流
在讀取數(shù)據(jù)時(shí)用數(shù)據(jù)流
DataInputStream/DataOutputStream
基于Socket技術(shù)實(shí)現(xiàn)藍(lán)牙聊天
藍(lán)牙的配對
查找已配對的藍(lán)牙設(shè)備
Set<BluetoothDevice> BluetoothAdapter.getBondedDevices()
查找附件的藍(lán)牙設(shè)備
BluetoothAdapter.startDiscovery())
BluetoothAdapter.isDiscovering() 是否正在查找
BluetoothAdapter.cancelDiscovery() 取消查找
注冊廣播接收器接收查到的設(shè)備信息
BluetoothAdapter.ACTION_DISCOVERY_STARTED 開始查找
BluetoothDevice.ACTION_FOUND 查找到藍(lán)牙設(shè)備
BluetoothDevice.EXTRA_DEVICE 獲取查找到的設(shè)備信息,此數(shù)據(jù)為ParcelableExtra,需要intent.getParcelableExtra()獲取到BluetoothDevice對象
BluetoothAdapter.ACTION_DISCOVERY_FINISHED 查找結(jié)束
判斷配對狀態(tài)
int BluetoothDevice.getBondState() 獲取設(shè)備的配對狀態(tài)
BluetoothDevice.BOND_BONDED 已配對
BluetoothDevice.BOND_BONDING 正在配對
BluetoothDevice.BOND_NONE 未配對
與指定未配對的設(shè)備配對
配對:通過反射獲取BluetoothDevice的boolean createBond()方法,并執(zhí)行
取消配對:通過反射獲取BluetoothDevice的boolean removeBond()方法,并執(zhí)行
三、藍(lán)牙通信案例【實(shí)現(xiàn)服務(wù)器端與多個(gè)客戶端通過藍(lán)牙聊天】
(一)、服務(wù)器端程序制作步驟:
1、服務(wù)器線程
構(gòu)造方法,創(chuàng)建BluetoothServerSocket對象;
通過bluetoothAdapter 的listenUsingRfcommWithServiceRecord()方法;
重寫run()方法。死循環(huán)中,BluetoothServerSocket對象等待接收客戶端的請求 ,如果建立連接,則將客戶端線程放入客戶端線程集合,并啟動客戶端線程。
BluetoothSocket clientSocket = serverSocket.accept();
ClientThread clientThread = new ClientThread(clientSocket);
clientsList.add(clientThread);
clientThread.start();
2、客戶端線程
構(gòu)造方法,獲取客戶端設(shè)備名稱,并獲取客戶端套接字對象的輸入、輸出流對象;
clientName = clientSocket.getRemoteDevice().getName();
is = new DataInputStream(clientSocket.getInputStream());
os = new DataOutputStream(clientSocket.getOutputStream());
重寫run()方法。死循環(huán)中,讀取客戶端發(fā)送過來的數(shù)據(jù),追加到聊天記錄中。啟動發(fā)送線程,向所有客戶端發(fā)送聊天數(shù)據(jù)。
String info = is.readUTF();
appendContent(info);
new SendThread(info).start(); // 向所有客戶端發(fā)送此數(shù)據(jù)
自定義sendInfo()消息發(fā)送方法。
os.writeUTF(info);
3、發(fā)送消息線程
構(gòu)造方法,初始化要發(fā)送的信息數(shù)據(jù);
this.info = info;
重寫run()方法。循環(huán)客戶端線程集合,獲取當(dāng)前已連接的客戶端,并逐一向其發(fā)送數(shù)據(jù) 。
clientThread.sendInfo(info);
(二)、客戶端程序制作步驟:
1、客戶端線程
構(gòu)造方法,初始化BluetoothDevice,連接選擇的設(shè)備,建立連接,并獲取客戶端套接字對象的輸入、輸出流對象;
this.bluetoothDevice = device;
clientSocket = bluetoothDevice .createRfcommSocketToServiceRecord(MainActivity.MY_UUID);
clientSocket.connect();
is = new DataInputStream(clientSocket.getInputStream());
os = new DataOutputStream(clientSocket.getOutputStream());
重寫run()方法。死循環(huán)中,讀取客戶端輸入流數(shù)據(jù),追加到聊天記錄中。
String info = is.readUTF();
appendContent(info);
自定義sendInfo()消息發(fā)送方法。
os.writeUTF(info);
2、發(fā)送消息線程
構(gòu)造方法,初始化要發(fā)送的信息數(shù)據(jù);
this.info = info;
重寫run()方法。調(diào)用連接線程的sendInfo()方法,向服務(wù)器端發(fā)送數(shù)據(jù) 。
clientThread.sendInfo(info);
一、藍(lán)牙介紹:
(一)、Bluetooth的由來及現(xiàn)狀
藍(lán)牙一詞源于公元十世紀(jì)丹麥國王HaraldBlatand名字中的Blatand。Blatand的英文之意就是Blue tooth。這是因?yàn)檫@位讓丹麥人引以為傲的國王酷愛吃藍(lán)莓以至于牙齦都被染成藍(lán)色。由于Blatand統(tǒng)一了丹麥和挪威,所以,作為無線通信技術(shù)的一種,藍(lán)牙技術(shù)之所以取名Bluetooth可謂志向遠(yuǎn)大。
不過,在以Android為代表的智能機(jī)出現(xiàn)以前,藍(lán)牙在早期智能機(jī)甚至功能機(jī)中一直扮演著“雞肋”的角色。那么,隨著無線通信技術(shù)的快速發(fā)展以及Android的普及,藍(lán)牙技術(shù)在我們生活中的應(yīng)用也越來越多,包括藍(lán)牙耳機(jī)和鼠標(biāo),及藍(lán)牙局域網(wǎng)應(yīng)用(聊天、游戲等)。
(二)、藍(lán)牙規(guī)范介紹
Core Specification(核心規(guī)范)
作用:用于規(guī)定藍(lán)牙設(shè)備必須實(shí)現(xiàn)的通用功能和協(xié)議層次。它由軟件和硬件模塊組成,兩個(gè)模塊之間的信息和數(shù)據(jù)通過主機(jī)控制接口(HCI)的解釋才能進(jìn)行傳遞
核心規(guī)范是藍(lán)牙協(xié)議家族的基礎(chǔ),自藍(lán)牙技術(shù)聯(lián)盟(Bluetooth SIG,Special Interest Group)在1999年頒布藍(lán)牙核心規(guī)范1.0版本以來,到目前為止藍(lán)牙SIG一共發(fā)布了七個(gè)重要版本。每一個(gè)版本都促使藍(lán)牙技術(shù)朝著更快、更安全、更省電的方向發(fā)展。
二、藍(lán)牙的用法
(一)、藍(lán)牙API
Android所有關(guān)于藍(lán)牙開發(fā)的類都在android.bluetooth包下,只有8個(gè)類:
BluetoothAdapter 本地藍(lán)牙適配器
BluetoothClass 藍(lán)牙類(主要包括服務(wù)和設(shè)備)
BluetoothClass.Device 藍(lán)牙設(shè)備類
BluetoothClass.Device.Major 藍(lán)牙設(shè)備管理
BluetoothClass.Service 藍(lán)牙服務(wù)類
BluetoothDevice 藍(lán)牙設(shè)備(遠(yuǎn)程藍(lán)牙設(shè)備)
BluetoothServiceSocket 監(jiān)聽藍(lán)牙連接的類
BluetoothSocket 藍(lán)牙連接類
1、BluetoothAdapter :
表示本地的藍(lán)牙適配器 (藍(lán)牙射頻)。BluetoothAdapter 是為所有藍(lán)牙交互的入口點(diǎn)。它可以發(fā)現(xiàn)其他藍(lán)牙設(shè)備、 查詢綁定 (配對) 設(shè)備的列表、 實(shí)例化已知的 MAC 地址的BluetoothDevice(藍(lán)牙設(shè)備) 和創(chuàng)建 BluetoothServerSocket 用于偵聽來自其他設(shè)備的通信。直到我們建立bluetoothSocket連接之前,都要不斷操作它 。BluetoothAdapter里的方法很多,常用的有以下幾個(gè):
cancelDiscovery() 根據(jù)字面意思,是取消發(fā)現(xiàn),也就是說當(dāng)我們正在搜索設(shè)備的時(shí)候調(diào)用這個(gè)方法將不再繼續(xù)搜索;
disable()關(guān)閉藍(lán)牙;
enable()打開藍(lán)牙;這個(gè)方法打開藍(lán)牙不會彈出提示,更多的時(shí)候我們需要問下用戶是否打開,以下兩行代碼同樣是打開藍(lán)牙,不過會提示用戶:
Intemtenabler=new Intent(BluetoothAdapter.ACTION_REQUEST_ENABLE);
startActivityForResult(enabler,reCode);//同startActivity(enabler);
getAddress()獲取本地藍(lán)牙地址
getDefaultAdapter()獲取默認(rèn)BluetoothAdapter,實(shí)際上,也只有這一種方法獲取BluetoothAdapter
getName()獲取本地藍(lán)牙名稱
getRemoteDevice(String address)根據(jù)藍(lán)牙地址獲取遠(yuǎn)程藍(lán)牙設(shè)備
getState()獲取本地藍(lán)牙適配器當(dāng)前狀態(tài)(感覺可能調(diào)試的時(shí)候更需要)
isDiscovering()判斷當(dāng)前是否正在查找設(shè)備,是返回true
isEnabled()判斷藍(lán)牙是否打開,已打開返回true,否則,返回false
listenUsingRfcommWithServiceRecord(String name,UUID uuid)根據(jù)名稱,UUID創(chuàng)建并返回BluetoothServerSocket對象,這是創(chuàng)建BluetoothSocket服務(wù)器端的第一步 。第一個(gè)參數(shù)表示藍(lán)牙服務(wù)的名稱,可以是任意字符串,第二個(gè)參數(shù)是UUID。
startDiscovery()開始搜索,這是搜索的第一步
2、BluetoothDevice
表示遠(yuǎn)程藍(lán)牙設(shè)備。使用此類并通過BluetoothSocket類可以請求連接遠(yuǎn)程設(shè)備,或查詢這臺設(shè)備的信息如其名稱、 地址、 類和綁定狀態(tài)。
createRfcommSocketToServiceRecord(UUIDuuid)
根據(jù)UUID創(chuàng)建并返回一個(gè)BluetoothSocket,這個(gè)方法也是我們獲取BluetoothDevice的目的——創(chuàng)建BluetoothSocket。這個(gè)類其他的方法,如getAddress()、getName(),同BluetoothAdapter。
【備注:】藍(lán)牙—RFCOMM協(xié)議
串口仿真協(xié)議(RFCOMM),RFCOMM是一個(gè)簡單的協(xié)議,其中針對9針RS-232串口仿真附加了部分條款.可支持在兩個(gè)藍(lán)牙設(shè)備之間同時(shí)保持高達(dá)60路的通信連接.RFCOMM的目的是針對如何在兩個(gè)不同設(shè)備上的應(yīng)用之間保證一條完整的通信路徑。
3、BluetoothServerSocket
表示打開服務(wù)器套接字偵聽傳入的請求 (類似于 TCP ServerSocket)。為了連接兩臺 Android 設(shè)備,一臺設(shè)備必須用此類打開一個(gè)服務(wù)器套接字。當(dāng)遠(yuǎn)程藍(lán)牙設(shè)備向此設(shè)備發(fā)出連接請求時(shí),而且當(dāng)連接被接收時(shí),BluetoothServerSocket 將返回連接的 BluetoothSocket。這個(gè)類有三個(gè)方法。
accept()
accept(inttimeout): 兩者的區(qū)別在于后者指定了過時(shí)時(shí)間,需要注意的是,執(zhí)行這兩個(gè)方法的時(shí)候,直到接收到了客戶端的請求(或是過期之后),都會阻塞線程,應(yīng)該放在新線程里運(yùn)行! 還需要注意,這兩個(gè)方法都返回一個(gè)BluetoothSocket,最后的連接也是服務(wù)器端與客戶端這兩個(gè)BluetoothSocket的連接。
close():關(guān)閉
4、BluetoothSocket
跟BluetoothServerSocket相對,是客戶端。表示一個(gè)藍(lán)牙套接字 (類似于 TCP Socket) 的接口。這是一個(gè)允許應(yīng)用程序與另一臺藍(lán)牙設(shè)備通過InputStream和OutputStream來交換數(shù)據(jù)的連接點(diǎn)。其一共5個(gè)方法,一般都會用到。
close():關(guān)閉
connect():連接
getInptuStream():獲取輸入流
getOutputStream():獲取輸出流
getRemoteDevice():獲取遠(yuǎn)程設(shè)備,這里指的是獲取bluetoothSocket指定連接的那個(gè)遠(yuǎn)程藍(lán)牙設(shè)備
5、BluetoothClass
描述的一般特征和藍(lán)牙設(shè)備的功能。這是一整套只讀的屬性用于定義設(shè)備的主要和次要設(shè)備類和它的服務(wù)。然而,這并不是支持所有藍(lán)牙配置文件和服務(wù)的設(shè)備,但很適用于獲取設(shè)備類型
6、BluetoothProfile
表示一個(gè)藍(lán)牙配置文件。藍(lán)牙配置文件是基于藍(lán)牙通信設(shè)備之間的無線接口規(guī)范。如免提規(guī)范(Hands-Free profile)
7、BluetoothHeadset
藍(lán)牙耳機(jī)與手機(jī)一起使用配置文件 ,這包括藍(lán)牙耳機(jī)和免提(v1.5) 的配置文件
8、BluetoothA2dp
定義了如何高質(zhì)量的音頻可以進(jìn)行流式處理從一個(gè)設(shè)備到另一個(gè)通過藍(lán)牙連接。"A2DP"代表先進(jìn)音頻分配協(xié)議
9、BluetoothHealth
表示控制藍(lán)牙服務(wù)健康設(shè)備協(xié)議
10、BluetoothHealthCallback
BluetoothHealthCallback 一個(gè)抽象類,您使用來實(shí)現(xiàn) BluetoothHealth 回調(diào),你必須擴(kuò)展此類并實(shí)現(xiàn)回調(diào)方法以接收有關(guān)更改的更新應(yīng)用程序的注冊和藍(lán)牙通道狀態(tài)。BluetoothHealthAppConfiguration 表示一個(gè)藍(lán)牙健康第三方應(yīng)用程序注冊與遠(yuǎn)程藍(lán)牙健康設(shè)備進(jìn)行通信的應(yīng)用程
11、BluetoothHealthAppConfiguration
表示一個(gè)藍(lán)牙健康第三方應(yīng)用程序注冊與遠(yuǎn)程藍(lán)牙健康設(shè)備進(jìn)行通信的應(yīng)用程序配置
12、BluetoothProfile.ServiceListener
通知 BluetoothProfile IPC 客戶端界面時(shí)已被連接或斷開服務(wù) (即運(yùn)行一個(gè)特定的配置文件內(nèi)部服務(wù))
(二)、使用藍(lán)牙的權(quán)限
<uses-permission android:name="android.permission.BLUETOOTH"/>
<uses-permission android:name="android.permission.BLUETOOTH_ADMIN"/>
(三)、 UUID(universal unique identifier , 全局唯一標(biāo)識符)
格式如下:UUID格式一般是"xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx",可到http://www.uuidgenerator.com 申請。UUID分為5段,是一個(gè)8-4-4-4-12的字符串,這個(gè)字符串要求永不重復(fù)。
String uuid = java.util.UUID.randomUUID().toString();
一般在創(chuàng)建Socket時(shí)需要UUID作為端口的唯一性,如果兩臺Android設(shè)備互聯(lián),則沒有什么特殊的,如果讓非Android的藍(lán)牙設(shè)備連接Android藍(lán)牙設(shè)備,則UUID必須使用某個(gè)固定保留的UUID
Android中創(chuàng)建UUID:
UUID uuid = UUID.fromString("00001101-0000-1000-8000-00805F9B34FB")
常用固定的UUID
藍(lán)牙串口服務(wù)(SPP)
SerialPortServiceClass_UUID = '{00001101-0000-1000-8000-00805F9B34FB}'
LANAccessUsingPPPServiceClass_UUID = '{00001102-0000-1000-8000-00805F9B34FB}'
撥號網(wǎng)絡(luò)服務(wù)
DialupNetworkingServiceClass_UUID = '{00001103-0000-1000-8000-00805F9B34FB}'
信息同步服務(wù)
IrMCSyncServiceClass_UUID = '{00001104-0000-1000-8000-00805F9B34FB}'
SDP_OBEXObjectPushServiceClass_UUID = '{00001105-0000-1000-8000-00805F9B34FB}'
文件傳輸服務(wù)
OBEXFileTransferServiceClass_UUID = '{00001106-0000-1000-8000-00805F9B34FB}'
IrMCSyncCommandServiceClass_UUID = '{00001107-0000-1000-8000-00805F9B34FB}'
SDP_HeadsetServiceClass_UUID = '{00001108-0000-1000-8000-00805F9B34FB}'
CordlessTelephonyServiceClass_UUID = '{00001109-0000-1000-8000-00805F9B34FB}'
SDP_AudioSourceServiceClass_UUID = '{0000110A-0000-1000-8000-00805F9B34FB}'
SDP_AudioSinkServiceClass_UUID = '{0000110B-0000-1000-8000-00805F9B34FB}'
SDP_AVRemoteControlTargetServiceClass_UUID = '{0000110C-0000-1000-8000-00805F9B34FB}'
SDP_AdvancedAudioDistributionServiceClass_UUID = '{0000110D-0000-1000-8000-00805F9B34FB}'
SDP_AVRemoteControlServiceClass_UUID = '{0000110E-0000-1000-8000-00805F9B34FB}'
VideoConferencingServiceClass_UUID = '{0000110F-0000-1000-8000-00805F9B34FB}'
IntercomServiceClass_UUID = '{00001110-0000-1000-8000-00805F9B34FB}'
藍(lán)牙傳真服務(wù)
FaxServiceClass_UUID = '{00001111-0000-1000-8000-00805F9B34FB}'
HeadsetAudioGatewayServiceClass_UUID = '{00001112-0000-1000-8000-00805F9B34FB}'
WAPServiceClass_UUID = '{00001113-0000-1000-8000-00805F9B34FB}'
WAPClientServiceClass_UUID = '{00001114-0000-1000-8000-00805F9B34FB}'
藍(lán)牙打印服務(wù)
HCRPrintServiceClass_UUID = '{00001126-0000-1000-8000-00805F9B34FB}'
HCRScanServiceClass_UUID = '{00001127-0000-1000-8000-00805F9B34FB}'
CommonISDNAccessServiceClass_UUID = '{00001128-0000-1000-8000-00805F9B34FB}'
VideoConferencingGWServiceClass_UUID = '{00001129-0000-1000-8000-00805F9B34FB}'
UDIMTServiceClass_UUID = '{0000112A-0000-1000-8000-00805F9B34FB}'
UDITAServiceClass_UUID = '{0000112B-0000-1000-8000-00805F9B34FB}'
AudioVideoServiceClass_UUID = '{0000112C-0000-1000-8000-00805F9B34FB}'
SIMAccessServiceClass_UUID = '{0000112D-0000-1000-8000-00805F9B34FB}'
PnPInformationServiceClass_UUID = '{00001200-0000-1000-8000-00805F9B34FB}'
GenericNetworkingServiceClass_UUID = '{00001201-0000-1000-8000-00805F9B34FB}'
GenericFileTransferServiceClass_UUID = '{00001202-0000-1000-8000-00805F9B34FB}'
GenericAudioServiceClass_UUID = '{00001203-0000-1000-8000-00805F9B34FB}'
GenericTelephonyServiceClass_UUID = '{00001204-0000-1000-8000-00805F9B34FB}'
個(gè)人局域網(wǎng)服務(wù)
PANUServiceClass_UUID = '{00001115-0000-1000-8000-00805F9B34FB}'
NAPServiceClass_UUID = '{00001116-0000-1000-8000-00805F9B34FB}'
GNServiceClass_UUID = '{00001117-0000-1000-8000-00805F9B34FB}'
DirectPrintingServiceClass_UUID = '{00001118-0000-1000-8000-00805F9B34FB}'
ReferencePrintingServiceClass_UUID = '{00001119-0000-1000-8000-00805F9B34FB}'
ImagingServiceClass_UUID = '{0000111A-0000-1000-8000-00805F9B34FB}'
ImagingResponderServiceClass_UUID = '{0000111B-0000-1000-8000-00805F9B34FB}'
ImagingAutomaticArchiveServiceClass_UUID = '{0000111C-0000-1000-8000-00805F9B34FB}'
ImagingReferenceObjectsServiceClass_UUID = '{0000111D-0000-1000-8000-00805F9B34FB}'
SDP_HandsfreeServiceClass_UUID = '{0000111E-0000-1000-8000-00805F9B34FB}'
HandsfreeAudioGatewayServiceClass_UUID = '{0000111F-0000-1000-8000-00805F9B34FB}'
DirectPrintingReferenceObjectsServiceClass_UUID = '{00001120-0000-1000-8000-00805F9B34FB}'
ReflectedUIServiceClass_UUID = '{00001121-0000-1000-8000-00805F9B34FB}'
BasicPringingServiceClass_UUID = '{00001122-0000-1000-8000-00805F9B34FB}'
PrintingStatusServiceClass_UUID = '{00001123-0000-1000-8000-00805F9B34FB}'
人機(jī)輸入服務(wù)
HumanInterfaceDeviceServiceClass_UUID = '{00001124-0000-1000-8000-00805F9B34FB}'
HardcopyCableReplacementServiceClass_UUID = '{00001125-0000-1000-8000-00805F9B34FB}'
(四)、使用藍(lán)牙的步驟:【五步曲】
1、獲取本地藍(lán)牙適配器
BluetoothAdapter mAdapter= BluetoothAdapter.getDefaultAdapter();
2、打開藍(lán)牙
if(!mAdapter.isEnabled()){
//彈出對話框提示用戶是否打開
Intent enabler = new Intent(BluetoothAdapter.ACTION_REQUEST_ENABLE);
startActivityForResult(enabler, REQUEST_ENABLE);
//不做提示,強(qiáng)行打開
// mAdapter.enable();
}
補(bǔ)充一下,使設(shè)備能夠被搜索
Intent enabler = new Intent(BluetoothAdapter.ACTION_REQUEST_DISCOVERABLE);
startActivityForResult(enabler,REQUEST_DISCOVERABLE);
3、搜索設(shè)備
1)mAdapter.startDiscovery()是第一步,可是你會發(fā)現(xiàn)沒有返回的藍(lán)牙設(shè)備,怎么知道查找到了呢?
2)定義BroadcastReceiver,代碼如下
BroadcastReceiver mReceiver = new BroadcastReceiver() {
public void onReceive(Context context, Intent intent) {
String action = intent.getAction();
//找到設(shè)備
if (BluetoothDevice.ACTION_FOUND.equals(action)) {
BluetoothDevice device = intent.getParcelableExtra(BluetoothDevice.EXTRA_DEVICE);
if (device.getBondState() != BluetoothDevice.BOND_BONDED) {
Log.v(TAG, "find device:" + device.getName()+ device.getAddress());
}
//搜索完成
}else if (BluetoothAdapter.ACTION_DISCOVERY_FINISHED.equals(action)) {
setTitle("搜索完成");
if (mNewDevicesAdapter.getCount() == 0) {
Log.v(TAG,"find over");
}
}
//執(zhí)行更新列表的代碼
}
};
這樣,沒查找到新設(shè)備或是搜索完成,相應(yīng)的操作都在上段代碼的兩個(gè)if里執(zhí)行了,不過前提是你要先注冊
BroadcastReceiver,具體代碼如下,該段代碼,一般寫在onCreate()里.
IntentFilter filter = new IntentFilter(BluetoothDevice.ACTION_FOUND);
registerReceiver(mReceiver, filter);
filter = new IntentFilter(BluetoothAdapter.ACTION_DISCOVERY_FINISHED);
registerReceiver(mReceiver, filter);
4、建立連接
首先Android sdk(2.0以上版本)支持的藍(lán)牙連接是通過BluetoothSocket建立連接,服務(wù)器端(BluetoothServerSocket)和客戶端(BluetoothSocket)需指定同樣的UUID,才能建立連接,因?yàn)榻⑦B接的方法會阻塞線程,所以服務(wù)器端和客戶端都應(yīng)啟動新線程連接
1)服務(wù)器端:
BluetoothServerSocket serverSocket = mAdapter. listenUsingRfcommWithServiceRecord(serverSocketName,UUID);
serverSocket.accept();
2)客戶端:
還記得剛才在BroadcastReceiver獲取了BLuetoothDevice么?
BluetoothSocket clienSocket=dcvice. createRfcommSocketToServiceRecord(UUID);
clienSocket.connect();
5、數(shù)據(jù)傳遞
通過以上操作,就已經(jīng)建立的BluetoothSocket連接了,數(shù)據(jù)傳遞無非是通過流的形式
1)獲取流
inputStream = socket.getInputStream();
outputStream = socket.getOutputStream();
2)寫出、讀入
BluetoothServerSocket
BluetoothServerSocket BluetoothAdapter.listenUsingRfcommWithServiceRecord(String name, UUID)
通過此方法監(jiān)聽BluetoothSocket的連接
BluetoothServerSocket.accept() 開始接收BluetoothSocket
BluetoothServerSocket.close() 關(guān)閉服務(wù)
BluetoothSocket
BluetoothSocket BluetoothDevice.createInsecureRfcommSocketToServiceRecord(UUID uuid)
通過此方法向指定的BluetoothDevice發(fā)送Socket連接
UUID:00001101-0000-1000-8000-00805F9B34FB
connect() 嘗試連接
boolean isConnected() 是否已連接,要求最低sdk 14+
BluetoothDevice getRemoteDevice() 獲取當(dāng)前正在或已連接的設(shè)備
InputStream getInputStream() 獲取輸入流
OutputStream getOutputStream() 獲取輸出流
在讀取數(shù)據(jù)時(shí)用數(shù)據(jù)流
DataInputStream/DataOutputStream
基于Socket技術(shù)實(shí)現(xiàn)藍(lán)牙聊天
藍(lán)牙的配對
查找已配對的藍(lán)牙設(shè)備
Set<BluetoothDevice> BluetoothAdapter.getBondedDevices()
查找附件的藍(lán)牙設(shè)備
BluetoothAdapter.startDiscovery())
BluetoothAdapter.isDiscovering() 是否正在查找
BluetoothAdapter.cancelDiscovery() 取消查找
注冊廣播接收器接收查到的設(shè)備信息
BluetoothAdapter.ACTION_DISCOVERY_STARTED 開始查找
BluetoothDevice.ACTION_FOUND 查找到藍(lán)牙設(shè)備
BluetoothDevice.EXTRA_DEVICE 獲取查找到的設(shè)備信息,此數(shù)據(jù)為ParcelableExtra,需要intent.getParcelableExtra()獲取到BluetoothDevice對象
BluetoothAdapter.ACTION_DISCOVERY_FINISHED 查找結(jié)束
判斷配對狀態(tài)
int BluetoothDevice.getBondState() 獲取設(shè)備的配對狀態(tài)
BluetoothDevice.BOND_BONDED 已配對
BluetoothDevice.BOND_BONDING 正在配對
BluetoothDevice.BOND_NONE 未配對
與指定未配對的設(shè)備配對
配對:通過反射獲取BluetoothDevice的boolean createBond()方法,并執(zhí)行
取消配對:通過反射獲取BluetoothDevice的boolean removeBond()方法,并執(zhí)行
三、藍(lán)牙通信案例【實(shí)現(xiàn)服務(wù)器端與多個(gè)客戶端通過藍(lán)牙聊天】
(一)、服務(wù)器端程序制作步驟:
1、服務(wù)器線程
構(gòu)造方法,創(chuàng)建BluetoothServerSocket對象;
通過bluetoothAdapter 的listenUsingRfcommWithServiceRecord()方法;
重寫run()方法。死循環(huán)中,BluetoothServerSocket對象等待接收客戶端的請求 ,如果建立連接,則將客戶端線程放入客戶端線程集合,并啟動客戶端線程。
BluetoothSocket clientSocket = serverSocket.accept();
ClientThread clientThread = new ClientThread(clientSocket);
clientsList.add(clientThread);
clientThread.start();
2、客戶端線程
構(gòu)造方法,獲取客戶端設(shè)備名稱,并獲取客戶端套接字對象的輸入、輸出流對象;
clientName = clientSocket.getRemoteDevice().getName();
is = new DataInputStream(clientSocket.getInputStream());
os = new DataOutputStream(clientSocket.getOutputStream());
重寫run()方法。死循環(huán)中,讀取客戶端發(fā)送過來的數(shù)據(jù),追加到聊天記錄中。啟動發(fā)送線程,向所有客戶端發(fā)送聊天數(shù)據(jù)。
String info = is.readUTF();
appendContent(info);
new SendThread(info).start(); // 向所有客戶端發(fā)送此數(shù)據(jù)
自定義sendInfo()消息發(fā)送方法。
os.writeUTF(info);
3、發(fā)送消息線程
構(gòu)造方法,初始化要發(fā)送的信息數(shù)據(jù);
this.info = info;
重寫run()方法。循環(huán)客戶端線程集合,獲取當(dāng)前已連接的客戶端,并逐一向其發(fā)送數(shù)據(jù) 。
clientThread.sendInfo(info);
(二)、客戶端程序制作步驟:
1、客戶端線程
構(gòu)造方法,初始化BluetoothDevice,連接選擇的設(shè)備,建立連接,并獲取客戶端套接字對象的輸入、輸出流對象;
this.bluetoothDevice = device;
clientSocket = bluetoothDevice .createRfcommSocketToServiceRecord(MainActivity.MY_UUID);
clientSocket.connect();
is = new DataInputStream(clientSocket.getInputStream());
os = new DataOutputStream(clientSocket.getOutputStream());
重寫run()方法。死循環(huán)中,讀取客戶端輸入流數(shù)據(jù),追加到聊天記錄中。
String info = is.readUTF();
appendContent(info);
自定義sendInfo()消息發(fā)送方法。
os.writeUTF(info);
2、發(fā)送消息線程
構(gòu)造方法,初始化要發(fā)送的信息數(shù)據(jù);
this.info = info;
重寫run()方法。調(diào)用連接線程的sendInfo()方法,向服務(wù)器端發(fā)送數(shù)據(jù) 。
clientThread.sendInfo(info);
總結(jié)
以上是生活随笔為你收集整理的蓝牙及蓝牙通讯Bluetooth概述的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: Y86-64指令集体系结构
- 下一篇: hbase空间清理