问题
I have a BroadcastReceiver and declared it like this:
<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>
and the receiver is:
@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);
}
When I change the wallpaper here it should be called once. It is really working as by my expectations for a while, after some minutes it calls onreceive()
multiple (10-18) times, even though the change in wallpaper is done once. Even more strange about this is that it is working fine on a Samsung Galaxy tablet version 4.4.2, but not working on Motorola (Moto E 4.4.4).
My service:
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();
}
}
My Logcat output is:
## 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 >>
回答1:
The repeated WALLPAPER_CHANGED
calls are caused by smaller Android devices running crop-scale cycles on the image to fit the screen. This is observed in the AOSP code. You're less likely to see this behavior when the screen ratio fits or is bigger than the image, hence why the tablet doesn't exhibit this behavior.
You can fix this problem by double-checking for signs of the unwanted behavior:
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);
}
回答2:
I'm not sure why this happens on some devices but it would seem to me to most likely be a problem with that specific device. Whilst I cannot resolve that issue, potentially you could hold a variable that is toggled once your listener is hit and reset after a period of time. This will thus cause your listener to ignore future calls for a short period of time.. think of it like flood protection.
I know that doesn't resolve your actual issue but I hope it will provide a suitable workaround.
回答3:
Most possibly a device specific problem.
In general using a flag I guess is the recommended solution
@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);
}
}
Note that I haven't reset the flag again in the Loop, you should probably do it after a certain amount of time since last change OR save some current wallpaper identifier in shared pref and match against that and set the flag etc., based on your requirement
The idea is to workaround the issue, so you get over the false positives and actually change for real wallpaper_change
calls. This is a Workaround
and not an actual solution to why the problem exists.
来源:https://stackoverflow.com/questions/29666294/broadcastreceiver-for-wallpaper-changed-calls-onreceive-multiple-times-andro