1.搜索
从上一节我们可以知道,蓝牙状态发生了改变,并发生了回调。咱们就从回调开始。
DevicePickerFragment.java 用于蓝牙设置界面的蓝牙配置和管理
@Override
public 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 scanning
if (!mAdapter.isDiscovering()) {
if (!force) {
// Don't scan more than frequently than SCAN_EXPIRATION_MS,
// unless forced
if (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里面
@Override
public 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 discovery
if (mLocalAdapter.isDiscovering()) {
mLocalAdapter.cancelDiscovery();
}
if (!mDevice.createBond()) {
return false;
}
mConnectAfterPairing = true; // auto-connect after pairing
return 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-connect
setPhonebookPermissionChoice(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。