2012-06-19 115 views
0

我最近在我的動態壁紙中發佈了一個關於屏幕旋轉的問題。爲了測試我爲什麼有這些問題,我創建了下面的簡單程序:RE:動態壁紙屏幕旋轉

package com.live.waller; 

import android.graphics.Canvas; 
import android.graphics.Color; 
import android.os.Handler; 
import android.service.wallpaper.WallpaperService; 
import android.view.MotionEvent; 
import android.view.SurfaceHolder; 

public class LiveWallpaperService extends WallpaperService { 


/** Called when the activity is first created. */ 

@Override 
public Engine onCreateEngine() { 
    // TODO Auto-generated method stub 
    return new LiveWallerEngine(); 
} 


class LiveWallerEngine extends Engine { 

    SurfaceHolder holder; 
    private Handler mHandle; 

    LiveWallerEngine() { 
     mHandle = new Handler(); 
     holder = getSurfaceHolder(); 
    } 


    private Runnable runner = new Runnable() { 

     public void run() { 
      // TODO Auto-generated method stub 
      drawFrame(); 
     } 

    }; 

    public void drawFrame() { 
     while(isVisible()) { 
      if(!holder.getSurface().isValid()) 
       continue; 

      Canvas c = null; 

      try{ 
       c = holder.lockCanvas(); 

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

    public void drawSurface(Canvas c) { 


     c.save(); 

     c.drawColor(Color.argb(255, 100, 200, 124)); 

     c.restore(); 

    } 

    @Override 
    public void onCreate(SurfaceHolder surfaceHolder) { 
     // TODO Auto-generated method stub 
     super.onCreate(surfaceHolder); 

     setTouchEventsEnabled(true); 
     mHandle.post(runner); 

    } 

    @Override 
    public void onOffsetsChanged(float xOffset, float yOffset, 
      float xOffsetStep, float yOffsetStep, int xPixelOffset, 
      int yPixelOffset) { 
     // TODO Auto-generated method stub 
     super.onOffsetsChanged(xOffset, yOffset, xOffsetStep, yOffsetStep, 
       xPixelOffset, yPixelOffset); 
    } 

    @Override 
    public void onSurfaceChanged(SurfaceHolder holder, int format, 
      int width, int height) { 
     // TODO Auto-generated method stub 
     super.onSurfaceChanged(holder, format, width, height); 

     mHandle.post(runner); 
    } 

    @Override 
    public void onTouchEvent(MotionEvent event) { 
     // TODO Auto-generated method stub 
     super.onTouchEvent(event); 
    } 

    @Override 
    public void onVisibilityChanged(boolean visible) { 
     // TODO Auto-generated method stub 
     super.onVisibilityChanged(visible); 

    } 

    @Override 
    public void setTouchEventsEnabled(boolean enabled) { 
     // TODO Auto-generated method stub 
     super.setTouchEventsEnabled(enabled); 
    } 
} 

}

當我旋轉我的牆紙,我正與一個空白屏幕映入眼簾。有人知道我的代碼有什麼問題嗎?

當我運行了牆紙,我在logcat中得到這些錯誤:

ActivityManager: force stopping package com.live.waller uid=10046 
PackageManager: Not granting permission android.permission.BIND_WALLPAPER to package com.live.waller (protectionLevel=3 flags=0xbe46) 
dalvikvm: GC_CONCURRENT freed 609K, 43% free 4604K/8071K, external 904K/1222K, paused 6ms+7ms 
dalvikvm: GC_EXPLICIT freed 320K, 44% free 4561K/8071K, external 904K/1222K, paused 138ms 
dalvikvm: GC_EXTERNAL_ALLOC freed 197K, 51% free 2955K/6023K, external 1736K/1742K, paused 78ms 

什麼奇怪的是,我在logcat中得到了強行停止的消息,但不是當我把我的壁紙模擬器。

+0

您的while(isVisible())和holder.getSurface()。isValid())如何評估?它是否可見?並且表面有效? – Davos555

+0

是的,當我運行壁紙屏幕是綠色的。只有當我旋轉屏幕時它纔會變黑。 – Denizen

+0

當您旋轉屏幕時,這兩個條件是否爲真? – Davos555

回答

2

只要isVisible()返回true,drawFrame()方法就會卡在一個無限循環中。當您使用處理程序獲得Runnable時,無需使用while語句來循環鎖定和張貼新鮮繪製的Canvas。

可以在SDK的Cube Live Wallpaper示例中找到更好的drawFrame()實現。

private void drawFrame() { 
    Canvas c = null; 

    try { 
     // Get a Canvas from the surfaceHolder, so we got something to paint on 
     c = holder.lockCanvas(); 

     // Make sure we got a valid (non-null) canvas. 
     if(c != null) { 
      // Draw something onto the canvas 
      drawSurface(c); 
     } 
    } finally { 
     if(c != null) 
      // Notify the SurfaceHolder that we are done painting the canvas, 
      // and we want it shown on the screen 
      holder.unlockCanvasAndPost(c); 
    } 

    // If your wallpaper is going to have animated objects, you will have to tell 
    // the handler to schedule new runs on your Runnable object. 

    // First we remove any pending task in the Handlers message queue 
    mHandle.removeCallbacks(runner); 

    // Then we tell the Handler to schedule a new run some time in the future. The 
    // time we specify here will decide how often the screen updates, or in other words 
    // the FPS of your wallpaper. If the wallpaper is not visible, there is no reason to update wallpaper. So we only schedule a new run, if mIsVisible is true.  
    if(mIsVisible) { 
     mHandle.postDelayed(runner, 1000/desiredFPS); 
    } 
} 

現在,我們使用Engine.onVisibilityChanged()來決定壁紙是否可見。

@Override 
public void onVisibilityChanged(boolean visible) { 
    // Set mIsVisible equal to visible, so that drawFrame() can decide wheter to reschedule run or not. 
    mIsVisible = visible; 

    if (visible) { 
     // Since drawFrame() tells the handler to schedule new runs, we only need to call drawFrame() once. In drawFrame(), mHandle.postDelayed() will then continuously update the screen, as long as its visible. 
     drawFrame(); 
    } else { 
     // If not, remove any pending posts, since we no longer need to update the wallpaper. 
     mHandle.removeCallbacks(runner); 
    } 
} 

如果我們烤漆表面以某種方式被破壞(例:如果用戶設置了新的背景下),我們也希望消除任何未決的職務。因此,在Engine.onSurfaceDestroyed(),我們做

@Override 
public void onSurfaceDestroyed(SurfaceHolder holder) { 
    super.onSurfaceDestroyed(holder); 
    mHandle.removeCallbacks(runner); 
} 

關於力閉合問題: 什麼API級別的你去上運行壁紙?

+0

謝謝,屏幕旋轉現在工作正常! – Denizen

+0

至於力量關閉,我正在編譯到2.3.3模擬器。 – Denizen

+0

你確定你的AndroidManifest設置正確嗎?如果不是,發佈它將是有用的;) – Ole