Android集成Google Drive上传时遇Application Default Credentials不可用错误
问题解决:Android Google Drive上传时的默认凭据错误
错误原因
你使用的GoogleCredentials.getApplicationDefault()是仅适用于Google Compute Engine(GCE)等云服务器环境的凭据方式,Android客户端需要通过OAuth 2.0授权用户的个人Google Drive账号,而非默认服务凭据。
解决方案步骤
1. 配置OAuth 2.0客户端ID
在Google Cloud控制台创建Android类型的OAuth客户端ID,确保填写的包名和SHA-1指纹与你的应用完全匹配。
2. 集成用户授权流程
使用Google Play Services的Auth库实现用户登录授权,获取访问用户Drive的权限:
- 在build.gradle中添加Google Sign-In和Drive API依赖
- 实现登录按钮逻辑,请求
DriveScopes.DRIVE_FILE权限
3. 修改上传代码
替换默认凭据逻辑,用OAuth授权后的用户凭据创建Drive服务:
完整示例代码
private static final int RC_SIGN_IN = 1001; private static final String TAG = "DriveUpload"; // 触发Drive授权 private void requestDriveAuthorization() { GoogleSignInOptions gso = new GoogleSignInOptions.Builder(GoogleSignInOptions.DEFAULT_SIGN_IN) .requestScopes(new Scope(DriveScopes.DRIVE_FILE)) .requestEmail() .build(); GoogleSignInClient signInClient = GoogleSignIn.getClient(this, gso); startActivityForResult(signInClient.getSignInIntent(), RC_SIGN_IN); } // 处理授权回调 @Override protected void onActivityResult(int requestCode, int resultCode, 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); // 授权成功,启动上传 uploadFileToDrive(account); } catch (ApiException e) { Log.w(TAG, "授权失败,错误码:" + e.getStatusCode()); } } // 后台执行文件上传 private void uploadFileToDrive(GoogleSignInAccount account) { new AsyncTask<Void, Void, String>() { @Override protected String doInBackground(Void... voids) { try { // 从授权账号获取有效凭据 String accessToken = account.getIdToken(); GoogleCredentials credentials = GoogleCredentials.create(new AccessToken(accessToken, null)) .createScoped(Arrays.asList(DriveScopes.DRIVE_FILE)); HttpRequestInitializer requestInitializer = new HttpCredentialsAdapter(credentials); // 构建Drive服务实例 Drive service = new com.google.api.services.drive.Drive.Builder( new NetHttpTransport(), GsonFactory.getDefaultInstance(), requestInitializer) .setApplicationName(getString(R.string.app_name)) .build(); // 设置文件元数据 File fileMetadata = new File(); fileMetadata.setName(getString(R.string.db_name_lists)); // 假设fileContent是你准备好的InputStreamContent类型文件内容 File uploadedFile = service.files().create(fileMetadata, fileContent) .setFields("id") .execute(); return uploadedFile.getId(); } catch (IOException e) { e.printStackTrace(); return null; } } @Override protected void onPostExecute(String fileId) { if (fileId != null) { Toast.makeText(MainActivity.this, fileId + " 已创建", Toast.LENGTH_SHORT).show(); } else { Toast.makeText(MainActivity.this, "上传失败", Toast.LENGTH_SHORT).show(); } } }.execute(); }
关键注意事项
- 后台线程执行:Android禁止在主线程调用网络请求,必须用AsyncTask、Coroutine等方式处理
- 权限声明:在AndroidManifest.xml中添加网络权限
<uses-permission android:name="android.permission.INTERNET" /> - 最小权限原则:使用
DRIVE_FILE而非全量DRIVE权限,符合Google权限规范
内容的提问来源于stack exchange,提问作者Arash Torkaman
相关产品推荐
相关产品推荐

