基礎:
這篇文檔描述瞭怎麼使用Android Bluetooth APIs完成數據交換的四個主要的任務:創建Bluetooth,找到本地區域可用的藍牙設備或匹配的藍牙設備,連接設備,傳輸數據。
所有的Bluetooth APIs都在android.bluetooth包下。下面是創建藍牙連接需要實現的類和接口:
BluetoothAdapter:
表示本地的藍牙適配器。BluetoothAdapter是所有藍牙交換的接入點。使用它,你可以發現其他的藍牙設備,查找一些匹配的設備,用MAC地址來實例化一個BluetoothDevice。創建一個BluetoothServerSocket來監聽其他設備,進而和它們進行通信。
BluetoothDevice:
表示遠程的藍牙設備。用它通過BluetoothSocket來請求與遠程的設備進行連接。後者查詢設備的基本信息,例如名稱,地址,類或者結合的狀態。
BluetoothSocket:
表示一個Bluetooth socket接口(與TCP socket相似)。它是一個連接點,運行設備通過InputStream和OutputStream的形式來交換數據。
BluetoothServiceSocket:
表示一個打開服務socket,用來監聽收到的請求(與TCP server socket相似)。為瞭連接設備,一個設備必須打開服務socket。當一個遠程的設備請求連接的時候,當連接被接收的時候,BluetoothServiceSocket返回一個BluetoothSocket。
BluetoothClass:
描述藍牙設備的一般特征和性能。這是個隻讀的一系列屬性。定義瞭主要和最小的設備類和服務。然而,它描述的設備屬性和和服務是不完全可靠的,但是,在表示設備類型時,它是有用的。
BluetoothProfile:
一個代表藍牙屬性的接口。指基於無線藍牙交流的無線接口規則。
BluetoothHeadset:
提供在手機手機上使用藍牙耳機的支持。
BluetoothA2dp:
定義什麼樣的數據可以在藍牙之間傳遞。
BluetoothProfiles.ServiceListener:
當藍牙設備連接或者斷開時,用它來通知BluetoothProfiles IPC客戶端。它是一個接口。
藍牙權限:
為瞭使用藍牙,你必須在你的應用程序中聲明權限。
<manifest … >
<uses-permission android:name="android.permission.BLUETOOTH" />
…
</manifest>
兩種權限:BLUETOOTH和BLUETOOTH ADMIN.
當使用BLUETOOTH ADMIN時,一定要聲明BLUETOOTH。
創建Bluetooth:
1.得到BluetoothAdaper。
BluetoothAdapter mBluetoothAdapter = BluetoothAdapter.getDefaultAdapter();
if (mBluetoothAdapter == null) {
// Device does not support Bluetooth
}
如何不為null,說明本機可用藍牙設備。
2.使用Bluetooth。
if (mBluetoothAdapter.isEnabled()) {
Intent enableBtIntent = new Intent(BluetoothAdapter.ACTION_REQUEST_ENABLE);
startActivityForResult(enableBtIntent, REQUEST_ENABLE_BT);
}
查看匹配的設備:
Set<BluetoothDevice> pairedDevices = mBluetoothAdapter.getBondedDevices();
// If there are paired devices
if (pairedDevices.size() > 0) {
// Loop through paired devices
for (BluetoothDevice device : pairedDevices) {
// Add the name and address to an array adapter to show in a ListView
mArrayAdapter.add(device.getName() + "\n" + device.getAddress());
}
}
發現設備:
// Create a BroadcastReceiver for ACTION_FOUND
private final BroadcastReceiver mReceiver = new BroadcastReceiver() {
public void onReceive(Context context, Intent intent) {
String action = intent.getAction();
// When discovery finds a device
if (BluetoothDevice.ACTION_FOUND.equals(action)) {
// Get the BluetoothDevice object from the Intent
BluetoothDevice device = intent.getParcelableExtra(BluetoothDevice.EXTRA_DEVICE);
// Add the name and address to an array adapter to show in a ListView
mArrayAdapter.add(device.getName() + "\n" + device.getAddress());
}
}
};
// Register the BroadcastReceiver
IntentFilter filter = new IntentFilter(BluetoothDevice.ACTION_FOUND);
registerReceiver(mReceiver, filter); // Don't forget to unregister during onDestroy
連接設備:
做為一個服務者:
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) { }
}
}
做為客戶端:
private class ConnectThread extends Thread {
private final BluetoothSocket mmSocket;
private final BluetoothDevice mmDevice;
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) { }
}
}
管理連接:
private class ConnectedThread extends Thread {
private final BluetoothSocket mmSocket;
private final InputStream mmInStream;
private final OutputStream mmOutStream;
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) { }
}
}
摘自 燕龍安的專欄