Android SurfaceView вылетает при переходе на задний план - PullRequest
4 голосов
/ 21 октября 2011

мое приложение зависает, когда вид поверхности переходит в фоновый режим после получения вызова или выхода и возврата в приложение.Я читал, что Surfacedestroyed не получает вызова в этих ситуациях, но решения, которые были даны, не сработали для меня.Я буду благодарен, если кто-то может помочь мне с моим кодом.спасибо

public GameLoopThread(GameView view)
{

this.view=view;
}
public void setRunning (boolean run)
{
    running=run;
}
@Override
public void run() {

    long ticksPerSecond=1000/FPS;
    long startTime;
    long sleepTime;
    while (running)
    {
        Canvas c=null;
        startTime=System.currentTimeMillis();
        try {
        c=view.getHolder().lockCanvas();
        synchronized (view.getHolder()) {
            view.onDraw(c);
        }

        } catch (Exception e) {
            // TODO: handle exception
        }
        finally{
            if(c!=null)
            view.getHolder().unlockCanvasAndPost(c);
        }
        sleepTime=ticksPerSecond-(System.currentTimeMillis()-startTime);
        try
        {if(sleepTime>0)
            sleep(sleepTime);
        else
            sleep(10);

        }
        catch(Exception e){}

        synchronized (mPauseLock) {
            while (!running) {
                try {
                    mPauseLock.wait();
                } catch (InterruptedException e) {
                }
            }
        }
    }

and in the surfaceview:
 public void surfaceDestroyed(SurfaceHolder holder) {
 if(gameLoopThread.isAlive())
            {
                boolean retry = true;
                gameLoopThread.setRunning(false);
                while (retry) {
                    try {
                        gameLoopThread.join();
                        retry = false;
                    } catch (InterruptedException e) {
                    }
                }
            }
            }

            @Override
            public void surfaceCreated(SurfaceHolder holder) {
                if(!gameLoopThread.isAlive())
                    {           

                     gameLoopThread.setRunning(true);
                     gameLoopThread.start();

                    }
            }

возможно, logcat поможет:

10-22 09: 35: 06.310: ОТЛАДКА / Друзья ---------------------------> (10985): служба: OnReceive ACTION_HOME_RESUME вызывается 10-22 09: 35: 06.315: DEBUG / AndroidRuntime (3275): выключение виртуальной машины 10-22 09: 35: 06.315: WARN / dalvikvm (3275): threadid = 1: поток выходит с необработанным исключением (группа = 0x4001e578) 10-22 09: 35: 06.315: ERROR / AndroidRuntime (3275): ИСКЛЮЧИТЕЛЬНОЕ ИСКЛЮЧЕНИЕ: главное 10-22 09: 35: 06.315: ОШИБКА / AndroidRuntime (3275): java.lang.NullPointerException 10-22 09: 35: 06.315: ОШИБКА / AndroidRuntime (3275): в tomer.idunku3.GameView $ 1.surfaceDestroyed (GameView.java:126) 10-22 09: 35: 06.315: ОШИБКА / AndroidRuntime (3275): на android.view.SurfaceView.reportSurfaceDestroyed (SurfaceView.java:613) 10-22 09: 35: 06.315: ОШИБКА / AndroidRuntime (3275): на android.view.SurfaceView.updateWindow (SurfaceView.java:498) 10-22 09: 35: 06.315: ОШИБКА / AndroidRuntime (3275): в android.view.SurfaceView.updateWindow (SurfaceView.java:407) 10-22 09: 35: 06.315: ОШИБКА/AndroidRuntime (3275): в android.view.SurfaceView.onWindowVisibilityChanged (SurfaceView.java:217) 10-22 09: 35: 06.315: ОШИБКА / AndroidRuntime (3275): в android.view.View.dispatchWindowVisibilityChanged (View.java:4080)) 10-22 09: 35: 06.315: ОШИБКА / AndroidRuntime (3275): в android.view.ViewGroup.dispatchWindowVisibilityChanged (ViewGroup.java:720) 10-22 09: 35: 06.315: ОШИБКА / AndroidRuntime (3275): в Android.view.ViewGroup.dispatchWindowVisibilityChanged (ViewGroup.java:720) 10-22 09: 35: 06.315: ОШИБКА / AndroidRuntime (3275): в android.view.ViewRoot.performTraversals (ViewRoot.java:790) 10-22 09:35: 06.315: ОШИБКА / AndroidRuntime (3275): в android.view.ViewRoot.handleMessage (ViewRoot.java:1868) 10-22 09: 35: 06.315: ОШИБКА / AndroidRuntime (3275): в android.os.Handler.dispatchMessage (Handler.java:99) 10-22 09: 35: 06.315: ОШИБКА / AndroidRuntime (3275): на android.os.Looper.loop (Looper.java:123) 10-22 09: 35: 06.315: ОШИБКА / AndroidRuntime (3275): на android.app.ActivityThread.main (ActivityThread.java:3691) 10-22 09: 35: 06.315: ОШИБКА / AndroidRuntime (3275): в java.lang.reflect.Method.invokeNative (собственный метод) 10-22 09: 35: 06.315: ОШИБКА / AndroidRuntime (3275): в java.lang.reflect.Method.invoke (Method.java:507) 10-22 09: 35: 06.315: ОШИБКА / AndroidRuntime (3275): на com.android.internal.os.ZygoteInit $ MethodAndArgsCaller.run (ZygoteInit.java:847) 10-22 09:35:06.315: ОШИБКА / AndroidRuntime (3275): в com.android.internal.os.ZygoteInit.main (ZygoteInit.java:605) 10-22 09: 35: 06.315: ОШИБКА / AndroidRuntime (3275): в dalvik.system.NativeStart.main (собственный метод) 10-22 09: 35: 06.320: ОШИБКА / (18080): состояние дампа> / data / log / dumpstate_app_error

Ответы [ 2 ]

3 голосов
/ 03 февраля 2012

Мое приложение случайно (довольно часто) зависало при возврате к предыдущей активности. Оказывается, что оператор try не работает должным образом, так как Canvas c может иметь значение null еще после метода getHolder ().

while (running) {
    Canvas c=null;
    startTime=System.currentTimeMillis();
    try {
        c=view.getHolder().lockCanvas();
        if(c!=null){ // <- this is the line of code I had to add to make it work
            synchronized (view.getHolder()) {
                view.onDraw(c);
            }
        }
    } catch (Exception e) {}
    finally{
        if(c!=null)
        view.getHolder().unlockCanvasAndPost(c);
    }
    //...
}
2 голосов
/ 21 октября 2011

Я не думаю, что эта часть необходима:

synchronized (mPauseLock) {
        while (!running) {
            try {
                mPauseLock.wait();
            } catch (InterruptedException e) {
            }
        }
    }

Если вы используете это, вам нужно будет уведомить, чтобы снять блокировку по ожиданию ();Но попробуйте использовать тот же код без синхронизированного (mPauseLock)

РЕДАКТИРОВАТЬ:

Решение вашей проблемы, когда вы нажимаете на кнопку Home, приложение вылетает, сделайте это:*

@Override
protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    gameView = new GameView(this);
    setContentView(gameView); 
}

@Override
public void onPause(){
    super.onPause();
    gameView.gameLoopThread.setRunning(false);
    finish();
}

А в GameView (SurfaceView) создайте конструктор:

public GameLoopThread gameLoopThread;

public GameView(Context context) {
    super(context);
    gameLoopThread = new GameLoopThread(this);
}
...