IgorB IgorB - 3 months ago 29
Android Question

Uncaught exception in Firebase runloop (3.0.0)

I'm using the latest firebase(9.0.2):

build.gradle:


dependencies {
...
compile "com.google.firebase:firebase-database:9.0.2"
compile 'com.google.firebase:firebase-auth:9.0.2'
}
apply plugin: 'com.google.gms.google-services'


Project
build.gradle


classpath 'com.google.gms:google-services:3.0.0'


And after some time application starts crashing with this Exception:

Fatal Exception: java.lang.RuntimeException: Uncaught exception in Firebase runloop (3.0.0). Please report to support@firebase.com
at com.google.android.gms.internal.zzadp$1$1.run(Unknown Source)
at android.os.Handler.handleCallback(Handler.java:739)
at android.os.Handler.dispatchMessage(Handler.java:95)
at android.os.Looper.loop(Looper.java:135)
at android.app.ActivityThread.main(ActivityThread.java:5274)
at java.lang.reflect.Method.invoke(Method.java)
at java.lang.reflect.Method.invoke(Method.java:372)
at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:909)
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:704)
Caused by java.lang.AssertionError: hardAssert failed:
at com.google.android.gms.internal.zzaiv.zzb(Unknown Source)
at com.google.android.gms.internal.zzaiv.zzaN(Unknown Source)
at com.google.android.gms.internal.zzagh.zzb(Unknown Source)
at com.google.android.gms.internal.zzagh.<init>(Unknown Source)
at com.google.android.gms.internal.zzaga.<init>(Unknown Source)
at com.google.android.gms.internal.zzaga.<init>(Unknown Source)
at com.google.android.gms.internal.zzadp.zza(Unknown Source)
at com.google.android.gms.internal.zzaeu.zzic(Unknown Source)
at com.google.android.gms.internal.zzafc.zzRy(Unknown Source)
at com.google.android.gms.internal.zzafc.zza(Unknown Source)
at com.google.android.gms.internal.zzafc$1.run(Unknown Source)
at java.util.concurrent.Executors$RunnableAdapter.call(Executors.java:422)
at java.util.concurrent.FutureTask.run(FutureTask.java:237)
at java.util.concurrent.ScheduledThreadPoolExecutor$ScheduledFutureTask.access$201(ScheduledThreadPoolExecutor.java:152)
at java.util.concurrent.ScheduledThreadPoolExecutor$ScheduledFutureTask.run(ScheduledThreadPoolExecutor.java:265)
at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1112)
at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:587)
at java.lang.Thread.run(Thread.java:818)


in onCreate of Application I have:

@Override
public void onCreate() {
...
FirebaseDatabase.getInstance().setPersistenceEnabled(true);
}


and also we created singleton helper class for Firebase what called from Activities(all activities in the same process)/Fragments:

private FirebaseHelper() {
mFirebaseRef = FirebaseDatabase.getInstance().getReference();
mFirebaseAuth = FirebaseAuth.getInstance();
mFirebaseAuth.addAuthStateListener(this);
authentication();
}

public static synchronized FirebaseHelper getInstance() {
if (mInstance == null || mInstance.getFirebaseRef() == null) {
mInstance = new FirebaseHelper();
}
return mInstance;
}


Libraries:

dependencies {
testCompile 'junit:junit:4.12'
compile('com.crashlytics.sdk.android:crashlytics:2.5.6@aar') {
transitive = true;
}
compile 'com.google.code.gson:gson:2.6.2'
compile 'com.android.support:support-v4:23.4.0'
compile 'com.android.support:support-v13:23.4.0'
compile 'com.android.support:appcompat-v7:23.4.0'
compile 'com.android.support:design:23.4.0'
compile 'com.android.support:support-annotations:23.4.0'
compile 'com.android.support:gridlayout-v7:23.4.0'
compile 'com.google.android.gms:play-services-base:9.0.2'
compile 'com.google.android.gms:play-services-maps:9.0.2'
compile 'com.google.android.gms:play-services-location:9.0.2'
compile 'com.google.android.gms:play-services-appindexing:9.0.2'
compile 'com.google.android.gms:play-services-analytics:9.0.2'
compile 'com.google.firebase:firebase-messaging:9.0.2'
compile 'com.facebook.android:facebook-android-sdk:4.11.0'
compile 'de.greenrobot:eventbus:2.4.0'
compile 'com.amazonaws:aws-android-sdk-core:2.2.12'
compile 'com.amazonaws:aws-android-sdk-cognito:2.2.12'
compile 'com.amazonaws:aws-android-sdk-s3:2.2.12'
compile 'com.android.support:multidex:1.0.1'
compile 'com.squareup.retrofit2:retrofit:2.0.2'
compile 'com.squareup.retrofit2:converter-gson:2.0.2'
compile 'com.squareup.retrofit2:adapter-rxjava:2.0.2'
compile 'io.reactivex:rxandroid:1.2.0'
compile 'io.reactivex:rxjava:1.1.5'
compile 'com.squareup.okhttp3:logging-interceptor:3.3.1'
compile 'com.github.curioustechizen.android-ago:library:1.3.0'
compile 'com.cedarsoftware:json-io:4.4.0'
compile 'com.timehop.stickyheadersrecyclerview:library:0.4.3@aar'
compile 'joda-time:joda-time:2.9.3'
compile 'com.facebook.fresco:fresco:0.10.0'
compile 'com.facebook.fresco:imagepipeline-okhttp3:0.10.0'
compile 'com.google.firebase:firebase-core:9.0.2'
compile 'com.google.firebase:firebase-invites:9.0.2'
compile 'com.google.firebase:firebase-database:9.0.1'
compile 'com.google.firebase:firebase-auth:9.0.1'
compile 'com.github.jd-alexander:LikeButton:0.2.0'

debugCompile 'com.squareup.leakcanary:leakcanary-android:1.4-beta2'
releaseCompile 'com.squareup.leakcanary:leakcanary-android-no-op:1.4-beta2'
androidTestCompile 'junit:junit:4.12'
androidTestCompile 'com.android.support:support-annotations:23.4.0'
androidTestCompile 'com.android.support.test:runner:0.5'
androidTestCompile 'com.android.support.test:rules:0.5'
compile files('libs/core-3.2.1.jar')
}

Answer

We are facing the same issue on version 9.0.2 and 9.2.0. After many hours of investigation, we found that one way to reproduce this issue is to have a query with fixed endAt and startAt parameters. Let me explain with a sample code:

// Firebase dependencies
compile 'com.google.firebase:firebase-core:9.2.0'
compile 'com.google.firebase:firebase-database:9.2.0'

...

public class MainActivity extends AppCompatActivity {

    private FirebaseDatabase m_Database;
    private static boolean s_persistenceInitialized = false;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);

        m_Database = FirebaseDatabase.getInstance();

        if (!s_persistenceInitialized) {
            m_Database.setPersistenceEnabled(true);
            s_persistenceInitialized = true;
        }

        m_Database.setLogLevel(Level.DEBUG);
    }

    @Override
    protected void onStart() {
        super.onStart();

        long endAt = 100L; // Fixed value: CRASH on third app restart
    //  long endAt = new Date().getTime(); // Dynamic value: NO CRASH
        getGoal("min_per_day", endAt, "some_uid");
    }

    private void getGoal(String p_goalId, long p_endAt, String p_uid) {
        Query ref = m_Database.getReference("v0/data/meditation/goals").child(p_goalId).child(p_uid)
            .orderByChild("time").endAt(p_endAt).limitToLast(1);

        ref.addValueEventListener(new ValueEventListener() {
            @Override
            public void onDataChange(DataSnapshot dataSnapshot) {
                Log.i("FB", "Snapshot: " + dataSnapshot);
            }

            @Override
            public void onCancelled(DatabaseError error) {
                Log.e("FB", "Error: " + error);
            }
        });
    }
}

So the fixed endAt param will crash the app on third start. I assume queries are cached to disk and then corrupted at some point if we recreate the same query from local cache multiple times (three). On the other hand, if endAt is not fixed, for example current time in millis, then everything works as expected. The same applies for startAt query parameter.

Comments