使用 Google Play 游戏进行 Firebase 身份验证

Posted

技术标签:

【中文标题】使用 Google Play 游戏进行 Firebase 身份验证【英文标题】:Firebase Authentication with Google Play Games 【发布时间】:2019-10-30 06:44:25 【问题描述】:

我正在为安卓创建游戏。每个用户都需要经过身份验证。

目前,当新用户启动游戏时,它会从我的服务器请求一个识别码,并将其存储到 SharedPreferences。下次用户启动游戏时,它会使用此存储的识别码进行身份验证。问题是,当用户清除这个应用的数据时,他无法找回他的ID,所以他永远失去了他的进步。

有没有办法使用 Firebase Play 游戏身份验证方法生成唯一且对于一个玩家始终相同的识别码?

GoogleSignInOptions gso = new GoogleSignInOptions.Builder(GoogleSignInOptions.DEFAULT_GAMES_SIGN_IN)
                .requestServerAuthCode("MyCID")
                .build();

        mAuth = FirebaseAuth.getInstance();
        super.onCreate(savedInstanceState);
        final FirebaseAuth auth = FirebaseAuth.getInstance();
        AuthCredential credential = PlayGamesAuthProvider.getCredential("MyCID");
        auth.signInWithCredential(credential)
                .addOnCompleteListener(this, new OnCompleteListener<AuthResult>() 
                    public void onComplete(@NonNull Task<AuthResult> task) 
                        if (task.isSuccessful()) 
                            currentUser = auth.getCurrentUser();
                         else 
                            Toast.makeText(MainActivity.this, "Authentication failed.",
                                    Toast.LENGTH_SHORT).show();
                        
                    
                );
        if (currentUser == null) 
            cu = "NO UID";
         else 
            cu = currentUser.getUid();
        

我尝试了这段代码(MyCID 在哪里:我使用了下图中的 CID),但没有显示 Google Play 游戏弹出窗口,我得到 Authentication Failed toast 并且 cu 设置为“NO UID”。

有人可以解释一下这是如何工作的吗?


编辑

感谢@crysxd,我的应用现在显示绿色的 google play 游戏弹出窗口。但是,正如我在其他使用谷歌游戏登录的游戏中看到的那样,我收到了一个错误,提示“com.google.android.gms.common.api.ApiException: 4:”,而不是预期的“选择一个帐户”弹出窗口。

我需要运行一个函数来显示这个对话框吗?是我遗漏了什么,还是我在 Google Play 控制台中错误地配置了游戏?

我当前的代码:link

【问题讨论】:

【参考方案1】:

您在这里跳过了一个重要步骤。 Firebase 文档通常非常好,但对 Play 登录的描述很差。

第一步做对了:您需要设置GoogleSignInOptions,但您错过了将它们传递给GoogleSignInClient

onCreate中创建一个客户端:

private static final int RC_SIGN_IN = 543;
private GoogleSignInClient mGoogleSignInClient;

public void onCreate(Bundle savedInstancestate) 
    super.onCreate(savedInstancestate)

    // ...

    GoogleSignInOptions gso = new GoogleSignInOptions.Builder(GoogleSignInOptions.DEFAULT_GAMES_SIGN_IN)
            .requestServerAuthCode("MyCID")
            .build();

    mGoogleSignInClient= GoogleSignIn.getClient(this, gso)

当点击登录按钮或您想开始登录时调用此方法。这将导致显示登录对话框。

private void signIn() 
    Intent signInIntent = mGoogleSignInClient.getSignInIntent();
    startActivityForResult(signInIntent, RC_SIGN_IN);

获取登录响应并处理它

@Override
public void onActivityResult(int requestCode, int resultCode, Intent data) 
    super.onActivityResult(requestCode, resultCode, data);

    // Result returned from launching the Intent from 
    GoogleSignInApi.getSignInIntent(...);
    if (requestCode == RC_SIGN_IN) 
        Task<GoogleSignInAccount> task = GoogleSignIn.getSignedInAccountFromIntent(data);
        try 
            // Google Sign In was successful, authenticate with Firebase
            GoogleSignInAccount account = task.getResult(ApiException.class);
            firebaseAuthWithGoogle(account);
         catch (ApiException e) 
            // Google Sign In failed, update UI appropriately
            Log.w(TAG, "Google sign in failed", e);
        
    

最后,您的代码开始发挥作用。现在我们有了调用PlayGamesAuthProvider.getCredential(...) 所需的GoogleSignInAccount。您在这里传递了您的客户 ID,但这是错误的。它是这样工作的:您将您的客户 ID 提供给 Google 只是为了告诉他们您是谁(或哪个应用程序)。他们会让用户登录并给你一个特殊的令牌(“id 令牌”),然后 Firebase 可以使用它从 Google Play 游戏中获取有关用户的信息。这就是您需要在此处提供给 Firebase 的令牌:

private void firebaseAuthWithGoogle(GoogleSignInAccount acct) 
    Log.d(TAG, "firebaseAuthWithGoogle:" + acct.getId());

    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()) 
                    // Sign in success, update UI with the signed-in user's information
                    Log.d(TAG, "signInWithCredential:success");
                    FirebaseUser user = mAuth.getCurrentUser();
                    updateUI(user);
                 else 
                    // If sign in fails, display a message to the user.
                    Log.w(TAG, "signInWithCredential:failure", task.getException());
                    Snackbar.make(findViewById(R.id.main_layout), "Authentication Failed.", Snackbar.LENGTH_SHORT).show();
                    updateUI(null);
                

                // ...
            
        );

希望对您有所帮助!您可以在文档 here 和 here 中找到引用的完整代码(这些是他们在文档中显示 sn-ps 的文件)。

【讨论】:

好吧,它有效,我得到了 google play games 弹出窗口,但我在 onActivityResult 方法中遇到错误,就在这里GoogleSignInAccount account = task.getResult(ApiException.class);ApiException e 说“com.google.android.gms.common.api.ApiException: 4:”我找不到这个错误代码 4 是什么意思。 image Google 只为您提供定义为 here 的错误代码。 4 表示需要登录,这没有太大意义。看看here 好像少了点什么。我找到了一个带有 Google Games Auth 的应用程序,并且有一个弹出窗口显示“选择帐户以继续”。我没有这个弹出窗口,它只显示“需要登录”错误。 是的,当您启动意图时应该会弹出对话框。对话框的结果被传递给 onActivityResult。如第一条评论中所述,我认为这已经对您有用。您还看到什么其他对话框?您是否在设备上使用 Google 帐户登录?你能和整个班级一起做一个 GitHub 要点吗?

以上是关于使用 Google Play 游戏进行 Firebase 身份验证的主要内容,如果未能解决你的问题,请参考以下文章

Unity Google Play 游戏插件:错误未授权

Unity 中的 Google Play 游戏服务无法进行身份验证

Google Play 游戏无法在 Android 中进行身份验证

通过 Firebase 身份验证使用 Google Play 游戏

如何将 Google Play 游戏登录与 Firebase 身份验证结合使用

google play services 分别开发登录活动和游戏活动