如何在 Firebase 中将 emailAndPasswordAuth 与 PhoneAuth 合并?

2024-01-03

我正在尝试首先使用用户登录Email and Password,然后在它之后,我想要user's Phone Number也。所以我首先使用他的用户签名EmailAndPasswordAuth在一个活动(自定义登录)上,然后,我在下一个活动中通过用户的电话号码登录用户。但由于它成为同一部手机上的两个帐户,我想将这些谷歌和电话凭据合并到一个帐户中。

然后我尝试跟随https://firebase.google.com/docs/auth/android/account-linking https://firebase.google.com/docs/auth/android/account-linking,但这给了我例外。

com.google.firebase.FirebaseException:用户已链接到给定的提供程序。

PhoneAuthActivity.java

String email = intent.getStringExtra("email");
    String password = intent.getStringExtra("pass");

    Toast.makeText(this, "Email" + email + "Password" + password, Toast.LENGTH_SHORT).show();// this is working

    emailCredential = EmailAuthProvider.getCredential(email, password);

    mPhoneNumberField = findViewById(R.id.field_phone_number);
    mVerificationField = findViewById(R.id.field_verification_code);

    mStartButton = findViewById(R.id.button_start_verification);
    mVerifyButton = findViewById(R.id.button_verify_phone);
    mResendButton = findViewById(R.id.button_resend);

    mStartButton.setOnClickListener(this);
    mVerifyButton.setOnClickListener(this);
    mResendButton.setOnClickListener(this);

    mAuth = FirebaseAuth.getInstance();
    mCallbacks = new PhoneAuthProvider.OnVerificationStateChangedCallbacks() {
        @Override
        public void onVerificationCompleted(PhoneAuthCredential credential) {
            Log.d(TAG, "onVerificationCompleted:" + credential);
            signInWithPhoneAuthCredential(credential);
        }

        @Override
        public void onVerificationFailed(FirebaseException e) {
            Log.w(TAG, "onVerificationFailed", e);
            if (e instanceof FirebaseAuthInvalidCredentialsException) {
                mPhoneNumberField.setError("Invalid phone number.");
            } else if (e instanceof FirebaseTooManyRequestsException) {
                Snackbar.make(findViewById(android.R.id.content), "Quota exceeded.",
                        Snackbar.LENGTH_SHORT).show();
            }
        }

        @Override
        public void onCodeSent(String verificationId,
                               PhoneAuthProvider.ForceResendingToken token) {
            Log.d(TAG, "onCodeSent:" + verificationId);
            mVerificationId = verificationId;
            mResendToken = token;
        }
    };
}

private void signInWithPhoneAuthCredential(PhoneAuthCredential credential) {
    mAuth.signInWithCredential(credential)
            .addOnCompleteListener(this, new OnCompleteListener<AuthResult>() {
                @Override
                public void onComplete(@NonNull Task<AuthResult> task) {
                    if (task.isSuccessful()) {
                        Log.d(TAG, "signInWithCredential:success");
                        FirebaseUser user = task.getResult().getUser();
                        linkCredential(emailCredential);
                        startActivity(new Intent(PhoneActivity.this, MainActivity.class));
                        finish();
                    } else {
                        Log.w(TAG, "signInWithCredential:failure", task.getException());
                        if (task.getException() instanceof FirebaseAuthInvalidCredentialsException) {
                            mVerificationField.setError("Invalid code.");
                        }
                    }
                }
            });
}


private void startPhoneNumberVerification(String phoneNumber) {
    PhoneAuthProvider.getInstance().verifyPhoneNumber(
            phoneNumber,        // Phone number to verify
            60,                 // Timeout duration
            TimeUnit.SECONDS,   // Unit of timeout
            this,               // Activity (for callback binding)
            mCallbacks);        // OnVerificationStateChangedCallbacks
}

private void verifyPhoneNumberWithCode(String verificationId, String code) {
    PhoneAuthCredential credential = PhoneAuthProvider.getCredential(verificationId, code);
    signInWithPhoneAuthCredential(credential);
}

private void resendVerificationCode(String phoneNumber,
                                    PhoneAuthProvider.ForceResendingToken token) {
    PhoneAuthProvider.getInstance().verifyPhoneNumber(
            phoneNumber,        // Phone number to verify
            60,                 // Timeout duration
            TimeUnit.SECONDS,   // Unit of timeout
            this,               // Activity (for callback binding)
            mCallbacks,         // OnVerificationStateChangedCallbacks
            token);             // ForceResendingToken from callbacks
}

private boolean validatePhoneNumber() {
    String phoneNumber = mPhoneNumberField.getText().toString();
    if (TextUtils.isEmpty(phoneNumber)) {
        mPhoneNumberField.setError("Invalid phone number.");
        return false;
    }
    return true;
}

@Override
public void onStart() {
    super.onStart();
    FirebaseUser currentUser = mAuth.getCurrentUser();
    if (currentUser != null) {
    }
}

@Override
public void onClick(View view) {
    switch (view.getId()) {
        case R.id.button_start_verification:
            if (!validatePhoneNumber()) {
                return;
            }
            startPhoneNumberVerification(mPhoneNumberField.getText().toString());
            break;
        case R.id.button_verify_phone:
            String code = mVerificationField.getText().toString();
            if (TextUtils.isEmpty(code)) {
                mVerificationField.setError("Cannot be empty.");
                return;
            }

            verifyPhoneNumberWithCode(mVerificationId, code);
            break;
        case R.id.button_resend:
            resendVerificationCode(mPhoneNumberField.getText().toString(), mResendToken);
            break;
    }

}


public void linkCredential(AuthCredential credential) {
    mAuth.getCurrentUser().linkWithCredential(credential)
            .addOnCompleteListener(this, new OnCompleteListener<AuthResult>() {
                @Override
                public void onComplete(@NonNull Task<AuthResult> task) {
                    if (task.isSuccessful()) {
                        Log.d(TAG, "linkWithCredential:success");
                        FirebaseUser user = task.getResult().getUser();
                        Toast.makeText(PhoneActivity.this, "Merged", Toast.LENGTH_SHORT).show();

                    } else {
                        Log.w(TAG, "linkWithCredential:failure", task.getException());


                        Toast.makeText(PhoneActivity.this, "Failed to merge" + task.getException().toString(), Toast.LENGTH_SHORT).show();
                    }

                }
            });
}

正如下面评论的那样,我使用了自己的自定义手机身份验证,而不是使用 Firebase UI 提供的身份验证,请帮助我将这两个帐户合并为一个。

在 firebase Console 中,它正在形成两个帐户。


我猜你的做法是错误的。

文档中提到的流程:

完成新身份验证提供程序的登录流程,直至(但不包括)调用 FirebaseAuth.signInWith 方法之一。例如,获取用户的 Google ID 令牌、Facebook 访问令牌或电子邮件和密码。

正如引自链接身份验证提供者步骤的文档 https://firebase.google.com/docs/auth/android/account-linking#link-auth-provider-credentials-to-a-user-account,提到你不应该调用任何FirebaseAuth.signInWith方法,而不是你需要:-

  1. 获取 AuthCredentialnew认证提供者
  2. 通过AuthCredential反对登录用户的linkWithCredential方法,像这样:

    mAuth.getCurrentUser().linkWithCredential(credential)

由于用户已经与一个身份验证提供商进行了签名,因此我们不需要再次对其进行签名。我们只需要链接两个提供商,以便他能够再次使用任一提供商登录。

正如代码流程所示,验证电话号码后,您将使用以下命令再次让用户登录PhoneAuthCredential,然后您尝试链接emailCredential;当前登录的用户已链接到该用户,因此会出现错误。

这应该是你的代码mCallbacks:

mCallbacks = new PhoneAuthProvider.OnVerificationStateChangedCallbacks() {
        @Override
        public void onVerificationCompleted(PhoneAuthCredential credential) {
            Log.d(TAG, "onVerificationCompleted:" + credential);
            linkCredential(credential);
        }

        @Override
        public void onVerificationFailed(FirebaseException e) {
            Log.w(TAG, "onVerificationFailed", e);
            if (e instanceof FirebaseAuthInvalidCredentialsException) {
                mPhoneNumberField.setError("Invalid phone number.");
            } else if (e instanceof FirebaseTooManyRequestsException) {
                Snackbar.make(findViewById(android.R.id.content), "Quota exceeded.",
                        Snackbar.LENGTH_SHORT).show();
            }
        }

        @Override
        public void onCodeSent(String verificationId,
                               PhoneAuthProvider.ForceResendingToken token) {
            Log.d(TAG, "onCodeSent:" + verificationId);
            mVerificationId = verificationId;
            mResendToken = token;
        }
    };

这是linkCredentials method.

    public void linkCredential(AuthCredential credential) {
    mAuth.getCurrentUser().linkWithCredential(credential)
            .addOnCompleteListener(this, new OnCompleteListener<AuthResult>() {
                @Override
                public void onComplete(@NonNull Task<AuthResult> task) {
                    if (task.isSuccessful()) {
                        Log.d(TAG, "linkWithCredential:success");
                        FirebaseUser user = task.getResult().getUser();
                        Toast.makeText(PhoneActivity.this, "Merged", Toast.LENGTH_SHORT).show();
                        moveToHome();

                    } else {
                        Log.w(TAG, "linkWithCredential:failure", task.getException());
                        Toast.makeText(PhoneActivity.this, "Failed to merge" + task.getException().toString(), Toast.LENGTH_SHORT).show();
                    }
                }
            });
}
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

如何在 Firebase 中将 emailAndPasswordAuth 与 PhoneAuth 合并? 的相关文章

  • 如何替换 Android 中已弃用的 Bundle/Argument get(key) 调用

    我有以下扩展函数 允许我在应用程序活动和片段之间传递捆绑数据项 inline fun
  • 如何使用 gradle 从 3 个子模块构建 1 个 jar

    I have 安卓工作室3 gradle 4 1 梯度工具3 classpath com android tools build gradle 3 0 1 当我有一个模块并使用 gradle 工具 2 时 我使用了 task makeJar
  • 带有 Android 支持库 v7 的 Maven Android 插件

    我使用 maven android plugin 构建我的 android 应用程序 它依赖于 android 支持库 v4 和 v7 由于我没有找到如何从developer android com下载整个sdk 因此我无法使用maven
  • 错误类型 3 - 活动类不存在

    我正在尝试运行 webRTC 应用程序 但返回以下错误 启动应用程序 com onlinevoicecallapp com onlinevoicecallapp MainActivity 设备外壳命令 am start n com onli
  • ExpandableListview OnGroupClickListener 未触发

    我正在关注这个 以编程方式折叠 ExpandableListView 中的组 https stackoverflow com questions 4314777 programmatically collapse a group in ex
  • Android -room 持久库 - DAO 调用是异步的,因此如何获取回调?

    从我读到的Room 不允许您在主线程上发出数据库查询 因为可能会导致主线程延迟 所以想象一下我正在尝试更新 UI 主线程上的文本视图 其中一些数据我将如何得到回调 让我给你举个例子 想象一下 我想将我的业务模型数据存储到一个名为 事件 的对
  • Android蓝牙java.io.IOException:bt套接字已关闭,读取返回:-1

    我正在尝试编写一个代码 仅连接到运行 Android 5 0 KitKat 的设备上的 目前 唯一配对的设备 无论我尝试了多少方法 我仍然会收到此错误 这是我尝试过的最后一个代码 它似乎完成了我看到人们报告为成功的所有事情 有人能指出我做错
  • 控制 OverlayItem 大小

    我正在构建一个在单个 ItemizedOverlay 中包含几十个 OverlayItems 的地图 我的地图设计为可以非常近距离地查看 大约缩放级别 18 并且 OverlayItems 彼此非常接近 地图放大时看起来不错 但是 如果用户
  • 是否可以通过 Android 应用程序来录音?

    我是一名开发人员 希望创建一个 Android 应用程序来记录电话 这是出于我个人的需要 为了我自己的目的和记录而记录电话 是否有可能做到这一点 是否可以访问麦克风以及通过扬声器发出的声音 我对 Android 开发有点陌生 所以请耐心等待
  • 移动设备上的 TensorFlow(Android、iOS、Windows Phone)

    我目前正在寻找不同的深度学习框架 特别是用于训练和部署卷积神经网络 要求是 它可以在带有 GPU 的普通 PC 上进行训练 但训练后的模型必须部署在三个主要的移动操作系统上 即 Android iOS 和 Windows Phone Ten
  • Android 中的库可以有自己的意图过滤器吗?

    我想开发一个可以包含在其他 Android 应用程序中的库来拦截某些类型的意图 是否可以 我创建了一个库和一个测试项目 两者都有自己的AndroidManifest xml文件 在库的清单中 我为操作 TEST 定义了一个意图过滤器 但是
  • 哪个视图最亮?

    在Android中 哪个是轻量级视图 例如 View Textview Edittext 等 在某些情况下 我们需要使用视图来填充区域而不向用户显示视图 同时屏幕加载速度应该很快 您可以使用空间 android widget Space S
  • 受信任的网络活动 - 地址栏不隐藏(Android 72 的 Chrome)

    我已经关注了this https developers google com web updates 2017 10 using twa了解如何使用受信任的 Web 活动的指南 一切正常 但地址栏仍然出现 一开始我认为这是因为当应用程序正在
  • 如何在android中通过蓝牙向配对设备发送短信?

    在我的应用程序中 我想通过蓝牙发送和接收短信 我可以在列表视图中看到配对设备名称和地址的列表 但是当我尝试向配对设备发送文本时 什么也没有发生 在其他设备中没有收到文本 这是我向配对设备发送消息的代码 private void sendDa
  • 如何更改操作栏背景和文本颜色

    我正在使用本教程中的导航抽屉 http www androidhive info 2013 11 android sliding menu using navigation drawer http www androidhive info
  • 检查应用程序是否在 Android Market 上可用

    给定 Android 应用程序 ID 包名称 如何以编程方式检查该应用程序是否在 Android Market 上可用 例如 com rovio angrybirds 可用 而 com random app ibuilt 不可用 我计划从
  • Android MulticastSocket.joinGroup 不会触发发送 IGMP 消息

    Code MulticastSocket s new MulticastSocket InetAddress addr InetAddress getByName 230 230 230 1 s joinGroup addr 在 Ubunt
  • 将对象从手机共享到 Android Wear

    我创建了一个应用程序 在此应用程序中 您拥有包含 2 个字符串 姓名和年龄 和一个位图 头像 的对象 所有内容都保存到 sqlite 数据库中 现在我希望可以在我的智能手表上访问这些对象 所以我想实现的是你可以去启动 启动应用程序并向左和向
  • 从文件路径显示图像视图?

    我需要仅使用文件名而不是资源 ID 来显示图像 ImageView imgView new ImageView this imgView setBackgroundResource R drawable img1 我在可绘制文件夹中有图像
  • LifeCycleAware Fragment 中的片段生命周期事件

    我有一个生命周期感知片段和一个LifecycleObserver class public class MyFragment extends Fragment Override public void onCreate Nullable B

随机推荐

  • 如何在 Visual Studio Team Services 中的托管代理上查找 Android SDK 的位置?

    我想在 VSTS 中的托管构建代理上构建我的 android 项目 因此 我创建了一个 Android 构建定义 将其在 托管 Linux 预览 代理上排队 但我的构建失败并出现以下错误 未找到 SDK 位置 使用 sdk dir 定义位置
  • 如何在没有 FlexBuilder 的情况下将 Cairngorm 的 SWC 文件添加到我的应用程序中?

    我没有使用 FlexBuilder 我使用的是免费的 Flex SDKTextMate http macromates com 我有点不明白什么这个FlexBuilder进程 http nwebb co uk blog p 58实际上 在所
  • 如何在 F# 交互中使用断点?

    我已经开始使用 VS2010 和 F 交互式研究算法中的一些想法 所以 我创建了一个DebugScript fsx 我在那里编写了一些代码 并最终将其发送到 F Int 进行测试 有时我需要捕捉一个错误 但即使是简单的我也无法放置断点for
  • 将背景图像叠加到背景颜色上

    我的网站 http www webbuddies co za http www webbuddies co za 工作完美 但是当以 1280x1024 分辨率查看时 页面底部有一点可见的白色 我想去掉它 背景是渐变图像 我只想更改背景颜色
  • 如何将 TextBlock 设置为属性值?

    I used this http www c sharpcorner com uploadfile mahesh user control in wpf 构建自定义控件的教程 现在 我想向用户控件添加一条简单的消息 文本块 来为用户提供一些
  • 禁用 mongo docker 中的默认身份验证

    我想禁用默认身份验证 避免使用 mongo authenticationDatabase auth db 在 mongo 中使用 docker compose 这是我的docker 撰写 file version 2 services mo
  • 为什么增加 Nginx 中的worker_connections 会使应用程序在node.js 集群中变慢?

    我正在将我的应用程序转换为 Node js 集群 我希望它能够提高我的应用程序的性能 目前 我正在将该应用程序部署到 2 个 EC2 t2 medium 实例 我有 Nginx 作为代理和 ELB 这是我的 Express 集群应用程序 从
  • Keras 的 TensorBoard 回调中嵌入不匹配的张量数量

    我使用的是 CIFAR 10 数据集 因此有 10000 张测试图像 我成功创建了一个 tsv包含元数据的文件 10000 行中每一行的测试集标签 以人类可读的文本形式 而不是索引 但是 在 TensorBoard 中 当我打开嵌入选项卡时
  • Qt fitInView 和调整大小

    我正在尝试做一个QGraphicsView宽度与窗口中心的高度相同 我创建了一个普通的QGraphicsView在 Qt Designer 中并设置最小尺寸 添加了一些居中的计算QGraphicsView进入主窗口的中心 并将宽度设置为与高
  • 使用形状或 9 块图像创建聊天气泡

    我正在尝试在我目前正在开发的 Android 应用程序中为我的聊天气泡创建一个模板 最终结果应该是这样的 我尝试使用 形状 但无法获得正确的多个图层 我还尝试了 9 补丁图像 但创建 9 补丁是我所能做到的 我不知道如何使用它 特别是头像
  • 莺:我的影像在哪里

    我正在使用 Jruby 和 Warbler 将 Jruby on Rails 应用程序部署到 Tomcat 服务器 当我使用 Webrick 部署服务器时 我可以看到所有图像 jruby S server script 但是 当我使用 jr
  • 如何使用 runc 列出 docker 容器

    据我所知runc list允许传递容器存储的根目录 但我不知道要为 docker 传递什么根目录 我试过 var lib docker containers但它说容器不存在 我确实有容器出现在docker ps fyi 或者我假设 dock
  • 大量回调的 NodeJS 性能

    我正在开发 NodeJS 应用程序 有一个特定的 RESTful API GET 当用户触发时 它要求服务器执行大约 10 20 个网络操作 以从不同来源提取信息 所有这些网络操作都是异步回调 一旦它们全部完成 结果将由nodejs应用程序
  • 如何在本地访问Docker容器应用程序?

    我有一个简单的 Node js Express 应用程序 const port 3000 app get req res gt res send Hello World app listen port gt console log Exam
  • 自动增加/减少 UITableViewCell 中的 UILabelView 高度?

    你好 我有一个带有 x 个单元格的 UITableView 最后一个单元格我有两个 UILabel 设置第二个 UILabel 文本时 我试图调整单元格和 UILabel 的大小以显示文本 这是我所拥有的 UILabel LabelBio
  • 使用 AJAX (PHP) 使用另一个 中的值

    我正在尝试使用另一个选择来更改一个选择的值 正如您所看到的 两个选择都是使用 PHP 填充的 现在我想要的是 当选择某个专业时 包含医生的选择会改变 这是代码
  • 文本搜索不适用于 Spring Boot MongoDB

    我正在开发Spring Boot MongoDB spring data mongo Text search例子 通过从链接中获取参考 https spring io blog 2014 07 17 text search your doc
  • 如何从霍夫变换(rho,theta)将坐标转换回图像(x,y)?

    我有一个通过调用 Opencv 中的霍夫变换函数生成的线向量 需要将它们转换回图像坐标 我从Opencv的官方文档中找到了这段示例代码 但我不明白 请有人解释一下吗 for size t i 0 i lt lines gt size i f
  • data.table 中闭包的处理

    我正在使用 data table 包返回函数闭包列表j表达式作为输出approxfun来自 stats 包的函数 基本上 在每个日期 我想要一个闭包 它允许我根据由下式确定的任意 xval 计算任意 yvalapproxfun 然而 app
  • 如何在 Firebase 中将 emailAndPasswordAuth 与 PhoneAuth 合并?

    我正在尝试首先使用用户登录Email and Password 然后在它之后 我想要user s Phone Number也 所以我首先使用他的用户签名EmailAndPasswordAuth在一个活动 自定义登录 上 然后 我在下一个活动