简体   繁体   中英

Android live wallpaper service onStop is not getting called

I've created a Live Wallpaper which takes a file chosen by the user to be the GIF as background image.

The problem I'm having is that when I click 'Set Wallpaper' it begins my wallpaper service, then if I go back into my live wallpaper and click 'Set Wallpaper' again, it doesn't seem to close the previous service, but just runs another as well. This means each time I click 'Set Wallpaper' an image from the users SD card is read into a Bitmap variable

My onDestroy() method nullifies all Bitmap references and does System.gc(), however in this case, it seems the service isn't being destroyed when setting the same wallpaper over it.

here is my wallpersetter class

@Override
public void onBackPressed() {
    super.onBackPressed();
    this.finish();
}

@Override
public void onClick(View v) {
    if (v.getId() == R.id.button) {
        Intent intent2 = new Intent(DisplayImage.this, GifWallpaper.class);
        intent2.putExtra("pos", imageUrl);
        stopService(intent2);
        startService(intent2);


        Intent intent = new Intent(
                WallpaperManager.ACTION_CHANGE_LIVE_WALLPAPER);

        if (Build.VERSION.SDK_INT > 15) {

            String pkg = GifWallpaper.class.getPackage().getName();
            String cls = GifWallpaper.class.getCanonicalName();
            intent.putExtra(
                    WallpaperManager.EXTRA_LIVE_WALLPAPER_COMPONENT,
                    new ComponentName(pkg, cls));
        } else {
            intent.setAction(WallpaperManager.ACTION_LIVE_WALLPAPER_CHOOSER);
        }


        startActivityForResult(intent, 0);
    } else if (v.getId() == R.id.button2) {
        this.finish();
    }

}

@Override
protected void onActivityResult(int requestCode, int resultCode, Intent data) {

    if (requestCode == 0)
        this.finish();

    super.onActivityResult(requestCode, resultCode, data);

}

here is my wallpaper engine class

 public WallPaperEngine() throws IOException {

        InputStream is = getResources().openRawResource(imag);

        if (is != null) {

            try {
                liveMovie = Movie.decodeStream(is);
                duration = liveMovie.duration();

            } finally {
                is.close();
            }
        } else {
            throw new IOException("Unable to open R.raw.hand");
        }
        mWhen = -1;
        runnable = new Runnable() {
            public void run() {
                nyan();
            }
        };
    }

    @Override
    public void onDestroy() {
        super.onDestroy();
        liveHandler.removeCallbacks(runnable);

    }

    @Override
    public void onVisibilityChanged(boolean visible) {
        super.onVisibilityChanged(visible);

        if (visible) {
            nyan();
        } else {
            liveHandler.removeCallbacks(runnable);
        }
    }

    @Override
    public void onSurfaceChanged(SurfaceHolder holder, int format,
                                 int width, int height) {
        super.onSurfaceChanged(holder, format, width, height);
        mScaleX = width / (1f * liveMovie.width());
        mScaleY = height / (1f * liveMovie.height());
        // mScaleX =  (width -liveMovie.width())/2;
        //  mScaleY=   (height - liveMovie.height())/2;

        nyan();
    }

    @Override
    public void onOffsetsChanged(float xOffset, float yOffset,
                                 float xOffsetStep, float yOffsetStep, int xPixelOffset,
                                 int yPixelOffset) {
        super.onOffsetsChanged(xOffset, yOffset, xOffsetStep, yOffsetStep,
                xPixelOffset, yPixelOffset);
        nyan();
    }

    void nyan() {
        tick();
        SurfaceHolder surfaceHolder = getSurfaceHolder();
        Canvas canvas = null;
        try {
            canvas = surfaceHolder.lockCanvas();
            if (canvas != null) {
                drawGif(canvas);
            }
        } finally {
            if (canvas != null) {
                surfaceHolder.unlockCanvasAndPost(canvas);
            }
        }
        liveHandler.removeCallbacks(runnable);
        if (isVisible()) {
            liveHandler.postDelayed(runnable, 1000L / 25L);
        }
    }

    void tick() {
        if (mWhen == -1L) {
            mWhen = 0;
            mStart = SystemClock.uptimeMillis();
        } else {
            long mDiff = SystemClock.uptimeMillis() - mStart;
            mWhen = (int) (mDiff % duration);
        }
    }

    void drawGif(Canvas canvas) {
        Bitmap bitmap = BitmapFactory.decodeResource(getResources(), imag);
        cX = (canvas.getWidth() - bitmap.getWidth()) / 1.0f; //Width/2 gives the horizontal centre
        cY = (canvas.getHeight() - bitmap.getHeight()) / 8f;
        float cx, cy;
        cx = bitmap.getWidth();
        cy = bitmap.getHeight();

        canvas.save();
        if (cx > cy) {
            canvas.scale(mScaleX, mScaleY / 2);

            liveMovie.setTime(mWhen);
            liveMovie.draw(canvas, 0, cY);
        } else {
            canvas.scale(mScaleX, mScaleY);
            liveMovie.setTime(mWhen);
            liveMovie.draw(canvas, 0, 0);
        }

        canvas.restore();
    }

    @Override
    public void onSurfaceDestroyed(SurfaceHolder holder) {
        super.onSurfaceDestroyed(holder);
   visible=false;
        liveHandler.removeCallbacks(runnable);
    }
}

The WallpaperEngine is running on a different thread indefinitely, so you have to explicitly tell it to finish.

Somewhere in your code when you press back, you should be able to access the running service and execute:

myService.getThread().interrupt();

First of all check if

"Is the service calling stopSelf() once it is finished?"

Because it should be called once the service has finished doing what you started it for. Have a read of this. Just Have a Look at this .

I've run some tests on a live wallpaper I created and the WallpaperService onCreate() is only getting called once, no matter how many times I reapply it, then onDestory() is also only getting called once, when I apply a different wallpaper. So If I understand your problem Correctly, then I would suggest you this. but I'm not sure what is causing it. You can look into this code , You can add Log.d() in onCreate() and onDestroy() . let me know if it helps.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM