Unity Google登录
目录
一:导入java文件💦
二:创建按钮和绑定编写的cs文件💦
三:获取Web客户端id 💦
四:打包配置相关 💦
五:注意:
后言
👑👑👑
版本:Unity 2021.3.44f1c1(低版本可能不支持❗️ )
前提条件:你要有Google(邮箱)账户(非GooglePlay 开发者账户)登录Google Cloud要用到❗️
查看项目包名
Edit -> Project Settings -> Player -> Other Settings
我的项目是安卓打包平台(需要签名证书❗️ )(如何创建签名证书 点击跳转)👈
一:导入java文件💦
在Assets\Plugins\Android文件夹下导入两个java文件
例如图所示
如果你的java文件第一行报错
可以试着放在根据你的包名的文件目录下Assets\Plugins\Android\libs\java\com\my(你的包名)\game\googlelogin
AndroidBriage.java
package com.my.game.googlelogin;
import android.app.Activity;
import android.app.Application;
import android.content.Context;
import com.unity3d.player.UnityPlayer;
import java.lang.reflect.Field;
import java.util.Map;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
public class AndroidBriage {
public static String WEB_CLIENT_ID = "这里填写Web客户端id";
//初始化
public static void init()
{
Activity mActivity = getCurrentActivity();
Context context = getApplication().getApplicationContext();
GoogleCredentialManagerSign.init(mActivity, context);
}
//登录
public static void googleLogin()
{
GoogleCredentialManagerSign.googleLogin();
}
//登出
public static void googleLoginOut()
{
GoogleCredentialManagerSign.googleLoginOut();
}
//打印Log
public static void SendInfo(String result)
{
UnityPlayer.UnitySendMessage("你Unity上挂载脚本的对象名字", "OnGoogleLoginMessage", result);//挂载的对象名
}
public static Activity getCurrentActivity()
{
try
{
Class activityThreadClass = Class.forName("android.app.ActivityThread");
Object activityThread = activityThreadClass.getMethod("currentActivityThread", new Class[0]).invoke(new Object[]{}, new Object[0]);
Field activitiesField = activityThreadClass.getDeclaredField("mActivities");
activitiesField.setAccessible(true);
Map activities = (Map)activitiesField.get(activityThread);
for (Object activityRecord : activities.values())
{
Class activityRecordClass = activityRecord.getClass();
Field pausedField = activityRecordClass.getDeclaredField("paused");
pausedField.setAccessible(true);
if (!pausedField.getBoolean(activityRecord))
{
Field activityField = activityRecordClass.getDeclaredField("activity");
activityField.setAccessible(true);
return (Activity)activityField.get(activityRecord);
}
}
}
catch (ClassNotFoundException e)
{
e.printStackTrace();
}
catch (InvocationTargetException e)
{
e.printStackTrace();
}
catch (NoSuchMethodException e)
{
e.printStackTrace();
}
catch (NoSuchFieldException e)
{
e.printStackTrace();
}
catch (IllegalAccessException e)
{
e.printStackTrace();
}
return null;
}
public static Application getApplication()
{
Application application = null;
try
{
Class<?> activityThreadClass = Class.forName("android.app.ActivityThread");
Method method2 = activityThreadClass.getMethod("currentActivityThread", new Class[0]);
Object localObject = method2.invoke(new Object[]{}, new Object[]{});
Method method = activityThreadClass.getMethod("getApplication", new Class[0]);
application = (Application)method.invoke(localObject, new Object[]{});
}
catch (ClassNotFoundException e)
{
e.printStackTrace();
}
catch (NoSuchMethodException e)
{
e.printStackTrace();
}
catch (IllegalAccessException e)
{
e.printStackTrace();
}
catch (IllegalArgumentException e)
{
e.printStackTrace();
}
catch (InvocationTargetException e)
{
e.printStackTrace();
}
return application;
}
}
注意这两处是填写根据你们的(继续看后续,看该填写什么)❗️
GoogleCredentialManagerSign.java
package com.my.game.googlelogin;
import android.annotation.SuppressLint;
import android.app.Activity;
import android.content.Context;
import android.util.Log;
import com.google.android.libraries.identity.googleid.GetGoogleIdOption;
import com.google.android.libraries.identity.googleid.GetSignInWithGoogleOption;
import com.google.android.libraries.identity.googleid.GoogleIdTokenCredential;
import org.json.JSONException;
import org.json.JSONObject;
import java.util.concurrent.Executors;
import java.util.logging.Level;
import java.util.logging.Logger;
import java.util.function.Consumer;
import androidx.annotation.NonNull;
import androidx.credentials.ClearCredentialStateRequest;
import androidx.credentials.Credential;
import androidx.credentials.CredentialManager;
import androidx.credentials.CredentialManagerCallback;
import androidx.credentials.CustomCredential;
import androidx.credentials.GetCredentialRequest;
import androidx.credentials.GetCredentialResponse;
import androidx.credentials.PasswordCredential;
import androidx.credentials.PublicKeyCredential;
import androidx.credentials.exceptions.ClearCredentialException;
import androidx.credentials.exceptions.GetCredentialException;
//谷歌凭据管理器登录
public class GoogleCredentialManagerSign {
private static Activity mActivity = null;
private static Context mContext = null;
private static CredentialManager credentialManager;
private static boolean oneTapStatus = false;
public static void init(Activity activity, Context context) {
mActivity = activity;
mContext = context;
}
public static void googleLogin() {
credentialManager = CredentialManager.Companion.create(mContext);
//WEB_CLIENT_ID Web 应用客户端ID
GetSignInWithGoogleOption googleIdOption = new GetSignInWithGoogleOption.Builder(AndroidBriage.WEB_CLIENT_ID).build();
//实例化
GetCredentialRequest request = new GetCredentialRequest.Builder()
.addCredentialOption(googleIdOption)
.build();
android.os.CancellationSignal cancellationSignal = new android.os.CancellationSignal();
cancellationSignal.setOnCancelListener(() -> {
if (oneTapStatus) oneTapStatus = false;
Log.e("GoogleLog", "Preparing credentials with Google was cancelled.");
});
credentialManager.getCredentialAsync(
mActivity,
request,
cancellationSignal,
Executors.newSingleThreadExecutor(),
new CredentialManagerCallback<GetCredentialResponse, GetCredentialException>() {
@Override
public void onResult(GetCredentialResponse result) {
handleSignIn(result);
}
@Override
public void onError(GetCredentialException e) {
Log.e("GoogleLog", "Unexpected type of credential." + e);
handleFailure(e);
}
});
}
public static void handleSignIn(GetCredentialResponse result) {
// Handle the successfully returned credential.
Credential credential = result.getCredential();
if (credential instanceof PublicKeyCredential) {
String responseJson = ((PublicKeyCredential) credential).getAuthenticationResponseJson();
// Share responseJson i.e. a GetCredentialResponse on your server to validate and authenticate
} else if (credential instanceof PasswordCredential) {
String username = ((PasswordCredential) credential).getId();
String password = ((PasswordCredential) credential).getPassword();
// Use id and password to send to your server to validate and authenticate
} else if (credential instanceof CustomCredential) {
if (GoogleIdTokenCredential.TYPE_GOOGLE_ID_TOKEN_CREDENTIAL.equals(credential.getType())) {
// Use googleIdTokenCredential and extract id to validate and
// authenticate on your server
GoogleIdTokenCredential googleIdTokenCredential = GoogleIdTokenCredential.createFrom(((CustomCredential) credential).getData());
String idToken = googleIdTokenCredential.getIdToken();
//这里是给服务器发送的东西 发什么取决于你们
//AndroidBriage.SendInfo(idToken);
try {
JSONObject googleLoginInfoReturn = new JSONObject();
googleLoginInfoReturn.put("userId", googleIdTokenCredential.getId());
googleLoginInfoReturn.put("displayName",googleIdTokenCredential.getDisplayName());
googleLoginInfoReturn.put("imageUrl",googleIdTokenCredential.getProfilePictureUri());
googleLoginInfoReturn.put("givenName",googleIdTokenCredential.getGivenName());
googleLoginInfoReturn.put("familyName",googleIdTokenCredential.getFamilyName());
googleLoginInfoReturn.put("phoneNumber",googleIdTokenCredential.getPhoneNumber());
googleLoginInfoReturn.put("IdToken",idToken);
//返回相关信息
AndroidBriage.SendInfo(googleLoginInfoReturn.toString());
} catch (JSONException e) {
e.printStackTrace();
}
} else {
// Catch any unrecognized custom credential type here.
Log.e("GoogleLog", "Unexpected type of credential");
}
} else {
// Catch any unrecognized credential type here.
Log.e("GoogleLog", "Unexpected type of credential");
}
}
@SuppressLint("RestrictedApi")
private static void handleFailure(@NonNull GetCredentialException e) {
Logger logger = Logger.getLogger(Thread.currentThread().getStackTrace()[1].getClassName());
logger.log(Level.SEVERE, "Error getting (or preparing) credential: " + e);
}
/**
* 注销登录
*/
public static void googleLoginOut() {
ClearCredentialStateRequest clearCredentialStateRequest = new ClearCredentialStateRequest();
android.os.CancellationSignal cancellationSignal = new android.os.CancellationSignal();
cancellationSignal.setOnCancelListener(() -> {
if (oneTapStatus) oneTapStatus = false;
Log.e("GoogleLog", "Preparing credentials with Google was cancelled.");
});
if (credentialManager != null) {
credentialManager.clearCredentialStateAsync(
clearCredentialStateRequest,
cancellationSignal,
Executors.newSingleThreadExecutor(),
new CredentialManagerCallback<Void, ClearCredentialException>() {
@Override
public void onResult(Void unused) {
Log.e("GoogleLog", "google注销登录成功");
}
@Override
public void onError(@NonNull ClearCredentialException e) {
Log.e("GoogleLog","注销出错"+e);
}
}
);
}
}
}
二:创建按钮和绑定编写的cs文件💦
创建按钮不用我说了吧,将下面的cs文件绑定(拖)到按钮身上
GoogleLoginScript.cs
using System;
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.UI;
public class GoogleLoginScript : MonoBehaviour
{
private static AndroidJavaObject googleSignObj;
void Awake()
{
GoogleSignInit();
}
// Start is called before the first frame update
void Start()
{
}
// Update is called once per frame
void Update()
{
}
//调用登录接口
public void OnSignIn()
{
googleSignObj.CallStatic("googleLogin");
}
//调用登出接口
public void OnSignOut()
{
googleSignObj.CallStatic("googleLoginOut");
}
//登录回调
public void OnGoogleLoginMessage(string message)
{
Debug.LogError("message: " + message);
//给服务器发消息 发message
}
public static AndroidJavaObject GoogleSignObj()
{
if(Application.platform==RuntimePlatform.Android)
{
if(googleSignObj==null)
{
googleSignObj = new AndroidJavaObject("com.my.game.googlelogin.AndroidBriage");//填你的包名相关
if (googleSignObj == null)
{
Debug.LogError("AndroidBriage init faild");
}
}
return googleSignObj;
}
else
{
return null;
}
}
public static void GoogleSignInit()
{
try
{
googleSignObj = GoogleSignObj();
if(googleSignObj != null)
{
googleSignObj.CallStatic("init");
}
}
catch(Exception e)
{
Debug.LogError("Failed:" + e.Message);
}
}
}
我这用的NGUI。
按钮对象上绑定这个脚本GoogleLoginScript,那么AndroidBriage.java这里就要填写这个按钮对象的名字,反正谁绑定填谁的就完事
双引号里替换掉。
记得按钮绑定事件OnSignIn方法,懒得写代码就像上上图一样在OnClick上选选就行
三:获取Web客户端id 💦
Google Cloud平台 (点击跳转)
1.创建项目
2.启用 identity toolkit api API
搜索 identity toolkit api 启用它
3.创建Web类型的凭据
4.创建Android类型的凭据
需要包名和证书指纹
证书指纹怎么获取(点击跳转)!!!👈😄
5.获取Web客户端id 找到Web应用类型复制他的客户端ID,然后放到AndroidBriage.java文件的指定位置
四:打包配置相关 💦
圈住的都是重点❗️
Edit -> Project Settings -> Player -> Publishing Settings
1.settingsTemplate.gradle文件
配置了多个 Maven 仓库,包括 JitPack 和阿里云 Maven 仓库,因为用国外的可能访问不到某些
pluginManagement {
repositories {
maven { url "https://jitpack.io" }
maven { url 'https://maven.aliyun.com/repository/releases' }
maven { url 'https://maven.aliyun.com/repository/jcenter' }
maven { url 'https://maven.aliyun.com/repository/google' }
maven { url 'https://maven.aliyun.com/repository/central' }
maven { url 'https://maven.aliyun.com/repository/gradle-plugin' }
maven { url 'https://maven.aliyun.com/repository/public' }
gradlePluginPortal()
google()
mavenCentral()
}
}
include ':launcher', ':unityLibrary'
**INCLUDES**
dependencyResolutionManagement {
repositoriesMode.set(RepositoriesMode.PREFER_SETTINGS)
repositories {
maven { url "https://jitpack.io" }
maven { url 'https://maven.aliyun.com/repository/releases' }
maven { url 'https://maven.aliyun.com/repository/jcenter' }
maven { url 'https://maven.aliyun.com/repository/google' }
maven { url 'https://maven.aliyun.com/repository/central' }
maven { url 'https://maven.aliyun.com/repository/gradle-plugin' }
maven { url 'https://maven.aliyun.com/repository/public' }
google()
mavenCentral()
// Android Resolver Repos Start
def unityProjectPath = $/file:///**DIR_UNITYPROJECT**/$.replace("\\", "/")
maven {
url (unityProjectPath + "/Assets/GeneratedLocalRepo/Firebase/m2repository") // Assets/Firebase/Editor/AppDependencies.xml:22, Assets/Firebase/Editor/AuthDependencies.xml:20
}
mavenLocal()
// Android Resolver Repos End
flatDir {
dirs "${project(':unityLibrary').projectDir}/libs"
}
}
}
2.AndroidManifest.xml文件
需要有网络权限,里面还有package包名,这个一般Unity会自动设置为你的包名
<?xml version="1.0" encoding="utf-8"?>
<manifest
xmlns:android="http://schemas.android.com/apk/res/android"
package="com.my.game"
xmlns:tools="http://schemas.android.com/tools">
<application>
<activity android:name="com.unity3d.player.UnityPlayerActivity"
android:theme="@style/UnityThemeSelector">
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
<meta-data android:name="unityplayer.UnityActivity" android:value="true" />
</activity>
</application>
<uses-permission android:name="android.permission.INTERNET" />
</manifest>
3.gradleTemplate.properties文件
org.gradle.jvmargs=-Xmx**JVM_HEAP_SIZE**M
org.gradle.parallel=true
unityStreamingAssets=**STREAMING_ASSETS**
# Android Resolver Properties Start
android.useAndroidX=true
android.enableJetifier=true
# Android Resolver Properties End
**ADDITIONAL_PROPERTIES**
4.mainTemplate.gradle文件
注意四个依赖必须有❗️ ❗️ ❗️
apply plugin: 'com.android.library'
**APPLY_PLUGINS**
dependencies {
implementation fileTree(dir: 'libs', include: ['*.jar'])
implementation 'androidx.appcompat:appcompat:1.3.1'
implementation "androidx.credentials:credentials:1.3.0"
implementation "androidx.credentials:credentials-play-services-auth:1.3.0"
implementation "com.google.android.libraries.identity.googleid:googleid:1.1.1"
**DEPS**}
android {
namespace "com.unity3d.player"
ndkPath "**NDKPATH**"
compileSdkVersion **APIVERSION**
buildToolsVersion '**BUILDTOOLS**'
compileOptions {
sourceCompatibility JavaVersion.VERSION_11
targetCompatibility JavaVersion.VERSION_11
}
defaultConfig {
minSdkVersion **MINSDKVERSION**
targetSdkVersion **TARGETSDKVERSION**
ndk {
abiFilters **ABIFILTERS**
}
versionCode **VERSIONCODE**
versionName '**VERSIONNAME**'
consumerProguardFiles 'proguard-unity.txt'**USER_PROGUARD**
}
lintOptions {
abortOnError false
}
aaptOptions {
noCompress = **BUILTIN_NOCOMPRESS** + unityStreamingAssets.tokenize(', ')
ignoreAssetsPattern = "!.svn:!.git:!.ds_store:!*.scc:.*:!CVS:!thumbs.db:!picasa.ini:!*~"
}**PACKAGING_OPTIONS**
}
**IL_CPP_BUILD_SETUP**
**SOURCE_BUILD_SETUP**
**EXTERNAL_SOURCES**
五:注意:
签名证书(点击跳转)👈
测试的时候用真机测,真机要有Google三件套,要开VPN(魔法)🌟
后言
👉💓👈 😁😁
你努力不一定会成功,但你不努力一定会失败。
环境不会改变,解决之道在于改变自我。