Unity接入Google登录Credential Manager超详细流程(2025年最新版)

本文亮点

1、不需要App上架google,任意APP都可以使用google登录
2、不需要google开发者账号,任意google账号都可以创建API项目
3、Unity与安卓通信不需要打aar包或jar包,完全不需要打开AndroidStudio
4、图文超多,细节满满、只要按照我的步骤来,一定能成功,(前提是一定要按照我的步骤来,每一步都是必要的)

接入环境

1、unity版本:2021.3.41f1
Credential Manager需要安卓目标版本34以上,所以unity最低版本是2021.3.41f1

开始接入

创建工程

1、新建Unity工程
2、创建UI,一个登录按钮,一个显示用文本,一个挂载脚本的空物体。
在这里插入图片描述

3、新建脚本GoogleLoginScript.cs,把脚本拖到SDKobj上,statusText拖过去进行赋值
代码如下

using System;
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.UI;

public class GoogleLoginScript : MonoBehaviour
{
    public Text statusText;

    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");
        AddStatusText("Calling SignIn");
    }

    //登录回调
    public void OnGoogleLoginMessage(string message)
    {
        Debug.LogError("message: " + message);
        //开始登录逻辑
        AddStatusText("OnGoogleLoginMessage Callback:"+ message);
    }

    public static AndroidJavaObject GoogleSignObj()
    {
        if(Application.platform==RuntimePlatform.Android)
        {
            if(googleSignObj==null)
            {
                googleSignObj = new AndroidJavaObject("com.abc.def.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);
        }
    }

    private List<string> messages = new List<string>();
    void AddStatusText(string text)
    {
        if (messages.Count == 5)
        {
            messages.RemoveAt(0);
        }
        messages.Add(text);
        string txt = "";
        foreach (string s in messages)
        {
            txt += "\n" + s;
        }
        statusText.text = txt;
    }
}

4、给按钮添加点击事件,绑定GoogleLoginScript的OnSignIn函数。
5、Assets\Plugins\Android\libs\java\com\abc\def\googlelogin路径下添加两个java脚本
GoogleCredentialManagerSign.java用于和API库交互
AndroidBriage.java用于和C#交互

GoogleCredentialManagerSign.java

package com.abc.def.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();
                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);
                        }
                    }
            );
        }
    }
}

AndroidBriage.java

package com.abc.def.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 = "110374893644-hm7kbef5vntgke1ig9dhpomrhsq1aslv.apps.googleusercontent.com";
 
    //初始化
    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("SDKobj", "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;
    }
}

其中需要的脚本就这些,需要注意的地方如下
在这里插入图片描述

打包设置

1、包名和目标版本

在这里插入图片描述

2、Keystore,自定义打包设置
在这里插入图片描述

3、包名
在这里插入图片描述

4、gradle版本
在这里插入图片描述

5、依赖
在这里插入图片描述

6、properties
在这里插入图片描述

WebClientId获取

1,新建Google Cloud项目
进入这个地址:谷歌API控制台,如果没有cloud项目的话需要新建cloud项目,如果已有直接选择项目进入。
在这里插入图片描述

2、开启Identity API
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

3、创建OAuth 同意屏幕,如果已有可以忽略。
在这里插入图片描述

4、在“凭据”页面上,创建 Web 类型的凭据

在这里插入图片描述

5、在“凭据”页面上,创建一个 Android 类型的客户端凭据
在这里插入图片描述

6、找到创建完成的凭据,复制出WebClientId
在这里插入图片描述
在这里插入图片描述

7、把这个WebClientId赋值到AndroidBriage.java的WEB_CLIENT_ID字段

参考链接

接入谷歌最新登录SDK凭据管理器Credential Manager
Google官方文档
谷歌API控制台

整个工程已上传,点击下面的链接下载,keystore密码是123456,可以直接用测试工程打包测试
1、测试工程下载

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值