当进入后台时,Android SurfaceView 崩溃。

4

当SurfaceView被接收到电话或退出并返回应用程序时,我的应用程序崩溃。我读到了surfacdestroyed在这些情况下不会被调用,但是给出的解决方案对我无效。

如果有人能帮我解决代码问题,我将不胜感激。

谢谢。

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: DEBUG/Buddies--------------------------->(10985): Service:OnReceive ACTION_HOME_RESUME called 10-22 09:35:06.315: DEBUG/AndroidRuntime(3275): 关闭VM虚拟机 10-22 09:35:06.315: WARN/dalvikvm(3275): 线程id=1: 线程退出时出现未捕获的异常 (group=0x4001e578) 10-22 09:35:06.315: ERROR/AndroidRuntime(3275): 致命错误:java.lang.NullPointerException 10-22 09:35:06.315: ERROR/AndroidRuntime(3275): at tomer.idunku3.GameView$1.surfaceDestroyed(GameView.java:126) 10-22 09:35:06.315: ERROR/AndroidRuntime(3275): at android.view.SurfaceView.reportSurfaceDestroyed(SurfaceView.java:613) 10-22 09:35:06.315: ERROR/AndroidRuntime(3275): at android.view.SurfaceView.updateWindow(SurfaceView.java:498) 10-22 09:35:06.315: ERROR/AndroidRuntime(3275): at android.view.SurfaceView.updateWindow(SurfaceView.java:407) 10-22 09:35:06.315: ERROR/AndroidRuntime(3275): at android.view.SurfaceView.onWindowVisibilityChanged(SurfaceView.java:217) 10-22 09:35:06.315: ERROR/AndroidRuntime(3275): at android.view.View.dispatchWindowVisibilityChanged(View.java:4080) 10-22 09:35:06.315: ERROR/AndroidRuntime(3275): at android.view.ViewGroup.dispatchWindowVisibilityChanged(ViewGroup.java:720) 10-22 09:35:06.315: ERROR/AndroidRuntime(3275): at android.view.ViewGroup.dispatchWindowVisibilityChanged(ViewGroup.java:720) 10-22 09:35:06.315: ERROR/AndroidRuntime(3275): at android.view.ViewRoot.performTraversals(ViewRoot.java:790) 10-22 09:35:06.315: ERROR/AndroidRuntime(3275): at android.view.ViewRoot.handleMessage(ViewRoot.java:1868) 10-22 09:35:06.315: ERROR/AndroidRuntime(3275): at android.os.Handler.dispatchMessage(Handler.java:99) 10-22 09:35:06.315: ERROR/AndroidRuntime(3275): at android.os.Looper.loop(Looper.java:123) 10-22 09:35:06.315: ERROR/AndroidRuntime(3275): at android.app.ActivityThread.main(ActivityThread.java:3691) 10-22 09:35:06.315: ERROR/AndroidRuntime(3275): at java.lang.reflect.Method.invokeNative(Native Method) 10-22 09:35:06.315: ERROR/AndroidRuntime(3275): at java.lang.reflect.Method.invoke(Method.java:507) 10-22 09:35:06.315: ERROR/AndroidRuntime(3275): at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:847) 10-22 09:35:06.315: ERROR/AndroidRuntime(3275): at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:605) 10-22 09:35:06.315: ERROR/AndroidRuntime(3275): at dalvik.system.NativeStart.main(Native Method) 10-22 09:35:06.320: ERROR/(18080): Dumpstate > /data/log/dumpstate_app_error

谢谢,但不用了。现在当我按下主页按钮几秒钟后,我的应用程序会崩溃。还有其他的想法吗? - goote
当你按下主页按钮时,你想销毁SurfaceView吗?这是你在问什么? - Carnal
不,我希望游戏能够在后台继续运行,并且可以像其他应用程序一样返回到它。 - goote
2个回答

3

当返回到之前的活动时,我的应用程序经常(随机地)崩溃。 原来"try"语句没有像预期的那样工作,因为Canvas c仍然可能为空,即使在使用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);
    }
    //...
}

我有一个可用的游戏,但在重构后,我在恢复它时遇到了问题。我可以在运行顶部活动后恢复surfaceview,或者在按下HOME后正确地工作并从主屏幕恢复。由于您建议检查c是否为null,因此按下HOME后崩溃部分得到了修复。所以,谢谢! - MacD

2
我认为这部分并不必要:
synchronized (mPauseLock) {
        while (!running) {
            try {
                mPauseLock.wait();
            } catch (InterruptedException e) {
            }
        }
    }

如果您使用此代码,需要通知以释放wait()上的锁定; 但是,尝试在不使用synchronized(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);
}

谢谢你的帮助。我现在看到了你的编辑。这样结束应用程序不会崩溃,但游戏状态没有保存。有什么想法吗? - goote
看一下这个:https://dev59.com/MnVC5IYBdhLWcg3w51hv - Carnal

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接