5

I'm developing a Live Wallpaper for Honeycomb 3.0, but I get a random error.

When I'm in wallpaper picker (the window with "Set Wallpaper" and "Settings..." buttons, to understand) and Live Wallpaper is displayed, if I rotate the device, the wallpaper should reload with the configuration adapted for new orientation. Sometimes it does, sometimes it crashes.

The error is in some way related to BaseSurfaceHolder.unlockCanvasAndPost method, but I really don't know were is the issue. I think it cannot load correctly some resources..

Here's error log:

07-21 16:07:38.490: WARN/WindowManager(292): java.lang.IllegalArgumentException: Requested window android.os.BinderProxy@40d19f28 does not exist
07-21 16:07:38.490: WARN/WindowManager(292):     at com.android.server.wm.WindowManagerService.windowForClientLocked(WindowManagerService.java:6731)
07-21 16:07:38.490: WARN/WindowManager(292):     at com.android.server.wm.WindowManagerService.windowForClientLocked(WindowManagerService.java:6722)
07-21 16:07:38.490: WARN/WindowManager(292):     at com.android.server.wm.WindowManagerService.removeWindow(WindowManagerService.java:2414)
07-21 16:07:38.490: WARN/WindowManager(292):     at com.android.server.wm.Session.remove(Session.java:149)
07-21 16:07:38.490: WARN/WindowManager(292):     at android.view.IWindowSession$Stub.onTransact(IWindowSession.java:120)
07-21 16:07:38.490: WARN/WindowManager(292):     at com.android.server.wm.Session.onTransact(Session.java:111)
07-21 16:07:38.490: WARN/WindowManager(292):     at android.os.Binder.execTransact(Binder.java:320)
07-21 16:07:38.490: WARN/WindowManager(292):     at dalvik.system.NativeStart.run(Native Method)
07-21 16:07:38.490: ERROR/AndroidRuntime(20768): FATAL EXCEPTION: main
07-21 16:07:38.490: ERROR/AndroidRuntime(20768): java.lang.IllegalArgumentException
07-21 16:07:38.490: ERROR/AndroidRuntime(20768):     at android.view.Surface.unlockCanvasAndPost(Native Method)
07-21 16:07:38.490: ERROR/AndroidRuntime(20768):     at com.android.internal.view.BaseSurfaceHolder.unlockCanvasAndPost(BaseSurfaceHolder.java:215)
07-21 16:07:38.490: ERROR/AndroidRuntime(20768):     at mx.livewallpaper.clock.CubeWallpaper1$CubeEngine.drawFrame(CubeWallpaper1.java:686)
07-21 16:07:38.490: ERROR/AndroidRuntime(20768):     at mx.livewallpaper.clock.CubeWallpaper1$CubeEngine$1.run(CubeWallpaper1.java:292)
07-21 16:07:38.490: ERROR/AndroidRuntime(20768):     at android.os.Handler.handleCallback(Handler.java:587)
07-21 16:07:38.490: ERROR/AndroidRuntime(20768):     at android.os.Handler.dispatchMessage(Handler.java:92)
07-21 16:07:38.490: ERROR/AndroidRuntime(20768):     at android.os.Looper.loop(Looper.java:132)
07-21 16:07:38.490: ERROR/AndroidRuntime(20768):     at android.app.ActivityThread.main(ActivityThread.java:4028)
07-21 16:07:38.490: ERROR/AndroidRuntime(20768):     at java.lang.reflect.Method.invokeNative(Native Method)
07-21 16:07:38.490: ERROR/AndroidRuntime(20768):     at java.lang.reflect.Method.invoke(Method.java:491)
07-21 16:07:38.490: ERROR/AndroidRuntime(20768):     at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:844)
07-21 16:07:38.490: ERROR/AndroidRuntime(20768):     at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:602)
07-21 16:07:38.490: ERROR/AndroidRuntime(20768):     at dalvik.system.NativeStart.main(Native Method)
07-21 16:07:38.500: ERROR/android.os.Debug(292): Dumpstate > /data/log/dumpstate_app_error

EDIT: code below is the drawFrame() method at line 686:

void drawFrame() {
            final SurfaceHolder holder = getSurfaceHolder();

            Canvas c = null;
            try {
                c = holder.lockCanvas();
                if (c != null) {

                    drawLogo3(c);
                }
            } finally {
                if (c != null) holder.unlockCanvasAndPost(c);
            }

It's a default method ppresent in all live wallpapers, I took it from CubeWallpaper Live Wallpaper Sample from Android SDK.

EDIT 2:

It sounds like a buffer error. If I set the framerate to 10fps instead of 40fps, the Live Wallpaper Picker doesn't crash at all. Is it possible to edit Live Wallpaper behaviour only for the Activity "Live Wallpaper Picker"?

Mariux
  • 494
  • 6
  • 19
  • Could you tell us what's happening at CubeWallpaper1.java line 686? – mopsled Jul 21 '11 at 17:14
  • at Line 686 there's the default live wallpaper drawFrame() method, see code in the edit above. – Mariux Jul 21 '11 at 22:36
  • 3
    when the device changes orientation, all your stuff is destroyed and re-created. you need to account for that in your naive drawing. the stack trace is indicating that `unlockCanvasAndPost` is generating the illegal argument exception. it is doing that because, as indicated in the very first line of your trace, the window you are trying to draw to is destroyed and no longer available, because of the orientation change. you should be getting a surface holder callback for that, which you are probably ignoring. you must be prepared for surface to go away at any time. – escape-llc Dec 30 '11 at 18:13
  • Hi @escape-llc! My drawFrame-method is similar to the one listed above, but I'm not sure if I got it: I have to add `holder.addCallback(new Callback() { public void surfaceDestroyed(SurfaceHolder holder) { destroyed = true; }});` after `getSurfaceHolder()` and before the try-catch block? And before calling `unlockCanvasAndPost(c)` I have to check if `!destroyed`? Maybe you could convert your comment to an answer and post a code snippet. Thanks! – Ethan Leroy May 17 '12 at 12:19

2 Answers2

1

have the thread join before you destroy the surface

@Override
public void onSurfaceDestroyed(SurfaceHolder holder)
{
    try 
    {
        updater.join();
    } 
    catch (InterruptedException e) 
    {

    }
    super.onSurfaceDestroyed(holder);
}
1

when you change the orientation of device,the function "onsurfacechange()" called.you must do somthing there.I guess the when you change the orientant the "surfaceholder"also changed.I do it like :

@Override
        public void onSurfaceChanged(SurfaceHolder holder, int format,
                int width, int height) {
                        int lockwidth = 0;
            int lockheight = 0;
            mholder = holder;
            try {

                canvas = mholder.lockCanvas();
                lockwidth = canvas.getWidth();
                lockheight = canvas.getHeight();
                if (width > height) {
                    Utils.Width = lockheight;
                    Utils.screenWidth = lockheight;
                    Utils.screenHeight = lockwidth;
                    Utils.isWidth = true;
                    if (width == 1280 && height == 720 && lockwidth == 800
                            && lockheight == 480) {
                        Utils.screenWidth = 480;
                        Utils.screenHeight = 854;
                    }
                } else {
                    Utils.Width = lockwidth;
                    Utils.screenWidth = lockwidth;
                    Utils.screenHeight = lockheight;
                    Utils.isWidth = false;
                    if (width == 720 && height == 1280 && lockwidth == 480
                            && lockheight == 800) {
                        Utils.screenWidth = 480;
                        Utils.screenHeight = 854;
                    }
                }
                mholder.unlockCanvasAndPost(canvas);
            } catch (Exception e) {
            }
            Utils.rateX = (float) Utils.Width / (float) Utils.FLA_Width;
            Utils.ratio = Utils.screenWidth / Utils.FLA_Width;
            Utils.Width = lockwidth;
            Utils.Height = lockheight;
        }
wickedone
  • 542
  • 1
  • 6
  • 18
jakie
  • 11
  • 1