用于WALLPAPER_CHANGED的BroadcastReceiver多次调用onReceive():Android

我有一个BroadcastReceiver并声明如下:

<receiver android:name="com.services.Receiver" android:enabled="true" android:exported="true" > <intent-filter android:priority="999" > <action android:name="android.intent.action.WALLPAPER_CHANGED" /> </intent-filter> </receiver> 

接收者是:

 @Override public void onReceive(final Context context, final Intent intent) { change_wallpepar.myPrefs = context.getSharedPreferences("myPrefs", Context.MODE_PRIVATE); new Handler().postDelayed(new Runnable() { @Override public void run() { Log.d("MAYUR", "<< wallpepar changed >>"); if (change_wallpepar.myPrefs.getLong("temp_for_change", 1) == 0) { context.stopService(new Intent(context, change_wallpepar.class)); } else { SharedPreferences.Editor e = change_wallpepar.myPrefs.edit(); e.putLong("temp_for_change", 0); e.commit(); } } }, 4000); } 

当我在这里更换壁纸时,应该调用一次。 它实际上是按照我的期望工作了一段时间,几分钟后,它调用了onreceive()多次(10-18)次,即使墙纸的更改只完成一次。 更奇怪的是,它在三星Galaxy平板4.4.2版本上工作正常,但在摩托罗拉(摩托罗拉4.4.4)没有工作。

我的服务:

 public class change_wallpepar extends Service { @Override public void onCreate() { // TODO Auto-generated method stub super.onCreate(); mytimer = new Timer(); wpm = WallpaperManager.getInstance(change_wallpepar.this); } @Override public int onStartCommand(Intent intent, int flags, int startId) { // TODO Auto-generated method stub myPrefs = getSharedPreferences("myPrefs", MODE_PRIVATE); intervall = myPrefs.getLong("someValue", 60000); path_of_wallpepar.clear(); path_of_wallpepar.add("" + "/storage/emulated/0/Android/data/WallpeparAppHistoryPhotos/514.jpg"); path_of_wallpepar.add("" + "/storage/emulated/0/Android/data/WallpeparAppHistoryPhotos/513.jpg"); DisplayImageOptions defaultOption = new DisplayImageOptions.Builder().cacheInMemory(true).cacheOnDisk(true).bitmapConfig(Bitmap.Config.RGB_565).build(); ImageLoaderConfiguration config = new ImageLoaderConfiguration.Builder(change_wallpepar.this).defaultDisplayImageOptions(defaultOption).build(); ImageLoader.getInstance().init(config); mytimer.schedule(new TimerTask() { @Override public void run() { try { wpm.setBitmap(ImageLoader.getInstance().loadImageSync("file://" + path_of_wallpepar.get(temper))); } catch (IOException e) { e.printStackTrace(); } temper++; if (temper == path_of_wallpepar.size()) temper = 0; SharedPreferences.Editor e = change_wallpepar.myPrefs.edit(); e.putLong("temp_for_change", 1); e.commit(); Log.e("MAYUR", "wallpepar seted"); } }, 0, intervall); return super.onStartCommand(intent, flags, startId); } @Override public IBinder onBind(Intent intent) { // TODO Auto-generated method stub return null; } public void onDestroy() { Toast.makeText(this, "Service Destroyed", Toast.LENGTH_SHORT).show(); Vibrator v = (Vibrator) getSystemService(Context.VIBRATOR_SERVICE); v.vibrate(1000); mytimer.cancel(); super.onDestroy(); } } 

我的Logcat输出是:

 ## Logcat ## 04-16 11:06:30.654: E/MAYUR(3405): wallpepar seted 04-16 11:06:34.636: D/MAYUR(3405): << wallpepar changed >> 04-16 11:06:59.584: E/MAYUR(3405): wallpepar seted 04-16 11:07:03.551: D/MAYUR(3405): << wallpepar changed >> 04-16 11:07:30.078: E/MAYUR(3405): wallpepar seted 04-16 11:07:33.979: D/MAYUR(3405): << wallpepar changed >> 04-16 11:07:59.433: E/MAYUR(3405): wallpepar seted 04-16 11:08:03.340: D/MAYUR(3405): << wallpepar changed >> 04-16 11:08:30.029: E/MAYUR(3405): wallpepar seted 04-16 11:08:33.933: D/MAYUR(3405): << wallpepar changed >> 04-16 11:08:59.481: E/MAYUR(3405): wallpepar seted 04-16 11:09:03.383: D/MAYUR(3405): << wallpepar changed >> 04-16 11:09:30.066: E/MAYUR(3405): wallpepar seted 04-16 11:09:33.966: D/MAYUR(3405): << wallpepar changed >> 04-16 11:09:59.448: E/MAYUR(3405): wallpepar seted 04-16 11:10:03.353: D/MAYUR(3405): << wallpepar changed >> 04-16 11:10:30.049: E/MAYUR(3405): wallpepar seted 04-16 11:10:33.955: D/MAYUR(3405): << wallpepar changed >> 04-16 11:10:59.455: E/MAYUR(3405): wallpepar seted 04-16 11:11:03.350: D/MAYUR(3405): << wallpepar changed >> 04-16 11:11:30.182: E/MAYUR(3405): wallpepar seted 04-16 11:11:34.177: D/MAYUR(3405): << wallpepar changed >> 04-16 11:11:59.406: E/MAYUR(3405): wallpepar seted 04-16 11:12:03.315: D/MAYUR(3405): << wallpepar changed >> 04-16 11:12:30.025: E/MAYUR(3405): wallpepar seted 04-16 11:12:33.929: D/MAYUR(3405): << wallpepar changed >> 04-16 11:12:34.103: D/MAYUR(3405): << wallpepar changed >> 04-16 11:12:34.298: D/MAYUR(3405): << wallpepar changed >> 04-16 11:12:34.497: D/MAYUR(3405): << wallpepar changed >> 04-16 11:12:34.676: D/MAYUR(3405): << wallpepar changed >> 04-16 11:12:34.854: D/MAYUR(3405): << wallpepar changed >> 04-16 11:12:35.022: D/MAYUR(3405): << wallpepar changed >> 04-16 11:12:35.190: D/MAYUR(3405): << wallpepar changed >> 04-16 11:12:35.355: D/MAYUR(3405): << wallpepar changed >> 04-16 11:12:35.522: D/MAYUR(3405): << wallpepar changed >> 04-16 11:12:35.683: D/MAYUR(3405): << wallpepar changed >> 04-16 11:12:35.852: D/MAYUR(3405): << wallpepar changed >> 04-16 11:12:36.023: D/MAYUR(3405): << wallpepar changed >> 04-16 11:12:36.187: D/MAYUR(3405): << wallpepar changed >> 04-16 11:12:36.350: D/MAYUR(3405): << wallpepar changed >> 04-16 11:12:36.513: D/MAYUR(3405): << wallpepar changed >> 

Solutions Collecting From Web of "用于WALLPAPER_CHANGED的BroadcastReceiver多次调用onReceive():Android"

重复的WALLPAPER_CHANGED调用是由较小的Android设备在图像上运行裁剪缩放周期来适应屏幕的。 这是在AOSP代码中观察到的。 当屏幕比例适合或大于图像时,您不太可能看到此行为,因此平板电脑为何不显示此行为。

您可以通过仔细检查不需要的行为的迹象来解决这个问题:

 long lastExec = System.currentTimeMillis(); @Override public void onReceive(final Context context, final Intent intent) { change_wallpepar.myPrefs = context.getSharedPreferences("myPrefs", Context.MODE_PRIVATE); new Handler().postDelayed(new Runnable() { @Override public void run() { if(System.currentTimeMillis()-lastExec>1000) { Log.d("MAYUR", "<< wallpepar changed >>"); if (change_wallpepar.myPrefs.getLong("temp_for_change", 1) == 0) { context.stopService(new Intent(context, change_wallpepar.class)); } else { SharedPreferences.Editor e = change_wallpepar.myPrefs.edit(); e.putLong("temp_for_change", 0); e.commit(); } } lastExec = System.currentTimeMillis(); } }, 4000); } 

我不确定为什么会在某些设备上出现这种情况,但在我看来这很可能是特定设备的问题。 虽然我无法解决这个问题,但是一旦听众在一段时间内被击中并重置之后,潜在地,你可以保存一个被切换的variables。 这会使你的听众在短时间内忽略未来的呼叫。把它想象成防洪。

我知道这并不能解决你的实际问题,但我希望它能提供一个合适的解决方法。

最可能的一个设备特定的问题。

通常使用一个标志,我猜是推荐的解决scheme

 @Override public void onReceive(final Context context, final Intent intent) { private static boolean firstReceive = true; change_wallpepar.myPrefs = context.getSharedPreferences("myPrefs", Context.MODE_PRIVATE); new Handler().postDelayed(new Runnable() { @Override public void run() { if(firstReceive){ Log.d("MAYUR", "<< wallpepar changed >>"); if (change_wallpepar.myPrefs.getLong("temp_for_change", 1) == 0) { context.stopService(new Intent(context, change_wallpepar.class)); } else { SharedPreferences.Editor e = change_wallpepar.myPrefs.edit(); e.putLong("temp_for_change", 0); e.commit(); } } ///CHANGE firstReceive BASED ON EITHER TIME SINCE LAST WALLPAPER CHANGE ///OR ANY OTHER PARAMETER THAT SUITS YOUR REQUIREMENT }, 4000); } } 

请注意,我没有在循环中重新设置标志 ,您应该在上次更改之后的一定时间内执行该操作或者将当前墙纸标识符保存在共享的pref中,并与之匹配并设置标志等。你的要求

这个想法是解决这个问题,所以你克服了误报,并真正改变为真正的wallpaper_change调用。 这是一个Workaround而不是问题存在的实际解决scheme。