1. 使用藍(lán)牙的響應(yīng)權(quán)限
在這里首先要了解對(duì)藍(lán)牙操作一個(gè)核心類BluetoothAdapter
使用BluetoothAdapter的startDiscovery()方法來搜索藍(lán)牙設(shè)備
startDiscovery()方法是一個(gè)異步方法,調(diào)用后會(huì)立即返回。該方法會(huì)進(jìn)行對(duì)其他藍(lán)牙設(shè)備的搜索,該過程會(huì)持續(xù)12秒。該方法調(diào)用后,搜索過程實(shí)際上是在一個(gè)System Service中進(jìn)行的,所以可以調(diào)用cancelDiscovery()方法來停止搜索(該方法可以在未執(zhí)行discovery請(qǐng)求時(shí)調(diào)用)。
請(qǐng)求Discovery后,系統(tǒng)開始搜索藍(lán)牙設(shè)備,在這個(gè)過程中,系統(tǒng)會(huì)發(fā)送以下三個(gè)廣播:
ACTION_DISCOVERY_START:開始搜索
ACTION_DISCOVERY_FINISHED:搜索結(jié)束
ACTION_FOUND:找到設(shè)備,這個(gè)Intent中包含兩個(gè)extra fields:EXTRA_DEVICE和EXTRA_CLASS,分別包含BluetooDevice和BluetoothClass。
我們可以自己注冊(cè)相應(yīng)的BroadcastReceiver來接收響應(yīng)的廣播,以便實(shí)現(xiàn)某些功能
如果打算建議兩個(gè)藍(lán)牙設(shè)備之間的連接,則必須實(shí)現(xiàn)服務(wù)器端與客戶端的機(jī)制。當(dāng)兩個(gè)設(shè)備在同一個(gè)RFCOMM channel下分別擁有一個(gè)連接的BluetoothSocket,這兩個(gè)設(shè)備才可以說是建立了連接。
服務(wù)器設(shè)備與客戶端設(shè)備獲取BluetoothSocket的途徑是不同的。服務(wù)器設(shè)備是通過accepted一個(gè)incoming connection來獲取的,而客戶端設(shè)備則是通過打開一個(gè)到服務(wù)器的RFCOMM channel來獲取的。
服務(wù)器端的實(shí)現(xiàn)
通過調(diào)用BluetoothAdapter的listenUsingRfcommWithServiceRecord(String, UUID)方法來獲取BluetoothServerSocket(UUID用于客戶端與服務(wù)器端之間的配對(duì))
調(diào)用BluetoothServerSocket的accept()方法監(jiān)聽連接請(qǐng)求,如果收到請(qǐng)求,則返回一個(gè)BluetoothSocket實(shí)例(此方法為block方法,應(yīng)置于新線程中)
如果不想在accept其他的連接,則調(diào)用BluetoothServerSocket的close()方法釋放資源(調(diào)用該方法后,之前獲得的BluetoothSocket實(shí)例并沒有close。但由于RFCOMM一個(gè)時(shí)刻只允許在一條channel中有一個(gè)連接,則一般在accept一個(gè)連接后,便close掉BluetoothServerSocket)
public AcceptThread() {
// Use a temporary object that is later assigned to mmServerSocket,
// because mmServerSocket is final
BluetoothServerSocket tmp = null;
try {
// MY_UUID is the app's UUID string, also used by the client code
tmp = mBluetoothAdapter.listenUsingRfcommWithServiceRecord(NAME, MY_UUID);
} catch (IOException e) { }
mmServerSocket = tmp;
}
public void run() {
BluetoothSocket socket = null;
// Keep listening until exception occurs or a socket is returned
while (true) {
try {
socket = mmServerSocket.accept();
} catch (IOException e) {
break;
}
// If a connection was accepted
if (socket != null) {
// Do work to manage the connection (in a separate thread)
manageConnectedSocket(socket);
mmServerSocket.close();
break;
}
}
}
/** Will cancel the listening socket, and cause the thread to finish */
public void cancel() {
try {
mmServerSocket.close();
} catch (IOException e) { }
}
}
調(diào)用BluetoothService的listenUsingRfcommWithServiceRecord(String, UUID)方法獲取BluetoothSocket(該UUID應(yīng)該同于服務(wù)器端的UUID)
調(diào)用BluetoothSocket的connect()方法(該方法為block方法),如果UUID同服務(wù)器端的UUID匹配,并且連接被服務(wù)器端accept,則connect()方法返回
注意:在調(diào)用connect()方法之前,應(yīng)當(dāng)確定當(dāng)前沒有搜索設(shè)備,否則連接會(huì)變得非常慢并且容易失敗
public ConnectThread(BluetoothDevice device) {
// Use a temporary object that is later assigned to mmSocket,
// because mmSocket is final
BluetoothSocket tmp = null;
mmDevice = device;
// Get a BluetoothSocket to connect with the given BluetoothDevice
try {
// MY_UUID is the app's UUID string, also used by the server code
tmp = device.createRfcommSocketToServiceRecord(MY_UUID);
} catch (IOException e) { }
mmSocket = tmp;
}
public void run() {
// Cancel discovery because it will slow down the connection
mBluetoothAdapter.cancelDiscovery();
try {
// Connect the device through the socket. This will block
// until it succeeds or throws an exception
mmSocket.connect();
} catch (IOException connectException) {
// Unable to connect; close the socket and get out
try {
mmSocket.close();
} catch (IOException closeException) { }
return;
}
// Do work to manage the connection (in a separate thread)
manageConnectedSocket(mmSocket);
}
/** Will cancel an in-progress connection, and close the socket */
public void cancel() {
try {
mmSocket.close();
} catch (IOException e) { }
}
}
使用read(bytes[])和write(bytes[])方法分別進(jìn)行讀寫操作
注意:read(bytes[])方法會(huì)一直block,知道從流中讀取到信息,而write(bytes[])方法并不是經(jīng)常的block(比如在另一設(shè)備沒有及時(shí)read或者中間緩沖區(qū)已滿的情況下,write方法會(huì)block)
public ConnectedThread(BluetoothSocket socket) {
mmSocket = socket;
InputStream tmpIn = null;
OutputStream tmpOut = null;
// Get the input and output streams, using temp objects because
// member streams are final
try {
tmpIn = socket.getInputStream();
tmpOut = socket.getOutputStream();
} catch (IOException e) { }
mmInStream = tmpIn;
mmOutStream = tmpOut;
}
public void run() {
byte[] buffer = new byte[1024]; // buffer store for the stream
int bytes; // bytes returned from read()
// Keep listening to the InputStream until an exception occurs
while (true) {
try {
// Read from the InputStream
bytes = mmInStream.read(buffer);
// Send the obtained bytes to the UI Activity
mHandler.obtainMessage(MESSAGE_READ, bytes, -1, buffer)
.sendToTarget();
} catch (IOException e) {
break;
}
}
}
/* Call this from the main Activity to send data to the remote device */
public void write(byte[] bytes) {
try {
mmOutStream.write(bytes);
} catch (IOException e) { }
}
/* Call this from the main Activity to shutdown the connection */
public void cancel() {
try {
mmSocket.close();
} catch (IOException e) { }
}
}
新聞熱點(diǎn)
疑難解答
圖片精選