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

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.28 09:07:39