简体   繁体   English

在 Firebase 中检查用户是否首次通过身份验证 在 Android 中进行 Google 身份验证

[英]Check if user is authenticated for the first time in Firebase Google Authentication in Android

I am using Firebase Authentication in an Android application, and I am using Google account authentication as an option to sign in to the application.我在 Android 应用程序中使用 Firebase 身份验证,并且我使用 Google 帐户身份验证作为登录应用程序的选项。

How can I know if the user is signed in to the application for the first time or not?我如何知道用户是否是第一次登录应用程序?

To check if it's the first time user logs in, simply call the AdditionalUserInfo.isNewUser() method in the OnCompleteListener.onComplete callback.要检查用户是否是第一次登录,只需在OnCompleteListener.onComplete回调中调用AdditionalUserInfo.isNewUser()方法即可。

Example code below, be sure to check for null.下面的示例代码,请务必检查是否为空。

OnCompleteListener<AuthResult> completeListener = new OnCompleteListener<AuthResult>() {
        @Override
        public void onComplete(@NonNull Task<AuthResult> task) {
            if (task.isSuccessful()) {
                boolean isNew = task.getResult().getAdditionalUserInfo().isNewUser();
                Log.d("MyTAG", "onComplete: " + (isNew ? "new user" : "old user"));
            }
        }
    };

Check the docs for more reference AdditionalUserInfo检查文档以获取更多参考AdditionalUserInfo

From theFirebase-ui docs , you can check the last sign-in timestamp against the created-at timestamp like this:Firebase-ui docs ,您可以检查上次登录时间戳与 created-at 时间戳,如下所示:

FirebaseUserMetadata metadata = auth.getCurrentUser().getMetadata();
if (metadata.getCreationTimestamp() == metadata.getLastSignInTimestamp()) {
    // The user is new, show them a fancy intro screen!
} else {
    // This is an existing user, show them a welcome back screen.
}

According to the new version of Firebase auth (16.0.1) The AuthResult class has a member function which results true or false (is the user is new).根据Firebase auth (16.0.1)的新版本,AuthResult 类有一个成员函数,结果为真或假(用户是新用户)。 Assuming "credential" is defined in the scope(it is the google credential ) .假设在范围内定义了“凭据”(它是 google credential ) An example is shown below: `一个例子如下所示:`

private FirebaseAuth mAuth;

GoogleSignInOptions gso = new GoogleSignInOptions.Builder(GoogleSignInOptions.DEFAULT_SIGN_IN)
            .requestIdToken(getString(R.string.default_web_client_id))
            .requestEmail()
            .build();

mAuth = FirebaseAuth.getInstance();
Task<GoogleSignInAccount> task = GoogleSignIn.getSignedInAccountFromIntent(data);
GoogleSignInAccount acct = task.getResult(ApiException.class);
AuthCredential credential = GoogleAuthProvider.getCredential(acct.getIdToken(), null);

mAuth.signInWithCredential(credential)
            .addOnCompleteListener(this, new OnCompleteListener<AuthResult>() {
                @Override
                public void onComplete(@NonNull Task<AuthResult> task) {
                    if (task.isSuccessful()) {
                        Log.d(TAG, "linkWithCredential:success");


                        boolean newuser = task.getResult().getAdditionalUserInfo().isNewUser();



                        if(newuser){

                             //Do Stuffs for new user

                         }else{

                            //Continue with Sign up 
                        }

                    } else {

                        Toast.makeText(MyClass.this, "Authentication failed.",
                                Toast.LENGTH_SHORT).show();

                    }


            });

Thanks to firebase:)感谢火力基地:)

From version 11.6.0 we can use AdditionalUserInfo.isNewUser()从版本 11.6.0 我们可以使用AdditionalUserInfo.isNewUser()

https://firebase.google.com/docs/reference/android/com/google/firebase/auth/AdditionalUserInfo https://firebase.google.com/docs/reference/android/com/google/firebase/auth/AdditionalUserInfo

For Web , version 9.0 ( modular ):对于Web ,版本 9.0(模块化):

You will need to import "getAdditionalUserInfo" and call it as such:您将需要导入“getAdditionalUserInfo”并这样调用它:

signInWithPopup(firebaseAuth, provider)
  .then((result) => {
    const details = getAdditionalUserInfo(result)
    console.log(details.isNewUser);
  })
  .catch((error) => {
    console.log(error);
  });

The details returned includes an " isNewUser " boolean property.返回的详细信息包括一个“ isNewUser ”布尔属性。

Details on GitHub from August 2021 2021 年 8 月在 GitHub 上的详细信息

A solution when you use Firebase Auth together with Firestore将 Firebase Auth 与 Firestore 结合使用时的解决方案

The root architecture of the Firestore Database would look like this Firestore 数据库的根架构如下所示在此处输入图像描述

Use the Firebase Auth currentUser.uid to create a root document for each user.使用 Firebase Auth currentUser.uid为每个用户创建一个根文档。 Start by adding a field called registered_at to the root document as soon as the user is created the first time and then add your specific collections to your root document depending on your use case.首次创建用户后,首先向根文档添加一个名为registered_at的字段,然后根据您的用例将您的特定集合添加到根文档中。

When logging in or signing in you can then check if the document with the registered_at field already exists.登录或登录时,您可以检查带有registered_at字段的文档是否已经存在。 If it doesn't exist yet, then you can treat the user as a new user (assuming the user can not delete or alter the registered_at field later)如果它还不存在,那么您可以将用户视为新用户(假设用户以后不能删除或更改已registered_at的字段)

import com.google.firebase.auth.FirebaseAuth
import com.google.firebase.firestore.DocumentReference
import com.google.firebase.firestore.FirebaseFirestore

fun rootDocument(): DocumentReference? = rootPath()?.let {
    return fireStore().document(it)
}

fun rootPath(): String? {
    val loggedInUser = loggedInUser()
    if (loggedInUser != null) {
        return "users/${loggedInUser.uid}"
    }
    return null
}

fun fireStore() = FirebaseFirestore.getInstance()

fun createWriteBatch() = fireStore().batch()

fun loggedInUser() = fireAuth().currentUser

fun fireAuth(): FirebaseAuth = FirebaseAuth.getInstance()

fun afterSignIn() {

    val rootDocument = rootDocument()
            ?: throw IllegalStateException("root document not found")

    rootDocument.get().addOnCompleteListener {
        val isNewUser = it.result.exists().not()

        if (isNewUser) {
            val batch = createWriteBatch()

            batch.set(rootDocument, HashMap<Any, Any>().apply {
                put("registered_at", System.currentTimeMillis())
            })

            batch.commit().addOnCompleteListener {
                println("this is a new user")
            }

        } else {
            println("this is not a new user")
        }
    }
}

While I fully agree that the most correct way (given the inability to add new fields to the auth user table) is to create a new path for users and store info there, I didn't want to make an additional request after logging in to do this check (I'm using Firestore and requests = money).虽然我完全同意最正确的方法(鉴于无法向 auth user 表添加新字段)是为用户创建新路径并在那里存储信息,但我不想在登录后提出额外请求做这个检查(我正在使用 Firestore 并且请求 = 钱)。

I needed to do this first login check to prompt for a userName (as display name is pulled from Facebook/Google and I wanted to give the option of overriding if it's their first login).我需要进行第一次登录检查以提示输入用户名(因为显示名称是从 Facebook/Google 提取的,如果这是他们的第一次登录,我想提供覆盖选项)。 What I ended up doing was using the photoURL property as a flag to determine if it was their first time or not.我最终做的是使用 photoURL 属性作为标志来确定这是否是他们的第一次。 It's not ideal but maybe someone that wants to save on requests can use this as a workaround.这并不理想,但也许想要节省请求的人可以将其用作解决方法。 It's not as big a deal for Firebase but for Firestore it's more costly for your plan这对 Firebase 来说没什么大不了,但对于 Firestore 来说,这对您的计划来说成本更高

In Firebase UI, JAVA:在 Firebase 用户界面、JAVA 中:

 @Override
    protected void onActivityResult(int requestCode, int resultCode, Intent data) {
        super.onActivityResult(requestCode, resultCode, data);
        Intent i;


        if (requestCode == RC_SIGN_IN) {
            IdpResponse response = IdpResponse.fromResultIntent(data);

            if (resultCode == RESULT_OK) {


                if(response.isNewUser()){
                Log.d(TAG, "onActivityResult: isNewUser "+response.isNewUser());
} else {

                // Successfully signed in
                }

                // ...
            } else {



//               handle error
            }
        }
    }

Workaround I used-我使用的解决方法-

  1. Created a collection in Firestore named 'Users'.在 Firestore 中创建了一个名为“用户”的集合。
  2. Whenever someone signs in, get its uid每当有人登录时,获取其 uid
  3. Search for that uid in the 'Users'.在“用户”中搜索该 uid。 Make sure to name 'Users' documents = user's UID.确保将“用户”文档命名为用户的 UID。
  4. If the document exists, then its the new user, if it doesn't如果文档存在,那么它是新用户,如果不存在
  5. then add that particular user's doc in that collection 'Users'.然后将该特定用户的文档添加到该集合“用户”中。

Trick Used - Use UID to solve this problem. Trick Used - 使用 UID 来解决这个问题。 Thanks, upvote if helpful谢谢,有帮助的话点个赞

First of all Check - if current user uid match with your documents id then it's old user otherwise it's new user首先检查 - 如果当前用户 uid 与您的文档 id 匹配,那么它是旧用户,否则它是新用户

Example例子

private boolean isUserMatch(String currentUserId) {
    firestore.collection(COLLECTION_USER).get().addOnCompleteListener(new OnCompleteListener< QuerySnapshot >() {
        @Override
        public void onComplete(@NonNull @NotNull Task< QuerySnapshot > task) {
            if (task.isSuccessful()) {
                for (QueryDocumentSnapshot documentSnapshot : task.getResult()) {
                    if (currentUserId.equals(documentSnapshot.getId())) {
                        return;
                    }
                }
            }
        }
    }).addOnFailureListener(new OnFailureListener() {
        @Override
        public void onFailure(@NonNull @NotNull Exception e) {
            Log.e(TAG, "onFailure: ", e.getCause());
        }
    });
    return false;
}

Firebase V9 (modular) Firebase V9 (模块化)

Here is a function that worked for me这是对我有用的 function

function isNewUser(auth) {
    let newUser;
    const metadata = auth.currentUser.metadata;
    if (metadata.creationTime == metadata.lastSignInTime) {
      newUser = true;
    } else {
      newUser = false;
    }
    return newUser;
  }

You could use a shorter way:您可以使用更短的方法:

  function isNewUser(auth) {
    const metadata = auth.currentUser.metadata;
    return metadata.creationTime == metadata.lastSignInTime ? true : false;
  }

I have seen something similar that uses functions on the metadata like metadata.getCreationTimeStamp() but that did not work for me.我见过类似的东西,它在元数据上使用函数,比如metadata.getCreationTimeStamp()但这对我不起作用。

Hope that helps!希望有帮助!

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM