Android 9 原生设置关于蓝牙设置(五)

蓝牙配对及A2DP连接

参考:蓝牙配置流程

  当点击设置界面的某个蓝牙设备时会调用DeviceListPreferenceFragment里面:
在这里插入图片描述
  最终调用BluetoothDevicePreference.onClicked(),主要代码如下:
在这里插入图片描述
  上面的逻辑里会根据不同的情况执行不同的逻辑,一目了然。

蓝牙配对

  调用CachedBluetoothDevice.startPairing()
在这里插入图片描述
  配对之前,如果当前处于蓝牙扫描状态,则停止蓝牙扫描。然后调用createBond()开始绑定(即配对)了。
  BluetoothDevice.createBond()>adapterservice.createBond()>adapterservice.createBond()>向状态机发送绑定消息》  BondStateMachine.createBond()>AdapterService.createBondNative()>JNI==>hw,
在这里插入图片描述

蓝牙连接

  当配对成功之后,会发送BONDING_STATE_CHANGE消息到BondStateMachine:
  BondStateMachine::PendingCommandState.processMessage()
在这里插入图片描述
  调用BondStateMachine::PendingCommandState.sendIntent()发ACTION_BOND_STATE_CHANGED消息给应用软件:
在这里插入图片描述
  上面先调用了AdapterProperties.onBondStateChanged(),其中调用setBondState更新远程设备的Bond状态。
  ACTION_BOND_STATE_CHANGED消息给Setting软件的BluetoothEventManager处理,比如接收到bond完成事件BondStateChangedHandler,里面调用了

            cachedDevice.onBondingStateChanged(bondState);

在这里插入图片描述
  这里省略一些逻辑,之后调用到connectAutoConnectableProfiles()
在这里插入图片描述
  for循环遍历了所以支持的蓝牙协议,如果该协议允许自动连接,则尝试connect。
在这里插入图片描述
  连接成功会有以下打印:
在这里插入图片描述
这里了解一下A2dpProfile.connect()
在这里插入图片描述
  先断开已经连接的A2DP远程设备,再连接指定的设备。
A2dpProfile.connect()–>BluetoothA2dp.connect()–>A2dpService.connect() 发送A2dpStateMachine.CONNECT给状态机–>A2dpStateMachine.Disconnected.processMessage() -->connectA2dpNative(),连接超时时间是30秒。
在这里插入图片描述
在这里插入图片描述
  上面代码
  (1)处是发送一个连接蓝牙状态改变事件。
  (2)进行a2dp连接,很明显就要进入jni里了
  (3)把要连接的远程蓝牙设备设置为目标设备mTargetDevice,状态转换到==》pending==>connected
这里只讲连接,所以下面要分析jni了。com_android_bluetooth_a2dp.cpp

static jboolean connectA2dpNative(JNIEnv *env, jobject object, jbyteArray address) {
    jbyte *addr;
    bt_bdaddr_t * btAddr;
    bt_status_t status;
 
    ALOGI("%s: sBluetoothA2dpInterface: %p", __FUNCTION__, sBluetoothA2dpInterface);
    if (!sBluetoothA2dpInterface) return JNI_FALSE;
 
    addr = env->GetByteArrayElements(address, NULL);
    btAddr = (bt_bdaddr_t *) addr;
    if (!addr) {
        jniThrowIOException(env, EINVAL);
        return JNI_FALSE;
    }
 
    if ((status = sBluetoothA2dpInterface->connect((bt_bdaddr_t *)addr)) != BT_STATUS_SUCCESS) {
        ALOGE("Failed HF connection, status: %d", status);
    }
    env->ReleaseByteArrayElements(address, addr, 0);
return (status == BT_STATUS_SUCCESS) ? JNI_TRUE : JNI_FALSE;
}

  那么这个sBluetoothA2dpInterface这个是什么呢?其实这个就相当于java中对外提供的api接口,只是在c中是头文件而已。既然是蓝牙肯定是在蓝牙的头文件里bt_av.h里

typedef struct {
 
    /** set to sizeof(btav_interface_t) */
    size_t          size;
    /**
     * Register the BtAv callbacks
     */
    bt_status_t (*init)( btav_callbacks_t* callbacks );
 
    /** connect to headset */
    bt_status_t (*connect)( bt_bdaddr_t *bd_addr );
    /** dis-connect from headset */
    bt_status_t (*disconnect)( bt_bdaddr_t *bd_addr );
 
    /** Closes the interface. */
    void  (*cleanup)( void );
} btav_interface_t;

  接下来就调用到./btif/src/btif_av.c,此处省略。
  

  蓝牙A2DP连接成功,bluedroid回调com_android_bluetooth_a2dp.cpp bta2dp_connection_state_callback(),然后回调A2dpStateMachine.onConnectionStateChanged()
在这里插入图片描述
  发送STACK_EVENT消息,因当前状态是Pending,所以调用Pending.processMessage():
在这里插入图片描述
processConnectionEvent()
在这里插入图片描述
在这里插入图片描述
发送MSG_CONNECTION_STATE_CHANGED消息,留意下参数内容。
在这里插入图片描述
  发送BluetoothA2dp.ACTION_CONNECTION_STATE_CHANGED广播,并把状态信息传递过去。另外会调用notifyProfileConnectionStateChanged(),修改Profile的优先级等(因为蓝牙带宽是有限的)。
  在LocalBluetoothProfileManager.updateLocalProfiles()有注册接收BluetoothA2dp.ACTION_CONNECTION_STATE_CHANGED广播,由StateChangedHandler类处理广播:
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
  cachedDevice.refresh()–>dispatchAttributesChanged()–>BluetoothDevicePreference.onDeviceAttributesChanged(),更新了UI界面关于蓝牙远程设备对应的Prcference。

你可以通过使用 AndroidBluetoothAdapter 类提供的方法来监听蓝牙的状态。以下是一个示例代码: ``` import android.bluetooth.BluetoothAdapter; import android.content.BroadcastReceiver; import android.content.Context; import android.content.Intent; import android.content.IntentFilter; public class BluetoothStateListener { private BluetoothAdapter bluetoothAdapter; private BluetoothStateReceiver bluetoothStateReceiver; public BluetoothStateListener(Context context) { bluetoothAdapter = BluetoothAdapter.getDefaultAdapter(); bluetoothStateReceiver = new BluetoothStateReceiver(); IntentFilter filter = new IntentFilter(BluetoothAdapter.ACTION_STATE_CHANGED); context.registerReceiver(bluetoothStateReceiver, filter); } public void unregisterReceiver(Context context) { context.unregisterReceiver(bluetoothStateReceiver); } private class BluetoothStateReceiver extends BroadcastReceiver { @Override public void onReceive(Context context, Intent intent) { if (intent.getAction().equals(BluetoothAdapter.ACTION_STATE_CHANGED)) { int state = intent.getIntExtra(BluetoothAdapter.EXTRA_STATE, -1); switch (state) { case BluetoothAdapter.STATE_ON: // 蓝牙已打开 break; case BluetoothAdapter.STATE_OFF: // 蓝牙已关闭 break; } } } } } ``` 以上代码中,我们通过注册一个 BroadcastReceiver 来监听 BluetoothAdapter.ACTION_STATE_CHANGED 广播事件,当蓝牙状态发生变化时,会触发该广播事件,我们可以在 BroadcastReceiver 的 onReceive 方法中处理蓝牙状态的变化。在使用完后,记得调用 unregisterReceiver 方法来注销 BroadcastReceiver。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值