sendbroadcast que oreo example custom android android-service android-broadcast android-wallpaper

android - oreo - broadcast receiver que es



BroadcastReceiver para WALLPAPER_CHANGED llama onReceive() varias veces: Android (3)

Tengo un BroadcastReceiver y lo declaré así:

<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>

y el receptor es:

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

Cuando cambio el fondo de pantalla aquí debería llamarse una vez. Realmente está funcionando como por mis expectativas por un tiempo, después de algunos minutos se llama onreceive() varias veces (10-18), aunque el cambio en el fondo de pantalla se realiza una vez. Aún más extraño acerca de esto es que funciona bien en una tableta Samsung Galaxy versión 4.4.2, pero no funciona en Motorola (Moto E 4.4.4).

Mi servicio

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

La salida de mi Logcat es:

## 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 >>


Las llamadas WALLPAPER_CHANGED repetidas son causadas por dispositivos Android más pequeños que ejecutan ciclos de escala de recorte en la imagen para ajustarse a la pantalla. Esto se observa en el código AOSP . Es menos probable que vea este comportamiento cuando la proporción de la pantalla se ajusta o es más grande que la imagen, por lo tanto, la tableta no presenta este comportamiento.

Puede solucionar este problema haciendo una doble comprobación de signos de comportamiento no deseado:

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


Muy posiblemente un problema específico del dispositivo.

En general, usar una bandera supongo que es la solución recommended .

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

Tenga en cuenta que no he restablecido la bandera de nuevo en el bucle , probablemente debería hacerlo después de un cierto período de tiempo desde el último cambio O guardar un identificador de fondo de pantalla actual en pref compartido y emparejar contra eso y configurar la bandera , etc., en función de su requerimiento

La idea es solucionar el problema, de modo que supere los falsos positivos y cambie realmente para llamadas de wallpaper_change reales. Esta es una Workaround y no una solución real a por qué existe el problema.


No estoy seguro de por qué sucede esto en algunos dispositivos, pero me parece que probablemente sea un problema con ese dispositivo específico. Si bien no puedo resolver ese problema, potencialmente podría mantener una variable que se alterna una vez que su oyente es golpeado y restablecido después de un período de tiempo. Esto provocará que su interlocutor ignore las llamadas futuras durante un corto período de tiempo.

Sé que eso no resuelve su problema real, pero espero que le brinde una solución adecuada.