【问题标题】:Firebase Auth - A network error (such as timeout, interrupted connection or unreachable host) has occurredFirebase 身份验证 - 发生网络错误(例如超时、连接中断或主机无法访问)
【发布时间】:2019-07-25 01:53:34
【问题描述】:

更新

我的应用在实时应用中不断出现这种崩溃。每周有 100-200 次崩溃。所以我开始在这个问题上悬赏。如果有人解决了。请帮忙。

但是,99% 的用户没有崩溃。这些崩溃可能会影响我的应用在 Play-store 上的存储库。因此,如果我没有得到解决方案,那么我最终将删除此功能以在 FirebaseAuth 中通过电子邮件/密码登录:/

问题:

我在 Android 应用 Firebase Auth Login 中遇到了很多崩溃(来自 249 位用户的 295 次崩溃)。 1-2% 尝试通过电子邮件密码登录的用户会遇到此崩溃。我研究了这个错误并得到提示,当播放服务未运行时会发生这种情况this answer.

仅供参考,google/facebook auth 运行良好。此问题仅在通过电子邮件密码登录时出现。

我尝试了什么?

我试图在登录方法上放置一个 try-catch 块。并试图捕捉到这个异常。作为解决方案,我想显示一个关于通知用户播放服务未运行的对话框。并且他可以手动打开play-store启动play-service,然后再访问这个。

但正如我在 Fabric 上看到的,崩溃永远不会出现在 catch 块中,并且当发生此异常时应用程序会崩溃。因为这个错误是在 FirebaseAuth SDK 中抛出的。

需要什么?

首先我想确定这个异常的原因。如果由于播放服务未运行而发生这种情况,那么我想向用户显示一个对话框。当前从不显示,并且在出现以下异常后崩溃。

Fatal Exception: com.google.android.gms.g.f: com.google.firebase.e: A network error (such as timeout, interrupted connection or unreachable host) has occurred.
       at com.google.android.gms.tasks.zzu.getResult(Unknown Source)
       at com.startech.dreamteam11.app.activities.ActivityLogin.tryLogin(Unknown Source)
       at com.startech.dreamteam11.app.activities.ActivityLogin.lambda$-wlX6lv_j3Q0nUN9OuqzHS7ZGP4(Unknown Source)
       at com.startech.dreamteam11.app.activities.-$$Lambda$ActivityLogin$-wlX6lv_j3Q0nUN9OuqzHS7ZGP4.onComplete(lambda)
       at com.google.android.gms.tasks.zzj.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:145)
       at android.app.ActivityThread.main(ActivityThread.java:6946)
       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:1404)
       at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:1199)

代码

    private void loginViaEmailPassword(String email, String pass) {
        showProgressBar();
        try {
             // check if user is registered. then try login
            FirebaseAuth.getInstance().fetchSignInMethodsForEmail(email).addOnCompleteListener(task -> {
                SignInMethodQueryResult result = task.getResult();
                if (task.isSuccessful() && result != null && result.getSignInMethods() != null && result.getSignInMethods().size() > 0) {
                    // user is registered, now try login
                    tryLogIn(email, pass, new OnFireBaseLogin() {
                        @Override
                        public void onSuccess(FirebaseUser user) {
                            // check if email is verified, if not send verification email.
                            if (user.isEmailVerified()) {
                                // user is verified, redirect to main screen
                                startMainActivity();
                            } else {
                                sendVerificationEmail(user, task1 -> {
                                    hideProgressBar();
                                    FirebaseAuth.getInstance().signOut();
                                    if (task1.isSuccessful()) {
                                        Utilities.getInstance().showDialog(ActivityLogin.this, getString(R.string.sent_verification_email), getString(R.string.msg_sent_verification_email), (dialog, which) -> {
                                            dialog.dismiss();
                                        });
                                    } else {
                                        errorMessage(getString(R.string.msg_error_sending_email));
                                    }
                                });
                            }
                        }

                        @Override
                        public void onError(int error, @Nullable Throwable exception) {
                            hideProgressBar();
                            assert exception != null;
                            {
                                App.getInstance().logException(new Exception(exception), getClass());
                                errorMessage(exception.getMessage());
                            }
                        }
                    });
                } else {
                    hideProgressBar();
                    errorMessage(getString(R.string.msg_email_not_registered));
                }
            });
        } catch (Exception e) {
            hideProgressBar();
            App.getInstance().logException(e, getClass(), true);
            Utilities.getInstance().showDialog(this, getString(R.string.some_error_occurred), getString(R.string.msg_fail_login_play_service)).show();
        }
    }

    public void tryLogIn(String email, String pass) {
        FirebaseAuth.getInstance().signInWithEmailAndPassword(email, pass).addOnCompleteListener(new OnCompleteListener<AuthResult>() {
            @Override
            public void onComplete(@NonNull Task<AuthResult> task) {
                FirebaseUser currentUser = FirebaseAuth.getInstance().getCurrentUser();
                if (task.isSuccessful() && currentUser != null) {
                    Log.w(TAG, "signInWithCustomToken:success", task.getException());
                    successResponse(currentUser);
                } else {
                    Log.w(TAG, "signInWithCustomToken:failure", task.getException());
                    errorResponse(0, task.getException());
                }
            }
        });
    }

【问题讨论】:

  • @Frank van Puffelen 请查看问题。
  • 上周与 GCP 状态无关,也许吧? status.cloud.google.com
  • @Racu 没有找到你。
  • 由于我在您的 logcat 中看到网络错误,认为可能与大约三天前的 GCP 中断有关。但是,如果您仍然有这些问题,则可能与此无关。在此期间,我遇到了与这些中断有关的一些问题。
  • @Racu 是的,我也可以看到过去 24 小时内的崩溃。

标签: android firebase firebase-authentication


【解决方案1】:

试试这个代码

bt.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                if (Validation.loginValidation(edtEmail, edtPass)) {
                    loginFirebase(edtEmail.getText().toString(), edtPass.getText().toString(), firebaseAuth);
                }
            }
        });




public void loginFirebase(String email, String pass, FirebaseAuth firebaseAuth) {
        progressDialog.setTitle("Please Wait.....");
        progressDialog.setMessage("Processing....");
        progressDialog.setCancelable(false);
        progressDialog.show();
        (firebaseAuth.signInWithEmailAndPassword(email, pass)).addOnCompleteListener(new OnCompleteListener<AuthResult>() {
            @Override
            public void onComplete(@NonNull Task<AuthResult> task) {
                if (task.isSuccessful()) {
                    progressDialog.dismiss();
                    Toast.makeText(getActivity(), "Login Successful", Toast.LENGTH_LONG).show();
                    Intent i = new Intent(getActivity(), DrawerMain.class);
                    startActivity(i);
                    edtEmail.setText("");
                    edtPass.setText("");
                } else {
                    Log.e("Error", task.getException().toString());
                    Toast.makeText(getActivity(), task.getException().getMessage(), Toast.LENGTH_LONG).show();
                }
            }
        });
    }

希望对你有帮助!

谢谢。

【讨论】:

  • 这段代码有什么不同?您正在使用相同的方式登录。调用相同的方法。顺便说一句,我的代码也运行良好。只是在 1% 的情况下它会崩溃。
  • 您使用了很多 if 和 else 条件,所以我认为这会变得复杂,因此会产生错误。
  • 而且当 google play 服务没有运行时也可能发生。尝试启动 Play 商店并检查它是否正常工作。如果不是重启设备问题。如果不更新 google play 服务,还比较项目中使用的 google play 服务和设备中的 google play 服务是否相同。这只是一个小但可能的情况,它给出了例外。
  • 对于您的第一条评论 - 我试图处理这个异常。所以你看看还有没有。这不是原因,很多if-else 发生错误。
  • 第二条评论 - 我已经出于同样的原因进行了编码(播放服务未运行)。但这似乎行不通。所以我问了先生。
【解决方案2】:

在使用addOnCompleteListener时,总是需要检查task是否成功。

试试看,

somethingTask().addOnCompleteListener(task -> {
    if (!task.isSuccessful()) {
        Log.wtf(TAG, "somethingTask:ERROR", task.getException());
        return;
    }
    Log.i(TAG, "somethingTask:SUCCESS");
    // Now we are logged in, let's write next code!
}

我正在根据您在 tryLogin 方法中从 getResult 抛出错误的错误堆栈跟踪来编写此答案。

+ 你不会像这种方式捕获异常,因为addOnCompleteListener 是一个asynchronous 方法。

【讨论】:

  • 感谢您的帮助。你检查我的鳕鱼了吗?我正在我的代码中检查task.isSuccessFull()
  • @Khemraj 我检查了您的代码,您的错误堆栈跟踪和提供的代码看起来略有不同。你的错误有tryLogin,但代码有tryLogInOnFireBaseLogin定义在哪里?
  • @Khemraj 特别是,您在isSuccessful 检查方法之外使用getResult。我建议您仅在任务成功时使用getResult
  • OnFireBaseLogin 是一个接口回调,我删除了它以使问题简短易懂。
  • 哦,我怎么错过了。也许这就是问题所在。检查task.isSuccessful() 后,我应该移动getResult()。我会试试的。
猜你喜欢
  • 2020-04-13
  • 1970-01-01
  • 2021-11-02
  • 2018-01-26
  • 2017-02-24
  • 2021-08-28
  • 1970-01-01
  • 2019-10-04
  • 2021-01-03
相关资源
最近更新 更多