思路:接入sdk相关Android接口以aar形式提供给Unity使用
目录
一、创建Firebase项目工程
二、创建Android工程 接入Android接口
三、Unity工程配置
参考文档:https://firebase.google.com/docs/auth/android/google-signin#java_1
https://console.firebase.google.com
进入到console创建工程,按照步骤进行,进入到具体工程console面板后,找到
添加测试用户
启动Google身份验证
进行到此时下载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更新工程!不然是不会生效的
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
用的是这个Web client (auto created by Google Service) 这个玩意在google-services.json配置创建时就会同时创建它,在google-services.json里面也有这个客户端ID。(但是话也不是说的那么绝对,如果发现有问题那试试上面那2个)
以前理解的错误方法:
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日更新:
最终会通过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代码,不再阐述。
1、classes.jar 和 AndroidManifest.xml (上面已经提及)
2、google-services.json (上面已经提及)
3、配置Unity的gradle配置!(这个和安卓一样也是应用级的gradle)
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身份验证,所以采用这种特别的方式去进行。
验证支付订单有效性:申请服务器所需的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博客