Issue
I have an app that i've recently noticed crashes on devices that do not have Google Play Services installed. After a bit of debugging i've noticed the cause is Firebase.
This is fine with me because i figured Firebase needs Google Play Services to run.
The issue however is the sudden crash. I have tried detecting if Google Play Service is available first thing in the launcher activity so that i can show the user a proper message, but the app crashes immediately without even executing code in the launcher activity or in the Application class.
How can i properly handle this Firebase error. I need a proper way to catch the error or prevent it from occurring and display a proper message instead of a crash. I have looked at a lot of similar questions and tried the solutions out but this case looks a bit different.
Note, this ONLY happens when the app is in Release mode. Also, you will notice the logcat highlights SQLite, nowhere do i use SQLite in this project, i reckon maybe Firebase is referencing it.
App level gradle:
plugins{
id 'com.android.application'
id 'kotlin-android'
id 'kotlin-android-extensions'
id 'kotlin-kapt'
id 'realm-android'
id 'com.google.gms.google-services'
id 'com.google.firebase.crashlytics'
}
repositories {
maven { url 'https://maven.google.com' }
}
android {
compileSdkVersion 31
defaultConfig {
applicationId "com.myapp"
minSdkVersion 19
targetSdkVersion 31
versionCode 14
versionName "2.3.3"
multiDexEnabled true
testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner"
}
compileOptions {
sourceCompatibility JavaVersion.VERSION_1_8
targetCompatibility JavaVersion.VERSION_1_8
}
buildTypes {
release {
minifyEnabled true
proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'
}
}
packagingOptions {
exclude 'META-INF/DEPENDENCIES'
}
configurations {
all {
exclude module: 'httpclient'
exclude module: 'commons-logging'
}
}
}
realm {
syncEnabled = true
}
dependencies {
implementation fileTree(dir: 'libs', include: ['*.jar'])
implementation"org.jetbrains.kotlin:kotlin-stdlib-jdk7:1.5.31"
implementation 'androidx.appcompat:appcompat:1.3.1'
implementation 'com.google.android.material:material:1.4.0'
implementation 'androidx.constraintlayout:constraintlayout:2.1.1'
implementation 'androidx.preference:preference-ktx:1.1.1'
implementation 'androidx.legacy:legacy-preference-v14:1.0.0'
//if i remove the firebase dependencies, everything runs smoothly
implementation 'com.google.firebase:firebase-core:20.0.0'
implementation 'com.google.firebase:firebase-crashlytics:18.2.4'
implementation 'com.google.firebase:firebase-analytics:20.0.0'
implementation 'com.google.firebase:firebase-messaging:23.0.0'
implementation 'com.google.code.gson:gson:2.8.7'
implementation 'com.android.support:multidex:1.0.3'
implementation 'com.google.android.gms:play-services-maps:18.0.0'
implementation "com.squareup.retrofit2:retrofit:2.9.0"
implementation "com.squareup.retrofit2:adapter-rxjava:2.9.0"
implementation "com.squareup.retrofit2:converter-gson:2.9.0"
testImplementation 'junit:junit:4.13.2'
androidTestImplementation 'androidx.test.ext:junit:1.1.3'
androidTestImplementation 'androidx.test.espresso:espresso-core:3.4.0'
}
Project level gradle:
// Top-level build file where you can add configuration options common to all sub-projects/modules.
buildscript {
ext.kotlin_version = '1.5.31'
repositories {
google()
mavenCentral()
gradlePluginPortal()
maven { url 'https://plugins.gradle.org/m2/'}
// jcenter() //for now(31Jul2021) Realm depends on this, will remove when Realm has moved - maybe to mavenCentral
}
dependencies {
classpath 'com.android.tools.build:gradle:7.0.3'
classpath "org.jetbrains.kotlin:kotlin-gradle-plugin:$kotlin_version"
classpath 'com.google.gms:google-services:4.3.10'
classpath "io.realm:realm-gradle-plugin:10.8.0"
classpath 'com.google.firebase:firebase-crashlytics-gradle:2.8.0'
}
}
allprojects {
repositories {
google()
mavenCentral()
maven { url 'https://jitpack.io' }
}
}
task clean(type: Delete) {
delete rootProject.buildDir
}
Logcat:
2021-11-02 23:15:31.406 17886-17886/com.myapp I/FirebaseApp: Device unlocked: initializing all Firebase APIs for app [DEFAULT]
2021-11-02 23:15:31.459 17886-17900/com.myapp E/SQLiteLog: (1) table log_event_dropped already exists
2021-11-02 23:15:31.459 17886-17886/com.myapp I/FirebaseCrashlytics: Initializing Firebase Crashlytics 18.2.4 for com.myapp
2021-11-02 23:15:31.466 17886-17900/com.myapp E/TransportRuntime.Executor: Background execution failure.
android.database.sqlite.SQLiteException: table log_event_dropped already exists (code 1): , while compiling: CREATE TABLE log_event_dropped (log_source VARCHAR(45) NOT NULL,reason INTEGER NOT NULL,events_dropped_count BIGINT NOT NULL,PRIMARY KEY(log_source, reason))
at android.database.sqlite.SQLiteConnection.nativePrepareStatement(Native Method)
at android.database.sqlite.SQLiteConnection.acquirePreparedStatement(SQLiteConnection.java:887)
at android.database.sqlite.SQLiteConnection.prepare(SQLiteConnection.java:498)
at android.database.sqlite.SQLiteSession.prepare(SQLiteSession.java:588)
at android.database.sqlite.SQLiteProgram.<init>(SQLiteProgram.java:58)
at android.database.sqlite.SQLiteStatement.<init>(SQLiteStatement.java:31)
at android.database.sqlite.SQLiteDatabase.executeSql(SQLiteDatabase.java:1674)
at android.database.sqlite.SQLiteDatabase.execSQL(SQLiteDatabase.java:1605)
at com.google.android.datatransport.runtime.scheduling.persistence.SchemaManager.k(SourceFile:1)
at com.google.android.datatransport.runtime.scheduling.persistence.SchemaManager.e(SourceFile)
at w20.upgrade(SourceFile)
at com.google.android.datatransport.runtime.scheduling.persistence.SchemaManager.m(SourceFile:2)
at com.google.android.datatransport.runtime.scheduling.persistence.SchemaManager.onUpgrade(SourceFile:2)
at android.database.sqlite.SQLiteOpenHelper.getDatabaseLocked(SQLiteOpenHelper.java:256)
at android.database.sqlite.SQLiteOpenHelper.getWritableDatabase(SQLiteOpenHelper.java:163)
at g20.a(SourceFile)
at com.google.android.datatransport.runtime.scheduling.persistence.SQLiteEventStore.r0(SourceFile:2)
at com.google.android.datatransport.runtime.scheduling.persistence.SQLiteEventStore.E(SourceFile:3)
at com.google.android.datatransport.runtime.scheduling.persistence.SQLiteEventStore.runCriticalSection(SourceFile:1)
at com.google.android.datatransport.runtime.scheduling.jobscheduling.WorkInitializer.d(SourceFile:1)
at com.google.android.datatransport.runtime.scheduling.jobscheduling.WorkInitializer.b(SourceFile)
at le0.run(SourceFile)
at q20$a.run(SourceFile:1)
at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1113)
at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:588)
at java.lang.Thread.run(Thread.java:818)
2021-11-02 23:15:31.482 17886-17906/com.myapp E/FirebaseMessaging: Google Play services missing or without correct permission.
2021-11-02 23:15:31.492 17886-17907/com.myapp E/ActivityThread: Failed to find provider info for com.google.android.gms.chimera
2021-11-02 23:15:31.493 17886-17907/com.myapp W/DynamiteModule: Failed to retrieve remote module version.
2021-11-02 23:15:31.500 17886-17907/com.myapp W/GooglePlayServicesUtil: Google Play Store is missing.
2021-11-02 23:15:31.500 17886-17907/com.myapp I/DynamiteModule: Considering local module com.google.android.gms.measurement.dynamite:55 and remote module com.google.android.gms.measurement.dynamite:0
2021-11-02 23:15:31.500 17886-17907/com.myapp I/DynamiteModule: Selected local version of com.google.android.gms.measurement.dynamite
2021-11-02 23:15:31.501 17886-17907/com.myapp W/GooglePlayServicesUtil: Google Play Store is missing.
2021-11-02 23:15:31.579 17886-17886/com.myapp I/FirebaseInitProvider: FirebaseApp initialization successful
2021-11-02 23:15:31.590 17886-17886/com.myapp D/WM-WrkMgrInitializer: Initializing WorkManager with default configuration.
2021-11-02 23:15:31.609 17886-17913/com.myapp V/FA: App measurement enabled for app package, google app id: com.myapp, 1:483778118943:android:c6a45e2f9497b6ac
2021-11-02 23:15:31.610 17886-17913/com.myapp I/FA: App measurement initialized, version: 46000
2021-11-02 23:15:31.610 17886-17913/com.myapp I/FA: To enable debug logging run: adb shell setprop log.tag.FA VERBOSE
2021-11-02 23:15:31.610 17886-17913/com.myapp I/FA: To enable faster debug mode event logging run:
adb shell setprop debug.firebase.analytics.app com.myapp
2021-11-02 23:15:31.610 17886-17913/com.myapp D/FA: Debug-level message logging enabled
2021-11-02 23:15:31.669 17886-17886/com.myapp W/GooglePlayServicesUtil: Google Play Store is missing.
2021-11-02 23:15:31.677 17886-17913/com.myapp V/FA: Checking service availability
2021-11-02 23:15:31.679 17886-17913/com.myapp W/GooglePlayServicesUtil: Google Play Store is missing.
2021-11-02 23:15:31.679 17886-17913/com.myapp W/FA: Service invalid
2021-11-02 23:15:31.681 17886-17913/com.myapp V/FA: Using local app measurement service
2021-11-02 23:15:31.706 17886-17913/com.myapp V/FA: Connection attempt already in progress
2021-11-02 23:15:31.721 17886-17886/com.myapp E/ResourceType: Style contains key with bad entry: 0x0101056c
2021-11-02 23:15:31.722 17886-17913/com.myapp V/FA: Connection attempt already in progress
2021-11-02 23:15:31.736 17886-17907/com.myapp V/FA: onActivityCreated
2021-11-02 23:15:31.857 17886-17913/com.myapp V/FA: Activity resumed, time: 67518553
2021-11-02 23:15:31.865 17886-17913/com.myapp I/FA: Tag Manager is not found and thus will not be used
2021-11-02 23:15:31.869 17886-17924/com.myapp D/OpenGLRenderer: Use EGL_SWAP_BEHAVIOR_PRESERVED: true
2021-11-02 23:15:31.869 17886-17913/com.myapp W/GooglePlayServicesUtil: Google Play services is missing.
2021-11-02 23:15:31.879 17886-17886/com.myapp V/FA: Local AppMeasurementService is starting up
2021-11-02 23:15:31.895 17886-17913/com.myapp V/FA: Connection attempt already in progress
2021-11-02 23:15:31.895 17886-17913/com.myapp V/FA: Connection attempt already in progress
2021-11-02 23:15:31.921 17886-17924/com.myapp I/OpenGLRenderer: Initialized EGL, version 1.4
2021-11-02 23:15:31.921 17886-17924/com.myapp W/OpenGLRenderer: Failed to choose config with EGL_SWAP_BEHAVIOR_PRESERVED, retrying without...
2021-11-02 23:15:31.925 17886-17924/com.myapp D/EGL_emulation: eglCreateContext: 0x7ff0504fa320: maj 3 min 0 rcv 3
2021-11-02 23:15:31.925 17886-17913/com.myapp V/FA: Upload scheduled in approximately ms: 2087017
2021-11-02 23:15:31.926 17886-17913/com.myapp V/FA: Unscheduling upload
2021-11-02 23:15:31.927 17886-17913/com.myapp V/FA: Scheduling upload, millis: 2087017
2021-11-02 23:15:31.928 17886-17924/com.myapp D/EGL_emulation: eglMakeCurrent: 0x7ff0504fa320: ver 3 0 (tinfo 0x7ff05d016b40)
2021-11-02 23:15:31.929 17886-17924/com.myapp E/eglCodecCommon: glUtilsParamSize: unknow param 0x00008cdf
2021-11-02 23:15:31.929 17886-17924/com.myapp E/eglCodecCommon: glUtilsParamSize: unknow param 0x00008824
2021-11-02 23:15:31.942 17886-17924/com.myapp D/EGL_emulation: eglMakeCurrent: 0x7ff0504fa320: ver 3 0 (tinfo 0x7ff05d016b40)
2021-11-02 23:15:31.952 17886-17886/com.myapp V/FA: Bound to IMeasurementService interface
2021-11-02 23:15:31.953 17886-17913/com.myapp V/FA: Connected to service
2021-11-02 23:15:31.954 17886-17913/com.myapp V/FA: Processing queued up service tasks: 5
2021-11-02 23:15:31.956 17886-17913/com.myapp V/FA: Storage concurrent access okay
2021-11-02 23:15:31.971 17886-17913/com.myapp V/FA: Parsed config. version, gmp_app_id: 1630707713501066, 1:483778118943:android:c6a45e2f9497b6ac
2021-11-02 23:15:31.975 17886-17913/com.myapp D/FA: Unable to get advertising id: com.google.android.gms.common.GooglePlayServicesNotAvailableException: com.google.android.gms.measurement.internal.zzjp.b(SourceFile:12)
2021-11-02 23:15:32.027 17886-17913/com.myapp V/FA: Logging event: origin=auto,name=screen_view(_vs),params=Bundle[{ga_event_origin(_o)=auto, ga_screen_class(_sc)=SplashActivity, ga_screen_id(_si)=-5424791619731338053}]
2021-11-02 23:15:32.029 17886-17913/com.myapp A/libc: Fatal signal 11 (SIGSEGV), code 1, fault addr 0x25ff70 in tid 17913 (Measurement Wor)
2021-11-02 23:15:32.119 17886-17900/com.myapp E/SQLiteLog: (1) table log_event_dropped already exists
2021-11-02 23:15:32.119 17886-17900/com.myapp W/TransportRuntime: Error scheduling event table log_event_dropped already exists (code 1): , while compiling: CREATE TABLE log_event_dropped (log_source VARCHAR(45) NOT NULL,reason INTEGER NOT NULL,events_dropped_count BIGINT NOT NULL,PRIMARY KEY(log_source, reason))
2021-11-02 23:15:32.120 17886-17908/com.myapp W/FirebaseCrashlytics: Crashlytics report could not be enqueued to DataTransport
android.database.sqlite.SQLiteException: table log_event_dropped already exists (code 1): , while compiling: CREATE TABLE log_event_dropped (log_source VARCHAR(45) NOT NULL,reason INTEGER NOT NULL,events_dropped_count BIGINT NOT NULL,PRIMARY KEY(log_source, reason))
at android.database.sqlite.SQLiteConnection.nativePrepareStatement(Native Method)
at android.database.sqlite.SQLiteConnection.acquirePreparedStatement(SQLiteConnection.java:887)
at android.database.sqlite.SQLiteConnection.prepare(SQLiteConnection.java:498)
at android.database.sqlite.SQLiteSession.prepare(SQLiteSession.java:588)
at android.database.sqlite.SQLiteProgram.<init>(SQLiteProgram.java:58)
at android.database.sqlite.SQLiteStatement.<init>(SQLiteStatement.java:31)
at android.database.sqlite.SQLiteDatabase.executeSql(SQLiteDatabase.java:1674)
at android.database.sqlite.SQLiteDatabase.execSQL(SQLiteDatabase.java:1605)
at com.google.android.datatransport.runtime.scheduling.persistence.SchemaManager.k(SourceFile:1)
at com.google.android.datatransport.runtime.scheduling.persistence.SchemaManager.e(SourceFile)
at w20.upgrade(SourceFile)
at com.google.android.datatransport.runtime.scheduling.persistence.SchemaManager.m(SourceFile:2)
at com.google.android.datatransport.runtime.scheduling.persistence.SchemaManager.onUpgrade(SourceFile:2)
at android.database.sqlite.SQLiteOpenHelper.getDatabaseLocked(SQLiteOpenHelper.java:256)
at android.database.sqlite.SQLiteOpenHelper.getWritableDatabase(SQLiteOpenHelper.java:163)
at g20.a(SourceFile)
at com.google.android.datatransport.runtime.scheduling.persistence.SQLiteEventStore.r0(SourceFile:2)
at com.google.android.datatransport.runtime.scheduling.persistence.SQLiteEventStore.E(SourceFile:3)
at com.google.android.datatransport.runtime.scheduling.persistence.SQLiteEventStore.runCriticalSection(SourceFile:1)
at com.google.android.datatransport.runtime.scheduling.DefaultScheduler.d(SourceFile:8)
at com.google.android.datatransport.runtime.scheduling.DefaultScheduler.a(SourceFile)
at fd.run(SourceFile)
at q20$a.run(SourceFile:1)
at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1113)
at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:588)
at java.lang.Thread.run(Thread.java:818)
2021-11-02 23:15:32.124 17886-17900/com.myapp E/SQLiteLog: (1) table log_event_dropped already exists
2021-11-02 23:15:32.124 17886-17900/com.myapp W/TransportRuntime: Error scheduling event table log_event_dropped already exists (code 1): , while compiling: CREATE TABLE log_event_dropped (log_source VARCHAR(45) NOT NULL,reason INTEGER NOT NULL,events_dropped_count BIGINT NOT NULL,PRIMARY KEY(log_source, reason))
2021-11-02 23:15:32.125 17886-17908/com.myapp W/FirebaseCrashlytics: Crashlytics report could not be enqueued to DataTransport
android.database.sqlite.SQLiteException: table log_event_dropped already exists (code 1): , while compiling: CREATE TABLE log_event_dropped (log_source VARCHAR(45) NOT NULL,reason INTEGER NOT NULL,events_dropped_count BIGINT NOT NULL,PRIMARY KEY(log_source, reason))
at android.database.sqlite.SQLiteConnection.nativePrepareStatement(Native Method)
at android.database.sqlite.SQLiteConnection.acquirePreparedStatement(SQLiteConnection.java:887)
at android.database.sqlite.SQLiteConnection.prepare(SQLiteConnection.java:498)
at android.database.sqlite.SQLiteSession.prepare(SQLiteSession.java:588)
at android.database.sqlite.SQLiteProgram.<init>(SQLiteProgram.java:58)
at android.database.sqlite.SQLiteStatement.<init>(SQLiteStatement.java:31)
at android.database.sqlite.SQLiteDatabase.executeSql(SQLiteDatabase.java:1674)
at android.database.sqlite.SQLiteDatabase.execSQL(SQLiteDatabase.java:1605)
at com.google.android.datatransport.runtime.scheduling.persistence.SchemaManager.k(SourceFile:1)
at com.google.android.datatransport.runtime.scheduling.persistence.SchemaManager.e(SourceFile)
at w20.upgrade(SourceFile)
at com.google.android.datatransport.runtime.scheduling.persistence.SchemaManager.m(SourceFile:2)
at com.google.android.datatransport.runtime.scheduling.persistence.SchemaManager.onUpgrade(SourceFile:2)
at android.database.sqlite.SQLiteOpenHelper.getDatabaseLocked(SQLiteOpenHelper.java:256)
at android.database.sqlite.SQLiteOpenHelper.getWritableDatabase(SQLiteOpenHelper.java:163)
at g20.a(SourceFile)
at com.google.android.datatransport.runtime.scheduling.persistence.SQLiteEventStore.r0(SourceFile:2)
at com.google.android.datatransport.runtime.scheduling.persistence.SQLiteEventStore.E(SourceFile:3)
at com.google.android.datatransport.runtime.scheduling.persistence.SQLiteEventStore.runCriticalSection(SourceFile:1)
at com.google.android.datatransport.runtime.scheduling.DefaultScheduler.d(SourceFile:8)
at com.google.android.datatransport.runtime.scheduling.DefaultScheduler.a(SourceFile)
at fd.run(SourceFile)
at q20$a.run(SourceFile:1)
at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1113)
at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:588)
at java.lang.Thread.run(Thread.java:818)
Solution
I finally figured how to go about this.
FirebaseCrashlytics initializes even before the Application class is executed and therefore in release mode on a device without Google Play Service it instantly crashes. The best way to handle this properly is to disable FirebaseCrashlytics from immediately trying to collect any analytics data when running the app by disabling analytics collection in the Android Manifest:
<meta-data
android:name="firebase_analytics_collection_enabled"
android:value="false" />
Then in the Application class, we can check if Google Play Services is available. If so we can proceed to enable analytics by Firebase:
class MyApp : Application(){
override fun onCreate() {
super.onCreate()
if(isGooglePlayServicesAvailable()){
FirebaseCrashlytics.getInstance().setCrashlyticsCollectionEnabled(true)
}else{
//show user proper error
}
}
private fun isGooglePlayServicesAvailable(): Boolean {
val googleApiAvailability = GoogleApiAvailability.getInstance()
val status = googleApiAvailability.isGooglePlayServicesAvailable(this)
if (status != ConnectionResult.SUCCESS) {
return false
}
return true
}
}
Answered By - tendai
0 comments:
Post a Comment
Note: Only a member of this blog may post a comment.