如何防止android应用程序由于后台线程异常而崩溃?

Posted

技术标签:

【中文标题】如何防止android应用程序由于后台线程异常而崩溃?【英文标题】:How to prevent android app from crashing due to exception in background thread? 【发布时间】:2014-05-23 13:57:37 【问题描述】:

这是一个笼统的问题,从具体场景中提出来,但我想得到一个笼统的答案,如何处理以下情况:

背景:

我有一个应用程序,它使用一些 3rd 方库(广告网络提供商 SDK - 特别是 - AdMob SDK,基于 Google Play Services)。这个库的功能对应用程序来说并不重要。该库创建一个或多个后台工作线程。有时(非常罕见的情况)这些后台线程之一中存在未处理的异常,导致应用程序崩溃。我想忽略由这个库引起的所有异常,不管它们的原因是什么:在最坏的情况下,应用程序用户不会看到广告——这比应用程序崩溃要好得多。

由于库本身创建了后台线程 - 我不能只通过 try/catch 包装它们。

问题

有什么方法可以捕获所有未处理的后台(非主)线程异常,并在这种情况下杀死线程,并防止应用崩溃?

相关问题

我看到了很多问题,但其中一些问题太具体(并没有涵盖我的情况),其他问题则指开发人员可以控制线程创建并能够用 try/ 包装整个线程的情况抓住。如果我仍然错过了涉及此案例的相关问题,我将不胜感激该链接

【问题讨论】:

您是否尝试过为工作线程安装处理程序并尝试不终止该进程?我不知道这是否可能,因为您可能无法访问正在崩溃的工作线程。我知道 Flurry 设法为整个过程安装一个处理程序,并在应用程序崩溃之前发送一个错误报告。也许通过这条路线是可行的。 @over_optimistic 谢谢!我尝试使用 Thread.setDefaultUncaughtExceptionHandler ,它就像一个魅力:)!请写下这个答案,以便我接受 ***.com/questions/2764394/… 【参考方案1】:

您需要做的就是使用 BaseActivity 扩展所有活动。该应用永远不会崩溃

BaseActivity 的代码片段:

public class BaseActivity extends Activity
    @Override
    protected void onCreate(Bundle savedInstanceState) 
        super.onCreate(savedInstanceState);
        Thread.setDefaultUncaughtExceptionHandler(new Thread.UncaughtExceptionHandler() 
            public void uncaughtException(Thread paramThread, Throwable paramThrowable) 
                Log.e("Error"+Thread.currentThread().getStackTrace()[2],paramThrowable.getLocalizedMessage());
            
        );
    

【讨论】:

我认为最好将此代码放入自定义应用程序类中,因为它旨在在应用程序的生命周期中仅运行一次 将此添加到我的应用程序后,每当我的应用程序崩溃时,它就会卡在黑屏上。请帮我解决这个问题 您绝对不应该在 all 活动中设置未捕获的异常处理程序,因为只能分配一个全局处理程序并且只会调用一个(来自文档:This handler is invoked in case any Thread dies due to an unhandled exception. )。通过活动分配处理程序实际上会导致代码引用死活动的属性。如前所述,在应用程序范围内只分配一个处理程序。【参考方案2】:

如上所述,Thread.setDefaultUncaughtExceptionHandler 是处理此问题的正确方法。创建类:

 private class MyThreadUncaughtExceptionHandler implements Thread.UncaughtExceptionHandler 

    @Override
    public void uncaughtException(Thread thread, Throwable ex) 
        Log.e(TAG, "Received exception '" + ex.getMessage() + "' from thread " + thread.getName(), ex);
    

然后从你的主线程调用 setDefaultUncaughtExceptionHandler:

 Thread t = Thread.currentThread();
 t.setDefaultUncaughtExceptionHandler(new MyThreadUncaughtExceptionHandler());

【讨论】:

Thread.setDefaultUncaughtExceptionHandler(new MyThreadUncaughtExceptionHandler()); 为什么需要一个新实例?

以上是关于如何防止android应用程序由于后台线程异常而崩溃?的主要内容,如果未能解决你的问题,请参考以下文章

Espresso 测试被后台线程阻塞。应用程序未空闲异常:“AppNotIdleException”。

如何防止主线程ios杀死后台线程

自己定义Application的未捕获异常处理

让 Android 应用程序在后台运行,防止它停止/死亡

如何防止android应用程序由于recyclerview中的空列表而崩溃? [复制]

Android:如何在所有后台线程完成后启用按钮