我正在使用一些工作代码,我在服务中找到了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手机的问题或者什么,但似乎我需要一种方式只响应一次多次发送相同的广播。
答案 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");
}
}
}
}
}
}