2012-01-17 34 views
0

我在寫一個基本的應用程序來測試加速度計的行爲。目前我註冊和註銷的加速度計是這樣的:Android - onPause和WidgetLocker

public void pause() { 
    mSensorManager.unregisterListener(this); 
} 

public void resume(Context context) { 
    mSensorManager.registerListener(this, mAccelerometer,  
      SensorManager.SENSOR_DELAY_FASTEST);   
} 

我已經暫停,並繼續由活動引發的方法,如加速計在子類中運行。當我鎖定屏幕時,程序中斷。實際上我必須結束這個過程才能讓程序再次運行。我目前正在使用WidgetLocker。該程序適用於股票鎖定屏幕。我的假設是,簡歷永遠不會運行。

有沒有辦法確保傳感器將被重新註冊?如果他們正在使用正常鎖屏以外的任何內容,我不希望我的程序中斷。

編輯:完整的源添加。關於這一問題的主要邏輯發生在MainGamePanel.java底部

TiltBallActivity.java

package com.tornquist.nathan; 

import android.app.Activity; 
import android.content.pm.ActivityInfo; 
import android.os.Bundle; 
import android.view.Window; 
import android.view.WindowManager; 

public class TiltBallActivity extends Activity{ 
    /** Called when the activity is first created. */ 
    MainGamePanel viewPanel; 
    @Override 
    public void onCreate(Bundle savedInstanceState) { 
     super.onCreate(savedInstanceState); 

     //Window state functions. 
     requestWindowFeature(Window.FEATURE_NO_TITLE); 
     getWindow().setFlags(WindowManager.LayoutParams.FLAG_FULLSCREEN, WindowManager.LayoutParams.FLAG_FULLSCREEN); 
     setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_PORTRAIT); 

     //This works without declaring a viewPanel instance here. 
     //The instance declaration is needed to pass the 
     //onPause and onResume commands though. 
     viewPanel = new MainGamePanel(this); 
     setContentView(viewPanel); 
    } 

    //Restarts the accelerometer after onPause 
    protected void onResume() { 

     viewPanel.resume(this); 
     super.onResume(); 
    } 

    //Standard Method run when the Application loses focus. 
    //This runs the pause() function in the viewPanel so that 
    //the accelerometer can be paused. 
    protected void onPause() { 

     viewPanel.pause(); 
     super.onPause(); 
    } 
} 

MainThread.java

package com.tornquist.nathan; 

import com.tornquist.nathan.MainGamePanel; 
import android.graphics.Canvas; 
import android.view.SurfaceHolder; 

public class MainThread extends Thread { 

    private SurfaceHolder surfaceHolder; 
    private MainGamePanel gamePanel; 
    private boolean running; 
    public void setRunning(boolean running) { 
     this.running = running; 
    } 

    public MainThread(SurfaceHolder surfaceHolder, MainGamePanel gamePanel) { 
     super(); 
     this.surfaceHolder = surfaceHolder; 
     this.gamePanel = gamePanel; 
    } 

    @Override 
    public void run() 
    { 
     Canvas canvas; 
     while (running) { 
      canvas = null; 
      // try locking the canvas for exclusive pixel editing on the surface 
      try { 
       canvas = this.surfaceHolder.lockCanvas(); 
       synchronized (surfaceHolder) { 
        // update game state 
        this.gamePanel.update(); 

        // draws the canvas on the panel 
        this.gamePanel.onDraw(canvas); 
       } 
      } finally { 
       // in case of an exception the surface is not left in 
       // an inconsistent state 
       if (canvas != null) { 
        surfaceHolder.unlockCanvasAndPost(canvas); 
       } 
      } // end finally 
     } 
    } 
} 

MainGamePanel.java

package com.tornquist.nathan; 

import android.app.Activity; 
import android.content.Context; 
import android.graphics.Canvas; 
import android.graphics.Color; 
import android.graphics.Paint; 
import android.graphics.Paint.Style; 
import android.hardware.Sensor; 
import android.hardware.SensorEvent; 
import android.hardware.SensorEventListener; 
import android.hardware.SensorManager; 
import android.view.Display; 
import android.view.MotionEvent; 
import android.view.SurfaceHolder; 
import android.view.SurfaceView; 

public class MainGamePanel extends SurfaceView implements SensorEventListener, SurfaceHolder.Callback 
{ 
    //Variable Declarations. 
    private MainThread thread; 
    public int xColor; 
    public int yColor; 
    public int zColor; 

    public float xPos; 
    public float yPos; 
    public float oldXPos; 
    public float oldYPos; 

    public int screenWidth; 
    public int screenHeight; 

    private SensorManager mSensorManager; 
    private Sensor mAccelerometer;  

    Paint paint; 

    public MainGamePanel(Context context) 
    { 
     //Standard Initialization 
     super(context); 

     //This line adds a callback for the touch screen. 
     //This allows you to actually capture touch input. 
     getHolder().addCallback(this); 

     thread = new MainThread(getHolder(),this); 

     xColor = 100; 
     yColor = 100; 
     zColor = 100; 

     paint = new Paint(); 
     paint.setAntiAlias(true); 

     Display display = ((Activity) context).getWindowManager().getDefaultDisplay(); 
     screenWidth = display.getWidth(); 
     screenHeight = display.getHeight(); 

     yPos = screenHeight/2; 
     xPos = screenWidth/2; 
     oldYPos = yPos; 
     oldXPos = xPos; 

     //This registers the accelerometer. Without registering it, the onSensorChanged 
     //event will never be called, and you cannot get the accelerometer values. 
     mSensorManager = (SensorManager) context.getSystemService(Context.SENSOR_SERVICE); 

     mAccelerometer = mSensorManager.getDefaultSensor(Sensor.TYPE_ACCELEROMETER); 

     mSensorManager.registerListener(this, mAccelerometer, SensorManager.SENSOR_DELAY_FASTEST); 

     //Also required for touch input. 
     setFocusable(true); 
    } 

    @Override 
    public void surfaceChanged(SurfaceHolder holder, int format, int width, 
      int height) { 
    } 

    @Override 
    public void surfaceCreated(SurfaceHolder holder) { 
     // at this point the surface is created and 
     // we can safely start the game loop 
     thread.setRunning(true); 
     thread.start(); 
    } 

    @Override 
    public void surfaceDestroyed(SurfaceHolder holder) { 
     boolean retry = true; 
     while (retry) { 
      try { 
       thread.join(); 
       retry = false; 
      } catch (InterruptedException e) { 
       // try again shutting down the thread 
      } 
     } 
    } 

    @Override 
    public boolean onTouchEvent(MotionEvent event) { 
     if (event.getAction() == MotionEvent.ACTION_DOWN) { 
         // check if in the lower part of the screen we exit 
      if (event.getY() > getHeight() - 50) { 
       thread.setRunning(false); 
       ((Activity)getContext()).finish(); 
      } 

      if (xColor < 235) 
       xColor = xColor + 20; 
      else 
       xColor = 0; 
      if (yColor < 235) 
       yColor = yColor + 20; 
      else 
       yColor = 0; 
      if (zColor < 235) 
       zColor = zColor + 20; 
      else 
       zColor = 0; 

      yPos = event.getY(); 
      xPos = event.getX(); 
     } 
     return true; 
    } 

    @Override 
    protected void onDraw(Canvas canvas) 
    { 
     //canvas.drawColor(Color.CYAN); 
     canvas.drawColor(Color.rgb(xColor, yColor, zColor)); 
     int xInvert = (int) (255 - xColor); 
     int yInvert = (int) (255 - yColor); 
     int zInvert = (int) (255 - zColor); 

     paint.setColor(Color.rgb(xInvert, yInvert, zInvert)); 
     paint.setStyle(Style.FILL); 
     canvas.drawCircle(xPos, yPos, 50, paint); 
    } 

    public void update() { 
    } 

    @Override 
    public void onAccuracyChanged(Sensor sensor, int accuracy) {   
    } 

    @Override 
    public void onSensorChanged(SensorEvent event) { 

     oldYPos = yPos; 
     oldXPos = xPos; 

     xColor = (int) (255 + (event.values[0])*11); 
     if (xColor > 255) 
      xColor = 255; 
     if (xColor < 0) 
      xColor = 0; 

     yColor = (int) (255 + (event.values[1])*11); 
     if (yColor > 255) 
      yColor = 255; 
     if (yColor < 0) 
      yColor = 0; 

     zColor = (int) (255 + (event.values[2])*11); 
     if (zColor > 255) 
      zColor = 255; 
     if (zColor < 0) 
      zColor = 0; 

     xPos = xPos + -1*(event.values[0])*5; 
     yPos = yPos + event.values[1]*5; 

     if (xPos < 50) 
      xPos = 50; 
     if (xPos > screenWidth - 50) 
      xPos = screenWidth - 50; 
     if (yPos < 50) 
      yPos = 50; 
     if (yPos > screenHeight - 50) 
      yPos = screenHeight - 50; 

     if ((oldYPos == yPos) && (oldXPos == xPos)) 
     { 
      invalidate(); 
     } 

    } 

    public void pause() { 
     mSensorManager.unregisterListener(this); 

     //thread.setRunning(false); 
     //((Activity)getContext()).finish(); 
    } 

    public void resume(Context context) { 
     //mSensorManager = (SensorManager) context.getSystemService(Context.SENSOR_SERVICE); 

     //mAccelerometer = mSensorManager.getDefaultSensor(Sensor.TYPE_ACCELEROMETER); 

     mSensorManager.registerListener(this, mAccelerometer, SensorManager.SENSOR_DELAY_FASTEST);  
    } 


} 
+0

你使用'pause'和'簡歷',或'onPause'和'onResume'? – asaelr 2012-01-17 00:47:17

+0

onPause和onResume。暫停和恢復在一個孩子班。它們由onPause和onResume方法執行。正如我上面所說的,當我不使用WidgetLocker時,這完美地工作。我需要爲任何情況編程。 – 2012-01-17 00:50:46

+0

你可以發佈你的活動代碼嗎? – 2012-01-19 17:14:19

回答

2

我認爲你可以使用ACTION_SCREEN_ON和ACTION_SCREEN_OFF意圖行動,你不必處理onPause和onResume事情。因此,像這樣:

mReceiver = new BroadcastReceiver() { 
    public void onReceive(Context context, Intent intent) { 
    String action = intent.getAction(); 
    if (Intent.ACTION_SCREEN_OFF.equals(action)) { 
     //deregister 
    } 
    else if (Intent.ACTION_SCREEN_ON.equals(action)) { 
     //register 
    } 
}}; 

IntentFilter filter = new IntentFilter(Intent.ACTION_SCREEN_ON); 
registerReceiver(mReceiver, filter); 

filter = new IntentFilter(Intent.ACTION_SCREEN_OFF); 
registerReceiver(mReceiver, filter); 

,並註銷該接收器中的onDestroy()方法


好吧,我想我找到了解決辦法。 onSurfaceDestroyed方法代碼中的thread.join部分以某種方式阻止活動。我對你的代碼做了一些修改,這對我的作品:

public MainGamePanel(Context context) 
{ 
    ... 

    //Also required for touch input. 
    setFocusable(true); 

    //start thread 
    thread.setRunning(true); 
    thread.start(); 
} 

@Override 
public void surfaceChanged(SurfaceHolder holder, int format, int width, 
     int height) { 
} 

@Override 
public void surfaceCreated(SurfaceHolder holder) { 
    //continue the thread 
    synchronized (thread) { 
     thread.pleaseWait = false; 
     thread.notifyAll(); 
    } 
} 

@Override 
public void surfaceDestroyed(SurfaceHolder holder) { 
    //pause the thread 
    synchronized (thread) { 
     thread.pleaseWait = true; 
    } 
} 

和線程類

public class MainThread extends Thread { 

private SurfaceHolder surfaceHolder; 
private MainGamePanel gamePanel; 
private boolean running; 
public boolean pleaseWait = true; 
public void setRunning(boolean running) { 
    this.running = running; 
} 

public MainThread(SurfaceHolder surfaceHolder, MainGamePanel gamePanel) { 
    super(); 
    this.surfaceHolder = surfaceHolder; 
    this.gamePanel = gamePanel; 
} 

@Override 
public void run() 
{ 
    Canvas canvas; 
    while (running) { 
     if(!pleaseWait) { 
      canvas = null; 
      // try locking the canvas for exclusive pixel editing on the surface 
      try { 
       canvas = this.surfaceHolder.lockCanvas(); 
       synchronized (surfaceHolder) { 
        // update game state 
        this.gamePanel.update(); 

        // draws the canvas on the panel 
        this.gamePanel.onDraw(canvas); 
       } 
      } finally { 
       // in case of an exception the surface is not left in 
       // an inconsistent state 
       if (canvas != null) { 
        surfaceHolder.unlockCanvasAndPost(canvas); 
       } 
      } // end finally    
     } 
     else { 
      synchronized (this) { 
       try { 
        wait(); 
       } catch (Exception e) { } 
      } 
     } 
    } 
} 
} 

並摧毀線程中的onDestroy方法

+0

我肯定會嘗試,但最終並不能解決問題。如果有人切換應用程序,我的應用程序將繼續消耗電池。這將解決問題的唯一方法是,如果他們總是鎖定屏幕從我的應用程序,並解鎖屏幕直接返回到它。 – 2012-01-22 05:12:35

+0

我調試你的代碼:我認爲電池耗盡問題是因爲線程。我認爲你應該暫停。還有一個想法是,當我調試你的代碼時,onResume不會爲我開火。 – tungi52 2012-01-22 11:01:36

+0

onResume不開火是我所問的全部問題。 – 2012-01-22 13:31:24

0

我想想,如果你使用onCreate()來註冊並且使用onDestroy()來取消註冊,那麼這個問題就解決了我們的問題。 Becoz onDestory在屏幕鎖定時不會被調用,這可能會解決您的問題。

+0

當屏幕鎖定時,我需要取消註冊加速度計。否則電池會很快耗盡。 – 2012-01-20 16:23:58