1.搜索
从上一节我们可以知道,蓝牙状态发生了改变,并发生了回调。咱们就从回调开始。
DevicePickerFragment.java 用于蓝牙设置界面的蓝牙配置和管理
@Overridepublic void onBluetoothStateChanged(int bluetoothState) {super.onBluetoothStateChanged(bluetoothState);if (bluetoothState == BluetoothAdapter.STATE_ON) {mLocalAdapter.startScanning(false);}}
最终会回调到这个地方,具体怎么回调到这的暂时没去分析,我猜测应该是回调到这,如果有知道请不吝赐教。
好了,蓝牙搜索开始了
LocalBluetoothAdapter.java
public void startScanning(boolean force) {// Only start if we're not already scanningif (!mAdapter.isDiscovering()) {if (!force) {// Don't scan more than frequently than SCAN_EXPIRATION_MS,// unless forcedif (mLastScan + SCAN_EXPIRATION_MS > System.currentTimeMillis()) {return;}// If we are playing music, don't scan unless forced.A2dpProfile a2dp = mProfileManager.getA2dpProfile();if (a2dp != null && a2dp.isA2dpPlaying()) {return;}}if (mAdapter.startDiscovery()) {mLastScan = System.currentTimeMillis();}}
下面会调到BluetoothAdapter.startDiscovery()==>AdapterService.startDiscovery()==>AS.startDiscoveryNative()==>JNI里面的startDiscoveryNative()==>再下面就到hw里面和bluetooth.start_discovery(void),这些暂时就不分析了,有兴趣的可以自行分析。
2.连接/断开/配对/取消配对
还是从蓝牙设置界面讲起吧,当点击设置界面的某个蓝牙设备时会回调到DeviceListPreferenceFragment里面
@Overridepublic boolean onPreferenceTreeClick(PreferenceScreen preferenceScreen,Preference preference) {if (KEY_BT_SCAN.equals(preference.getKey())) {mLocalAdapter.startScanning(true);return true;}if (preference instanceof BluetoothDevicePreference) {BluetoothDevicePreference btPreference = (BluetoothDevicePreference) preference;CachedBluetoothDevice device = btPreference.getCachedDevice();mSelectedDevice = device.getDevice();onDevicePreferenceClick(btPreference);return true;}return super.onPreferenceTreeClick(preferenceScreen, preference);}
void onDevicePreferenceClick(BluetoothDevicePreference btPreference) {btPreference.onClicked();}
==》
void onClicked() {int bondState = mCachedDevice.getBondState();if (mCachedDevice.isConnected()) {askDisconnect();} else if (bondState == BluetoothDevice.BOND_BONDED) {mCachedDevice.connect(true);} else if (bondState == BluetoothDevice.BOND_NONE) {pair();}}
上面的逻辑里会根据不同的情况执行不同的逻辑,一目了然。
1)配对
private void pair() {if (!mCachedDevice.startPairing()) {Utils.showError(getContext(), mCachedDevice.getName(),R.string.bluetooth_pairing_error_message);}
注意了,开始拉红线配对了。配对之前,如果有已婚的,那么不好意思,必须拆开重新选择对象了
public boolean startPairing() {// Pairing is unreliable while scanning, so cancel discoveryif (mLocalAdapter.isDiscovering()) {mLocalAdapter.cancelDiscovery();}if (!mDevice.createBond()) {return false;}mConnectAfterPairing = true; // auto-connect after pairingreturn true;}
==》BluetoothDevice.createBond()==>adapterservice.createBond()==>adapterservice.createBond()==>向状态机发送绑定消息==》BondStateMachine.createBond()==>AdapterService.createBondNative()==>JNI==>hw==>external,想了解的自行分析。借用一下图
配对完成之后,要干嘛?大家都是正经人,所以要去结婚然后再去开房了。所以当配对成功之后,肯定有一个事件提供给上面BluetoothEventManager
,接收到bond完成事件
private class BondStateChangedHandler implements Handler {
259 public void onReceive(Context context, Intent intent,
260 BluetoothDevice device) {
261 if (device == null) {
262 Log.e(TAG, "ACTION_BOND_STATE_CHANGED with no EXTRA_DEVICE");
263 return;
264 }
265 int bondState = intent.getIntExtra(BluetoothDevice.EXTRA_BOND_STATE,
266 BluetoothDevice.ERROR);
267 CachedBluetoothDevice cachedDevice = mDeviceManager.findDevice(device);
268 if (cachedDevice == null) {
269 Log.w(TAG, "CachedBluetoothDevice for device " + device +
270 " not found, calling readPairedDevices().");
271 if (!readPairedDevices()) {
272 Log.e(TAG, "Got bonding state changed for " + device +
273 ", but we have no record of that device.");
274 return;
275 }
276 cachedDevice = mDeviceManager.findDevice(device);
277 if (cachedDevice == null) {
278 Log.e(TAG, "Got bonding state changed for " + device +
279 ", but device not added in cache.");
280 return;
281 }
282 }
283
284 synchronized (mCallbacks) {
285 for (BluetoothCallback callback : mCallbacks) {
286 callback.onDeviceBondStateChanged(cachedDevice, bondState);
287 }
288 }
289 cachedDevice.onBondingStateChanged(bondState);
290
291 if (bondState == BluetoothDevice.BOND_NONE) {
292 int reason = intent.getIntExtra(BluetoothDevice.EXTRA_REASON,
293 BluetoothDevice.ERROR);
294
295 showUnbondMessage(context, cachedDevice.getName(), reason);
296 }
297 }
void onBondingStateChanged(int bondState) {if (bondState == BluetoothDevice.BOND_NONE) {mProfiles.clear();mConnectAfterPairing = false; // cancel auto-connectsetPhonebookPermissionChoice(ACCESS_UNKNOWN);setMessagePermissionChoice(ACCESS_UNKNOWN);setSimPermissionChoice(ACCESS_UNKNOWN);mMessageRejectionCount = 0;saveMessageRejectionCount();}refresh();if (bondState == BluetoothDevice.BOND_BONDED) {if (mDevice.isBluetoothDock()) {onBondingDockConnect();} else if (mConnectAfterPairing) { connect(false);}mConnectAfterPairing = false;}
请大家自己跟踪一下,下面我省略了一些逻辑。接下来会走到
synchronized void connectInt(LocalBluetoothProfile profile) {if (!ensurePaired()) {return;}if (profile.connect(mDevice)) {if (Utils.D) {Log.d(TAG, "Command sent successfully:CONNECT " + describe(profile));}return;}Log.i(TAG, "Failed to connect " + profile.toString() + " to " + mName);}
具体connect的蓝牙功能是什么就会通过相关的协议进行连接。
2)取消配对过程
与配对过程类似
3、连接与取消连接
1) 连接过程
2) 取消连接过程
和连接过程类似,略。
4、扫描
A、通过调用BluetoothAdapter的startDiscovery()方法告诉底层开始搜索;
B、底层发广播通知应用找到设备或者扫描状态变化,从而更新ui。