You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

AccountManager.getAccounts()在targetSdk>23环境下失效问题咨询

解决API26+下AccountManager.getAccounts()返回空数组的问题

你遇到的这个问题其实是Android 8.0(API26)之后Google对账号访问权限的收紧导致的——不仅运行时权限规则变了,AccountManager.getAccounts()这个方法本身也被限制了,第三方应用再也没法通过它获取Google类型的账号信息了。下面给你推荐官方认可的、无需用户再次登录的解决方案:

核心原因说明

  • 在API23之前,GET_ACCOUNTS是普通权限,安装时自动授予,所以getAccounts()能正常返回账号;
  • API23开始,GET_ACCOUNTS变成危险权限,需要动态申请,但此时还能获取到Google账号;
  • 到API26,Google直接限制了第三方应用对Google账号的访问:即使你申请了GET_ACCOUNTS,getAccounts()也只会返回非Google的账号,甚至空数组。同时这个方法也被标记为过时,官方不推荐再使用。

推荐解决方案:使用Google Sign-In静默登录

官方推荐用Google Sign-In API来获取已登录用户的信息,其中的silentSignIn()方法可以在用户已经登录过Google账号且授权过你的应用时,直接返回用户信息,完全不需要用户再次操作。

步骤1:添加依赖

在你的Module级别build.gradle中添加Google Sign-In的依赖:

implementation 'com.google.android.gms:play-services-auth:20.7.0'

步骤2:初始化客户端并执行静默登录

在你的Activity或Fragment中,初始化GoogleSignInClient并调用静默登录:

private static final int RC_SIGN_IN = 1001;
private GoogleSignInClient mGoogleSignInClient;

@Override
protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.activity_main);

    // 配置SignIn选项,请求邮箱、用户名和头像信息
    GoogleSignInOptions gso = new GoogleSignInOptions.Builder(GoogleSignInOptions.DEFAULT_SIGN_IN)
            .requestEmail()
            .requestProfile()
            .build();

    // 初始化客户端
    mGoogleSignInClient = GoogleSignIn.getClient(this, gso);

    // 执行静默登录
    Task<GoogleSignInAccount> silentSignInTask = mGoogleSignInClient.silentSignIn();
    silentSignInTask.addOnCompleteListener(this, task -> {
        if (task.isSuccessful()) {
            // 成功获取用户信息
            GoogleSignInAccount account = task.getResult();
            String userName = account.getDisplayName();
            String userEmail = account.getEmail();
            Uri avatarUri = account.getPhotoUrl();

            // 这里更新你的Drawer布局
            updateDrawerUserInfo(userName, userEmail, avatarUri);
        } else {
            // 静默登录失败,说明用户未登录或未授权,需要引导用户登录
            Intent signInIntent = mGoogleSignInClient.getSignInIntent();
            startActivityForResult(signInIntent, RC_SIGN_IN);
        }
    });
}

步骤3:处理登录回调(如果静默失败)

如果静默登录失败,用户需要手动登录,我们需要处理登录结果:

@Override
protected void onActivityResult(int requestCode, int resultCode, @Nullable Intent data) {
    super.onActivityResult(requestCode, resultCode, data);
    if (requestCode == RC_SIGN_IN) {
        Task<GoogleSignInAccount> task = GoogleSignIn.getSignedInAccountFromIntent(data);
        handleSignInResult(task);
    }
}

private void handleSignInResult(Task<GoogleSignInAccount> completedTask) {
    try {
        GoogleSignInAccount account = completedTask.getResult(ApiException.class);
        // 再次获取信息并更新Drawer
        String userName = account.getDisplayName();
        String userEmail = account.getEmail();
        Uri avatarUri = account.getPhotoUrl();
        updateDrawerUserInfo(userName, userEmail, avatarUri);
    } catch (ApiException e) {
        Log.w("DrawerAuth", "登录失败,错误码:" + e.getStatusCode());
        // 这里可以给用户提示登录失败
    }
}

步骤4:必要的权限配置

在AndroidManifest.xml中添加网络权限(因为需要和Google服务器交互):

<uses-permission android:name="android.permission.INTERNET" />

额外注意事项

  • 你需要在Google Cloud Console中为你的应用配置OAuth 2.0客户端ID,否则登录会失败;
  • 如果你的应用只需要获取账号基本信息(用户名、邮箱、头像),DEFAULT_SIGN_IN配置完全足够,不需要额外申请Google API的权限;
  • 静默登录的前提是用户设备上已经登录了Google账号,且之前授权过你的应用——如果是第一次使用,还是需要用户手动登录一次,但后续打开应用就可以自动获取信息了。

这个方案不仅符合API26+的权限规则,也是Google官方推荐的账号信息获取方式,安全且稳定。

内容的提问来源于stack exchange,提问作者Harshad Loya

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.25 03:46:56