如何对多个广播做出响应? Jelly Bean LG为一个活动发送两个广播

时间:2014-02-01 13:02:03

标签: java android broadcastreceiver android-broadcast

我正在使用一些工作代码,我在服务中找到了here,用于通过ACTION_HEADSET_PLUG检测耳机连接状态。我有两部手机用于测试,一部是Gingerbread Motorola和一台Jelly Bean LG。在Gingerbread手机上一切正常......我插上耳机,然后从Android获得一个广播,然后我执行我的工作。在Jelly Bean手机上,每次耳机状态改变都会收到两(2)个广播,因此我自己的东西会被调用两次。我不是100%肯定,但我不认为这与粘性广播有关,就好像我应该在Gingerbread和Jellybean手机上看到相同的行为。

在Jelly Bean手机上过滤“headset_plug”的所有系统logcat消息我将在耳机状态更改时看到类似的内容:

02-01 07:39:11.983: I/MusicBrowser(1739): [MediaPlaybackService.java:mHeadsetReceiver.onReady()] oooooo intentIntent { act=android.intent.action.HEADSET_PLUG flg=0x40000010 (has extras) }
02-01 07:39:12.083: I/MusicBrowser(1739): [MediaPlaybackService.java:mHeadsetReceiver.onReady()] oooooo intentIntent { act=android.intent.action.HEADSET_PLUG flg=0x40000010 (has extras) }

我可能会弄错,但似乎所有这些手机都会在几微秒内发送两个广播,而姜饼摩托罗拉只发送一个。我不知道这是一个Android错误,版本之间的故意更改,这个特定的LG手机的问题或者什么,但似乎我需要一种方式只响应一次多次发送相同的广播。

2 个答案:

答案 0 :(得分:1)

  

我需要一种方法,在多次发送同一广播时只响应一次

如果您连续收到两个,三个或一百万个广播,state值与之前的广播相比没有变化,则状态未发生变化。仅在state更改时执行“状态已更改”逻辑,而不仅仅是因为您收到了广播。

您是否需要专门的boolean lastHeadsetState数据成员来检测状态更改,或者可以从应用中的其他内容推断出最后状态,我不能说。

现在,理想情况下,您不需要这种逻辑,因为理想情况下,广播只会在状态发生变化时出现一次。越接近硬件,弹出的设备怪癖就越多。因此,robustness principle越接近硬件就越重要了。

答案 1 :(得分:0)

以防万一有人带来同样的问题......

我无法弄清楚如何使用状态的布尔值处理多个广播,但我确实通过为状态设置一个整数来解决这个问题。如果服务接收到“unplugged”的多个广播,它将始终将int lastHeadsetState设置为0.如果它接收多个插入的广播,则第一个广播将lastHeadsetState设置为1,另外的广播将lastHeadsetState增加1.然后检查lastHeadsetState是否等于正好1然后做我的工作。除1以外的任何值都意味着收到了多个广播,应该被忽略。

所以这是我的服务代码,用于监听耳机插拔状态的变化,忽略启动服务时产生的初始粘性广播,并包含容忍来自古怪硬件的多个广播的逻辑。如果有人愿意建议一种更优雅的方式来达到相同的结果,我会感兴趣。对以下任何格式错误表示道歉:

public class HeadsetService extends Service{

private static final String TAG = "HeadsetService";
private HeadsetReceiver hReceiver;
private int lastHeadsetState;

@Override
public IBinder onBind(Intent arg0) {
    // TODO Auto-generated method stub
    return null;
}

@Override
public void onCreate() {

    super.onCreate();       
    hReceiver = new HeadsetReceiver();

}

@Override
public int onStartCommand(Intent intent, int flags, int startId) {
    // Register a new HeadsetReceiver       
    IntentFilter hfilter = new IntentFilter(Intent.ACTION_HEADSET_PLUG);    
    registerReceiver(hReceiver, hfilter);

return START_STICKY;}

 private class HeadsetReceiver extends BroadcastReceiver {

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

    if (intent.getAction().equals(Intent.ACTION_HEADSET_PLUG)) {

        // ignore the initial sticky broadcast when the service starts
        if (isInitialStickyBroadcast()) {
        } 

        else { 

        int state = intent.getIntExtra("state", -1);
        switch (state) {
        case 0:             
            Log.d(TAG, "headset unplugged");
            //set lastHeadsetState to 0 for later comparison
        lastHeadsetState = 0;               
            Log.d(TAG, "lastHeadsetState set to 0");

        break;
        case 1:                             
            Log.d(TAG, "headset plugged in!");
            lastHeadsetState = (lastHeadsetState + 1);
            Log.d(TAG, "lastHeadsetState incremented by 1");
            //check if lastHeadsetState is exactly 1...any greater value means multiple broadcasts were received.
            if (lastHeadsetState == 1) {
        //do whatever you're going to do when the headset is plugged in here                   

        Log.d(TAG, "Headset state has changed from unplugged to plugged");
            }
             else 
                 Log.d(TAG, "Multiple broadcasts received, ignoring duplicates");

        break; 
        default:
            Log.w("uh", "I have no idea what the headset state is");
            }   
          }
       }
     }
   }
 }