首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >使用UncaughtExceptionHandler的Firebase Crashlytics

使用UncaughtExceptionHandler的Firebase Crashlytics
EN

Stack Overflow用户
提问于 2018-05-29 21:05:42
回答 5查看 4.6K关注 0票数 13

我已经集成了Firebase Crashlytics版本2.9.1来挖掘崩溃,以覆盖我的应用程序的性能和稳定性。

如果应用程序具有自己的UncaughtExceptionHandler,则不会在firebase crashlytics控制台上记录崩溃。

我的应用程序中有BaseActivity。在onCreate()方法中,我根据项目需求注册了自定义的UncaughtExceptionHandler。

无论何时由于任何原因导致应用程序崩溃,用户都应该被重定向到闪屏(MainActivity.java)。

代码语言:javascript
复制
public class BaseActivity extends FragmentActivity{ 

@Override 
protected void onCreate(Bundle arg0) { 
   // Enable global crash handler. 
   Thread.setDefaultUncaughtExceptionHandler(handleAppCrash); 
} 

/*** 
* @Purpose Called when any crash occurs in the application. 
***/ 
private Thread.UncaughtExceptionHandler handleAppCrash = new Thread.UncaughtExceptionHandler() { 
@Override 
public void uncaughtException(Thread thread, Throwable ex) { 

   Intent intent = new Intent(context, MainActivity.class); //redirect to Splash screen
   intent.addFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP); 
   context.startActivity(intent); 
   System.exit(0); 
  } 
}; 

} 
EN

回答 5

Stack Overflow用户

发布于 2020-10-05 14:46:33

对于最新的firebase crashlytics 17.x.x,他们在内容提供者内部设置了未捕获的异常处理程序,这样他们就不需要开发人员传递上下文并手动初始化。这样做是为了在应用程序启动时自动初始化firebase。因此,即使我们在Application类oncreate中设置了未捕获的异常处理程序,我们的实现也会覆盖firebase的异常处理程序,并且不会向firebase异常处理程序报告崩溃。

Fix:为了解决这个问题,我们必须编写一个自定义的内容提供者,并在我们的应用程序中将其优先级设置为最高。然后在内容提供者的oncreate中初始化未捕获的异常处理程序,而不是在应用程序类中进行初始化。这样,我们的将首先被初始化,并且不会覆盖firebase的。

票数 8
EN

Stack Overflow用户

发布于 2019-06-24 17:47:39

好的,我已经调查过这个问题了。

您不应该在BaseActivity内部创建自定义异常处理程序。最好在你的Application类中完成。在BaseActivity的情况下,您将在每次启动新活动时获得一个新的处理程序,这将扩展您的BaseActivity。

因此,在应用程序类onCreate()方法中,您可以获得默认应用程序处理程序

代码语言:javascript
复制
val defaultExceptionHandler = Thread.getDefaultUncaughtExceptionHandler()

在我的例子中,它是一个

代码语言:javascript
复制
com.crashlytics.android.core.CrashlyticsUncaughtExceptionHandler

这个"defaultExceptionHandler“用于向firebase发送正确的错误。然后,您可以创建自己的异常处理程序,但需要在此处保存此"defaultExceptionHandler“。

代码语言:javascript
复制
class DefaultExceptionHandler (private val  defaultExceptionHandler:Thread.UncaughtExceptionHandler?) : Thread.UncaughtExceptionHandler {
override fun uncaughtException(thread: Thread, ex: Throwable) {
        try {       
            // here you restore your activity and do other things
            // and of course you deal with defaultExceptionHandler
            // without it firebase will not work       
            defaultExceptionHandler?.uncaughtException(thread, ex)
            // only after firebase dealed with an exception, you can exit
            System.exit(0)
        } catch (e: IOException) {
            // just catch
        }

        }
    }

最后,firebase会在你需要的时候告诉你崩溃了。应用程序onCreate()示例

代码语言:javascript
复制
override fun onCreate() {
        super.onCreate()
        Fabric.with(this, Crashlytics())
        val defaultExceptionHandler = Thread.getDefaultUncaughtExceptionHandler()
        val customExceptionHandler = DefaultExceptionHandler(defaultExceptionHandler)
        Thread.setDefaultUncaughtExceptionHandler(customExceptionHandler)
    }
票数 7
EN

Stack Overflow用户

发布于 2020-10-31 02:31:10

我在我的应用中也遇到了同样的问题。根据@niyas的建议,我也使用了相同的解决方案,它对我来说工作得很好。Firebase使用内容提供程序初始化firebase crashlytics sdk及其未捕获的异常处理程序。因此,如果您在自定义内容提供程序中注册了未捕获的异常处理程序,其优先级高于firebase提供程序。则接收对处理程序的回调的顺序颠倒。首先,回调将发送到Firebase处理程序,然后再发送到您的处理程序。通过这种方式,firebase收集崩溃的堆栈跟踪,您还可以获得回调处理程序来重新启动应用程序/或任何其他用例。我在github上找到了这个解决方案,这是a link

代码片段:

代码语言:javascript
复制
 <application>
        ...
        <!-- Firebase SDK initOrder is 100. Higher order init first -->
        <provider
            android:name=".UncaughtExceptionHandlerContentProvider"
            android:authorities="${applicationId}"
            android:exported="false"
            android:initOrder="101"
            android:grantUriPermissions="false" />
        ... 
    </application>

 public class UncaughtExceptionHandlerContentProvider extends ContentProvider {
    @Override
    public boolean onCreate() {
        MyCustomCrashHandler myHandler = new MyCustomCrashHandler(Thread.getDefaultUncaughtExceptionHandler());
        Thread.setDefaultUncaughtExceptionHandler(myHandler);
        return true;
    }

    @Nullable
    @Override
    public Cursor query(@NonNull Uri uri, @Nullable String[] projection, @Nullable String selection, @Nullable String[] selectionArgs, @Nullable String sortOrder) { return null; }

    @Nullable
    @Override
    public String getType(@NonNull Uri uri) { return null; }

    @Nullable
    @Override
    public Uri insert(@NonNull Uri uri, @Nullable ContentValues values) { return null; }

    @Override
    public int delete(@NonNull Uri uri, @Nullable String selection, @Nullable String[] selectionArgs) { return 0; }

    @Override
    public int update(@NonNull Uri uri, @Nullable ContentValues values, @Nullable String selection, @Nullable String[] selectionArgs) { return 0; }
}


public class MyCustomCrashHandler implements UncaughtExceptionHandler {
    @Nullable 
    private final UncaughtExceptionHandler defaultHandler;
    
    public MyCustomCrashHandler(@Nullable UncaughtExceptionHandler defaultHandler)(){
         this.defaultHandler = defaultHandler;
    }

    @Override
    public void uncaughtException(@NonNull Thread thread, @NonNull Throwable ex) {
        // We are now safely being called after Crashlytics does its own thing. 
        // Whoever is the last handler on Thread.getDefaultUncaughtExceptionHandler() will execute first on uncaught exceptions.
        // Firebase Crashlytics will handle its own behavior first before calling ours in its own 'finally' block.
        // You can choose to propagate upwards (it will kill the app by default) or do your own thing and propagate if needed.
        
        try { 
            //do your own thing.
        } catch (Exception e) {
            e.printStackTrace();
        } finally {
            if (defaultHandler != null) {
                defaultHandler.uncaughtException(thread, ex) 
                // propagate upwards. With this workaround (and also without any other similar UncaughtExceptionHandler based on ContentProvider), 
                // defaultHandler should now be an instance of com.android.internal.os.RuntimeInit.KillApplicationHandler
                // hence properly killing the app via framework calls.
            }
        }
    }
票数 4
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/50585187

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档