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

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.18 20:31:34