簡體   English   中英

應用程序在Android 4.0上崩潰,但不是2.3 - 奇怪的異常

[英]App Crashes on Android 4.0, but not 2.3 — Strange Exception

我正在開發2.3版本的Android游戲,並開始在更多設備上進行測試,以便我可以發布它。

在一些,並非所有4.0設備上,我的游戲在最小化時崩潰。 你可以鎖定手機並將其解鎖,然后游戲恢復並暫停。 當您嘗試返回主屏幕時發生崩潰。

錯誤日志如下所示:

07-18 14:33:44.839 E/AndroidRuntime(15542)FATAL EXCEPTION: Thread-662
07-18 14:33:44.839 E/AndroidRuntime(15542)java.lang.NullPointerException
07-18 14:33:44.839 E/AndroidRuntime(15542)at com.petronicarts.stormthecastle.MainThread.run(MainThread.java:55)
07-18 14:33:44.846 W/IInputConnectionWrapper(15542)showStatusIcon on inactive InputConnection
07-18 14:33:45.081 I/ActivityManager(178)No longer want com.android.packageinstaller (pid 15351): hidden #16
07-18 14:33:45.143 W/InputDispatcher(178)channel '41bb4d28 com.android.packageinstaller/com.android.packageinstaller.InstallAppProgress (server)' ~ Consumer closed input channel or an error occurred.  events=0x8
07-18 14:33:45.143 E/InputDispatcher(178)channel '41bb4d28 com.android.packageinstaller/com.android.packageinstaller.InstallAppProgress (server)' ~ Channel is unrecoverably broken and will be disposed!
07-18 14:33:45.190 W/InputDispatcher(178)Attempted to unregister already unregistered input channel '41bb4d28 com.android.packageinstaller/com.android.packageinstaller.InstallAppProgress (server)'
07-18 14:33:45.190 I/WindowManager(178)WIN DEATH: Window{41bb4d28 com.android.packageinstaller/com.android.packageinstaller.InstallAppProgress paused=false}
07-18 14:33:45.198 I/WindowManager(178)WINDOW DIED Window{41bb4d28 com.android.packageinstaller/com.android.packageinstaller.InstallAppProgress paused=false}
07-18 14:33:47.268 D/dalvikvm(178)GC_EXPLICIT freed 338K, 20% free 22816K/28487K, paused 6ms+5ms
07-18 14:34:15.464 I/power   (178)*** set_screen_state 0
07-18 14:34:15.471 D/SurfaceFlinger(115)About to give-up screen, flinger = 0x1822918
07-18 14:34:15.596 D/NfcService(403)NFC-C OFF, disconnect

我相信重要的是這個:

com.petronicarts.stormthecastle.MainThread.run(MainThread.java:55)

看第55行,就是這樣:

canvas.setMatrix(matrix);

在我的運行線程中:

    @Override
public void run() 
{
    boolean ScaleGame = true;
    //boolean SkipFrame = false;
    Bitmap screen = Bitmap.createBitmap(960, 540, Config.RGB_565);
    Canvas canvas;
    Canvas canvas2 = new Canvas(screen);
    Paint paint = new Paint();
    Matrix matrix = new Matrix();
    matrix.preScale(gamePanel.getScaleX(), gamePanel.getScaleY());
    if (gamePanel.getScaleX() == 1 && gamePanel.getScaleY() == 1)
        ScaleGame = false;
    long startTime, elapsedTime;
    startTime = System.currentTimeMillis();
    elapsedTime = System.currentTimeMillis() - startTime;

    this.gamePanel.setScreenBitmap(screen);

    while (running) {
        if(!pleaseWait) {
            canvas = null;
            // try locking the canvas for exclusive pixel editing on the surface
            try {
                canvas = this.surfaceHolder.lockCanvas();
                if (ScaleGame)
                    canvas.setMatrix(matrix);
                synchronized (surfaceHolder) {
                    startTime = System.currentTimeMillis();
                    this.gamePanel.update((float)elapsedTime);

                    canvas.drawBitmap(screen, 0, 0, paint);
                    elapsedTime = System.currentTimeMillis() - startTime;

                }
            } finally {
                if (canvas != null) {
                    surfaceHolder.unlockCanvasAndPost(canvas);
                }
            }            
        }
        else {
            synchronized (this) {
                try {
                    wait();
                } catch (Exception e) { }
            }
        }
    }
}

我不知道為什么我無法設置矩陣。 似乎代碼應該工作得很好。 我認為這意味着我正在以一種僅適用於2.3的方式處理某些事情。

我的暫停,恢復和銷毀事件如下所示:

public void pause() {
    justPause = true;
    pauseGame = true;


    SharedPreferences fileStore = this.getContext().getSharedPreferences("userData", 0);
    SharedPreferences.Editor editor = fileStore.edit();
    editor.putInt("highscore", highscore);
    editor.commit();

    AudioService.StopMusic();

}

public void resume(Context context) {
    if (gameState == 1)
        AudioService.StartMusic();
    //gold += 1000;
}

public void destroy() {
    thread.setRunning(false);


    if (thread != null)
    {
        Thread killThread = thread;
        thread = null;
        killThread.interrupt();
    }   
}

如果您有任何想法,他們將非常歡迎。 謝謝。

我看到的一個問題是在調用“canvas = this.surfaceHolder.lockCanvas();”之后。 你只在finally塊中檢查null。 我會把它改成這樣:

if(!pleaseWait) {
    canvas = this.surfaceHolder.lockCanvas();

    if (canvas != null) {
        // try locking the canvas for exclusive pixel editing on the surface
        try {
            if (ScaleGame)
                canvas.setMatrix(matrix);
            synchronized (surfaceHolder) {
                startTime = System.currentTimeMillis();
                this.gamePanel.update((float)elapsedTime);
                canvas.drawBitmap(screen, 0, 0, paint);
                elapsedTime = System.currentTimeMillis() - startTime;
        }
        finally {
            surfaceHolder.unlockCanvasAndPost(canvas);
        }            
    }
}

如果未設置畫布矩陣(當ScaleGame為false時),我還會詢問是否應該運行synchronized塊。 我對問題或Canvas沒有足夠的洞察力來回答這個問題。 如果答案為否,那么synchronized塊應該包含在if語句中。

您永遠不應該對UI線程進行鎖定,因為它可以阻止UI線程並阻止用戶與您的應用程序平滑地交互。 lockCanvas的文檔建議與單獨的繪圖線程同步:

如果未返回null,則lockCanvas()內部持有鎖,直到相應的unlockCanvasAndPost(Canvas)調用,從而阻止SurfaceView在繪制時創建,銷毀或修改曲面。 這比直接訪問Surface更方便,因為您不需要在Callback.surfaceDestroyed與繪圖線程進行特殊同步。

Android 3.0+引入了StrictMode檢查以確保開發人員不會濫用UI線程,因此您的應用程序在Android 2.3上運行並且在Android 4.0上運行並不奇怪。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM