拨打电话通过蓝牙接通

本文详细解析了蓝牙耳机接通电话时声音播放的流程,从Phone进程到APP层,再到Framework层,直至最终通过BluetoothHeadsetService进行声音输出。包括蓝牙通道的开启、连接建立、音频配置调整等关键步骤。

我配对号蓝牙耳机,然后拨打电话,接通后,声音会从蓝牙耳机里面出来,这个流程是怎么样的呢?今天就来分析。

     首先肯定的是在开启蓝牙通话的这个通道是在Phone进程里面。

     APP层核文件:

    BluetoothHandsfree.java

接通开通蓝牙的通话通道不是在Incscreen,而是在这个BluetoothHandsfree内部类BluetoothPhoneState类里面注册了一个广播的监听器来监听电话的状态:

代码片段:

 case PRECISE_CALL_STATE_CHANGED:
                case PHONE_CDMA_CALL_WAITING:
                    Connection connection = null;
                    if (((AsyncResult) msg.obj).result instanceof Connection) {
                        connection = (Connection) ((AsyncResult) msg.obj).result;
                    }

                    handlePreciseCallStateChange(sendUpdate(), connection);

当Phone处于Dialing状态的时候就会去建立连接。

流程:handlePreciseCallStateChange---->audioOn();--->mHeadset.connect()   (mHeadset在原生态代码中为BluetoothAudioGateway,在MTK平台中为HeadsetBase,但实现的效果都一样)

Framework:

(BluetoothAudioGateway或则BluetoothAudioGateway)connect--->connectNative()---->connectNative()(android_bluetooth_BluetoothAudioGateway)----->


当系统建立连接后就会通过BluetoothHeadsetService来通知BluetoothAudioGateway进行出里。

BluetoothHeadsetService中的代码片段:

 case BluetoothAudioGateway.SCO_ACCEPTED:
                    case BluetoothAudioGateway.SCO_CONNECTED:
                    case BluetoothAudioGateway.SCO_CLOSED:
                        if(msg.obj == null) {
                            logWarn("Remote Device is null when receive SCO msg");
                            mBtHandsfree.handleSCOEvent(msg.what, null);


BluetoothAudioGateway:

 handleSCOEvent--->mAudioManager.setBluetoothScoOn(true);---->AudioManager----->AudioService

AudioService:

setBluetoothScoOn代码片段:

public void setBluetoothScoOn(boolean on){
        if (!checkAudioSettingsPermission("setBluetoothScoOn()")) {
            return;
        }
        mForcedUseForComm = on ? AudioSystem.FORCE_BT_SCO : AudioSystem.FORCE_NONE;

        sendMsg(mAudioHandler, MSG_SET_FORCE_USE, SHARED_MSG, SENDMSG_QUEUE,
                AudioSystem.FOR_COMMUNICATION, mForcedUseForComm, null, 0);
        sendMsg(mAudioHandler, MSG_SET_FORCE_USE, SHARED_MSG, SENDMSG_QUEUE,
                AudioSystem.FOR_RECORD, mForcedUseForComm, null, 0);
        Log.d(TAG, "setBluetoothScoOn " + mForcedUseForComm);
    }

注意这里发送了两次消息。猜测两次的目的是一次是告诉系统我要使用的是通话功能,二次是告诉系统录音功能,因为通话的时候应该是可以录音的,如果把第二次For_RECORD去掉,应该是也能成功设置的。

setForceUse---> AudioSystem.setForceUse------>AudioSystem::setForceUse-------->AudioPolicyService::setForceUse------->AudioYusuPolicyManager::setForceUse

AudioYusuPolicyManager:

这里面有个很重要的位置判断:

if(AudioSystem::popCount(newDevice) != 2 )
    {

一些蓝牙不能传出声音很有可能就是这里出现了问题!




在车载蓝牙连接项目中,核心目标是实现移动设备(如智能手机)与车载系统的无缝连接,从而提供音频播放、电话拨打、联系人同步以及外设控制等功能。这类项目通常基于Android平台开发,涉及对蓝牙协议栈的深度定制和集成。 项目的整体流程主要包括以下几个阶段: - **蓝牙开启**:系统初始化时启动蓝牙模块,并检查硬件状态以确保蓝牙功能可用。 - **设备发现**:车载系统主动搜索周围可配对的蓝牙设备,同时允许用户选择目标设备进行下一步操作。 - **配对过程**:通过PIN码或自动确认等方式完成安全认证,建立信任关系并保存配对信息以便后续快速连接。 - **连接建立**:根据所需服务类型(如A2DP用于音乐传输,HFP用于免提通话等),激活相应通道并维持稳定的数据通信链路[^1]。 为了保证兼容性和功能性,在设计时需考虑不同版本蓝牙标准的支持情况,包括经典蓝牙(Classic Bluetooth)和低功耗蓝牙(Bluetooth Low Energy, BLE)。此外还需针对特定应用场景优化用户体验,例如提高语音识别准确性、缩短延迟时间等[^3]。 ```java // 示例代码:检查是否支持蓝牙功能 BluetoothManager bluetoothManager = (BluetoothManager) getSystemService(Context.BLUETOOTH_SERVICE); BluetoothAdapter bluetoothAdapter = bluetoothManager.getAdapter(); if (bluetoothAdapter == null || !getPackageManager().hasSystemFeature(PackageManager.FEATURE_BLUETOOTH)) { // 设备不支持蓝牙 } else { if (!bluetoothAdapter.isEnabled()) { Intent enableBtIntent = new Intent(BluetoothAdapter.ACTION_REQUEST_ENABLE); startActivityForResult(enableBtIntent, REQUEST_ENABLE_BT); } } ``` 该项目还需要处理复杂的环境干扰问题,比如多设备共存下的信号冲突、不同厂商设备间的互操作性问题等。因此,开发者往往需要利用一些非公开API或者特定于芯片组的功能来增强性能表现[^2]。
评论 3
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值