藍牙開發相關
使用Android Bluetooth APIs将裝置通過藍牙連接配接并通信,設定藍牙,查找藍牙裝置,配對藍牙裝置
連接配接并傳輸資料,以下是Android系統提供的藍牙相關的類和接口
BluetoothAdapter
BluetoothDevice
BluetoothSocket
BluetoothServerSocket
BluetoothClass
BluetoothProfile
BluetoothHeadset
BluetoothA2dp
BluetoothHealth
BluetoothHealthCallback
BluetoothHealthAppConfiguration
BluetoothProfile.ServiceListener
藍牙權限
使用藍牙功能,需要在AndroidManifest.xml中聲明藍牙相關的權限
建立藍牙
初始化連接配接
在通過藍牙通信之前,需要先确定裝置是否支援藍牙功能,先初始化一個BluetoothAdapter的執行個體,
BluetoothAdapter提供了一個靜态方法getDefaultAdapter()來獲得BluetoothAdapter的執行個體
BluetoothAdapter mBluetoothAdapter = BluetoothAdapter.getDefaultAdapter();
if (mBluetoothAdapter == null) {
// 裝置不支援藍牙功能
}
打開藍牙
下一步就是打開藍牙,調用isEnabled()方法檢查藍牙功能是否已經打開,傳回true說明藍牙已開啟,
傳回false說明藍牙功能未開啟,開啟藍牙可以通過發送廣播ACTION_REQUEST_ENABLE,也可以通過方法
enable()直接打開,這兩種方法都會有藍牙權限的提示,選擇允許,否則無法打開藍牙
if (!mBluetoothAdapter.isEnabled()) {
Intent enableBtIntent = new Intent(BluetoothAdapter.ACTION_REQUEST_ENABLE);
startActivityForResult(enableBtIntent, REQUEST_ENABLE_BT);
}
mBluetoothAdapter.enable();
在應用中可以設定藍牙的狀态的監聽ACTION_STATE_CHANGED廣播,當藍牙的狀态的變化時,就會觸發這個
廣播,接收到這個廣播之後,在intent中可以獲得目前藍牙的狀态和前一次的藍牙的狀态
int state = intent.getIntExtra(BluetoothAdapter.EXTRA_STATE, BluetoothAdapter.ERROR);
藍牙的狀态值有:
int STATE_OFF = 10;//藍牙關閉狀态
int STATE_TURNING_ON = 11;//藍牙正在打開
int STATE_ON = 12;//藍牙打開狀态
int STATE_TURNING_OFF = 13;//藍牙正在關閉
查找藍牙裝置
打開藍牙之後,下一步就是查找可以使用的藍牙裝置,藍牙的api中也提供了相關的接口,由于藍牙的掃描
是一個耗電的操作,不用時計時取消掃描藍牙
mBluetoothAdapter.isDiscovering(); //監測藍牙是否正在掃描
mBluetoothAdapter.startDiscovery();//開始掃描
mBluetoothAdapter.cancelDiscovery();//取消掃描
為了發現可用的藍牙的裝置,必須在應用中注冊ACTION_FOUND的廣播,調用方法startDiscovery()如果查找到可用的
裝置會觸發這個廣播,這個廣播中帶有EXTRA_DEVICE的裝置資訊可以通過下面的方法獲得裝置的資訊
private final BroadcastReceiver mReceiver = new BroadcastReceiver() {
public void onReceive(Context context, Intent intent) {
String action = intent.getAction();
if (BluetoothDevice.ACTION_FOUND.equals(action)) {
BluetoothDevice device = intent.getParcelableExtra(BluetoothDevice.EXTRA_DEVICE);
Log.e("tag","device name: "+device.getName()+" address: "+device.getAddress());
}
}
};
IntentFilter filter = new IntentFilter(BluetoothDevice.ACTION_FOUND);
registerReceiver(mReceiver, filter);
查詢已經配對的裝置清單
在進行查找之前,可以先獲得之前已經配對成功的藍牙裝置的清單,可以調用方法getBondedDevices()獲得
已經配對的藍牙裝置清單
Set pairedDevices = mBluetoothAdapter.getBondedDevices();
if (pairedDevices.size() > 0) {
for (BluetoothDevice device : pairedDevices) {
//可以獲得已經配對的藍牙的名稱和位址
Log.e("tag","device name: "+device.getName()+" address: "+device.getAddress());
}
}
是其他裝置可見
上面講的都是發現其他的藍牙裝置,也可以設定裝置本身是否對其他裝置可見,通過發送ACTION_REQUEST_DISCOVERABLE
的廣播,會調用系統的方法,還可以設定多長時間内是可見的,在intent中設定EXTRA_DISCOVERABLE_DURATION,最大值是
3600s,超過3600s會設定為120s,點選允許會回調onActivityResult()方法
//設定裝置在300s内是可見的
Intent discoverableIntent = new
Intent(BluetoothAdapter.ACTION_REQUEST_DISCOVERABLE);
discoverableIntent.putExtra(BluetoothAdapter.EXTRA_DISCOVERABLE_DURATION, 300);
startActivity(discoverableIntent);
如果沒有打開藍牙,執行上面的操作會自動打開藍牙
可以通過監聽ACTION_SCAN_MODE_CHANGED廣播,可以在intent中根據EXTRA_SCAN_MODE的參數獲得目前裝置的SCAN MODE
有一些幾種模式
int SCAN_MODE_NONE = 20;//這個模式不能被發現也不能連接配接
int SCAN_MODE_CONNECTABLE = 21;//這個模式不能被掃描到,但是可以連接配接
int SCAN_MODE_CONNECTABLE_DISCOVERABLE = 23;//這個模式可以被發現,也能被連接配接
藍牙的連接配接
Server 端
通過BluetoothAdapter的listenUsingRfcommWithServiceRecord(String, UUID)方法獲得BluetoothServerSocket對象
的執行個體,然後socket就會通過accept()監聽用戶端的連接配接的狀态
private class AcceptThread extends Thread {
private final BluetoothServerSocket mmServerSocket;
public AcceptThread() {
BluetoothServerSocket tmp = null;
try {
tmp = mBluetoothAdapter.listenUsingRfcommWithServiceRecord(NAME, MY_UUID);
} catch (IOException e) { }
mmServerSocket = tmp;
}
public void run() {
BluetoothSocket socket = null;
// 在背景一直監聽用戶端的請求
while (true) {
try {
socket = mmServerSocket.accept();
} catch (IOException e) {
break;
}
if (socket != null) {
mmServerSocket.close();
break;
}
}
}
public void cancel() {
try {
mmServerSocket.close();
} catch (IOException e) { }
}
}
Client 端
使用BluetoothDevice的createRfcommSocketToServiceRecord(UUID)方法獲得BluetoothSocket對象的執行個體
然後調用connect()方法,這時server端會監聽到這個請求,之後就建立連接配接,然後就可以進行通信了
private class ConnectThread extends Thread {
private final BluetoothSocket mmSocket;
private final BluetoothDevice mmDevice;
public ConnectThread(BluetoothDevice device) {
BluetoothSocket tmp = null;
mmDevice = device;
try {
tmp = device.createRfcommSocketToServiceRecord(MY_UUID);
} catch (IOException e) { }
mmSocket = tmp;
}
public void run() {
mBluetoothAdapter.cancelDiscovery();
try {
mmSocket.connect();
} catch (IOException connectException) {
try {
mmSocket.close();
} catch (IOException closeException) { }
return;
}
}
public void cancel() {
try {
mmSocket.close();
} catch (IOException e) { }
}
}
連接配接的監聽
可以通過注冊廣播監聽藍牙裝置連接配接的狀态變化,廣播BluetoothDevice.ACTION_BOND_STATE_CHANGED,監聽到這個廣播之後,可以
在intent中獲得連接配接的狀态
int state = intent.getIntExtra(BluetoothDevice.EXTRA_BOND_STATE, BluetoothDevice.BOND_NONE);
裝置連接配接的狀态值
int BOND_NONE = 10;//沒有連接配接
int BOND_BONDING = 11;//正在連接配接
int BOND_BONDED = 12;//已經建立連接配接