BroadcastReceiver per WALLPAPER_CHANGED chiama suReceive () più volte: Android

Ho un BroadcastReceiver e l’ho dichiarato così:

     

e il ricevitore è:

 @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", "<>"); 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); } 

Quando cambio lo sfondo qui dovrebbe essere chiamato una volta. Funziona davvero secondo le mie aspettative per un po ‘, dopo alcuni minuti chiama onreceive() più volte (10-18) volte, anche se il cambio di sfondo viene eseguito una sola volta. Ancora più strano è che sta funzionando bene su un tablet Samsung Galaxy versione 4.4.2, ma non funziona su Motorola (Moto E 4.4.4).

Il mio servizio:

 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(); } } 

L’output di My Logcat è:

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

Le ripetute chiamate WALLPAPER_CHANGED sono causate da dispositivi Android più piccoli che eseguono cicli di ritaglio sull’immagine per adattarsi allo schermo. Questo è osservato nel codice AOSP . È meno probabile che tu veda questo comportamento quando il rapporto dello schermo si adatta o è più grande dell’immagine, quindi perché il tablet non mostra questo comportamento.

È ansible risolvere questo problema verificando i segni del comportamento indesiderato:

 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); } 

Non sono sicuro del motivo per cui ciò accade su alcuni dispositivi, ma mi sembra molto probabile che si tratti di un problema con quel dispositivo specifico. Anche se non riesco a risolvere il problema, potenzialmente potresti tenere una variabile che viene triggersta una volta che il listener viene colpito e ripristinato dopo un certo periodo di tempo. In questo modo, il tuo ascoltatore ignorerà le chiamate future per un breve periodo di tempo. Pensa ad esso come una protezione dalle inondazioni.

So che questo non risolve il tuo problema ma spero che fornisca una soluzione adeguata.

Molto probabilmente un problema specifico del dispositivo.

In generale, usando una bandiera credo sia la soluzione raccomandata

 @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); } } 

Nota che non ho reimpostato nuovamente il flag nel Loop , dovresti farlo probabilmente dopo un certo periodo di tempo dall’ultima modifica OPPURE salvare qualche identificatore di carta da parati corrente in pref condiviso e confrontarlo con quello e impostare il flag ecc., In base a il tuo requisito

L’idea è di risolvere il problema, in modo da superare i falsi positivi e in realtà cambiare per le vere chiamate wallpaper_change . Questa è una Workaround e non una soluzione effettiva al perché il problema esiste.