registerMediaButtonEventReceiver未能接收到事件。

7

我希望能够在我的应用程序中接收物理按钮事件,例如手机侧面的音量按钮点击。我需要在服务中完成此操作,因为我想在任何时候都能接收到用户按下音量加/减按钮的事件。

我在网络上阅读了很多资料,但我还是无法使其正常工作,也不知道哪里出了问题。这是我的代码:

在清单文件中:

    <receiver android:name=".clsMediaButtonReceiver" >
        <intent-filter android:priority="1000" >
            <action android:name="android.intent.action.MEDIA_BUTTON" />               
        </intent-filter>
    </receiver>  

在服务的OnStart()方法中:
   AudioManager manager = (AudioManager) getSystemService(AUDIO_SERVICE);
   manager.registerMediaButtonEventReceiver(new ComponentName(getPackageName(), clsMediaButtonReceiver.class.getName())); 

关于广播接收器:

public class clsMediaButtonReceiver extends BroadcastReceiver
{  

   @Override public void onReceive(Context context, Intent intent)
   {  //This is never shown
      Toast toast1 = Toast.makeText(Context, intent.getAction(), Toast.LENGTH_SHORT);
      toast1.show();
   }

} 

@Hi Ton,哪个Android版本允许您使用registerMediaButtonEventReceiver()?实际上,我想在我的应用程序中使用它,但它无法编译。似乎AudioManager中没有这种方法。您能回复一下吗? - Chandra Sekhar
3个回答

9

我向我的intent过滤器添加了 <action android:name="android.media.VOLUME_CHANGED_ACTION" /> ,现在我可以获取音量键事件。但我还没有弄清楚如何在我的应用程序中正确分发它们...希望这有所帮助!


我现在成功地运行了我的代码! 我有一个音量滑块需要监听音乐音量的改变。 我像问题中那样注册了一个接收器(加上我的答案中的操作),然后使用监听器模式从那里广播事件。 经过一段时间的苦思冥想,我意识到接收器直到接收到事件才会被实例化。我通过保持静态监听器列表来绕过这个问题,其他组件可以注册到该列表中,接收器将使用该列表来广播事件。 - matrixsmurfen
避免使用静态引用。这样很容易泄漏资源。 为了实现广播接收器和服务之间的通信,在您的服务中实现onBind并在广播接收器的onReceive中调用peekService。 我可以向您展示代码,但是它太长了,无法在评论中显示。 - 0xF

4

我知道这是一个旧问题,我遇到了同样的问题并发现我们必须在持有AudioManager.AUDIOFOCUS_GAIN后才能注册registerMediaButtonEventReceiver(..),否则它不起作用。

我尝试使用相同的清单和BroadcastReciever,由@Ton编写。

private class ClassOnAudioFocusChangeListener implements AudioManager.OnAudioFocusChangeListener {
    @Override
    public void onAudioFocusChange(int focusChange) {
         if (focusChange == AudioManager.AUDIOFOCUS_LOSS_TRANSIENT){    
             Log.e("ClassOnAudioFocusChangeListener: ", "AUDIOFOCUS_LOSS_TRANSIENT");
         }
         else if (focusChange == AudioManager.AUDIOFOCUS_LOSS_TRANSIENT_CAN_DUCK) {
             Log.e("ClassOnAudioFocusChangeListener: ", "AUDIOFOCUS_LOSS_TRANSIENT_CAN_DUCK");
         }
         else if (focusChange == AudioManager.AUDIOFOCUS_GAIN) {
             Log.e("ClassOnAudioFocusChangeListener: ", "AUDIOFOCUS_GAIN");
              mAudioManager.registerMediaButtonEventReceiver(mMediaButtonEventComponenName);
         }
         else if (focusChange == AudioManager.AUDIOFOCUS_LOSS) {
             Log.e("ClassOnAudioFocusChangeListener: ", "AUDIOFOCUS_LOSS");                              
         }
    }
};

这里是相同的清单文件。
    <receiver 
        android:name="MainActivity$MediaButtonEventReceiver">           
        <intent-filter android:priority="1000" >
        <action android:name="android.intent.action.MEDIA_BUTTON" />               
        </intent-filter>
    </receiver>

在Android L+版本上,您的建议很有效,但无法注销。我一直收到事件。在清单中静态注册具有完整意图过滤器和操作声明的接收器之后,您将无法注销它。解决方案:仅在清单中定义接收器而不使用意图过滤器。然后您可以在代码中动态地注册和注销它。 - Habib

0
我和你有同样的问题,我想知道你是否解决了它。我的代码与你的不同之处在于,我将broadcastReceiver类放在另一个类中。就像这样:
public class MyClass extends Activity 
{
    /// Code

    public class MediaButtonReceiver extends BroadcastReceiver
    {
         @Override
         public void onReceive(Context context, Intent intent)
         {
              /// Code
         }
    }
}

还有清单文件:

<receiver android:name="net.mypackage.MyClass.MediaButtonReceiver">
    <intent-filter android:priority="1000" >
        <action android:name="android.intent.action.MEDIA_BUTTON" />               
    </intent-filter>
</receiver>

感谢您的帮助


在Android清单文件中,您不能将非静态内部类指定为BroadcastReceiver。请参见https://dev59.com/EXA65IYBdhLWcg3w1SVC - 0xF

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接