Android应用程序化读写Google Sheet遇授权类缺失错误求助
解决Android中Google Sheets API授权时的
com.sun.net.httpserver.HttpServer找不到问题 错误原因
你当前使用的LocalServerReceiver是桌面Java应用的OAuth授权实现,它依赖JDK自带的com.sun.net.httpserver.HttpServer类,但Android的ART运行时不包含这个类,因此抛出ClassNotFoundException。
解决方法
改用Android官方提供的Google Sign-in SDK完成OAuth 2.0授权,替代原有的桌面端授权逻辑,步骤如下:
1. 添加依赖
在项目的Module级别build.gradle中添加以下依赖:
implementation 'com.google.android.gms:play-services-auth:20.7.0' implementation 'com.google.api-client:google-api-client-android:2.0.0' implementation 'com.google.apis:google-api-services-sheets:v4-rev20230815-2.0.0'
2. 替换授权逻辑
移除原getCredentials方法中LocalServerReceiver相关代码,改用Google Sign-in流程:
初始化登录客户端
private static final int RC_SIGN_IN = 1001; private GoogleSignInClient googleSignInClient; // 在Activity的onCreate中初始化 @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); // ...其他初始化代码 // 配置Google Sign-in选项,请求Sheets API权限 GoogleSignInOptions gso = new GoogleSignInOptions.Builder(GoogleSignInOptions.DEFAULT_SIGN_IN) .requestScopes(new Scope(SheetsScopes.SPREADSHEETS)) .requestEmail() .build(); googleSignInClient = GoogleSignIn.getClient(this, gso); }
启动登录流程
在触发读取Sheet的按钮点击事件中,替换原readListFromGSheet()调用:
// 原按钮点击逻辑替换为: GoogleSignInAccount account = GoogleSignIn.getLastSignedInAccount(this); if (account == null) { // 未登录,启动登录界面 signInLauncher.launch(googleSignInClient.getSignInIntent()); } else { // 已登录,直接读取Sheet try { readListFromGSheet(account); } catch (IOException | GeneralSecurityException e) { e.printStackTrace(); } }
处理登录结果
使用ActivityResultContracts接收登录结果:
private final ActivityResultLauncher<Intent> signInLauncher = registerForActivityResult( new ActivityResultContracts.StartActivityForResult(), result -> { if (result.getResultCode() == Activity.RESULT_OK && result.getData() != null) { Task<GoogleSignInAccount> task = GoogleSignIn.getSignedInAccountFromIntent(result.getData()); try { GoogleSignInAccount account = task.getResult(ApiException.class); readListFromGSheet(account); } catch (ApiException | IOException | GeneralSecurityException e) { e.printStackTrace(); } } });
修改Sheet读取方法
更新readListFromGSheet,从登录账号获取有效凭证:
public void readListFromGSheet(GoogleSignInAccount account) throws IOException, GeneralSecurityException { final NetHttpTransport HTTP_TRANSPORT = GoogleNetHttpTransport.newTrustedTransport(); final String spreadsheetId = "13NF1-XXXXXXXXXXXXXXXX-PaycpPb0AoAQ"; final String range = "web_register_tab!A2:F"; // 从登录账号构建Google Sheets API凭证 Credential credential = new GoogleCredential.Builder() .setTransport(HTTP_TRANSPORT) .setJsonFactory(JSON_FACTORY) .build() .setAccessToken(account.getIdToken()); // 构建Sheets服务实例 Sheets service = new Sheets.Builder(HTTP_TRANSPORT, JSON_FACTORY, credential) .setApplicationName(APPLICATION_NAME) .build(); // 后续读取逻辑与原代码一致 ValueRange response = service.spreadsheets().values() .get(spreadsheetId, range) .execute(); List<List<Object>> values = response.getValues(); if (values == null || values.isEmpty()) { System.out.println("No data found."); } else { for (List row : values) { int id = Integer.parseInt(row.get(0).toString()); String name = row.get(1).toString(); String phone = row.get(2).toString(); String email = row.get(3).toString(); String date = row.get(4).toString(); String register_time = row.get(5).toString(); WebinarRegister webinarRegister = new WebinarRegister(id, name, phone, email, date, register_time); String message = tvMessage.getText().toString(); tvMessage.setText(message + "\n" + webinarRegister.getName()); } } }
3. 配置权限
在AndroidManifest.xml中添加网络权限:
<uses-permission android:name="android.permission.INTERNET" />
关键说明
- Google Sign-in SDK会调用Android系统的账号选择器完成授权,无需本地HTTP服务器,完全适配Android平台
- 确保在Google Cloud Console中,你的OAuth 2.0客户端ID类型为Android,并正确配置SHA-1指纹和包名
内容的提问来源于stack exchange,提问作者Lokesh Tiwari
相关产品推荐
相关产品推荐

