.NET Maui中Google认证模拟器正常但真机失败的排查方案
问题描述
我在.NET Maui应用中使用Xamarin.GooglePlayServices.Auth实现Google认证功能,该功能在模拟器上运行正常,但在真实设备上认证失败:SilentSignInAsync抛出异常,手动调用AuthenticateAsync也无法完成认证。
已尝试操作:检查真机上Google Play服务权限;验证WebApiKey和请求的权限范围正确;尝试真机调试但未捕获到具体错误。
相关代码:
public partial class GoogleAuthService { public static Activity _activity; public static GoogleSignInOptions _gso; public static GoogleSignInClient _googleSignInClient; private TaskCompletionSource<GoogleUserDTO> _taskCompletionSource = new TaskCompletionSource<GoogleUserDTO>(); private Task<GoogleUserDTO> GoogleAuthentication { get => _taskCompletionSource.Task; } public GoogleAuthService() { _activity = Platform.CurrentActivity; _gso = new GoogleSignInOptions.Builder(GoogleSignInOptions.DefaultSignIn) .RequestIdToken(WebApiKey) .RequestEmail() .RequestId() .RequestProfile() .Build(); _googleSignInClient = GoogleSignIn.GetClient(_activity, _gso); MainActivity.ResultGoogleAuth += MainActivity_ResultGoogleAuth; } public Task<GoogleUserDTO> AuthenticateAsync() { _taskCompletionSource = new TaskCompletionSource<GoogleUserDTO>(); _activity.StartActivityForResult(_googleSignInClient.SignInIntent, 9001); return GoogleAuthentication; } private void MainActivity_ResultGoogleAuth(object sender, (bool Success, GoogleSignInAccount Account) e) { if (e.Success) { try { var currentAccount = e.Account; _taskCompletionSource.SetResult( new GoogleUserDTO { Email = currentAccount.Email, FullName = currentAccount.DisplayName, TokenId = currentAccount.IdToken, UserName = currentAccount.GivenName, }); } catch (Exception ex) { _taskCompletionSource.SetException(ex); } } } public async Task<GoogleUserDTO> GetCurrentUserAsync() { try { var user = await _googleSignInClient.SilentSignInAsync(); return new GoogleUserDTO { Email = user.Email, FullName = $"{user.DisplayName}", TokenId = user.IdToken, UserName = user.GivenName }; } catch (Exception ex) { return null; } } public Task LogoutAsync() => _googleSignInClient.SignOutAsync(); }
排查与解决步骤
检查Google Cloud Console配置
- 确保已将真机应用的SHA-1指纹添加到Google Cloud Console的OAuth 2.0客户端ID中。模拟器使用调试密钥的SHA-1,真机若使用不同签名密钥(如发布密钥或其他调试密钥),必须对应添加。
- 确认客户端ID类型为Android,且包名与真机应用的包名完全一致。
替换弃用的
StartActivityForResult
.NET Maui中StartActivityForResult已被弃用,改用RegisterForActivityResult处理认证结果,修改后的核心代码:private readonly ActivityResultLauncher<Intent> _signInLauncher; public GoogleAuthService() { _activity = Platform.CurrentActivity; _gso = new GoogleSignInOptions.Builder(GoogleSignInOptions.DefaultSignIn) .RequestIdToken(WebApiKey) .RequestEmail() .RequestId() .RequestProfile() .Build(); _googleSignInClient = GoogleSignIn.GetClient(_activity, _gso); // 用ActivityResultLauncher替代事件监听 _signInLauncher = _activity.RegisterForActivityResult(new ActivityResultContracts.StartActivityForResult(), result => { if (result.ResultCode == Result.Ok && result.Data != null) { var task = GoogleSignIn.GetSignedInAccountFromIntent(result.Data); if (task.IsSuccessful) { var account = task.Result; _taskCompletionSource.SetResult(new GoogleUserDTO { Email = account.Email, FullName = account.DisplayName, TokenId = account.IdToken, UserName = account.GivenName }); } else { _taskCompletionSource.SetException(task.Exception); } } else { _taskCompletionSource.SetException(new Exception("认证被取消或失败")); } }); } public Task<GoogleUserDTO> AuthenticateAsync() { _taskCompletionSource = new TaskCompletionSource<GoogleUserDTO>(); _signInLauncher.Launch(_googleSignInClient.SignInIntent); return _taskCompletionSource.Task; }移除原
MainActivity.ResultGoogleAuth事件绑定,避免逻辑冲突。完善异常捕获与日志
在GetCurrentUserAsync中捕获具体异常类型,精准定位问题:public async Task<GoogleUserDTO> GetCurrentUserAsync() { try { var user = await _googleSignInClient.SilentSignInAsync(); return new GoogleUserDTO { Email = user.Email, FullName = $"{user.DisplayName}", TokenId = user.IdToken, UserName = user.GivenName }; } catch (ApiException ex) { // 根据错误码判断原因,如SIGN_IN_REQUIRED需触发手动认证 if (ex.StatusCode == GoogleSignInStatusCodes.SignInRequired) { return null; } Console.WriteLine($"SilentSignIn失败:{ex.Message},错误码:{ex.StatusCode}"); return null; } catch (Exception ex) { Console.WriteLine($"未知错误:{ex.Message}"); return null; } }验证Google Play服务版本
检查真机Google Play服务是否为最新版本,旧版本可能存在兼容性问题。可通过GoogleApiAvailability.Instance.IsGooglePlayServicesAvailable(_activity)检查状态,若返回非SUCCESS,提示用户更新。确认应用签名匹配
确保真机安装的应用签名与Google Cloud Console中配置的SHA-1指纹一致:调试阶段用调试密钥库的SHA-1,发布版本用发布密钥库的SHA-1。
内容的提问来源于stack exchange,提问作者Vladyslav Malin

