近期发现android 11 版本上的某些PDA机器上存在某个BLE的连接在断开且removeBond后, 后台虽然看不到已绑定设备, 但 getBondState()依然处于bonding状态, 造成 startScan 扫描不到, 而且这种状态都重启PDA或其他方式都无法恢复, 这样在用户创建 createBond就会弹出PIN框. 解决方法只能是由用户手动进行配对连接 或者 {BANNED}中国{BANNED}中国第一次连接后不做removeBond操作.
{BANNED}最佳终解决方法
点击(此处)折叠或打开
-
<application>
-
...
-
...
-
<receiver android:name="aidc.uhf.pda.args_comm.nls_ble_impl.NlsBlePairReceiver"
-
android:exported="true">
-
<intent-filter android:priority="1000">
-
<action android:name="android.bluetooth.device.action.PAIRING_REQUEST" />
-
</intent-filter>
-
</receiver>
-
-
</application>
-
-
-
-------------------------------------------------------
-
@SuppressLint("MissingPermission")
-
@Override
-
public void onReceive(Context context, Intent intent) {
-
if (BluetoothDevice.ACTION_PAIRING_REQUEST.equals(intent.getAction())) {
-
int type = intent.getIntExtra(BluetoothDevice.EXTRA_PAIRING_VARIANT, BluetoothDevice.ERROR);
-
//if (type != BluetoothDevice.PAIRING_VARIANT_PIN) return;
-
-
BluetoothDevice device = intent.getParcelableExtra(BluetoothDevice.EXTRA_DEVICE);
-
if (device == null) return;
-
String mac = device.getAddress();
-
if ((mac == null) || (macPairing == null)) return;
-
if (!mac.equals(macPairing)) {
-
LogSdk.e(TAG, "setPin failed: mac not fit macPairing");
-
return;
-
}
-
String devName = device.getName();
-
if ((devName == null) || (devName.length() < 6)) {
-
LogSdk.e(TAG, "Device Name too short. [" + devName + "]");
-
return;
-
}
-
-
String szPin = devName.substring(devName.length() - 6);
-
boolean bResult = device.setPin(szPin.getBytes()); // 根据规则设定 PIN码
-
mBondOK.set((bResult) ? PAIRED_OK : PAIRED_FAILED);
-
Log.e(TAG, bResult ? "pairing OK" : "pairing failed");
-
-
abortBroadcast(); // 阻止广播继续传播
-
}
-
}
-
-
实际上不用 pin 连接, 直接跳过
-
mBleService = gatt.getService(BT_SERVICE_UUID);// 获取我们的服务的通道.
-
if (mBleService != null) {
-
connStatus = BLEDEV_STATE_CONNECTED_AND_PAIRED;
-
// if (nlsBleSyncPairOnce(mBleDev, TimeoutBlePaired)) { // 根据 PIN码 规则进行 配对
-
// connStatus = BLEDEV_STATE_CONNECTED_AND_PAIRED;
-
// LogSdk.w(TAG, "gatt: " + gatt + " mBleGatt: " + mBleGatt);
-
// } else { //配对失败.
-
// connStatus = BLEDEV_STATE_INVALID;
-
// }
-
} else { //未找到专属 service UUID.
-
connStatus = BLEDEV_STATE_INVALID;
-
}
-
- 这样, 后台是 bonding状态, 在进行 connectGatt 时会激发 PIN 提示框, 在 AndroidManifest.xml 中注册了拦截器, 就不会提示了. 然后在连接过程中根本不在进行Bond动作, 这样就可完美避坑
看下android的新版本源码到底哪里有bug造成这个问题. 主要看bluedroid的部分.
下载代码
-
-
mkdir /ws/android_11/bin
-
curl https://storage.googleapis.com/git-repo-downloads/repo > /ws/android_11/bin/repo
-
chmod a+x /ws/android_11/bin/repo
-
-
mkdir /ws/android_11/android-11.0.0_r3
-
cd /ws/android_11/android-11.0.0_r3
-
-
git config --global user.email "iibull@yeah.net"
-
git config --global user.name "iibull"
-
-
/ws/android_11/bin/repo init -u https://aosp.tuna.tsinghua.edu.cn/platform/manifest -b android-11.0.0_r3 --repo-url=https://gerrit-googlesource.lug.ustc.edu.cn/git-repo
- repo sync -c --no-tags ## 需要 至少50GB 空间(代码+编译)
点击(此处)折叠或打开
-
# 初始化编译环境( .可以用source代替,如 source build/envsetup.sh )
-
. build/envsetup.sh
-
# 执行
-
lunch 或者 lunch sdk_phone_x86_64
-
# 我这里使用模拟器所以选择 31 (即aosp_x86_64-eng)
-
Which would you like? [aosp_arm-eng] 31
-
# 开始编译(这里怕我电脑扛不住用的-j1,电脑好的可加大力度)
-
make -j8 ## 3个小时.
-
-
- emulator 内存{BANNED}{BANNED}最佳佳好 >= 12GB
点击(此处)折叠或打开
-
网上摘录
-
安卓中蓝牙协议栈主要分为三个时期,上古时期使用的是BlueZ,后来在4.2之后自己独立出来称为BlueDroid,现在好像又改名叫Fluoride了
- BlueZ蓝牙协议栈部分在内核中实现,socket系统调用提供了AF_BLUETOOTH的 family,可以支持获取HCI、L2CAP、RFCOMM类型的socket;
-
-
对于BlueDroid而言,协议栈是在用户层实现的,内核只暴露出HCI(USB/UART)的接口
-
-
Android 8.0 以后对蓝牙协议栈进行了重构,主要优化是使用HIDL来取代之前的硬件抽象层,方便厂商的接口集成
-
/packages/apps/bluetooth/{bluetooth service + profiles}
-
/packages/apps/bluetooth/jni (bluetooth stack 在 system/bt)通过 HIDL 和 (hardware/interfaces/bluetooth + Vendor impl的Bluetooth Controller)
-
- Android蓝牙协议栈的实现在system/bt目录中.
点击(此处)折叠或打开
-
从用户接口出发,参考Android的开发者文档是如何发现设备以及创建蓝牙连接的:
-
-
https://developer.android.com/guide/topics/connectivity/bluetooth
-
https://developer.android.com/guide/topics/connectivity/bluetooth-le
-
-
paired和connected的区别:
-
-
paired 表示两个设备知道彼此的存在,并且已经协商好了链路秘钥(Link Key),可用该秘钥来进行认证和创建加密链接
-
connected 表示两个已经配对的设备创建了一个RFCOMM链接,共享一个RFCOMM channel
-
- 其他分析参考 https://evilpan.com/2021/07/11/android-bt/