通过蓝牙耳机接听电话

时间:2018-07-18 10:28:18

标签: android android-bluetooth android-broadcastreceiver headset voip-android

我正在开发VoIP-Android-App。我想通过活动中的连接的蓝牙耳机接受和拒绝呼叫。

到目前为止,我已经尝试过:

  • 使用Media Session来接收Media Button单击。

    问题:如果我们开始BluetoothSCO,则不会收到任何媒体按钮点击。如果我们不启动BluetoothSCO,我们会收到媒体按钮点击,但由于停机时间始终为0,因此我们无法区分长按钮和短按钮点击,因此键代码始终为KEYCODE_MEDIA_PLAY,并且ACTION_DOWN之后紧跟着ACTION_UP。仅当我们通过蓝牙连接时,才会出现这些问题。如果我们通过电缆耳机进行连接,则会获得适当的键码(KEYCODE_HEADSETHOOK),并且停机时间不为0。

  • 使用BroadcastReceiver监听Bluetooth SCO连接更改。

    private val scoReceiver = object : BroadcastReceiver() {
        fun onReceive(context: Context, intent: Intent) {
            val state = intent.getIntExtra(AudioManager.EXTRA_SCO_AUDIO_STATE, -1)
            val previousState = intent.getIntExtra(AudioManager.EXTRA_SCO_AUDIO_PREVIOUS_STATE, -1)
            if (state == AudioManager.SCO_AUDIO_STATE_DISCONNECTED && previousState == AudioManager.SCO_AUDIO_STATE_CONNECTED) {
                Log.e(TAG, "SCO Disconnected")
                hangupCall()
            }
        }
    }
    
    protected fun onStart() {
        super.onStart()
        val intentFilter = IntentFilter()
        intentFilter.addAction(AudioManager.ACTION_SCO_AUDIO_STATE_UPDATED)
        registerReceiver(scoReceiver, intentFilter)
    }
    

    通过这种方法,我可以检测到用户何时想挂断电话,例如长按蓝牙耳机,因为这会触发SCO断开连接。

    问题::我们无法检测用户是否要接受来电。

  • 使用dispatchKeyEventonKeyDownonKeyUp

    问题:它们根本不会被呼叫。

有人对如何正确使用蓝牙耳机有任何建议或最佳做法吗?任何帮助都非常感谢。预先感谢!

2 个答案:

答案 0 :(得分:2)

在正常和虚拟语音呼叫(包括响铃)期间,Bluetooth耳机单元按钮的所有事件均由Bluetooth Headset Service内部处理,而不作为按钮事件广播。蓝牙耳机服务将这些事件重定向到电信框架(answer / hangupCall)。

答案 1 :(得分:1)

这些事件在HeadsetStateMachine内部处理(在package / apps / Bluetooth下)。

这些事件转发到IBluetoothHeadsetPhone接口。将所有事件转发到的单个应用程序是在运行时通过遵循HeadsetStateMachine.java中的绑定代码来定义的。这是为了让电话制造商在不使用默认电话的情况下将其转发到自定义电话应用程序,而不是默认电话。

Intent intent = new Intent(IBluetoothHeadsetPhone.class.getName());
    intent.setComponent(intent.resolveSystemService(context.getPackageManager(), 0));
    if (intent.getComponent() == null || !context.bindService(intent, mConnection, 0)) {
        Log.e(TAG, "Could not bind to Bluetooth Headset Phone Service");
    }

要使事件转发到您的应用程序而不是默认的电话应用程序,您必须修改aosp代码。 您需要在HeadsetStateMachine,BluetoothHeadsetPhone代理或电话应用程序之一处拦截事件。

不幸的是,如果不修改aosp代码,当前无法找到所需的内容。诸如Plantronics之类的某些耳机具有自定义的BT事件,这些事件会转发到所有应用程序-一些现有的VoIP应用程序支持这些自定义的意图,以支持某些耳机的至少应答呼叫。