无法从蓝牙耳机(PTT)设备获取KeyEvent Stop

时间:2017-01-02 13:54:17

标签: android bluetooth android-bluetooth

我正在使用MediaButton动作过滤器来接收蓝牙耳机媒体按钮事件。 Action过滤器正在运行android lollipop及以下版本,但在Android M及以上版本中无效。

在上述设备中,只有KeyEvent.KEYCODE_MEDIA_PLAY:正在运行。

执行的操作列表。 1.单击PTT(按键通话)按钮      - 使用事件onReceive(Context context, Intent intent)KeyEvent.KEYCODE_MEDIA_PLAY:中收到回调 2.释放PTT按钮      - 应该使用事件onReceive(Context context, Intent intent)KeyEvent.KEYCODE_MEDIA_STOP:中进行回调 - 但仅在上述设备中未收到此事件。

我已经提到了我在下面使用的代码。

清单

<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="com.pttsample">

<uses-permission android:name="android.permission.BLUETOOTH" />
<uses-permission android:name="android.permission.BLUETOOTH_ADMIN" />
<uses-permission android:name="android.permission.INTERNET" />

<application
    android:allowBackup="true"
    android:icon="@mipmap/ic_launcher"
    android:label="@string/app_name"
    android:supportsRtl="true"
    android:theme="@style/AppTheme">
    <activity android:name=".MainActivity">
        <intent-filter>
            <action android:name="android.intent.action.MAIN" />

            <category android:name="android.intent.category.LAUNCHER" />
        </intent-filter>
    </activity>
    <receiver android:name=".MediaButtonReceiver">
        <intent-filter android:priority="1000000">
            <action android:name="android.intent.action.MEDIA_BUTTON" />

        </intent-filter>
    </receiver>
</application>

接收机

public class MediaButtonReceiver extends BroadcastReceiver{

@Override
public void onReceive(Context context, Intent intent) {

    String action = intent.getAction();

    if (action.equalsIgnoreCase(Intent.ACTION_MEDIA_BUTTON))
    {

        KeyEvent event = (KeyEvent) intent
                .getParcelableExtra(Intent.EXTRA_KEY_EVENT);
        if (event == null)
            return;

        if (event.getKeyCode() != KeyEvent.KEYCODE_HEADSETHOOK
                && event.getKeyCode() != KeyEvent.KEYCODE_MEDIA_PLAY_PAUSE
                && event.getAction() != KeyEvent.ACTION_DOWN) {
            return;
        }

        Intent i = null;

                Log.e("MEDIA CONTROLLER","Power Button Play app destroy");
        switch (event.getKeyCode())
        {
           case KeyEvent.KEYCODE_HEADSETHOOK:
                Log.e("MEDIA CONTROLLER","Power Button Play KEYCODE_HEADSETHOOK");
                break;
            case KeyEvent.KEYCODE_MEDIA_PLAY_PAUSE:
                Log.e("MEDIA CONTROLLER","Power Button Play MEDIA_PLAY_PAUSE");
                switch (event.getAction())
                {
                    case KeyEvent.ACTION_DOWN:
                        if (event.getRepeatCount() > 0)
                            break;

                        break;
                    case KeyEvent.ACTION_UP:
                        // long click
                        Log.e("MEDIA CONTROLLER","Power Button Play Action Up");
                        break;
                    case KeyEvent.ACTION_MULTIPLE:
                        Log.e("MEDIA", "Action Multiple");
                        break;
                }
                break;
            //The following is the received from PTT device button
            case KeyEvent.KEYCODE_MEDIA_PLAY:
                 Log.e("MEDIA CONTROLLER>>>","Button Play");
                 break;
            case KeyEvent.KEYCODE_MEDIA_PAUSE:
                Log.e("MEDIA CONTROLLER","Power Button Pause");
                break;
            case KeyEvent.KEYCODE_MEDIA_AUDIO_TRACK:
                Log.e("MEDIA CONTROLLER","audio track");
                break;
            case KeyEvent.KEYCODE_MEDIA_CLOSE:
                Log.e("MEDIA CONTROLLER","close");
                break;
            case KeyEvent.KEYCODE_MEDIA_EJECT:
                Log.e("MEDIA CONTROLLER","eject");
                break;
            case KeyEvent.KEYCODE_MEDIA_FAST_FORWARD:
                Log.e("MEDIA CONTROLLER","fast forward");
                break;
            case KeyEvent.KEYCODE_MEDIA_NEXT:
                Log.e("MEDIA CONTROLLER","next");
                break;
            case KeyEvent.KEYCODE_MEDIA_PREVIOUS:
                Log.e("MEDIA CONTROLLER","previous");
                break;
            case KeyEvent.KEYCODE_MEDIA_RECORD:
                Log.e("MEDIA CONTROLLER","record");
                break;

            case KeyEvent.KEYCODE_MEDIA_REWIND:
                Log.e("MEDIA CONTROLLER","rewind");
                break;

            case KeyEvent.KEYCODE_MEDIA_STOP:
                Log.e("MEDIA CONTROLLER","stop");
                break;
        }

        if (isOrderedBroadcast())
            abortBroadcast();
        if (i != null)
            context.sendBroadcast(i);
    }


}

MainActivity

已经尝试添加以下内容。

    mMediaControlClientReceiverComponent = new ComponentName(
            getPackageName(), MediaButtonReceiver.class.getName());
    mMediaStopReceiverComponent = new ComponentName(
            getPackageName(), MediaButtonReceiver.class.getName());

    audioManager = (AudioManager) this.getSystemService(AUDIO_SERVICE);
    audioManagerStopOption = (AudioManager) this.getSystemService(AUDIO_SERVICE);

    audioManager.registerMediaButtonEventReceiver(mMediaControlClientReceiverComponent);
    audioManagerStopOption.registerMediaButtonEventReceiver(mMediaStopReceiverComponent);

1 个答案:

答案 0 :(得分:0)

我一直在努力解决同样的问题。 我不知道这是否是Android范围,但是我用于开发的三星S6上正在发生这种情况。

首先,即使没有MediaSession,当您的UI是活动的UI(在屏幕上如此可见)时,也会发生这种情况。当UI处于活动状态时,媒体密钥将发送到活动。

以下是我解决问题的方法。

您需要将Audiomanager设置为MODE_NORMAL

audioManager = (AudioManager)getApplicationContext().getSystemService(Context.AUDIO_SERVICE);    
audioManager.setMode(AudioManager.MODE_NORMAL);

此时,即使没有设置音频焦点,您也会收到通过按下麦克风PTT触发的MEDIA_PLAY。 您可以使用活动中触发的keyDown捕获此内容

@Override
public boolean(int keyCode KeyEvent event){
    if (keyCode == 126) startPlay();
    return true;
}

然后你可以开始玩MediaPlayer类。 只有在实际播放的内容中,MEDIA_STOP和其他键才会发送到您的应用程序。

但是我认为你正在创建某种Walky Talky应用程序。你将流式传输RTP。我自己用AudioTrack课程做这件事。当使用play()启动录音带时,也可以使其他媒体键可用。

由于您可能想要使用PTT MIC中的麦克风,您必须使用蓝牙sco进行连接。这也是通过AudioManager完成的。像这样的东西

  audio.setBluetoothScoOn(true);
  audio.stopBluetoothSco();

然而,这会破坏以上所有内容并且仅收到MEDIA_PLAY。 到目前为止,我发现只有一个解决方案,那就是使用蓝牙插座。以下是我使用的课程。特别适用于Dellking PTT Mic

package on4akh.be.remotehamming;

import android.bluetooth.BluetoothAdapter;
import android.bluetooth.BluetoothDevice;
import android.bluetooth.BluetoothSocket;

import java.io.IOException;
import java.io.InputStream;
import java.util.Set;
import java.util.UUID;

public class BluetoothPtt {
    private  byte[] mmBuffer = new byte[1024];
    private InputStream in;
    private BluetoothSocket socket;
    private boolean isRunning = true;
    private OnMessageReceived pttState = null;

    public BluetoothPtt(OnMessageReceived listener){
        pttState = listener;
        Set<BluetoothDevice> bs = BluetoothAdapter.getDefaultAdapter().getBondedDevices();
        for (BluetoothDevice device : bs){
            if (device.getName().equalsIgnoreCase("DellKing PTT Mic")){
                try{
                    socket = device.createRfcommSocketToServiceRecord(UUID.fromString("00001101-0000-1000-8000-00805F9B34FB"));
                    start();
                }
                catch (IOException e){
                    return;
                }
            }
            return;
        }
    }

    private void start(){
        new Thread(){
            @Override
            public void run(){
                try {
                    socket.connect();
                    in = socket.getInputStream();
                }
                catch (IOException e){
                    socket = null;
                    return;
                }

                while (isRunning){
                    try {
                        if (socket.isConnected()){
                            in.read(mmBuffer);
                            if (mmBuffer[5] == 80){
                                pttState.isPressed(true);
                            }
                            else
                                {
                                    pttState.isPressed(false);
                                }
                        }
                    } catch (IOException e) {

                    }
                }
            }
        }.start();
    }

    public void release(){
        isRunning = false;
        try {
            socket.close();
        }
        catch (IOException e){

        }
        socket = null;
    }

    public interface OnMessageReceived {
        public void isPressed(boolean state);
    }
}

每次按下并释放PTT按钮时,都会发送一个6字节的代码,其中第六个字节为80表示按下,82表示发布。 该类有一个onMessagedReceived侦听器,用于在我的应用程序中切换PTT

  BluetoothPtt  ptt = new BluetoothPtt(new BluetoothPtt.OnMessageReceived(){
            @Override
            public void isPressed(boolean state){
                togglePtt();
            }
        });

希望你能用我的答案。