Android Studio中Google Drive授权异常:调用API返回401未授权
Google Drive API调用返回401未授权问题解决
我开发Google Drive客户端时,完成认证与授权后调用Google Drive API获取文件列表,收到401未授权错误。
认证获取Token的代码(原代码)
class LogginViewModel: ViewModel() { private val _loginResult = MutableLiveData<Boolean>() val loginResult: LiveData<Boolean> get() = _loginResult private val _loginData = MutableLiveData<String>() val loginData: LiveData<String> get() = _loginData fun signInGoogle(context: Context) { val credentialManager = CredentialManager.create(context) val getGoogleIdOption: GetGoogleIdOption = GetGoogleIdOption.Builder() .setFilterByAuthorizedAccounts(false) .setServerClientId("77699025246-l0t92qgqq3bc8d699vj3o5cixxxxxxx.apps.googleusercontent.com") .setNonce(generateNonce()) .build() val request: GetCredentialRequest = GetCredentialRequest.Builder() .addCredentialOption(getGoogleIdOption) .build() viewModelScope.launch(Dispatchers.Main) { try { val result = credentialManager.getCredential( request = request, context = context, ) val credential = result.credential val googleIdTokenCredential = GoogleIdTokenCredential .createFrom(credential.data) val googleIdToken = googleIdTokenCredential.idToken _loginData.value = googleIdToken _loginResult.value = true } catch (e: androidx.credentials.exceptions.GetCredentialException) { _loginData.value = "1" + e.message _loginResult.value = false } catch (e: GoogleIdTokenParsingException) { _loginData.value = "2" + e.message _loginResult.value = false } } } private fun generateNonce(): String { val rawNonce = UUID.randomUUID().toString() val bytes = rawNonce.toByteArray() val md = MessageDigest.getInstance("SHA-256") val digest = md.digest(bytes) return digest.fold("") {str, it -> str + "%02x".format(it) } } }
调用Drive API的代码(原代码)
class MenuViewModel: ViewModel() { private val _driveFiles = MutableLiveData<List<com.google.api.services.drive.model.File>>() val driveFiles: LiveData<List<com.google.api.services.drive.model.File>> get() = _driveFiles fun fetchDriveFiles(googleIdToken: String) { viewModelScope.launch(Dispatchers.IO) { try { val HTTP_TRANSPORT = GoogleNetHttpTransport.newTrustedTransport() val JSON_FACTORY = GsonFactory.getDefaultInstance() val credential = GoogleCredential().setAccessToken(googleIdToken) val driveService = Drive.Builder(HTTP_TRANSPORT, JSON_FACTORY, credential) .setApplicationName("Drive API Kotlin Example") .build() val result: FileList = driveService.files().list() .setPageSize(10) .setFields("nextPageToken, files(id, name)") .execute() val files = result.files if (files != null && files.isNotEmpty()) { _driveFiles.postValue(files) } else { _driveFiles.postValue(emptyList()) } } catch (e: Exception) { e.printStackTrace() } } } }
问题根源
你混淆了Google ID Token和OAuth 2.0 Access Token的用途:
- Google ID Token仅用于验证用户身份(确认用户属于某个谷歌账号),不具备调用Google Drive API的权限。
- Google Drive API需要的是带有Drive权限范围的OAuth 2.0 Access Token,这个Token才是授权API访问的有效凭证。
修复步骤
1. 修改认证流程,请求Drive API权限并获取Access Token
更新LogginViewModel中的认证逻辑,添加Drive API的权限范围,并提取正确的Access Token:
fun signInGoogle(context: Context) { val credentialManager = CredentialManager.create(context) val getGoogleIdOption: GetGoogleIdOption = GetGoogleIdOption.Builder() .setFilterByAuthorizedAccounts(false) .setServerClientId("77699025246-l0t92qgqq3bc8d699vj3o5cixxxxxxx.apps.googleusercontent.com") .setNonce(generateNonce()) // 添加Drive只读权限,按需可更换为drive.file(仅授权用户选择的文件)或drive(全权限) .setScopes(listOf("https://www.googleapis.com/auth/drive.readonly")) .build() val request: GetCredentialRequest = GetCredentialRequest.Builder() .addCredentialOption(getGoogleIdOption) .build() viewModelScope.launch(Dispatchers.Main) { try { val result = credentialManager.getCredential( request = request, context = context, ) val credential = result.credential // 替换为解析OAuth2 Token凭证,提取Access Token val googleOAuth2TokenCredential = GoogleOAuth2TokenCredential.createFrom(credential.data) val accessToken = googleOAuth2TokenCredential.accessToken _loginData.value = accessToken // 现在存储的是可用于API调用的Access Token _loginResult.value = true } catch (e: androidx.credentials.exceptions.GetCredentialException) { _loginData.value = "1" + e.message _loginResult.value = false } catch (e: GoogleOAuth2TokenParsingException) { _loginData.value = "2" + e.message _loginResult.value = false } } }
2. 检查Google Cloud项目配置
- 确保已在Google Cloud控制台启用Google Drive API;
- 在OAuth同意屏幕中添加了对应的Drive权限范围;
- 确认使用的客户端ID(Server Client ID)已正确关联到你的Android应用(如果是Android客户端,建议使用Android类型的客户端ID)。
3. 调用Drive API的代码调整(可选)
现在传入fetchDriveFiles的是合法的Access Token,原代码可正常运行,建议修改参数名增强可读性:
fun fetchDriveFiles(accessToken: String) { viewModelScope.launch(Dispatchers.IO) { try { val HTTP_TRANSPORT = GoogleNetHttpTransport.newTrustedTransport() val JSON_FACTORY = GsonFactory.getDefaultInstance() val credential = GoogleCredential().setAccessToken(accessToken) val driveService = Drive.Builder(HTTP_TRANSPORT, JSON_FACTORY, credential) .setApplicationName("Drive API Kotlin Example") .build() val result: FileList = driveService.files().list() .setPageSize(10) .setFields("nextPageToken, files(id, name)") .execute() val files = result.files _driveFiles.postValue(files ?: emptyList()) } catch (e: Exception) { e.printStackTrace() } } }
内容的提问来源于stack exchange,提问作者Lekr01d
相关产品推荐
相关产品推荐

