2026-04-16 14:57:19 +08:00
|
|
|
|
using System;
|
|
|
|
|
|
using System.Threading.Tasks;
|
|
|
|
|
|
using Kill.Utils;
|
|
|
|
|
|
using UnityEngine;
|
|
|
|
|
|
|
|
|
|
|
|
#if UNITY_ANDROID && !UNITY_EDITOR
|
|
|
|
|
|
using Firebase;
|
|
|
|
|
|
using Firebase.Auth;
|
|
|
|
|
|
#endif
|
|
|
|
|
|
|
|
|
|
|
|
namespace Kill.Managers
|
|
|
|
|
|
{
|
|
|
|
|
|
/// <summary>
|
|
|
|
|
|
/// Firebase 谷歌登录管理器
|
|
|
|
|
|
/// 使用 Firebase 内置的 Google 登录支持
|
|
|
|
|
|
/// </summary>
|
|
|
|
|
|
public class FirebaseAuthManager : MonoBehaviour
|
|
|
|
|
|
{
|
|
|
|
|
|
public static FirebaseAuthManager Instance { get; private set; }
|
|
|
|
|
|
|
|
|
|
|
|
// Google 登录配置 - 从 Firebase 控制台获取的 Web 客户端 ID
|
|
|
|
|
|
private const string WEB_CLIENT_ID = "785438724947-kpjbqi43hbj6eddianbjsgkgkkclkfmd.apps.googleusercontent.com";
|
|
|
|
|
|
|
|
|
|
|
|
#if UNITY_ANDROID && !UNITY_EDITOR
|
|
|
|
|
|
private FirebaseAuth auth;
|
|
|
|
|
|
#endif
|
|
|
|
|
|
|
|
|
|
|
|
private void Awake()
|
|
|
|
|
|
{
|
|
|
|
|
|
Instance = this;
|
|
|
|
|
|
InitializeFirebase();
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/// <summary>
|
|
|
|
|
|
/// 初始化 Firebase
|
|
|
|
|
|
/// </summary>
|
|
|
|
|
|
private void InitializeFirebase()
|
|
|
|
|
|
{
|
|
|
|
|
|
#if UNITY_ANDROID && !UNITY_EDITOR
|
|
|
|
|
|
FirebaseApp.CheckAndFixDependenciesAsync().ContinueWith(task =>
|
|
|
|
|
|
{
|
|
|
|
|
|
var dependencyStatus = task.Result;
|
|
|
|
|
|
if (dependencyStatus == DependencyStatus.Available)
|
|
|
|
|
|
{
|
|
|
|
|
|
auth = FirebaseAuth.DefaultInstance;
|
|
|
|
|
|
Debug.Log("Firebase 初始化成功");
|
|
|
|
|
|
}
|
|
|
|
|
|
else
|
|
|
|
|
|
{
|
|
|
|
|
|
Debug.LogError($"Firebase 初始化失败: {dependencyStatus}");
|
|
|
|
|
|
}
|
|
|
|
|
|
});
|
|
|
|
|
|
#else
|
|
|
|
|
|
Debug.Log("Firebase 谷歌登录仅在 Android 平台可用");
|
|
|
|
|
|
#endif
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/// <summary>
|
|
|
|
|
|
/// 谷歌登录
|
|
|
|
|
|
/// 使用 Firebase 内置的 Google 登录弹窗
|
|
|
|
|
|
/// </summary>
|
2026-04-20 08:31:41 +08:00
|
|
|
|
/// <param name="timeoutSeconds">超时时间(秒),默认30秒</param>
|
|
|
|
|
|
public void SignInWithGoogle(Action<GoogleLoginResult> onSuccess, Action<string> onError, int timeoutSeconds = 30)
|
2026-04-16 14:57:19 +08:00
|
|
|
|
{
|
|
|
|
|
|
#if UNITY_ANDROID && !UNITY_EDITOR
|
|
|
|
|
|
if (auth == null)
|
|
|
|
|
|
{
|
|
|
|
|
|
onError?.Invoke("Firebase 未初始化");
|
|
|
|
|
|
return;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
2026-04-20 08:31:41 +08:00
|
|
|
|
bool isCompleted = false;
|
|
|
|
|
|
|
|
|
|
|
|
// 启动超时检测
|
|
|
|
|
|
Task.Run(async () =>
|
|
|
|
|
|
{
|
|
|
|
|
|
await Task.Delay(TimeSpan.FromSeconds(timeoutSeconds));
|
|
|
|
|
|
if (!isCompleted)
|
|
|
|
|
|
{
|
|
|
|
|
|
isCompleted = true;
|
|
|
|
|
|
MainThread.Enqueue(() => onError?.Invoke($"Google 登录超时({timeoutSeconds}秒)"));
|
|
|
|
|
|
}
|
|
|
|
|
|
});
|
|
|
|
|
|
|
2026-04-16 14:57:19 +08:00
|
|
|
|
// 获取 Google 登录 Provider
|
|
|
|
|
|
var provider = new FederatedOAuthProviderData("google.com");
|
|
|
|
|
|
provider.Scopes = new string[] { "email", "profile" };
|
|
|
|
|
|
|
|
|
|
|
|
var federatedProvider = new FederatedOAuthProvider(provider);
|
|
|
|
|
|
|
|
|
|
|
|
auth.SignInWithProviderAsync(federatedProvider).ContinueWith(task =>
|
|
|
|
|
|
{
|
2026-04-20 08:31:41 +08:00
|
|
|
|
if (isCompleted) return; // 已超时,忽略结果
|
|
|
|
|
|
isCompleted = true;
|
|
|
|
|
|
|
2026-04-16 14:57:19 +08:00
|
|
|
|
if (task.IsFaulted)
|
|
|
|
|
|
{
|
|
|
|
|
|
MainThread.Enqueue(() => onError?.Invoke("Google 登录失败"));
|
|
|
|
|
|
return;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
if (task.IsCanceled)
|
|
|
|
|
|
{
|
|
|
|
|
|
MainThread.Enqueue(() => onError?.Invoke("Google 登录被取消"));
|
|
|
|
|
|
return;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
var user = auth.CurrentUser;
|
|
|
|
|
|
if (user == null)
|
|
|
|
|
|
{
|
|
|
|
|
|
MainThread.Enqueue(() => onError?.Invoke("获取用户信息失败"));
|
|
|
|
|
|
return;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
// 构造登录结果
|
|
|
|
|
|
MainThread.Enqueue(() =>
|
|
|
|
|
|
{
|
|
|
|
|
|
var result = new GoogleLoginResult
|
|
|
|
|
|
{
|
|
|
|
|
|
FirebaseUserId = user.UserId,
|
|
|
|
|
|
Email = user.Email,
|
|
|
|
|
|
DisplayName = user.DisplayName,
|
|
|
|
|
|
PhotoUrl = user.PhotoUrl?.ToString(),
|
|
|
|
|
|
IdToken = ""
|
|
|
|
|
|
};
|
|
|
|
|
|
onSuccess?.Invoke(result);
|
|
|
|
|
|
});
|
|
|
|
|
|
});
|
|
|
|
|
|
#else
|
|
|
|
|
|
// 编辑器环境下模拟
|
|
|
|
|
|
Task.Delay(1000).ContinueWith(_ =>
|
|
|
|
|
|
{
|
|
|
|
|
|
Debug.Log("编辑器模拟谷歌登录");
|
|
|
|
|
|
MainThread.Enqueue(() =>
|
|
|
|
|
|
{
|
|
|
|
|
|
var mockResult = new GoogleLoginResult
|
|
|
|
|
|
{
|
2026-04-20 08:31:41 +08:00
|
|
|
|
FirebaseUserId = "1231232345",
|
2026-04-16 14:57:19 +08:00
|
|
|
|
Email = "mock@gmail.com",
|
|
|
|
|
|
DisplayName = "Mock User",
|
|
|
|
|
|
PhotoUrl = "",
|
|
|
|
|
|
IdToken = ""
|
|
|
|
|
|
};
|
2026-04-20 08:31:41 +08:00
|
|
|
|
//onSuccess?.Invoke(mockResult);
|
|
|
|
|
|
onError?.Invoke("Google 登录被取消");
|
2026-04-16 14:57:19 +08:00
|
|
|
|
});
|
|
|
|
|
|
});
|
|
|
|
|
|
#endif
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/// <summary>
|
|
|
|
|
|
/// 谷歌登出
|
|
|
|
|
|
/// </summary>
|
|
|
|
|
|
public void SignOut()
|
|
|
|
|
|
{
|
|
|
|
|
|
#if UNITY_ANDROID && !UNITY_EDITOR
|
|
|
|
|
|
auth?.SignOut();
|
|
|
|
|
|
Debug.Log("谷歌登出成功");
|
|
|
|
|
|
#endif
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/// <summary>
|
|
|
|
|
|
/// 谷歌登录结果
|
|
|
|
|
|
/// </summary>
|
|
|
|
|
|
public class GoogleLoginResult
|
|
|
|
|
|
{
|
|
|
|
|
|
public string FirebaseUserId; // Firebase 用户ID(用于绑定)
|
|
|
|
|
|
public string Email; // 邮箱
|
|
|
|
|
|
public string DisplayName; // 显示名称
|
|
|
|
|
|
public string PhotoUrl; // 头像URL
|
|
|
|
|
|
public string IdToken; // ID Token
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|