Android应用获取用户Google Drive文件遇阻,含NetworkOnMainThreadException错误
Android Google Drive 文件列表获取实现指导
1. 先解决android.os.NetworkOnMainThreadException异常
这个异常是Android的强制限制:主线程(UI线程)不允许执行网络请求,你需要把Drive API的调用逻辑放到子线程,完成后再切回主线程更新UI。
Java 实现示例(两种方案)
方案1:使用ExecutorService + Handler(推荐)
// 在MainActivity中执行 ExecutorService executor = Executors.newSingleThreadExecutor(); Handler mainHandler = new Handler(Looper.getMainLooper()); executor.execute(() -> { // 子线程中执行Drive API请求 List<com.google.api.services.drive.model.File> files = null; try { files = fetchDriveFiles(driveInstance); } catch (IOException e) { e.printStackTrace(); } final List<com.google.api.services.drive.model.File> finalFiles = files; // 切回主线程更新UI mainHandler.post(() -> { if (finalFiles != null) { // 绑定数据到RecyclerView/ListView等 updateFileListUI(finalFiles); } }); });
方案2:使用AsyncTask(兼容旧版本,已过时但易理解)
private class FetchDriveFilesTask extends AsyncTask<Void, Void, List<com.google.api.services.drive.model.File>> { private Drive driveInstance; public FetchDriveFilesTask(Drive drive) { this.driveInstance = drive; } @Override protected List<com.google.api.services.drive.model.File> doInBackground(Void... voids) { try { return fetchDriveFiles(driveInstance); } catch (IOException e) { e.printStackTrace(); return null; } } @Override protected void onPostExecute(List<com.google.api.services.drive.model.File> files) { super.onPostExecute(files); if (files != null) { updateFileListUI(files); } } } // 调用方式 new FetchDriveFilesTask(driveInstance).execute();
2. Google Drive API 正确集成步骤(无需后端)
你不需要后端服务器,直接在Android端即可完成,以下是完整流程:
步骤1:确认OAuth 2.0配置
- 确保Google Cloud控制台生成的是Android类型的OAuth客户端ID,而非Web/其他类型。
- 将
credentials.json放到app/src/main/res/raw目录下。 - 在OAuth同意屏幕中添加所需权限范围:比如
../auth/drive.readonly(读取所有文件)或../auth/drive.file(仅读取用户授权的文件)。 - 验证Google Cloud中配置的包名和SHA-1指纹与本地项目完全一致(debug和release指纹都要加)。
步骤2:从Firebase登录凭证初始化Drive服务
利用已有的Firebase Google登录凭证,直接生成Drive API的授权实例:
FirebaseUser firebaseUser = FirebaseAuth.getInstance().getCurrentUser(); if (firebaseUser != null) { firebaseUser.getIdToken(false).addOnSuccessListener(idTokenResult -> { String accessToken = idTokenResult.getToken(); // 创建授权凭证 GoogleCredential credential = new GoogleCredential().setAccessToken(accessToken); // 初始化Drive服务 Drive drive = new Drive.Builder( AndroidHttp.newCompatibleTransport(), new GsonFactory(), credential ).setApplicationName("你的应用名称").build(); // 拿到drive实例后,调用子线程获取文件列表(用上面的Executor/AsyncTask方案) fetchFilesInBackground(drive); }); }
步骤3:实现文件列表获取逻辑
private List<com.google.api.services.drive.model.File> fetchDriveFiles(Drive drive) throws IOException { // 调用Drive API获取文件列表,可自定义分页、字段 FileList result = drive.files().list() .setPageSize(20) // 每页返回20条 .setFields("nextPageToken, files(id, name, mimeType, modifiedTime)") // 指定返回的字段,减少数据量 .execute(); return result.getFiles(); }
步骤4:添加必要权限
在AndroidManifest.xml中声明网络权限:
<uses-permission android:name="android.permission.INTERNET" />
3. 是否需要后端服务器?
不需要。Android客户端可以直接通过OAuth 2.0授权调用Google Drive API。只有当你需要处理大规模文件操作、敏感数据处理,或者需要统一管理授权逻辑时,才考虑引入后端。
常见问题排查
- 如果出现授权失败:检查包名、SHA-1指纹、权限范围是否配置正确,确保OAuth同意屏幕已发布(测试阶段可添加测试用户)。
- 如果返回空文件列表:检查权限范围是否足够,比如
drive.file需要用户手动授权特定文件,而drive.readonly需要用户同意读取所有文件。 - 避免在主线程执行任何网络操作,包括Drive API的初始化和调用。
内容的提问来源于stack exchange,提问作者Edemir Santos de Paula
相关产品推荐
相关产品推荐

