目录
一:导入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();}//打印Logpublic 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 应用客户端IDGetSignInWithGoogleOption 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>() {@Overridepublic void onResult(GetCredentialResponse result) {handleSignIn(result);}@Overridepublic 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 serverGoogleIdTokenCredential 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>() {@Overridepublic void onResult(Void unused) {Log.e("GoogleLog", "google注销登录成功");}@Overridepublic 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 updatevoid Start(){}// Update is called once per framevoid 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 Startdef 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 EndflatDir {dirs "${project(':unityLibrary').projectDir}/libs"}}
}
2.AndroidManifest.xml文件
需要有网络权限,里面还有package包名,这个一般Unity会自动设置为你的包名
<?xml version="1.0" encoding="utf-8"?>
<manifestxmlns: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_11targetCompatibility 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(魔法)🌟
后言
👉💓👈 😁😁
你努力不一定会成功,但你不努力一定会失败。
环境不会改变,解决之道在于改变自我。