Firebase runloop(3.0.0)中未捕获的异常

时间:2016-06-09 11:32:50

标签: android firebase

我使用的是最新的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'

项目build.gradle

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

经过一段时间,应用程序开始崩溃,这个异常:

  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)

在onCreate of Application我有:

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

并且我们还为Firebase创建了单例助手类,从活动调用(同一进程中的所有活动)/片段:

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

库:

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')
}

7 个答案:

答案 0 :(得分:11)

更新:正如Kristijan在评论中所提到的那样,这就是这种症状的另一个原因。我们已经确定了一个错误,如果你有一个带有整数终点的startAt()或endAt()调用,例如startAt(10),它可以触发这种缓存损坏。此错误将在SDK的下一个版本中修复。在此期间,您可以使用非整数端点,例如startAt(10.001),作为解决方法。

这些症状符合Firebase实时数据库的已知限制,如果您在Android应用中的多个进程中启用了持久性,则会阻止其工作。

请注意,任何Application.onCreate()代码都会针对多进程Android应用中的每个进程运行,因此,如果您的应用是多进程的,那么您正在初始化Firebase数据库,并在多个进程中启用持久性,这是负责任的导致我们的脱机缓存损坏以及您报告的hardAssert错误。

请记住,有时您的应用可能是多进程,而您却没有意识到。例如,如果你正在使用firebase-crash,它目前会创建一个后台进程,以便更可靠地报告崩溃,因此如果你使用firebase-crash,你现在有了一个多进程应用程序。其他第三方库可能有类似的行为。

要进行测试,您可以向Application.onCreate()添加代码,例如:

System.out.println('INITIALIZING APP FROM PID: ' + android.os.Process.myPid());

如果你看到在logcat中记录了两次(有两个不同的PID),这意味着你的应用程序正在运行多个进程,而你正在达到我提到的限制。

作为解决方法,您可以:

  1. 修改您的应用,使其仅使用一个流程。
  2. 从Application类中删除setPersistenceEnabled()代码,并将其放在只在主进程中执行的地方。
  3. 请注意,您可能需要清除您的应用数据,以便在您点击之后摆脱hardAssert错误,因为错误表明离线缓存已进入无效状态,因此修复它,你必须完全清除它。

    在即将发布的版本中,我们添加了对此方案的更好检测,以便您获得更好的错误消息。此外,firebase-crash将来会避免产生第二个进程,这可能会降低这个问题。

答案 1 :(得分:8)

我们在版本9.0.29.2.0上遇到了同样的问题。经过数小时的调查,我们发现重现此问题的一种方法是使用固定的endAtstartAt参数进行查询。让我解释一下示例代码:

// 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);
            }
        });
    }
}

因此固定的endAt param会在第三次启动时崩溃应用程序。我假设查询被缓存到磁盘然后在某些时候损坏,如果我们多次从本地缓存重新创建相同的查询(三)。另一方面,如果endAt未修复,例如以毫秒为单位的当前时间,那么一切都按预期工作。这同样适用于startAt查询参数。

答案 2 :(得分:5)

我也面临同样的问题;经过一段时间后,应用程序在每次启动时都会崩溃。 暂时我已禁用此数据库持久性。 FirebaseDatabase.getInstance().setPersistenceEnabled(true)

我现在没有看到任何这种奇怪的崩溃!

Hope Firebase团队很快就会解决这个问题。

答案 3 :(得分:4)

我知道这是一个旧帖子,我遇到了这个问题,经过一番研究,我将gradle升级为:      实现'com.google.firebase:firebase-database:18.0.1' 这有助于消除错误。使用最新的库。 这解决了我的问题。

答案 4 :(得分:2)

This issue has been fixed in version 9.6. Check out the release notes.

However, when we enable the offline capabilities internet connection is still required for our app. Otherwise, write (at least) callbacks are never called.

答案 5 :(得分:0)

仅供记录:

我们通过删除后续行解决了Uncaught exception in Firebase runloop (3.0.0)

//remove this "feature" if you should use it
FirebaseApp.setAutomaticResourceManagmentEnabled(true)

API说明:

  

如果设置为true,则表示Firebase应关闭数据库   应用程序在后台时自动连接。残   默认情况下。

(可能是,我们错过了正确使用此功能的一些配置,但是在未启用ResourceManagment后App正在按预期工作)

答案 6 :(得分:-1)

我有这个问题,如果安装是新的,这个方法有用,如果把代码放在这个方法中,这个方法有效:

        FirebaseDatabase.getInstance().setPersistenceEnabled(true);
        FirebaseDatabase database = FirebaseDatabase.getInstance();

但如果在其他设备上测试,则需要卸载该应用