在父活动中从子活动捕捉exception

我一直想知道是否有可能通过捕获父级活动中的崩溃来阻止Android应用程序崩溃。

比方说,我在一个子活动的onCreate方法中导致致命的exception,我将能够捕获exception吗? 或者,无论我尝试什么应用程序崩溃?

这里是我的意思的一个例子:

Main.java

@Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.ly_main); // My Main activity starts try{ // Call the next activity Intent intent = new Intent(getApplicationContext(), Child.class); startActivity(intent); }catch(Exception e){ Log.wtf("Exception_WTF","Exception from child activity woohoo \n "+ e.toString()); } 

Child.java

 @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.ly_child); // Create exception... for science int a = 0; a = 1/a; } 

这不起作用。 孩子的活动死了,把父母带走。

是否有可能通过startActivityForResult做到这一点?

谢谢,

编辑:我不需要崩溃数据,我只是想知道如何避免应用程序崩溃。

环顾四周我发现: 在Android上使用全局exception处理

其中包括这件作品:

  Thread.setDefaultUncaughtExceptionHandler(new Thread.UncaughtExceptionHandler() { @Override public void uncaughtException(Thread paramThread, Throwable paramThrowable) { Log.e("Alert","Lets See if it Works !!!"); } }); 

那让我logginguncaughtException,避免“崩溃”,但是,应用程序去黑屏,并停止响应…

编辑2:经过大量的阅读(感谢user370305)在线程中如何从我的Android应用程序获取崩溃数据?

我已经到了死胡同,要么处理uncaughtException并调用defaultUEH.uncaughtException(paramThread,paramThrowable); 所以应用程序崩溃,或者我不会调用defaultUEH.uncaughtException,应用程序不会崩溃,但不反应任何想法?

 final Thread.UncaughtExceptionHandler defaultUEH = Thread.getDefaultUncaughtExceptionHandler(); Thread.setDefaultUncaughtExceptionHandler(new Thread.UncaughtExceptionHandler() { @Override public void uncaughtException(Thread paramThread, Throwable paramThrowable) { Log.e("Alert","Lets See if it Works !!!"); defaultUEH.uncaughtException(paramThread, paramThrowable); }); 

Solutions Collecting From Web of "在父活动中从子活动捕捉exception"

Android中的活动必须独立pipe理,因为它们有自己的生命周期 。 因此, 在产生它们的活动中捕捉exception

如果您的活动需要交互才能返回到之前的用户活动,请完成捕获exception(子)的活动,并让之前的活动(父级)了解结果 。 请参阅启动活动和获取结果作为彼此沟通父母和子女活动的方法。

希望我正确理解你想要什么。 你可以看看FBReaderJ的源代码,这是一个真实世界的例子来处理你的问题。 他们可以做得很好:每当应用程序有错误,他们将显示错误报告对话框给用户,他们可以通过阅读Throwable信息过滤错误。
例如,看看BookInfoActivity ,他们像这样注册了Exception Handler:

 Thread.setDefaultUncaughtExceptionHandler( new org.geometerplus.zlibrary.ui.android.library.UncaughtExceptionHandler(this) ); 

那么UncaughtExceptionHandler类将处理错误:

  @Override public void uncaughtException(Thread thread, Throwable exception) { final StringWriter stackTrace = new StringWriter(); exception.printStackTrace(new PrintWriter(stackTrace)); System.err.println(stackTrace); if(myContext != null && myContext instanceof Activity){ ((Activity)myContext).finish(); return; } // filter the error by get throwable class name and put them into // intent action which registered in manifest with particular handle activity. Intent intent = new Intent( "android.fbreader.action.CRASH", new Uri.Builder().scheme(exception.getClass().getSimpleName()).build() ); try { myContext.startActivity(intent); } catch (ActivityNotFoundException e) { // or just go to the handle bug activity intent = new Intent(myContext, BugReportActivity.class); intent.putExtra(BugReportActivity.STACKTRACE, stackTrace.toString()); myContext.startActivity(intent); } if (myContext instanceof Activity) { ((Activity)myContext).finish(); } // kill the error thread Process.killProcess(Process.myPid()); System.exit(10); } 

希望这可以帮助。

崩溃需要来自代码中的某个特定点。 您可以使用if语句筛选导致崩溃的条件,然后抛出exception。 父对象的调用周围会有try {} catch {}语句,以便在父对象中处理exception。 看到这里 。 所以对于你的代码,我想这个孩子看起来像

 import java.io.TantrumException; public class Child throws TantrumException() { @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.ly_child); // Create exception... for science int a = 0; if (a == 0) throw new TantrumException("Arrrggghhh!"); a = 1/a; } } 

对不起,忍不住:)

严重的是,捕捉全局exception听起来很危险,因为你不知道从哪里来,但是事先已经决定如何处理它,另外,看看你的代码,不pipe对孩子的呼叫什么时候终止。

我认为你误解了例外的性质。 您只能捕获源自代码的方法调用的exception。 换句话说,您只能在调用堆栈中捕获低于您的代码的调用。 请看下面的调用堆栈:

 main@830028322576, prio=5, in group 'main', status: 'RUNNING' at com.stuff.ui.MainActivity.onCreate(MainActivity.java:83) at android.app.Activity.performCreate(Activity.java:5372) at android.app.Instrumentation.callActivityOnCreate(Instrumentation.java:1104) at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:2257) at android.app.ActivityThread.handleLaunchActivity(ActivityThread.java:2349) at android.app.ActivityThread.access$700(ActivityThread.java:159) at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1316) at android.os.Handler.dispatchMessage(Handler.java:99) at android.os.Looper.loop(Looper.java:137) at android.app.ActivityThread.main(ActivityThread.java:5419) at java.lang.reflect.Method.invokeNative(Method.java:-1) at java.lang.reflect.Method.invoke(Method.java:525) at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:1187) at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:1003) at dalvik.system.NativeStart.main(NativeStart.java:-1) 

这只是我的应用程序中某些活动的onCreate方法中调用堆栈的一个示例。 正如你所看到的,第一行下面的所有代码都属于androidcom.androidjava或者dalvik包。 重要的是,第一行之后的这个调用堆栈中没有用户代码。 这意味着,除了onCreate方法本身之外,您无法捕获任何exception。 我希望这一点能够清楚说明在另外一个活动中捕捉exception情况。

如果您想知道子活动本身没有创build,您应该捕获活动的onCreate方法中的所有exception,然后使用一些标准的Android机制来通知父活动。 startActivityForResult可以是其中之一。

您可以使用从主活动意图中作为子活动意图捆绑中额外传递的ResultReceiver。

以下是您如何从主要活动开始儿童活动:

 private void startChildActivity(){ Intent childActivityIntent = new Intent(this, ChildActivity.class); ResultReceiver rr = new ResultReceiver(mainUiHandler){ @Override protected void onReceiveResult(int resultCode, Bundle resultData) { super.onReceiveResult(resultCode, resultData); switch(resultCode){ case RESULT_ERROR: String errorMessage = resultData.getString(RESULT_KEY_ERROR_MESSAGE); textView.setText(errorMessage); break; default:break; } } }; childActivityIntent.putExtra(INTENT_EXTRA_KEY_RESULT_RECEIVER, rr); startActivity(childActivityIntent); } 

这里是孩子活动的代码。

 public class ChildActivity extends Activity{ @Override protected void onCreate(Bundle savedInstanceState){ super.onCreate(savedInstanceState); setContentView(R.layout.activity_child); try{ int a = 0; a = 1/a; } catch(Exception e){ Log.e("Exception", e.getMessage()); Intent startIntent = getIntent(); ResultReceiver rr = startIntent.getParcelableExtra(MainActivity.INTENT_EXTRA_KEY_RESULT_RECEIVER); Bundle resultData = new Bundle(); resultData.putString(MainActivity.RESULT_KEY_ERROR_MESSAGE, e.getMessage()); rr.send(MainActivity.RESULT_ERROR, resultData); finish(); //close the child activity } } } 

如果您捕捉到所有可能的例外并提供适当的操作,您可以停止崩溃。

关于在家长中捕捉exception:为什么你要这样做? 您可以在孩子中发现exception,并通过意向将必要的信息发送给父母的活动。 我不认为有可能在父母中发现孩子的exception。

你不能。 当你得到UncaughtException时,它意味着它终止的线程,而你与此无关。 但是你可以使用UncaughtExceptionHandler来logging这个事件,并重新启动你的应用程序(并打开“新的”父活动)。 Android为所有活动和服务使用单一主线程。 所以如果有人在主线程中抛出未捕获的exception – everibody死亡。 您不能在单独的线程中运行活动。