3

I'm creating a live wallpaper and I'm using this tutorial as a starting point:

http://code.tutsplus.com/tutorials/create-a-live-wallpaper-on-android-using-an-animated-gif--cms-23088

I'm trying to add a settings menu to let the user choose one of four backgrounds. I have everything working using SharedPreferences. The only problem is that the wallpaper does not update after the setting is changed in the settings menu. If you restart the app, the background will be updated with the last background selected, but it only works after the wallpaper is restarted (i.e., selecting a different wallpaper, and then reselecting this wallpaper).

I've narrowed the problem down to the fact that the value from the SharedPreference is only updated in the onCreateEngine() method. Once the wallpaper service is running, the onCreateEngine() method doesn't get called, so even though the value of the SharedPreference has been changed, it doesn't get updated in the wallpaper service.

My question is how do I restart the wallpaper so that the onCreateEngine() method gets called after a setting gets changed? Again, the SharedPreferences are working, since everything works after restart. I know I need to use the onsharedPreferenceChanged method, but I'm not sure where that should occur, or what code should be included in that method to restart the wallpaper engine.

Here's the sample code. Mine is the same except where indicated by the comments:

    import android.graphics.Canvas;
    import android.graphics.Movie;
    import android.os.Handler;
    import android.service.wallpaper.WallpaperService;
    import android.util.Log;
    import android.view.SurfaceHolder;

    import java.io.IOException;

    public class GIFWallpaperService extends WallpaperService implements onsharedpreferencechangelistener {

        // Variable I added to change background
        String mBackgroundImage = null;

        // Method I added to update background image
        public void updatedBackgroundImage(){
             // code that sets mBackgroundImage based upon value of shared preference file. 
        }

        @Override
        public WallpaperService.Engine onCreateEngine() {

            // I call this method to change the value of mBackgroundImage
            updateBackgroundImage(); 

            try {
                Movie movie = Movie.decodeStream(
                        getResources().getAssets().open("mBackgroundImage"));

                return new GIFWallpaperEngine(movie);
            }catch(IOException e){
                Log.d("GIF", "Could not load asset");
                return null;
            }
        }

        @Override
        public void onSharedPreferenceChanged(SharedPreferences sp, String key) {
    // What do I do?  How do I make the wallpaper engine restart when settings are changed?  
        }

        private class GIFWallpaperEngine extends WallpaperService.Engine {

            private final int frameDuration = 20;

            private SurfaceHolder holder;
            private Movie movie;
            private boolean visible;
            private Handler handler;

            public GIFWallpaperEngine(Movie movie) {
                this.movie = movie;
                handler = new Handler();
            }

            @Override
            public void onCreate(SurfaceHolder surfaceHolder) {
                super.onCreate(surfaceHolder);
                this.holder = surfaceHolder;
            }

            private Runnable drawGIF = new Runnable() {
                public void run() {
                    draw();
                }
            };


            private void draw() {
                if (visible) {
                    Canvas canvas = holder.lockCanvas();
                    canvas.save();
                        // Adjust size and position so that
                        // the image looks good on your screen
                        canvas.scale(3f, 3f);
                        movie.draw(canvas, -100, 0);
                    canvas.restore();
                    holder.unlockCanvasAndPost(canvas);
                    movie.setTime((int) (System.currentTimeMillis() % movie.duration()));

                    handler.removeCallbacks(drawGIF);
                    handler.postDelayed(drawGIF, frameDuration);
                }
            }

            @Override
            public void onVisibilityChanged(boolean visible) {
                this.visible = visible;
                if (visible) {
                    handler.post(drawGIF);
                } else {
                    handler.removeCallbacks(drawGIF);
                }
            }

            @Override
            public void onDestroy() {
                super.onDestroy();
                handler.removeCallbacks(drawGIF);
            }
        }
    }
Kevin Bright
  • 961
  • 2
  • 9
  • 17
  • Can anyone help me with this? – Kevin Bright Oct 06 '15 at 20:31
  • After continuing to mess with this, I think the problem is that `onSharedPreferenceChange()` is not being called when the change occurs. I'm trying to figure out why. – Kevin Bright Oct 07 '15 at 01:14
  • Alright, I fixed the problem with `onSharedPreferenceChange()` not being called. It is now being called from within `WallpaperService`, but I can't figure out what to put in the implementation. Everything is working fine when the `Service` first starts... and the variable that sets the background image gets updated based upon what the user selects in the menu, but because the `Service` is already running, the updated variable has no effect. PLEASE HELP!!! – Kevin Bright Oct 08 '15 at 02:18
  • Have you solved this problem? – GAAAN Jan 06 '18 at 01:30

2 Answers2

1

I'm propably late, but hope someone will find this useful.

You need to specify and register you SharedPrefs first. Add this to your onCreate() method.

SharedPreferences preferences = getSharedPreferences("PREFERENCES NAME", Context.MODE_PRIVATE);
        preferences.registerOnSharedPreferenceChangeListener(this);
Firax
  • 31
  • 1
  • 4
-2

I don't know if you found your answer, but i saw this in the android ref:

WallpaperService.Engine onCreateEngine ()

Must be implemented to return a new instance of the wallpaper's engine. Note that multiple instances may be active at the same time, such as when the wallpaper is currently set as the active wallpaper and the user is in the wallpaper picker viewing a preview of it as well.

chris

Chris
  • 1