2012-01-17 5 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. Программа отлично работает со стоп-кадром. Мое предположение заключается в том, что резюме никогда не запускается.

Есть ли способ убедиться, что датчик будет повторно зарегистрирован? Я не хочу, чтобы моя программа прерывалась, если они используют что-либо за пределами обычного lockscreen.

EDIT: полный источник. Основная логика относительно этого вопроса происходит в нижней части 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' и 'resume', или' onPause' и 'onResume'? – asaelr

+0

onPause и onResume. пауза и возобновление находятся в дочернем классе. Они выполняются методами onPause и onResume. Как я сказал выше, это отлично работает, когда я не использую WidgetLocker. Однако мне нужно запрограммировать любую ситуацию. –

+0

Можете ли вы выслать свой код операции? –

ответ

2

Я думаю, вы могли бы использовать действия ACTION_SCREEN_ON и ACTION_SCREEN_OFF Intent, и вам не нужно иметь дело с 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()


Ok, я думаю, я нашел решение. Часть thread.join в коде метода onSurfaceDestroyed так или иначе блокирует действие. Я сделал несколько изменений в коде, и это работает для меня:

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

Я обязательно попробую это, но в конечном итоге это не решит проблему. Если кто-то переключит приложения, мое приложение будет продолжать истощать батарею. Единственный способ решить эту проблему - всегда закрывать экран из моего приложения и разблокировать экран, чтобы вернуться к нему прямо. –

+0

Я отлаживаю ваш код: я думаю, проблема с батареей из-за потока. Я думаю, вы должны сделать паузу.Еще один пример, когда я отлаживаю ваш код, onResume не срабатывает для меня. – tungi52

+0

OnResume не стрельба - это вся проблема, о которой я прошу. –

0

I подумайте, если вы используете onCreate() для регистрации и onDestroy(), чтобы отменить регистрацию, наша проблема. Becoz ваш onDestory не будет вызван, пока ваш экран заблокирован, и это может решить вашу проблему.

+0

Мне нужно отменить регистрацию акселерометра, когда экран заблокирован. В противном случае батарея будет разряжаться очень быстро. –

Смежные вопросы