【Unity】Firebase-Google登录身份验证功能接入流程

思路:接入sdk相关Android接口以aar形式提供给Unity使用

目录

一、创建Firebase项目工程

二、创建Android工程 接入Android接口

三、Unity工程配置


参考文档:https://firebase.google.com/docs/auth/android/google-signin#java_1

一、创建Firebase项目工程

https://console.firebase.google.com

进入到console创建工程,按照步骤进行,进入到具体工程console面板后,找到

【Unity】Firebase-Google登录身份验证功能接入流程_第1张图片

【Unity】Firebase-Google登录身份验证功能接入流程_第2张图片

 添加测试用户

【Unity】Firebase-Google登录身份验证功能接入流程_第3张图片

启动Google身份验证

 【Unity】Firebase-Google登录身份验证功能接入流程_第4张图片

 

 【Unity】Firebase-Google登录身份验证功能接入流程_第5张图片

进行到此时下载google-services.json  上面截图有这个按钮,下载下来后 把它拷贝到工程/Assets下,Unity工程,如果你是安卓则拷贝到安卓的应用工程根目录下。创建应用必须确保签名sha和包名和你Unity项目一样的。

【有坑:这里自己根据自己包签名生成的SHA-1只是测试用的,等发布到google之后需要用google提供的上传密钥签名SHA-1 具体在最下方已经有说明 和 一个报错关联com.google.android.gms.common.api.ApiException: 10:

此时已经进行完基本的Firebase工程配置

2022年2月10日补充说明:

查看密钥方法:keytool -list -v -keystore google.keystore
其中,google.keystore是密钥文件名,需先cd到该文件的目录下执行这条命令

编辑了SHA列表后需要重新导出google-services.json更新工程!不然是不会生效的

二、创建Android工程 接入Android接口

1、需在(应用级)app/build.gradle添加如下依赖

dependencies {

    ...

    implementation platform('com.google.firebase:firebase-bom:28.4.0')
    implementation 'com.google.firebase:firebase-analytics'
    implementation 'com.google.firebase:firebase-auth'
    implementation 'com.google.android.gms:play-services-auth:19.2.0'
}

 其中analytics可能不需要 它是一个firebase分析工具的依赖

2、配置Firebase项目具体应用的SHA指纹,需要准备Unity包签名文件keystore 用如下文档方式进行获取SHA。(上方已经提及,这里给个文档)

https://developers.google.com/android/guides/client-auth

3、具体接口代码接入 MainActivity.java代码源码:

package com.test.googleloginTest1102;

import androidx.annotation.NonNull;
import androidx.appcompat.app.AppCompatActivity;

import android.content.Intent;
import android.os.Bundle;
import android.util.Log;
import android.view.View;
import android.widget.Button;

import com.google.android.gms.auth.api.signin.GoogleSignIn;
import com.google.android.gms.auth.api.signin.GoogleSignInAccount;
import com.google.android.gms.auth.api.signin.GoogleSignInClient;
import com.google.android.gms.auth.api.signin.GoogleSignInOptions;
import com.google.android.gms.common.api.ApiException;
import com.google.android.gms.tasks.OnCompleteListener;
import com.google.android.gms.tasks.Task;
import com.google.firebase.FirebaseApp;
import com.google.firebase.auth.AuthCredential;
import com.google.firebase.auth.AuthResult;
import com.google.firebase.auth.FirebaseAuth;
import com.google.firebase.auth.FirebaseUser;
import com.google.firebase.auth.GoogleAuthProvider;

public class MainActivity extends UnityPlayerActivity {

    private GoogleSignInClient mGoogleSignInClient;
    private FirebaseAuth mAuth;
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        try {
            FirebaseApp.initializeApp(MainActivity.this);
        }catch (Exception e){
            Log.e("Unity", "App init fail: " + e.getMessage());
        }
        super.onCreate(savedInstanceState);
    }

    @Override
    public void onStart() {
        super.onStart();

        try {
            mAuth = FirebaseAuth.getInstance();
            // Check if user is signed in (non-null) and update UI accordingly.
            FirebaseUser currentUser = mAuth.getCurrentUser();
        }catch (Exception e){
            Log.e("Unity", "mAuth为nil \n" + e.getMessage());
        }
        //TODO 检查用户是否已登录
//        updateUI(currentUser);
    }

    public void GoogleLogin()
    {
        // Configure Google Sign In
        GoogleSignInOptions gso = new GoogleSignInOptions.Builder(GoogleSignInOptions.DEFAULT_SIGN_IN)
                .requestIdToken("填写你获取的idtoken")
                .requestEmail()
                .build();

        mGoogleSignInClient = GoogleSignIn.getClient(this, gso);
        Intent signInIntent = mGoogleSignInClient.getSignInIntent();
        startActivityForResult(signInIntent, 100);
    }

    @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 == 100) {
            Task task = GoogleSignIn.getSignedInAccountFromIntent(data);
            try {
                // Google Sign In was successful, authenticate with Firebase
                GoogleSignInAccount account = task.getResult(ApiException.class);
                Log.d("Unity", "firebaseAuthWithGoogle:" + account.getId());
                //沟通Unity传递idToken执行登录流程
                Log.i("Unity", "Id Token:" + account.getIdToken());
//                UnityPlayer.UnitySendMessage("GoogleLoginComponent", "GoogleLogin", account.getIdToken());
                firebaseAuthWithGoogle(account.getIdToken());
            } catch (ApiException e) {
//                com.google.android.gms.common.api.ApiException: 10:
                // Google Sign In failed, update UI appropriately
                Log.w("Unity", "Google sign in failed", e);
                //TODO Google登录异常回调?
            }
        }
    }

    private void firebaseAuthWithGoogle(String idToken) {
        Log.i("Unity", "firebaseAuthWithGoogle: " + idToken);
        AuthCredential credential = GoogleAuthProvider.getCredential(idToken, null);
        mAuth.signInWithCredential(credential)
                .addOnCompleteListener(this, new OnCompleteListener() {
                    @Override
                    public void onComplete(@NonNull Task task) {
                        if (task.isSuccessful()) {
                            // Sign in success, update UI with the signed-in user's information
                            Log.d("Unity", "signInWithCredential:success");
                            FirebaseUser user = mAuth.getCurrentUser();
                            //TODO 回调unity userId
                            Log.d("Unity", "用户id:" + user.getUid());
//                            updateUI(user);
                        } else {
                            // If sign in fails, display a message to the user.
                            Log.w("Unity", "signInWithCredential:failure", task.getException());
//                            updateUI(null);
                        }
                    }
                });
    }
}

上方,requestIdToken("填写你获取的idtoken"),这个idtoken获取方法:

2022年10月8日更新(正确idtoken获取方法)

Google文档:https://firebase.google.com/docs/auth/android/google-signin 

“凭据”页面链接:https://console.cloud.google.com/apis/credentials

【Unity】Firebase-Google登录身份验证功能接入流程_第6张图片

 用的是这个Web client  (auto created by Google Service) 这个玩意在google-services.json配置创建时就会同时创建它,在google-services.json里面也有这个客户端ID。(但是话也不是说的那么绝对,如果发现有问题那试试上面那2个)

以前理解的错误方法:

【Unity】Firebase-Google登录身份验证功能接入流程_第7张图片

https://developers.google.com/identity/sign-in/android/start-integrating#get_your_backend_servers_oauth_20_client_id

按照步骤进行选中你的项目和应用,填写应用使用的sha和包名,最终获得一份带idtoken的配置,复制粘贴到上面的方法里传递进去。

解决报错:com.google.android.gms.common.api.ApiException: 10:【有坑 安卓包签名会被google改掉】

(及其重要)2022年2月10日更新:

上面这个id,在发布到google时需要改写为https://console.developers.google.com 凭据API服务那的ID,它是会在你创建好firebase工程时自动创建的。

上方配置项目,通过SHA 签名获取到的ID是Web client (Auto-created for Google Sign-in)选项的ID,而实际正式要用的ID是Android client for com.xxxx.yyy (auto created by Google Service)选项的ID。(com.xxxx.yyy是你的包名)

如果你是iOS就选择iOS的这样的一个ID,其实这个ID已经在google-services.json保存好了,它就在"package_name": "com.xxxx.yyy",的附近,找到client_id:".........." 这.client_id里的就是ID。

2022年2月11日更新:【最下面还说明了一个原因,Google发布后会被改掉包签名 因此SHA-1会不一样,具体Google的SHA-1会在console那边提供的】

经过多次检查发现,并不是这个ID问题,而是网络问题,可能是有些线路突然连不上Google服务器导致,可尝试更换其他线路(我是美国线路成功),并且连美国线路进行安装的apk;requestIdToken所需的ID还是上方说明配置项目那里进行获取到,通过包名和SHA1,SHA1用的是你工程使用的keystore密钥获取的。

2022年10月8日更新:

【Unity】Firebase-Google登录身份验证功能接入流程_第8张图片

最终会通过Intent方式回调一个携带了GoogleSignInAccount的task获取到account之后拿到它的用户id token进行一个firebaseAuthWithGoogle方法,它是客户端的身份验证。

如需做服务器的身份验证,需要参考服务器文档如下:

http方式:https://developers.google.com/identity/sign-in/android/backend-auth

游戏服务器java c# python等:https://firebase.google.com/docs/auth/admin/verify-id-tokens

值得注意的地方:

1、AndroidManifest.xml需要添加

 

2、由于使用UnityPlayerActivity类,它是Unity的classes.jar包里的类,但是在Unity2019可能会发现它不见了,具体解决方法:

Unity接入第三方SDK aar/jar没有sdk的依赖文件 和 Unity2019丢失UnityPlayerActivity问题_两水先木示的博客-CSDN博客

注销用户方法:

FirebaseAuth.getInstance().signOut();

注意:登录邮箱尽可能不要选择用开发者邮箱,如果无法登录可以选择美国邮箱测试下

安卓工程需切成库工程,即app/build.gradle修改

 2点,改掉plugins内的 和 defaultConfig applicationId去掉。

Build生成aar,解压它,获取它根目录的classes.jar和AndroidManifest.xml,其中classes.jar里需要删除掉BuildConfig.class 不然会起冲突。(我使用【7z解压软件】能直接打开jar包 进行直接删除文件,如果不是需要解压jar后 删除文件 再压缩回去。)

接着jar和xml复制到工程Assests/Plugins/Android下,后续则是正常的Unity调用Android代码,不再阐述。

三、Unity工程配置

1、classes.jar 和 AndroidManifest.xml (上面已经提及)

2、google-services.json (上面已经提及)

3、配置Unity的gradle配置!(这个和安卓一样也是应用级的gradle)

【Unity】Firebase-Google登录身份验证功能接入流程_第9张图片

 PlayerSettings-Build里勾选这个,然后编辑它

dependencies {		
    implementation fileTree(dir: 'libs', include: ['*.jar'])	
	implementation 'com.google.android.gms:play-services-auth:19.2.0'
	implementation 'com.google.firebase:firebase-auth:21.0.1'
**DEPS**}

引入firebase和google的依赖。

此时还是会出点问题,缺少了FirebaseAuth.unitypackage包的一些依赖配置文件。需要去下载FirebaseAuth.unitypackage 进行force resolve之后,获取到FirebaseApp.androidlib文件夹,把这个文件夹拷贝到我们的工程Plugins/Android里即可。

(注意:FirebaseAuth.unitypackage的内容 需要删除掉,不过最好是新建一个空工程 并且签名一直 google-services.json要导入后,进行force resolve生成依赖配置文件,再直接拷贝FirebaseApp.androidlib文件夹到我们的项目!)

至于为什么我不直接用FirebaseAuth.unitypackage 而是采取这种特殊的方式,是因为这个包其实包含了很多额外的东西,我只需firebase google身份验证,所以采用这种特别的方式去进行。

2022年2月16日更新:

验证支付订单有效性:申请服务器所需的code

        GoogleSignInOptions gso = new GoogleSignInOptions.Builder(GoogleSignInOptions.DEFAULT_SIGN_IN)
                .requestIdToken(serverClientId)
                .requestEmail()
                .requestServerAuthCode(serverClientId)//申请code
                .build();


//...

    // Google Sign In was successful
                GoogleSignInAccount account = task.getResult(ApiException.class);
                m_IdToken = account.getIdToken();
                m_Code = account.getServerAuthCode();//获取code

//..传递服务器code和idtoken进行校验

 坑:

GoogleSignInAccount account = GoogleSignIn.getLastSignedInAccount(this);

这样获取到上一次登录account是无法正确拿到code的,必须是经过

startActivityForResult后才能拿到正确的code。不正确是指会拿到null

2022年10月26日11:04:57更新:

坑:com.google.android.gms.common.api.ApiException: 10:

原因:发布到Google Console之后拿到的包 它已经被改签名了,签名SHA-1变化了导致这个问题,要将-google console - 应用完整性 - 上传密钥SHA1和SHA256覆盖掉我们自己生成的,也就是firebase console那边的SHA-1配置要改掉。

具体有图的文章: Firebase-Google Auth(login): com.google.android.gms.common.api.ApiException: 10_两水先木示的博客-CSDN博客

你可能感兴趣的:(Unity3d,unity,android,游戏引擎)