【问题标题】:KeyEvent.ACTION_UP fired TWICE for ACTION_MEDIA_BUTTONKeyEvent.ACTION_UP 为 ACTION_MEDIA_BUTTON 触发了两次
【发布时间】:2013-02-16 14:35:03
【问题描述】:

我有这个 ACTION_MEDIA_BUTTON 广播接收器,它实际上适用于 Android 2.x 和 Android 4.1,但出于某种奇怪的原因,在 Android 2.x(仅限) 上,我什至都得到了 两次(当然是单击暂停按钮):

public class RemoteControlReceiver extends BroadcastReceiver {
  private static long prevEventTime = 0;

  @Override
  public void onReceive(Context ctx, Intent intent) {
    if (Intent.ACTION_MEDIA_BUTTON.equals(intent.getAction())) {
      KeyEvent event = (KeyEvent)intent.getParcelableExtra(Intent.EXTRA_KEY_EVENT);
      long curEventTime = event.getEventTime();
      if (event != null && (event.getAction() == KeyEvent.ACTION_UP) /*&& (curEventTime != prevEventTime)*/) {
        int keycode = event.getKeyCode();
        switch (keycode)
        {
          case KeyEvent.KEYCODE_MEDIA_NEXT:
            Log.i(TAG, "KEYCODE_MEDIA_NEXT"); 
            break;
          case KeyEvent.KEYCODE_HEADSETHOOK:
            Log.i(TAG, "KEYCODE_HEADSETHOOK" + " " +  curEventTime + " <> " + prevEventTime + " (" + event.getAction() + ")");
            prevEventTime = curEventTime;
            break;
          case KeyEvent.KEYCODE_MEDIA_PREVIOUS:
            Log.i(TAG, "KEYCODE_MEDIA_PREVIOUS"); 
            break;
          default:
        }
      }     
    }
  }

}

为了理解其中的奥秘,我记录了每次发生的事件时间:

03-01 18:27:05.264: I/RemoteControlReceiver.onReceive(22377): KEYCODE_HEADSETHOOK 142304436 <> 0 (1)
03-01 18:27:05.434: I/RemoteControlReceiver.onReceive(22377): KEYCODE_HEADSETHOOK 142304436 <> 142304436 (1)

03-01 18:27:14.054: I/RemoteControlReceiver.onReceive(22377): KEYCODE_HEADSETHOOK 142313265 <> 142304436 (1)
03-01 18:27:14.074: I/RemoteControlReceiver.onReceive(22377): KEYCODE_HEADSETHOOK 142313265 <> 142313265 (1)

03-01 18:27:24.254: I/RemoteControlReceiver.onReceive(22377): KEYCODE_HEADSETHOOK 142323464 <> 142313265 (1)
03-01 18:27:24.264: I/RemoteControlReceiver.onReceive(22377): KEYCODE_HEADSETHOOK 142323464 <> 142323464 (1)

03-01 18:27:37.574: I/RemoteControlReceiver.onReceive(22377): KEYCODE_HEADSETHOOK 142336795 <> 142323464 (1)
03-01 18:27:37.614: I/RemoteControlReceiver.onReceive(22377): KEYCODE_HEADSETHOOK 142336795 <> 142336795 (1)

03-01 18:27:45.214: I/RemoteControlReceiver.onReceive(22377): KEYCODE_HEADSETHOOK 142344433 <> 142336795 (1)
03-01 18:27:45.284: I/RemoteControlReceiver.onReceive(22377): KEYCODE_HEADSETHOOK 142344433 <> 142344433 (1)

03-01 18:27:52.474: I/RemoteControlReceiver.onReceive(22377): KEYCODE_HEADSETHOOK 142351687 <> 142344433 (1)
03-01 18:27:52.504: I/RemoteControlReceiver.onReceive(22377): KEYCODE_HEADSETHOOK 142351687 <> 142351687 (1)

同样,这种双重发生不会在 Android 4.1 中发生。它只会在 Android 2.x 中发生。

知道为什么?

(虽然我可以使用相同的事件时间日志记录技术来过滤第二次发生的事件,但我更愿意先了解发生了什么(我这边可能的编程错误?),然后看看是否有更好的解决方案)


回答以下问题:(“您如何准确地注册接收器”)

应用清单中的第一个:

<receiver android:name="com.example.mylib.RemoteControlReceiver" android:enabled="true">
    <intent-filter android:priority="2147483647" >
        <action android:name="android.intent.action.MEDIA_BUTTON" />
    </intent-filter>
</receiver>

然后,在我的图书馆活动中(根据this tip),在 OnCreate() 中:

mRemoteControlReceiver = new ComponentName(this, RemoteControlReceiver.class);
mAudioManager.registerMediaButtonEventReceiver(mRemoteControlReceiver);

我希望这提供了一个更完整的图片,可以帮助解开这个谜。

【问题讨论】:

  • 你是如何注册你的接收器的?
  • 现在我无法编辑我的赏金文本(可悲)。 “我没有使用任何库”是指我没有注册同一个监听器的应用程序。

标签: android broadcastreceiver android-audiomanager


【解决方案1】:

我注意到您在库中使用此接收器(清单中的“mylib”部分)。

如果确实如此,并且您的接收器由 两个 共享相同注册码的应用程序注册,您将看到这些事件 两次

如果三个应用程序注册了该接收器,您将收到三倍的事件...

确保每个应用程序使用不同的(唯一的)&lt;receiver android:name

【讨论】:

  • 不是我的情况,我确实观察到了这个问题。我只有在清单中定义的过滤器。这仅发生在 Android 2.x 中。这显然是一个错误,因为我已经验证了我自己的接收器被实例化并触发了两次(UP 两次,DOWN 两次)并且它只注册了一个(通过 PackageManager.queryBroadcastReceivers 检查。检查事件时间的解决方法是否可靠并且它是唯一的吗?
【解决方案2】:

我遇到了这个问题并花了一段时间把头撞在墙上,然后才意识到每次按下按钮都会产生两个事件:KeyEvent.ACTION_DOWN 和 KeyEvent.ACTION_UP。所以使用媒体按钮需要两个测试:

if (Intent.ACTION_MEDIA_BUTTON.equals(intent.getAction())) {}

if (event.getAction() == KeyEvent.ACTION_DOWN) {}

因此,如果其他人因同样的错误而发现自己在这里,也许此回复会有所帮助。

【讨论】:

  • 这为我解决了。现在看起来很明显,但之前没有想到。谢谢
  • 这就是魔法。啊!我什至读过一次并忽略了它,认为这不是问题。谢谢!
【解决方案3】:

为了确保始终是第一次,您可以使用标志来表明这是第一次操作。

boolean firstAction= false;
if (Intent.ACTION_MEDIA_BUTTON.equals(intent.getAction())) {
    firstAction= !firstAction;
    if(!firstAction)
    {
        return true;
    }

    KeyEvent event = (KeyEvent)intent.getParcelableExtra(Intent.EXTRA_KEY_EVENT);
    long curEventTime = event.getEventTime();
    if (event != null && (event.getAction() == KeyEvent.ACTION_UP) /*&& (curEventTime != prevEventTime)*/) {
        int keycode = event.getKeyCode();
        switch (keycode)
        {
          case KeyEvent.KEYCODE_MEDIA_NEXT:
            Log.i(TAG, "KEYCODE_MEDIA_NEXT"); 
            break;
          case KeyEvent.KEYCODE_HEADSETHOOK:
            Log.i(TAG, "KEYCODE_HEADSETHOOK" + " " +  curEventTime + " <> " + prevEventTime + " (" + event.getAction() + ")");
            prevEventTime = curEventTime;
            break;
          case KeyEvent.KEYCODE_MEDIA_PREVIOUS:
            Log.i(TAG, "KEYCODE_MEDIA_PREVIOUS"); 
            break;
          default:
        }
    }     
}

【讨论】:

  • 请注意我原始代码中注释掉的/*&amp;&amp; (curEventTime != prevEventTime)*/:这已经解决了上述问题。我要问的是为什么会发生这种情况,而不是如何解决这个问题。感谢您尝试提供帮助。 :)
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2022-11-28
  • 1970-01-01
  • 2018-10-28
  • 2018-10-16
相关资源
最近更新 更多