3

I'm studing live wallpaper on Android. I notice that my wallpaper is still running despite i select another wallpaper. To reproduce this behavior, i will use a simple live wallpaper. The manifest is:

<manifest xmlns:android="http://schemas.android.com/apk/res/android"
    package="org.wallpaper.test"
    android:versionCode="1"
    android:versionName="1.0" >

    <uses-sdk
        android:minSdkVersion="16"
        android:targetSdkVersion="23" />

    <uses-feature android:name="android.software.live_wallpaper" />

    <application
        android:allowBackup="true"
        android:icon="@drawable/ic_launcher"
        android:label="@string/app_name"
        android:theme="@style/AppTheme" >
        <service
            android:name=".DemoWallpaperService"
            android:label="Demo Live Wallpaper"
            android:permission="android.permission.BIND_WALLPAPER" >
            <intent-filter>
                <action android:name="android.service.wallpaper.WallpaperService" />
            </intent-filter>

            <meta-data
                android:name="android.service.wallpaper"
                android:resource="@xml/wallpaper" />
        </service>
    </application>

</manifest>

The service code is:

package org.wallpaper.test;

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

public class DemoWallpaperService extends WallpaperService {
    @Override
    public Engine onCreateEngine() {
        Log.i("DemoWallpaperService","DemoWallpaperService > onCreateEngine");      
        return new DemoWallpaperEngine();
    }

    @Override
    public void onCreate() {
        Log.i("DemoWallpaperService","DemoWallpaperService > onCreate");    
        super.onCreate();
    }

    @Override
    public void onDestroy() {
        Log.i("DemoWallpaperService","DemoWallpaperService > onDestroy");   
        super.onDestroy();
    }

    private class DemoWallpaperEngine extends Engine {
        private boolean mVisible = false;
        private final Handler mHandler = new Handler();
        private final Runnable mUpdateDisplay = new Runnable() {
            @Override
            public void run() {
                draw();
            }
        };

        private void draw() {
            SurfaceHolder holder = getSurfaceHolder();
            Canvas c = null;
            try {
                c = holder.lockCanvas();
                if (c != null) {
                    Paint p = new Paint();
                    p.setTextSize(20);
                    p.setAntiAlias(true);
                    String text = "system time: " + Long.toString(System.currentTimeMillis());
                    float w = p.measureText(text, 0, text.length());
                    int offset = (int) w / 2;
                    int x = c.getWidth() / 2 - offset;
                    int y = c.getHeight() / 2;
                    p.setColor(Color.BLACK);
                    c.drawRect(0, 0, c.getWidth(), c.getHeight(), p);
                    p.setColor(Color.WHITE);
                    c.drawText(text, x, y, p);
                }
            } finally {
                if (c != null)
                    holder.unlockCanvasAndPost(c);
            }
            mHandler.removeCallbacks(mUpdateDisplay);
            if (mVisible) {
                mHandler.postDelayed(mUpdateDisplay, 100);
            }
        }

        @Override
        public void onVisibilityChanged(boolean visible) {
            mVisible = visible;
            if (visible) {
                draw();
            } else {
                mHandler.removeCallbacks(mUpdateDisplay);
            }
        }

        @Override
        public void onSurfaceChanged(SurfaceHolder holder, int format, int width, int height) {
            draw();
        }

        @Override
        public void onSurfaceDestroyed(SurfaceHolder holder) {
            super.onSurfaceDestroyed(holder);
            mVisible = false;
            mHandler.removeCallbacks(mUpdateDisplay);
        }

        @Override
        public void onDestroy() {
            super.onDestroy();
            mVisible = false;
            mHandler.removeCallbacks(mUpdateDisplay);
        }
    }
}

After compile, deploy on device and select it.

enter image description here

Now i select another wallpaper, so i expect the wallpaper process die. If i go to DDMS i see that the process is still running:

enter image description here

And there many thread still alive:

enter image description here

This is correct, or the wallpaper does not close properly?

Thanks

xcesco
  • 4,690
  • 4
  • 34
  • 65

1 Answers1

0

After investigation i found that, despite the invocation onDestroy method of the service, the wallpaper is still alive. The process is put in the cached processes. It is done to resume it faster, if your reselect it.

The process will be kill when memory is claimed.

xcesco
  • 4,690
  • 4
  • 34
  • 65