Android - onPause и WidgetLocker - PullRequest
       19

Android - onPause и WidgetLocker

0 голосов
/ 17 января 2012

Я пишу базовое приложение для проверки поведения акселерометра.В настоящее время я регистрирую и отменяю регистрацию акселерометра следующим образом:

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

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

У меня есть методы паузы и возобновления, запускаемые Activity, поскольку акселерометр работает в дочернем классе.Когда я блокирую экран экрана, программа ломается.Я действительно должен закончить процесс, чтобы заставить программу работать снова.В настоящее время я использую 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);      
    }


}

Ответы [ 2 ]

2 голосов
/ 22 января 2012

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


Хорошо, я думаю, что нашел решение. Часть 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 голосов
/ 20 января 2012

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

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...