Android应用程序关闭并重新打开时崩溃

问题描述:

我有一个非常简单的android应用程序,只显示一个空白的白屏。当我通过按HOME按钮关闭应用程序时,然后尝试再次打开应用程序,它崩溃,我得到“强制关闭”按钮。在Eclipse中,我收到了这个错误,“ActivityManager:警告:活动未启动,因为当前活动正在为用户保留。”。我如何解决这个崩溃?Android应用程序关闭并重新打开时崩溃

public class HelloAndroid extends Activity { 

@Override 
public void onCreate(Bundle savedInstanceState) { 
    super.onCreate(savedInstanceState); 
    requestWindowFeature(Window.FEATURE_NO_TITLE); 
    getWindow().setFlags( WindowManager.LayoutParams.FLAG_FULLSCREEN, 
          WindowManager.LayoutParams.FLAG_FULLSCREEN); 

    setContentView(new Panel(this)); 
} 

class Panel extends SurfaceView implements SurfaceHolder.Callback { 

    private TutorialThread _thread; 

    public Panel(Context context) { 
     super(context); 

     // register our interest in hearing about changes to our surface 
     SurfaceHolder holder = getHolder(); 
     holder.addCallback(this); 
     _thread = new TutorialThread(holder, this); 

     setFocusable(true); 
    } 

    @Override 
    public void onDraw(Canvas canvas) { 

     // Clear the background 
     canvas.drawColor(Color.WHITE); 
    } 

    @Override 
    public void surfaceChanged(SurfaceHolder holder, int format, int width, int height) { 
     // resize canvas here 
    } 

    @Override 
    public void surfaceCreated(SurfaceHolder holder) { 
     _thread.setRunning(true); 
     _thread.start(); 
    } 

    @Override 
    public void surfaceDestroyed(SurfaceHolder holder) { 
     // simply copied from sample application LunarLander: 
     // we have to tell thread to shut down & wait for it to finish, or else 
     // it might touch the Surface after we return and explode 
     boolean retry = true; 
     _thread.setRunning(false); 
     while (retry) { 
      try { 
       _thread.join(); 
       retry = false; 
      } catch (InterruptedException e) { 
       // we will try it again and again... 
      } 
     } 
    } 
} 

class TutorialThread extends Thread { 
    private SurfaceHolder _surfaceHolder; 
    private Panel _panel; 
    private boolean _run = false; 

    public TutorialThread(SurfaceHolder surfaceHolder, Panel panel) { 
     _surfaceHolder = surfaceHolder; 
     _panel = panel; 
    } 

    public void setRunning(boolean run) { 
     _run = run; 
    } 

    @Override 
    public void run() { 
     Canvas c; 
     while (_run) { 
      c = null; 
      try { 
       c = _surfaceHolder.lockCanvas(null); 
       synchronized (_surfaceHolder) { 
        _panel.onDraw(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) { 
        _surfaceHolder.unlockCanvasAndPost(c); 
       } 
      } 
     } 
    } 
} 

}

添加logcat的

03-15 15:36:05.579: INFO/AndroidRuntime(4441): NOTE: attach of thread 'Binder Thread #2' failed 
03-15 15:36:05.719: DEBUG/AndroidRuntime(4449): >>>>>>>>>>>>>> AndroidRuntime START <<<<<<<<<<<<<< 
03-15 15:36:05.719: DEBUG/AndroidRuntime(4449): CheckJNI is OFF 
03-15 15:36:05.719: DEBUG/dalvikvm(4449): creating instr width table 
03-15 15:36:05.759: DEBUG/AndroidRuntime(4449): --- registering native functions --- 
03-15 15:36:05.969: INFO/ActivityManager(1294): Starting activity: Intent { act=android.intent.action.MAIN cat=[android.intent.category.LAUNCHER] flg=0x10000000 cmp=com.example.helloandroid/.HelloAndroid } 
03-15 15:36:05.979: DEBUG/Launcher(1371): onPause+ 
03-15 15:36:05.979: DEBUG/Launcher.DragController(1371): +endDrag: false 
03-15 15:36:05.979: DEBUG/Launcher.DragController(1371): mDragging == false 
03-15 15:36:05.979: DEBUG/Launcher.DragController(1371): -endDrag: false 
03-15 15:36:05.979: DEBUG/Launcher(1371): onPause- 
03-15 15:36:05.999: DEBUG/AndroidRuntime(4428): Shutting down VM 
03-15 15:36:05.999: DEBUG/AndroidRuntime(4449): Shutting down VM 
03-15 15:36:05.999: WARN/dalvikvm(4428): threadid=1: thread exiting with uncaught exception (group=0x4001d7e0) 
03-15 15:36:06.009: DEBUG/dalvikvm(4449): Debugger has detached; object registry had 1 entries 
03-15 15:36:06.009: INFO/AndroidRuntime(4449): NOTE: attach of thread 'Binder Thread #3' failed 
03-15 15:36:06.029: ERROR/AndroidRuntime(4428): FATAL EXCEPTION: main 
03-15 15:36:06.029: ERROR/AndroidRuntime(4428): java.lang.IllegalThreadStateException: Thread already started. 
03-15 15:36:06.029: ERROR/AndroidRuntime(4428):  at java.lang.Thread.start(Thread.java:1322) 
03-15 15:36:06.029: ERROR/AndroidRuntime(4428):  at com.example.helloandroid.HelloAndroid$Panel.surfaceCreated(HelloAndroid.java:55) 
03-15 15:36:06.029: ERROR/AndroidRuntime(4428):  at android.view.SurfaceView.updateWindow(SurfaceView.java:538) 
03-15 15:36:06.029: ERROR/AndroidRuntime(4428):  at android.view.SurfaceView.onWindowVisibilityChanged(SurfaceView.java:206) 
03-15 15:36:06.029: ERROR/AndroidRuntime(4428):  at android.view.View.dispatchWindowVisibilityChanged(View.java:3888) 
03-15 15:36:06.029: ERROR/AndroidRuntime(4428):  at android.view.ViewGroup.dispatchWindowVisibilityChanged(ViewGroup.java:725) 
03-15 15:36:06.029: ERROR/AndroidRuntime(4428):  at android.view.ViewGroup.dispatchWindowVisibilityChanged(ViewGroup.java:725) 
03-15 15:36:06.029: ERROR/AndroidRuntime(4428):  at android.view.ViewRoot.performTraversals(ViewRoot.java:748) 
03-15 15:36:06.029: ERROR/AndroidRuntime(4428):  at android.view.ViewRoot.handleMessage(ViewRoot.java:1737) 
03-15 15:36:06.029: ERROR/AndroidRuntime(4428):  at android.os.Handler.dispatchMessage(Handler.java:99) 
03-15 15:36:06.029: ERROR/AndroidRuntime(4428):  at android.os.Looper.loop(Looper.java:123) 
03-15 15:36:06.029: ERROR/AndroidRuntime(4428):  at android.app.ActivityThread.main(ActivityThread.java:4627) 
03-15 15:36:06.029: ERROR/AndroidRuntime(4428):  at java.lang.reflect.Method.invokeNative(Native Method) 
03-15 15:36:06.029: ERROR/AndroidRuntime(4428):  at java.lang.reflect.Method.invoke(Method.java:521) 
03-15 15:36:06.029: ERROR/AndroidRuntime(4428):  at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:868) 
03-15 15:36:06.029: ERROR/AndroidRuntime(4428):  at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:626) 
03-15 15:36:06.029: ERROR/AndroidRuntime(4428):  at dalvik.system.NativeStart.main(Native Method) 
03-15 15:36:06.039: WARN/ActivityManager(1294): Force finishing activity com.example.helloandroid/.HelloAndroid 
03-15 15:36:06.541: WARN/ActivityManager(1294): Activity pause timeout for HistoryRecord{450300c0 com.example.helloandroid/.HelloAndroid} 
03-15 15:36:06.549: DEBUG/Launcher(1371): onResume+ 
03-15 15:36:06.549: DEBUG/Launcher.DragController(1371): +endDrag: false 
03-15 15:36:06.549: DEBUG/Launcher.DragController(1371): mDragging == false 
03-15 15:36:06.549: DEBUG/Launcher.DragController(1371): -endDrag: false 
03-15 15:36:06.549: DEBUG/Launcher(1371): onResume- 
03-15 15:36:08.645: ERROR/KINETO(1370): KLOG0C3- xmk_QueryOSQueue SDL Queue empty : WAIT_FOREVER 
+1

请寄出logcat。 – EboMike 2011-03-15 22:31:11

+0

是的,错误是由你的'Thread'引起的。请看下面的答案。 – Wroclai 2011-03-15 22:46:27

+1

LunarLander和JetBoy在经过HOME之后都会崩溃并重新启动! – Lumis 2011-03-15 23:01:52

我已经回答了这样here的问题。

您遇到的错误可能是由您的Thread引起的(没有看到完整的Logcat,但很难说)。您每次启动表面已创建,这会使您的应用程序崩溃,因为您无法两次调用Thread.start()。看看我上面的链接,以更深入地描述问题以及如何解决问题。

因为我的解释是不够的,我将发布整个解决方案:

内,您的Runnable/Thread

private Object mPauseLock = new Object(); 
private boolean mPaused; 

// Constructor stuff.  

// This should be after your drawing/update code inside your thread's run() code. 
synchronized (mPauseLock) { 
    while (mPaused) { 
     try { 
      mPauseLock.wait(); 
     } catch (InterruptedException e) { 
     } 
    } 
} 

// Two methods for your Runnable/Thread class to manage the thread properly. 
public void onPause() { 
    synchronized (mPauseLock) { 
     mPaused = true; 
    } 
} 

public void onResume() { 
    synchronized (mPauseLock) { 
     mPaused = false; 
     mPauseLock.notifyAll(); 
    } 
} 

在你SurfaceView类:

private boolean mGameIsRunning; 

@Override 
public void surfaceCreated(SurfaceHolder holder) { 
    // Your own start method. 
    start(); 
} 

public void start() { 
    if (!mGameIsRunning) { 
     thread.start(); 
     mGameIsRunning = true; 
    } else { 
     thread.onResume(); 
    } 
} 
+0

谢谢Viktor,我会研究这个。 – Chris 2011-03-15 22:53:59

+0

感谢Viktor,该代码工作得很好。 – Chris 2011-03-16 17:05:13

+0

Viktor我不能让你的代码与问题中的线程一起工作。 On surfaceDestroyed调用关闭线程并在用户每次离开此活动时运行,其中包括按Home按钮时的情况。 – Lumis 2011-03-17 09:42:02

这里有一个简单的解决方案这在某些情况下可能是可以接受的,比如背景动画屏幕和状态不需要恢复的活动 - 表面vi新闻活动需要暂停时完成。

protected void onPause() { 
super.onPause(); 
finish(); 
} 

更好的解决方案是从构造移动线程的创建插入surfaceCretaed这样的:

@Override 
public void surfaceCreated(SurfaceHolder holder) { 
    _thread = new TutorialThread(holder, this); 
    _thread.setRunning(true); 
    _thread.start(); 
} 

然后在线程循环创建一个暂停标记:

if(!pause){ 
    _panel.onDraw(c); 
} 

终于在onPause和onRestore中为活动设置了暂停标志:

protected void onResume() { 
      super.onResume(); 
      pause = false;  
     } 

     protected void onPause() { 
      super.onPause(); 
      pause = true; 
     } 

当用户单击主页按钮surfaceDestroyed被调用将关闭当前线程“_thread”。当他返回到应用程序时,surfaceCreated会将引用“_thread”分配给新线程,而旧线程对象将被垃圾收集器删除。

+1

这不是一个正确的方法来处理它 – Wroclai 2011-03-16 09:56:56

+1

如果你知道为什么不编辑问题中的代码以使其正常工作,否则它就是所有的理论......当我想出一个工作代码时,我会发布它 – Lumis 2011-03-16 10:25:54

+0

@Lumis:看到我的答案和那里的链接。有一个解决方案,你必须正确管理线程,使用'synchronized'和锁。 – Wroclai 2011-03-16 10:28:38

对以下解决方案进行了测试。代码检查线程状态,如果终止则创建一个新状态。 没有崩溃,我能看到的唯一的问题是游戏状态没有保存,所以基本上从HOME键按回来,再次开始游戏。 p.s.记得从Lunarview视图中传递上下文并设置为mContextLunarView。 希望这有助于。这些论坛真棒。保持。

public void surfaceCreated(SurfaceHolder holder) { 
    // start the thread here so that we don't busy-wait in run() 
    // waiting for the surface to be created  

    if(thread.getState() == Thread.State.TERMINATED) { 
     //LunarView Thread state TERMINATED..make new...under CheckCreateThread 

     thread = new LunarThread(holder, mContextLunarView, new Handler() { 
      @Override 
      public void handleMessage(Message m) { 
       mStatusText.setVisibility(m.getData().getInt("viz")); 
       mStatusText.setText(m.getData().getString("text")); 
      } 
     });  
    } 

    thread.setRunning(true); 
    thread.start(); 
} 
+0

工作正常!非常感谢! – 2012-06-14 15:22:55