2012-06-19 3 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); 
    } 
} 

}

을 그리고 내 바탕 화면을 회전 할 때, 나는 빈 화면을 볼하고있다. 누구든지 내 코드에 어떤 문제가 있는지 알고 있습니까? 내가 배경 화면을 실행하면

, 나는 로그 캣에서 이러한 오류를 얻을 :

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 

어떤 이상한 것은 내가 로그 캣에 힘 중지 메시지를 얻을 수 있다는 것입니다하지만 내 배경 화면을 설정 에뮬레이터.

+0

while (isVisible()) 및 holder.getSurface(). isValid())는 어떻게 평가됩니까? 보이는거야? 표면은 유효합니까? – Davos555

+0

예, 배경 화면을 실행할 때 화면이 녹색입니다. 화면을 회전시킬 때만 검은 색으로 변합니다. – Denizen

+0

화면을 회전 할 때이 두 가지 조건이 true로 평가됩니까? – Davos555

답변

2

drawFrame() - isVisible()이 true를 반환하는 한 메서드가 무한 루프에 멈추게됩니다. Handler로 Runnable을 얻었을 때 새로 그린 Canvas를 잠그고 게시 할 때 while 문을 반복 할 필요가 없습니다.

더 좋은 drawFrame() 구현은 SDK의 Cube Live Wallpaper 예제에서 찾을 수 있습니다.

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