【问题标题】:Upgrade Firebase Crashlytics with custom UncaughtExceptionHandler使用自定义 UncaughtExceptionHandler 升级 Firebase Crashlytics
【发布时间】:2020-08-12 10:52:17
【问题描述】:

在处理 Update your apps to use latest Firebase Crashlytics SDKs before November 15, 2020 时,在我激活我的自定义 UncaughtExceptionHandler 后,它不会再向 Crashlytics 发送崩溃。

下面的代码我将它设置在ApplicationonCreate()中。

        FirebaseCrashlytics crashlytics = FirebaseCrashlytics.getInstance();
        crashlytics.setCrashlyticsCollectionEnabled(!BuildConfig.DEBUG); // only release able to send.
        crashlytics.sendUnsentReports(); // send reports
        Thread.setDefaultUncaughtExceptionHandler((t, e) -> {
            FirebaseCrashlytics.getInstance().recordException(e); // record exception.
            // below things are restart app when crash appeared.
            PackageManager packageManager = getPackageManager();
            Intent intent = packageManager.getLaunchIntentForPackage(getPackageName());
            if (intent != null) {
                ComponentName componentName = intent.getComponent();
                Intent mainIntent = Intent.makeRestartActivityTask(componentName);
                startActivity(mainIntent);
                Runtime.getRuntime().exit(0);
            }
        });

当我删除自定义 UncaughtExceptionHandler 时,它能够向 Crashlytics 报告。

以下代码在使用 Fabric 库时运行良好。 (https://stackoverflow.com/a/49266303/4316327)

        CrashlyticsCore core = new CrashlyticsCore.Builder()
                .disabled(BuildConfig.DEBUG)
                .build();
        Fabric.with(new Fabric.Builder(this).kits(new Crashlytics.Builder()
                .core(core).build()).initializationCallback(new InitializationCallback<Fabric>() {
            @Override
            public void success(Fabric fabric) {
                Thread.setDefaultUncaughtExceptionHandler((t, e) -> {
                    LogWrapper.logException(e);
                    PackageManager packageManager = getPackageManager();
                    Intent intent = packageManager.getLaunchIntentForPackage(getPackageName());
                    if (intent != null) {
                        ComponentName componentName = intent.getComponent();
                        Intent mainIntent = Intent.makeRestartActivityTask(componentName);
                        startActivity(mainIntent);
                        Runtime.getRuntime().exit(0);
                    }
                });
            }

            @Override
            public void failure(Exception e) {
                e.printStackTrace();
            }
        }).build());

对此有什么解决办法吗?任何帮助将不胜感激。非常感谢。

【问题讨论】:

  • 遇到同样的问题
  • @Truong Hieu:你解决了这个问题吗?我有同样的问题。如果是,您能否提供一下您是如何做到的?谢谢
  • @ItayFeldman:你解决了吗?以及如何?
  • @nibz 还没有

标签: android firebase crashlytics


【解决方案1】:

解决方案已发布here。我会将修改后的代码粘贴到这里,供任何寻找它的人使用:

以下代码是用 Java 编写的。对于 Kotlin,请访问原帖。

public class NewCrashHandlerContentProvider extends ContentProvider {
    public static final String TAG = "NewCrashHandler";
    static long PRE_DELAY_MILLIS = 3000L;
    static long POST_DELAY_MILLIS = 3000L;

    public static void initializeAfterFirebaseContentProvider() {
        Thread.setDefaultUncaughtExceptionHandler(new PreFirebaseCrashHandler(Thread.getDefaultUncaughtExceptionHandler()));
    }

    @Override
    public boolean onCreate() {
        try {
            Log.i(TAG, "+onCreate()");
            Thread.setDefaultUncaughtExceptionHandler(new PostFirebaseCrashHandler(Thread.getDefaultUncaughtExceptionHandler()));
            return true;
        }finally {
            Log.i(TAG, "-onCreate()");
        }
    }

    @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;
    }


    static class PreFirebaseCrashHandler implements Thread.UncaughtExceptionHandler {
        Thread.UncaughtExceptionHandler previousUncaughtExceptionHandler;
        public static final String TAG = "PreFirebaseCrashHandler";

        public PreFirebaseCrashHandler(Thread.UncaughtExceptionHandler previousUncaughtExceptionHandler) {
            this.previousUncaughtExceptionHandler = previousUncaughtExceptionHandler;
        }

        @Override
        public void uncaughtException(@NonNull Thread t, @NonNull Throwable e) {
            LogWrapper.logException(e);
            try {
                // my own logic
                Thread.sleep(PRE_DELAY_MILLIS);
            }catch (Throwable throwable) {
                LogWrapper.e(TAG, throwable.getLocalizedMessage());
            } finally {
                previousUncaughtExceptionHandler.uncaughtException(t,e);
            }
        }
    }

    static class PostFirebaseCrashHandler implements Thread.UncaughtExceptionHandler {
        Thread.UncaughtExceptionHandler previousUncaughtExceptionHandler;
        public static final String TAG = "PostFirebaseCrashHandler";

        public PostFirebaseCrashHandler(Thread.UncaughtExceptionHandler previousUncaughtExceptionHandler) {
            this.previousUncaughtExceptionHandler = previousUncaughtExceptionHandler;
        }

        @Override
        public void uncaughtException(@NonNull Thread t, @NonNull Throwable e) {
            LogWrapper.e(TAG, "+uncaughtException($thread, $throwable)");
            try {
                Thread.sleep(POST_DELAY_MILLIS);
            }catch (Throwable throwable) {
                LogWrapper.e(TAG, throwable.getLocalizedMessage());
            }finally {
                previousUncaughtExceptionHandler.uncaughtException(t,e);
            }
            LogWrapper.e(TAG, e.getLocalizedMessage());
        }
    }

}

在Application文件中,写入onCreate()方法:

NewCrashHandlerContentProvider.initializeAfterFirebaseContentProvider();

别忘了更新manifests

<provider
            android:authorities="${applicationId}"
            android:name=".utils.NewCrashHandlerContentProvider"
            android:exported="false"
            android:initOrder="101"
            android:grantUriPermissions="false"/>

【讨论】:

    【解决方案2】:

    您需要调用 getUncaughtExceptionHandler 并挂起它,然后设置您自己的 uncaughtexceptionhandler 并在退出之前回调我们的。

    【讨论】:

    • 试图实现这一点并没有奏效。你能举个例子吗?
    • ``` val previous = Thread.getDefaultUncaughtExceptionHandler() Thread.setDefaultUncaughtExceptionHandler((t, e) -> { ... previous?.uncaughtException(t, e) }); ```
    • @swooby 感谢您的评论,这正是我所做的,但仪表板中仍然没有崩溃
    • @ItayFeldman:你能解决这个问题吗?我面临着类似的问题。我没有在仪表板中看到发布版本崩溃
    • @Oleg Kodysh:你能详细说明我应该怎么做吗?谢谢
    猜你喜欢
    • 2014-10-01
    • 1970-01-01
    • 1970-01-01
    • 2020-10-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多