无法从蓝牙耳机 (PTT) 设备获取 KeyEvent Stop
Unable to get KeyEvent Stop from bluetooth headset(PTT) device
我正在使用 MediaButton 操作过滤器接收蓝牙耳机媒体按钮事件。动作过滤器在 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);
我一直在为同样的问题而苦苦挣扎。
我不知道这是否 Android 宽,但在我用来开发的三星 S6 上正在发生。
首先,即使没有 MediaSession,当您 UI 处于活动状态时(在屏幕上可见),也会发生这种情况。当 UI 处于活动状态时,媒体密钥将发送到 activity.
这是我解决问题的方法。
您需要将 Audiomanager 设置为 MODE_NORMAL
audioManager = (AudioManager)getApplicationContext().getSystemService(Context.AUDIO_SERVICE);
audioManager.setMode(AudioManager.MODE_NORMAL);
此时,即使不设置音频焦点,您也会收到MEDIA_PLAY按下麦克风PTT触发的消息。
您可以使用 activity
中触发的 keyDown 捕获此信息
@Override
public boolean(int keyCode KeyEvent event){
if (keyCode == 126) startPlay();
return true;
}
然后您可以开始使用 MediaPlayer 播放一些东西 class。
只有在实际播放某些内容时,MEDIA_STOP 和其他键才会发送到您的应用程序。
不过我认为您正在创建某种 Walky Talky 应用程序。您将流式传输 RTP。我自己用 AudioTrack class 来做这个。当使用 play() 启动音轨时,也会使其他媒体密钥可用。
由于您可能想使用 PTT MIC 中的麦克风,因此您必须使用蓝牙 sco 进行连接。这也是通过 AudioManager 完成的。像这样
audio.setBluetoothScoOn(true);
audio.stopBluetoothSco();
然而,这打破了以上所有内容,只收到了 MEDIA_PLAY。
到目前为止,我只找到了一种解决方案,那就是使用蓝牙插座。下面是我使用的class。特别适用于 Dellking PTT 麦克风
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 字节代码,其中第 6 个字节为 80 表示按下,82 表示释放。
class 有一个 onMessagedReceived 侦听器,我用它在我的应用程序中切换 PTT
BluetoothPtt ptt = new BluetoothPtt(new BluetoothPtt.OnMessageReceived(){
@Override
public void isPressed(boolean state){
togglePtt();
}
});
希望你能使用我的回答。
我正在使用 MediaButton 操作过滤器接收蓝牙耳机媒体按钮事件。动作过滤器在 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);
我一直在为同样的问题而苦苦挣扎。 我不知道这是否 Android 宽,但在我用来开发的三星 S6 上正在发生。
首先,即使没有 MediaSession,当您 UI 处于活动状态时(在屏幕上可见),也会发生这种情况。当 UI 处于活动状态时,媒体密钥将发送到 activity.
这是我解决问题的方法。
您需要将 Audiomanager 设置为 MODE_NORMAL
audioManager = (AudioManager)getApplicationContext().getSystemService(Context.AUDIO_SERVICE);
audioManager.setMode(AudioManager.MODE_NORMAL);
此时,即使不设置音频焦点,您也会收到MEDIA_PLAY按下麦克风PTT触发的消息。 您可以使用 activity
中触发的 keyDown 捕获此信息@Override
public boolean(int keyCode KeyEvent event){
if (keyCode == 126) startPlay();
return true;
}
然后您可以开始使用 MediaPlayer 播放一些东西 class。 只有在实际播放某些内容时,MEDIA_STOP 和其他键才会发送到您的应用程序。
不过我认为您正在创建某种 Walky Talky 应用程序。您将流式传输 RTP。我自己用 AudioTrack class 来做这个。当使用 play() 启动音轨时,也会使其他媒体密钥可用。
由于您可能想使用 PTT MIC 中的麦克风,因此您必须使用蓝牙 sco 进行连接。这也是通过 AudioManager 完成的。像这样
audio.setBluetoothScoOn(true);
audio.stopBluetoothSco();
然而,这打破了以上所有内容,只收到了 MEDIA_PLAY。 到目前为止,我只找到了一种解决方案,那就是使用蓝牙插座。下面是我使用的class。特别适用于 Dellking PTT 麦克风
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 字节代码,其中第 6 个字节为 80 表示按下,82 表示释放。 class 有一个 onMessagedReceived 侦听器,我用它在我的应用程序中切换 PTT
BluetoothPtt ptt = new BluetoothPtt(new BluetoothPtt.OnMessageReceived(){
@Override
public void isPressed(boolean state){
togglePtt();
}
});
希望你能使用我的回答。