13

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

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

  • 使用媒体会话接收媒体按钮点击。

    问题:如果我们启动BluetoothSCO,我们不会收到任何媒体按钮点击。如果我们不启动 BluetoothSCO,我们确实会收到媒体按钮点击,但我们无法区分长按钮和短按钮点击,因为停机时间始终为 0,键码始终为 KEYCODE_MEDIA_PLAY,ACTION_DOWN 紧随其后的是 ACTION_UP。只有当我们通过蓝牙连接时才会出现这些问题。如果我们通过有线耳机连接,我们会得到适当的键码 (KEYCODE_HEADSETHOOK),并且停机时间不是 0。

  • 使用 BroadcastReceiver 监听蓝牙 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

    问题:他们根本不会被调用。

有人对如何正确处理蓝牙耳机有任何建议或最佳做法吗?非常感谢任何帮助。提前致谢!

4

2 回答 2

2

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

于 2018-07-18T14:26:20.597 回答
2

这些事件在 HeadsetStateMachine 内部处理(在 packages/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 应用程序支持这些自定义意图,以支持至少应答某些耳机的呼叫。

于 2018-08-07T08:33:37.843 回答