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

Android Credential Manager:基于上次登录账号实现自动登录及切换

基于Credential Manager API实现带记忆上次登录账号的自动登录

现有实现代码

lifecycleScope.launch {
        
        val options = GetGoogleIdOption.Builder()
            .setFilterByAuthorizedAccounts(true|false)
            .setServerClientId(SERVER_CLIENT_ID)
            .setAutoSelectEnabled(true|false)
            .build()
        
        val request = GetCredentialRequest.Builder().addCredentialOption(options).build()
        
        val response = CredentialManager.create(requireContext())
            .getCredential(requireContext(),request)
        
        if(response.credential is CustomCredential && response.credential.type == GoogleIdTokenCredential.TYPE_GOOGLE_ID_TOKEN_CREDENTIAL) {
            val googleCredential = GoogleIdTokenCredential.createFrom(response.credential.data)
            Log.d(TAG, "onCreate: Signed In as: ${googleCredential.id}")
            // continue with signed in...
        }
    }

当前功能说明

  • setFilterByAuthorizedAccounts(true):仅显示已授权过本应用的账号
  • setAutoSelectEnabled(true):仅存在一个授权账号时自动完成登录

需求目标

  • 当设备存在多个已授权账号时,自动选择上次登录的账号完成登录(可显示UI但无需用户手动选择)
  • 切换登录账号后,后续自动登录默认使用新切换的账号

实现方案

1. 持久化存储上次登录用户ID

每次登录成功后,将当前用户的ID存入本地存储(推荐使用DataStore,也可使用SharedPreferences),确保下次启动时能读取到上次登录的账号标识:

// 示例:使用DataStore存储
private val Context.dataStore by preferencesDataStore(name = "auth_prefs")
private val LAST_LOGGED_IN_USER_ID = stringPreferencesKey("last_logged_in_user_id")

// 登录成功后执行存储
lifecycleScope.launch {
    requireContext().dataStore.edit { settings ->
        settings[LAST_LOGGED_IN_USER_ID] = googleCredential.id
    }
}

2. 配置Credential Manager优先选择历史登录账号

修改Credential请求的构建逻辑,读取存储的历史用户ID,通过setLoginHint方法让Credential Manager优先匹配该账号,实现自动登录:

lifecycleScope.launch {
    // 获取存储的上次登录用户ID
    val lastLoggedInUserId = requireContext().dataStore.data.map { it[LAST_LOGGED_IN_USER_ID] }.first()
    
    val optionsBuilder = GetGoogleIdOption.Builder()
        .setFilterByAuthorizedAccounts(true)
        .setServerClientId(SERVER_CLIENT_ID)
        .setAutoSelectEnabled(true)
    
    // 若存在历史登录ID,设置优先匹配该账号
    lastLoggedInUserId?.let {
        optionsBuilder.setLoginHint(it)
    }
    
    val options = optionsBuilder.build()
    
    val request = GetCredentialRequest.Builder().addCredentialOption(options).build()
    
    val response = CredentialManager.create(requireContext())
        .getCredential(requireContext(), request)
    
    if(response.credential is CustomCredential && response.credential.type == GoogleIdTokenCredential.TYPE_GOOGLE_ID_TOKEN_CREDENTIAL) {
        val googleCredential = GoogleIdTokenCredential.createFrom(response.credential.data)
        Log.d(TAG, "onCreate: Signed In as: ${googleCredential.id}")
        
        // 更新存储的用户ID(确保切换账号后记录新账号)
        requireContext().dataStore.edit { settings ->
            settings[LAST_LOGGED_IN_USER_ID] = googleCredential.id
        }
        
        // 执行后续登录逻辑...
    }
}

3. 处理账号切换场景

当用户主动触发账号切换时,清除存储的历史登录ID,强制显示账号选择UI,选择完成后更新存储的ID:

// 账号切换按钮点击事件示例
switchAccountBtn.setOnClickListener {
    lifecycleScope.launch {
        // 清除历史登录ID,触发账号选择UI
        requireContext().dataStore.edit { settings ->
            settings.remove(LAST_LOGGED_IN_USER_ID)
        }
        
        val options = GetGoogleIdOption.Builder()
            .setFilterByAuthorizedAccounts(true)
            .setServerClientId(SERVER_CLIENT_ID)
            .setAutoSelectEnabled(false) // 强制显示账号选择列表
            .build()
        
        val request = GetCredentialRequest.Builder().addCredentialOption(options).build()
        
        val response = CredentialManager.create(requireContext())
            .getCredential(requireContext(), request)
        
        if(response.credential is CustomCredential && response.credential.type == GoogleIdTokenCredential.TYPE_GOOGLE_ID_TOKEN_CREDENTIAL) {
            val googleCredential = GoogleIdTokenCredential.createFrom(response.credential.data)
            Log.d(TAG, "Switched account to: ${googleCredential.id}")
            
            // 更新存储为新账号ID
            requireContext().dataStore.edit { settings ->
                settings[LAST_LOGGED_IN_USER_ID] = googleCredential.id
            }
            
            // 执行账号切换后的逻辑...
        }
    }
}

关键逻辑说明

  • setLoginHint(it):告知Credential Manager优先匹配指定的用户ID,若该账号在已授权列表中,会自动选中完成登录,无需用户操作
  • 每次登录成功后更新存储的用户ID,确保切换账号后下次自动登录使用新账号
  • 账号切换时关闭自动选择,强制显示账号列表,让用户能选择其他账号

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.26 19:52:34