LG G4 在基于月球着陆器的 Android 游戏开始时崩溃

LG G4 crashes on start of Lunar Lander-based Android game

我根据 Google 的月球着陆器示例编写了一个 Android 游戏(使用 Android Canvas 进行 2D 绘图)。自 2009 年以来,该游戏在所有 Android 设备上运行良好,除了用户最近报告说它无法在 LG G4 上启动。有时 G4 会完全死机,因此用户必须取出电池才能重新启动。

我用LG的Developer程序借了一台LG G4,重现了问题。基本上,应用程序会停止而不会抛出任何异常。通常它最终会给出 "application not responding" 错误。我还观察到操作系统偶尔会完全崩溃,而且很少会成功启动游戏。

我找到了似乎可以解决问题的解决方法,所以我在下面回答我自己的问题,以防其他人 运行 参与其中。 (虽然真正的解决方案是让 LG 不在 Android OS 中引入错误。)

我通过添加日志语句来执行 "binary search" 以找到程序冻结的行。我发现冻结发生在初始启动时,当渲染线程试图获取 canvas 上的锁时。

如果我在渲染线程尝试获取锁之前立即插入 thread.sleep(),问题就会消失。我完全是偶然发现的:我在那里插入了一条日志语句,而日志语句本身造成的延迟足以让游戏开始运行!这是我的(简化的)代码结构和修复:

public class theview extends SurfaceView implements SurfaceHolder.Callback {
    private final SurfaceHolder mSurfaceHolder;
    public theview(Context context, AttributeSet attrs) {
        super(context, attrs);
        mSurfaceHolder = getHolder();
        //(other game-initialization code omitted)
        thread = new LunarThread();

    public void surfaceCreated(SurfaceHolder holder) {
        //(other game-resuming code omitted)
        mRun=True;
        thread.start();
    }

    class LunarThread extends Thread {
        @Override
        public void run() {
            Canvas c=null;
            while (mRun) {
                try {
                    LunarThread.sleep(0, 1); // <---the LG G4 needs this line or the game doesn't load! Sleep duration didn't matter.
                }catch(InterruptedException ignored){}

                if(c==null){
                    LunarThread.yield();//app is still loading; wait for it.
                }
                try {
                    c = mSurfaceHolder.lockCanvas(null); // <---- this is the line where the LG G4 freezes without the above sleep()
                    if (c != null) {
                        synchronized (mSurfaceHolder) {
                            if (mMode == STATE_RUNNING) doPhysics();
                            doDraw(c);
                        }
                    }
                }
                finally {
                    // do this in a finally so that if an exception is thrown
                    // during the above, we don't leave the Surface in an
                    // inconsistent state
                    if (c != null) {
                        mSurfaceHolder.unlockCanvasAndPost(c);
                    }
                }

}

1ns 延迟足够短,我刚刚为所有手机添加了它。

(不言而喻,但这显然只是对 LG G4 定制版 Android OS 中一个严重的潜在错误的缓解措施。客户报告说它没有发生在其他 LG 手机上。我将问题单独提交给 LG。)