Dur*_*tel 12 android firebase crashlytics
我已经集成了 Firebase Crashlytics 版本 2.9.1 来挖掘崩溃以涵盖我的应用程序的性能和稳定性。
如果应用程序有自己的 UncaughtExceptionHandler,则不会在 Firebase crashlytics 控制台上记录崩溃。
我的应用程序中有 BaseActivity。在 onCreate() 方法中,我根据项目要求注册了自定义 UncaughtExceptionHandler。
每当应用程序因任何原因崩溃时,都应将用户重定向到启动画面 ( MainActivity.java) 。
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); 
  } 
}; 
} 
Run Code Online (Sandbox Code Playgroud)
    好的,我已经调查过这个问题。
您不应在 BaseActivity 中创建自定义异常处理程序。最好在您的 Application 类中进行。在 BaseActivity 的情况下,每次启动新活动时都会有一个新的处理程序,它扩展了您的 BaseActivity。
因此,在您的应用程序类 onCreate() 方法中,您可以获得默认的应用程序处理程序
val defaultExceptionHandler = Thread.getDefaultUncaughtExceptionHandler()
Run Code Online (Sandbox Code Playgroud)
在我的情况下,它是一个实例
com.crashlytics.android.core.CrashlyticsUncaughtExceptionHandler
Run Code Online (Sandbox Code Playgroud)
您将使用此“defaultExceptionHandler”将正确的错误发送到 firebase。然后你可以创建你自己的异常处理程序,但需要在这里保存这个“defaultExceptionHandler”。
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
        }
        }
    }
Run Code Online (Sandbox Code Playgroud)
最后,firebase 会根据需要向您显示崩溃情况。应用程序 onCreate() 示例
override fun onCreate() {
        super.onCreate()
        Fabric.with(this, Crashlytics())
        val defaultExceptionHandler = Thread.getDefaultUncaughtExceptionHandler()
        val customExceptionHandler = DefaultExceptionHandler(defaultExceptionHandler)
        Thread.setDefaultUncaughtExceptionHandler(customExceptionHandler)
    }
Run Code Online (Sandbox Code Playgroud)
        小智 7
对于最新的 firebase crashlytics 17.xx,他们在 Content Provider 中设置了未捕获的异常处理程序,这样他们就不需要开发人员传递上下文并手动初始化。这样做是为了在应用程序启动时自动初始化 firebase。因此,即使我们在 Application 类 oncreate 中设置了未捕获的异常处理程序,我们的实现也会覆盖 firebase 并且崩溃不会报告给 firebase 异常处理程序。
修复:为了解决这个问题,我们必须编写一个自定义的内容提供器,并在我们的应用程序中将其优先级设置为最大值。然后在 content provider 的 oncreate 中初始化我们未捕获的异常处理程序,而不是在应用程序类中进行。这样,我们的将首先初始化并且不会覆盖 firebase 的。
小智 7
我的应用程序中也遇到了同样的问题。正如@niyas 所建议的,我也使用了相同的解决方案,它对我来说工作得很好。Firebase 使用内容提供程序来初始化 firebase crashlytics sdk 及其未捕获的异常处理程序。因此,如果您在自定义内容提供程序中注册未捕获的异常处理程序,其优先级高于 Firebase 的处理程序。然后接收处理程序回调的顺序相反。首先,回调将发送至 Firebase 处理程序,然后发送至您的处理程序。通过这种方式,Firebase 收集崩溃的堆栈跟踪,并且您还可以在处理程序中获得回调以重新启动应用程序/或任何其他用例。我在 github 上找到了这个解决方案,这是一个链接!
代码片段:
 <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.
            }
        }
    }
Run Code Online (Sandbox Code Playgroud)
        您是否尝试升级到最新版本:
implementation 'com.crashlytics.sdk.android:crashlytics:2.9.3'
Run Code Online (Sandbox Code Playgroud)
和谷歌服务(项目级别):
classpath 'com.google.gms:google-services:4.0.1'
Run Code Online (Sandbox Code Playgroud)
确保一切都是最新的。这是基于此链接的 firebase 库的最新更新,您可以检查以下内容:
implementation 'com.google.firebase:firebase-core:16.0.0'
implementation 'com.google.firebase:firebase-ads:15.0.1'
implementation 'com.google.firebase:firebase-analytics:16.0.0'
implementation 'com.google.firebase:firebase-appindexing:15.0.1'
implementation 'com.google.firebase:firebase-auth:16.0.1'
implementation 'com.google.firebase:firebase-firestore:17.0.1'
implementation 'com.google.firebase:firebase-functions:16.0.1'
implementation 'com.google.firebase:firebase-messaging:17.0.0'
implementation 'com.google.firebase:firebase-storage:16.0.1'
implementation 'com.google.firebase:firebase-crash:16.0.0'
implementation 'com.google.firebase:firebase-invites:16.0.0'
implementation 'com.google.firebase:firebase-perf:16.0.0'
implementation 'com.google.firebase:firebase-database:16.0.1'
implementation 'com.google.firebase:firebase-config:16.0.0'
Run Code Online (Sandbox Code Playgroud)
        |   归档时间:  |  
           
  |  
        
|   查看次数:  |  
           3946 次  |  
        
|   最近记录:  |