展会信息港展会大全

[Android源码分析]蓝牙配对之jni之上的点点滴滴
来源:互联网   发布日期:2015-09-28 15:58:44   浏览:3325次  

导读:??在之前晓东已经和大家分析完成了蓝牙打开和蓝牙搜索的过程了,在搜索到设备的下一步我们要做的就是蓝牙的配对了。本文晓东将和大家一起来看看蓝牙配对究竟涉及到了哪些内容。1、UI上的点击设备开...

??

在之前晓东已经和大家分析完成了蓝牙打开和蓝牙搜索的过程了,在搜索到设备的下一步我们要做的就是蓝牙的配对了。本文晓东将和大家一起来看看蓝牙配对究竟涉及到了哪些内容。

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;

}

}

赞助本站

人工智能实验室

相关热词: android开发 教程

AiLab云推荐
展开

热门栏目HotCates

Copyright © 2010-2024 AiLab Team. 人工智能实验室 版权所有    关于我们 | 联系我们 | 广告服务 | 公司动态 | 免责声明 | 隐私条款 | 工作机会 | 展会港