作為菜鳥鳞绕,記錄下今年藍(lán)牙入坑1年的一些問題,方便回顧尸曼;
藍(lán)牙的相應(yīng)api就不貼了们何;
要實(shí)現(xiàn)自動(dòng)配對(duì)先注冊(cè)廣播:
/**
* 搜索BroadcastReceiver
*/
private final BroadcastReceiver searchDevices = new BroadcastReceiver() {
@SuppressLint("NewApi")
@Override
public void onReceive(Context context, Intent intent) {
String action = intent.getAction();
BluetoothDevice device = null;
// 搜索設(shè)備時(shí),取得設(shè)備的MAC地址
if (BluetoothDevice.ACTION_FOUND.equals(action)) {
device = intent.getParcelableExtra(BluetoothDevice.EXTRA_DEVICE);
if (device.getBondState() == BluetoothDevice.BOND_NONE) {
String str = " 未配對(duì)|" + device.getName() + "|"
+ device.getAddress();
LogUtils.e(str);
}
} else if (BluetoothDevice.ACTION_BOND_STATE_CHANGED.equals(action)) {
LogUtils.e("action:" + action);
device = intent.getParcelableExtra(BluetoothDevice.EXTRA_DEVICE);
switch (device.getBondState()) {
case BluetoothDevice.BOND_BONDING:
LogUtils.e(TAG, "正在配對(duì)......");
break;
case BluetoothDevice.BOND_BONDED:
LogUtils.e(TAG, "配對(duì)成功控轿!");
break;
case BluetoothDevice.BOND_NONE:
LogUtils.e(TAG, "取消配對(duì)");
default:
break;
}
} else if (intent.getAction().equals(BluetoothDevice.ACTION_PAIRING_REQUEST)) {
LogUtils.e("action:" + action);
device = intent.getParcelableExtra(BluetoothDevice.EXTRA_DEVICE);
if (device.getBondState() != BluetoothDevice.BOND_BONDED) {
//1.確認(rèn)配對(duì)
device.setPin(strPsw.getBytes());
//如果沒有將廣播終止冤竹,則會(huì)出現(xiàn)一個(gè)一閃而過的配對(duì)框拂封。
abortBroadcast();
}
}
}
};
配對(duì):之前沒接觸藍(lán)牙相關(guān)api的時(shí)候,也是學(xué)網(wǎng)上的api用反射區(qū)實(shí)現(xiàn)鹦蠕;后來谷歌爸爸在9.0限制了不能使用反射獲取隱藏api(親測(cè)冒签,兩部p20,8.0可以配對(duì)钟病,9.0無法配對(duì))萧恕,這個(gè)反射實(shí)現(xiàn)的自動(dòng)陪對(duì)也就尷尬了。后面看api肠阱,發(fā)現(xiàn)可以直接使用票唆;
在掃描到設(shè)備后連接,根據(jù) BluetoothDevice.getBondState() == BluetoothDevice.BOND_NONE
判斷是否已經(jīng)配對(duì)屹徘,沒有配對(duì)調(diào)用BluetoothDevice.createBond()之后在廣播中監(jiān)聽走趋,在監(jiān)聽到BluetoothDevice.ACTION_PAIRING_REQUEST后調(diào)用 device.setPin(strPsw.getBytes());將PIN碼設(shè)置進(jìn)去,好了就是這么簡(jiǎn)單噪伊,目前我在華為p20簿煌、榮耀8等幾部手機(jī)上都測(cè)試沒問題。后續(xù)再多試幾部手機(jī)鉴吹。
發(fā)現(xiàn)服務(wù):藍(lán)牙連接后在BluetoothGattCallback接口回調(diào)方法onConnectionStateChange(BluetoothGatt gatt, int status, int newState)中調(diào)用gatt.discoverServices()發(fā)現(xiàn)服務(wù)姨伟,這個(gè)地方有坑。有時(shí)候發(fā)現(xiàn)服務(wù)不了(個(gè)人認(rèn)為因?yàn)檫@些回調(diào)都是在異步線程豆励,異步嘛就是得看看什么時(shí)候有空了就執(zhí)行)授滓。換了個(gè)辦法就是gatt不拿onConnectionStateChange回調(diào)回來的,直接用BluetoothGatt mBluetoothGatt=BluetoothDevice.connectGatt(Context context, boolean autoConnect, BluetoothGattCallback callback)連接時(shí)候的mBluetoothGatt.discoverServices()發(fā)現(xiàn)服務(wù)肆糕,在onConnectionStateChange回調(diào)后在主線程中調(diào)mBluetoothGatt.discoverServices()般堆;我目前試的基本都能成功。
切到主線程我是用的 handler诚啃。
@Override
public void onConnectionStateChange(BluetoothGatt gatt, int status, int newState) {
super.onConnectionStateChange(gatt, status, newState);
if (newState == BluetoothProfile.STATE_CONNECTED) {
Message message = mainHandler.obtainMessage();
message.what = BleMsg.MSG_DISCOVER_SERVICES;
mainHandler.sendMessage(message);
}
}
private MainHandler mainHandler = new MainHandler(Looper.getMainLooper());
private final class MainHandler extends Handler {
MainHandler(Looper looper) {
super(looper);
}
@Override
public void handleMessage(Message msg) {
switch (msg.what) {
case BleMsg.MSG_DISCOVER_SERVICES: {
if (bluetoothGatt != null) {
mBluetoothGatt.discoverServices()
}
}
default:
super.handleMessage(msg);
break;
}
}
}
以上記錄淮摔,有錯(cuò)誤還請(qǐng)?jiān)彙?br> 有問題可以一起交流~