我正在使用在服务中找到的一些工作代码,用于通过action_headset_plug检测耳机连接状态。我有两款用于测试的手机,一台摩托罗拉姜饼和一个果冻豆LG。在姜饼手机上,一切都很好...我插入耳机,然后从Android那里得到一个广播,然后我执行了工作。在果冻豆手机上,我会为每个耳机状态更改而获得两个(2)个广播,因此我自己的东西被称为两次。我不是100%确定的,但我认为这与粘性广播无关,好像是这种情况,我应该在姜饼和果冻手机上看到相同的行为。
在果冻豆手机上过滤所有系统logcat msgs for" headset_plug",我会在耳机状态更改上看到类似的东西:
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手机的问题,或者什么是什么,但似乎我需要一种在多次发送同一广播时仅一次响应的方法。
我需要一种方法,仅在多次发送同一广播
时一次响应一次
如果您连续收到两个,三个或一百万个广播,其中state
值与以前的广播没有更改,则该州没有更改。state
更改时仅执行您的"状态已更改"逻辑,而不仅仅是因为您收到了广播。
您是否需要专用的boolean lastHeadsetState
数据成员来检测状态的变化,或者可以从应用程序中的其他内容推断出最后一个状态,我不能说。
现在,理想情况下,您不需要这种逻辑,因为理想情况下,在状态变化时,广播只会出现一次。您离硬件越近,弹出的设备怪癖就越多。因此,鲁棒性原理在您离硬件越近更加重要。
以防万一任何人以后出现同样的问题...
我无法弄清楚如何使用该州的布尔值处理多个广播,但是我确实通过为状态设置整数来解决此问题。如果该服务收到了"插电"的多个广播,它将始终将int lastheadsettate设置为0。如果它收到了多个插入的广播,则第一个广播将将lastheadsettate设置为1,而其他广播将将lastheadsettate递增。恰好1,然后完成我的工作。除1以外的任何其他值都意味着收到了多个广播,应忽略。
因此,这是我的服务代码,用于听耳机插头/拔下插头状态的更改,忽略了启动服务时生成的初始粘性广播,并包含逻辑以容忍Wacky Hardware的多个广播。如果有人关心提出一种更优雅的方法来实现相同的结果,我会感兴趣。对于下面的任何格式错误表示歉意:
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");
}
}
}
}
}
}