在之前晓东已经和大家分析完成了蓝牙打开和蓝牙搜索的过程了,在搜索到设备的下一步我们要做的就是蓝牙的配对了。本文晓东将和大家一起来看看蓝牙配对究竟涉及到了哪些内容。
1、UI上的点击设备开始
在android中,对设备的点击都是在onclicked函数中实现的,所以我们就从这个函数开始分析了:
//对对应设备点击之后的操作 void onClicked() { int bondState = mCachedDevice.getBondState(); //若是该设备已经连接了,就断开连接 if (mCachedDevice.isConnected()) { askDisconnect(); } else { // Single link version, reject the second connect request if (mLocalAdapter.isSingleLinkVersion() == true && mLocalAdapter.getAdapterConnectionState() != BluetoothAdapter.STATE_DISCONNECTED) { Context context = getContext(); String toastMsg = context.getString(R.string.bluetooth_single_slave_pair_only_device); Toast.makeText(getContext(), toastMsg, Toast.LENGTH_SHORT).show(); return; } //若是已经配对过了,就开始连接 if (bondState == BluetoothDevice.BOND_BONDED) { mCachedDevice.connect(true); //若是还没有配对,则开始配对 } else if (bondState == BluetoothDevice.BOND_NONE) { pair(); } } }
所以,其实同样一个点击在设备处于不同状态下是有不同操作的,毫无疑问,最开始我们总是位于最初的状态,这个时候的点击就是开始配对了。我们去看看配对是怎么做的:
private void pair() { //开始配对 if (!mCachedDevice.startPairing()) { //配对出问题,显示error信息 Utils.showError(getContext(), mCachedDevice.getName(), R.string.bluetooth_pairing_error_message); } }
调动的是startpairing函数来实现真正的配对操作:
boolean startPairing() { // Pairing is unreliable while scanning, so cancel discovery //若是正在扫描,就先cancel掉扫描操作 if (mLocalAdapter.isDiscovering()) { mLocalAdapter.cancelDiscovery(); } //开始配对,这就到framework层了 if (!mDevice.createBond()) { return false; } //配对后自动连接 mConnectAfterPairing = true; // auto-connect after pairing return true; }
2、framework层的配对操作分析
上面的操作会真正调用下面这个framework的函数:
public synchronized boolean createBond(String address) { //看是否可以配对?比如有没有设备正在配对之类 if (!isBondingFeasible(address)) return false; //开始配对。timeout是1分钟,详细分析见4 if (!createPairedDeviceNative(address, 60000 /*1 minute*/ )) { return false; } //把这个地址赋值到pendingoutgonigbonding中 mBondState.setPendingOutgoingBonding(address); //设置状态为bonding mBondState.setBondState(address, BluetoothDevice.BOND_BONDING); return true; }
3、状态改变到bonding的分析
设置bond的状态
/*package*/ synchronized boolean setBondState(String address, int state) { return setBondState(address, state, 0); } /*package*/ synchronized boolean setBondState(String address, int state, int reason) { mBondState.setBondState(address.toUpperCase(), state, reason); return true; } public synchronized void setBondState(String address, int state) { setBondState(address, state, 0); } /** reason is ignored unless state == BOND_NOT_BONDED */ public synchronized void setBondState(String address, int state, int reason) { if (DBG) Log.d(TAG, "setBondState " + "address" + " " + state + "reason: " + reason); //检查状态是否真的改变 int oldState = getBondState(address); if (oldState == state) { return; } // Check if this was an pending outgoing bonding. // If yes, reset the state. //看是不是从bonding的状态变化的,若是,则把mPendingOutgoingBonding位清空 if (oldState == BluetoothDevice.BOND_BONDING) { if (address.equals(mPendingOutgoingBonding)) { mPendingOutgoingBonding = null; } } if (state == BluetoothDevice.BOND_BONDED) { boolean setTrust = false; if (mPairingRequestRcvd.contains(address)) setTrust = true; mService.addProfileState(address, setTrust); mPairingRequestRcvd.remove(address); } else if (state == BluetoothDevice.BOND_BONDING) { //若是bonding,则先得到a2dpproxy和headsetproxy,这个是为了后面的连接做准备的 if (mA2dpProxy == null || mHeadsetProxy == null) { getProfileProxy(); } } else if (state == BluetoothDevice.BOND_NONE) { mPairingRequestRcvd.remove(address); } //主要是bonded和none的处理,我们暂时不看 setProfilePriorities(address, state); if (DBG) { Log.d(TAG, address + " bond state " + oldState + " -> " + state + " (" + reason + ")"); }
3.1 getProfileProxy的分析
public boolean getProfileProxy(Context context, BluetoothProfile.ServiceListener listener, int profile) { if (context == null || listener == null) return false; //新建对应profile if (profile == BluetoothProfile.HEADSET) { BluetoothHeadset headset = new BluetoothHeadset(context, listener); return true; } else if (profile == BluetoothProfile.A2DP) { BluetoothA2dp a2dp = new BluetoothA2dp(context, listener); return true; } else if (profile == BluetoothProfile.INPUT_DEVICE) { BluetoothInputDevice iDev = new BluetoothInputDevice(context, listener); return true; } else if (profile == BluetoothProfile.PAN) { BluetoothPan pan = new BluetoothPan(context, listener); return true; } else if (profile == BluetoothProfile.HEALTH) { BluetoothHealth health = new BluetoothHealth(context, listener); return true; } else { return false; } }
以a2dp为例,就是返回对应的类
/*package*/ BluetoothA2dp(Context mContext, ServiceListener l) { IBinder b = ServiceManager.getService(BluetoothA2dpService.BLUETOOTH_A2DP_SERVICE); mServiceListener = l; mAdapter = BluetoothAdapter.getDefaultAdapter(); if (b != null) { //得到对应的service mService = IBluetoothA2dp.Stub.asInterface(b); if (mServiceListener != null) { //返回this mServiceListener.onServiceConnected(BluetoothProfile.A2DP, this); } } else { Log.w(TAG, "Bluetooth A2DP service not available!"); // Instead of throwing an exception which prevents people from going // into Wireless settings in the emulator. Let it crash later when it is actually used. mService = null; } }
所以,总得来说在jni之上,配对并没有做太多的东西,就是调用对应的配对的jni之下的函数。
若您觉得该文章对您有帮助,请在下面用鼠标轻轻按一下“顶”,哈哈~~·