Я интегрировал Firebase Crashlytics версии 2.9.1 для выявления сбоев, чтобы обеспечить производительность и стабильность моего приложения.
Сбои не регистрируются в консоли сбоев firebase, если у приложения есть собственный UncaughtExceptionHandler.
В моем приложении есть 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);
}
};
}
Я рекомендую вам обновить последнюю версию, но не могли бы вы предоставить нам файлы Gradle?
@ParaskevasNtsounos тоже обновился до последней версии, не работает :)
@DurgeshPatel у тестового приложения в эмуляторе?
@kevanaghera нет. в реальном устройстве
@DurgeshPatel, потому что я получил ошибку в эмуляторе не на реальных устройствах. и в приложении-эмуляторе приложение заходит в бесконечный цикл и каждый раз генерирует один и тот же журнал ошибок.
Обратитесь к stackoverflow.com/questions/44771420/…
та же проблема, сбой, не регистрирующийся на реальном устройстве с последней конфигурацией при использовании настраиваемого UncaughtExceptionHandler, даже при запуске mDefaultUncaughtExceptionHandler? .uncaughtException (thread, ex)
Вы пытались обновить последнюю версию:
implementation 'com.crashlytics.sdk.android:crashlytics:2.9.3'
И сервисы Google (уровень проекта):
classpath 'com.google.gms:google-services:4.0.1'
Убедитесь, что все обновлено. Это последнее обновление в библиотеках 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'
Установите свой собственный обработчик исключений внутри InitializationCallback ткани, как показано ниже.
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) {
// Get default exception handler
final Thread.UncaughtExceptionHandler defaultHandler = Thread.getDefaultUncaughtExceptionHandler();
// Set your custom exception handler
Thread.setDefaultUncaughtExceptionHandler(new Thread.UncaughtExceptionHandler() {
@Override
public void uncaughtException(Thread thread, Throwable ex) {
// redirect to Splash screen
Intent intent = new Intent(context, MainActivity.class);
intent.addFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP);
context.startActivity(intent);
// pass exception to default handler
defaultHandler.uncaughtException(thread, ex);
}
};);
}
@Override
public void failure(Exception e) {
}
}).build());
Я не хочу интегрировать крашлитику firebase, только мое собственное неперехваченное исключение. так я могу этого добиться?
@Priyank Patel, поскольку я поставил этот код в onCreate () BaseActivity.java, но нет обратного вызова успеха или неудачи :)
@kevanaghera, если вы хотите использовать только свой собственный обработчик исключений вместо аварийной обработки, вам просто нужно использовать Thread.setDefaultUncaughtExceptionHandler(UncaughtExceptionHandler); 'в методе onCreate класса приложения, чтобы поймать неперехваченное исключение.
@kevanaghera, я уже знал это. :) см. описание моего вопроса. :)
У меня это не работает. Мое требование - запустить действие обратной связи после сбоя и одновременно зарегистрировать фатальное исключение в Crashlytics, при этом приложение не будет отображать диалоговое окно сбоя по умолчанию и запрашивать перезапуск приложения.
Хорошо, я исследовал этот вопрос.
Вы не должны создавать собственный обработчик исключений внутри BaseActivity. Лучше сделать это в своем классе Application. В случае BaseActivity вы будете создавать новый обработчик каждый раз, когда начинаете новую активность, которая расширяет вашу BaseActivity.
Итак, в методе onCreate () вашего класса приложения вы можете получить обработчик приложения по умолчанию
val defaultExceptionHandler = Thread.getDefaultUncaughtExceptionHandler()
В моем случае это экземпляр
com.crashlytics.android.core.CrashlyticsUncaughtExceptionHandler
Этот "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
}
}
}
И, наконец, firebase покажет вам сбои по мере необходимости. Пример приложения onCreate ()
override fun onCreate() {
super.onCreate()
Fabric.with(this, Crashlytics())
val defaultExceptionHandler = Thread.getDefaultUncaughtExceptionHandler()
val customExceptionHandler = DefaultExceptionHandler(defaultExceptionHandler)
Thread.setDefaultUncaughtExceptionHandler(customExceptionHandler)
}
Для последней версии firebase crashlytics 17.x.x они настраивают обработчик неперехваченных исключений внутри Content Provider, чтобы разработчик не передавал контекст и вручную инициализировал. Это сделано для автоматической инициализации firebase при запуске приложения. Таким образом, даже если мы настроим наш обработчик неперехваченных исключений в классе Application oncreate, наша реализация переопределяет firebase, и о сбоях не будет сообщаться обработчику исключений firebase.
Исправление: чтобы исправить это, мы должны написать настраиваемого поставщика контента и установить для него максимальный приоритет в нашем приложении. Затем инициализируйте наш обработчик неперехваченных исключений внутри oncreate поставщика контента вместо того, чтобы делать это в классе приложения. Таким образом, наш будет инициализирован первым и не будет переопределять firebase.
Если мы это сделаем (добавим собственный ContentProvider), не переопределит ли обработчик Firebase нашу реализацию, и мы потеряем ее?
Если мы добавим настраиваемый ContentProvider для инициализации обработчика неперехваченных исключений, наш обработчик исключений будет инициализирован первым, и мы сначала получим все исключения, и он не будет конфликтовать с обработчиком исключений firebase, так что обработчик исключений firebase также получает те же исключения сразу после наш обработчик. Таким образом, сбой будет зарегистрирован в firebase без проблем. @Maksym
У меня тоже была такая же проблема в моем приложении. Как было предложено @niyas, я также использовал то же решение, и оно отлично работает для меня. Firebase использует поставщика контента для инициализации sdk firebase crashlytics и его обработчика неперехваченных исключений. Поэтому, если вы зарегистрируете свой обработчик неперехваченных исключений у настраиваемого поставщика контента с более высоким приоритетом, чем у 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.
}
}
}
У меня такая же проблема, как и вы нашли решение?