首页 > 解决方案 > 使用服务帐户从android更新谷歌表?

问题描述

在使用服务帐户将 Android 应用程序的数据记录到 Google 表格时,我需要帮助。我阅读了数百个线程,这些线程大多使用已弃用的 Google 凭据,但这些凭据不起作用。有人可以帮助或知道如何在 Google 表格中写一行(数据)吗?

更新:

在我的 gradle 中,我添加了这个:

implementation 'com.google.android.gms:play-services-auth:19.0.0'
implementation 'pub.devrel:easypermissions:0.3.0'
implementation('com.google.api-client:google-api-client-android:1.23.0') {
    exclude group: 'org.apache.httpcomponents'
}
implementation('com.google.apis:google-api-services-sheets:v4-rev581-1.25.0') {
    exclude group: 'org.apache.httpcomponents'
}
implementation 'com.google.oauth-client:google-oauth-client-jetty:1.23.0'

这是我从谷歌表中阅读的课程,如谷歌示例所示:

public class GoogleSheetHelper {
private static final String APPLICATION_NAME = "Google Sheets API Java Quickstart";
private static final JsonFactory JSON_FACTORY = JacksonFactory.getDefaultInstance();
private static final String TOKENS_DIRECTORY_PATH = "tokens";
private static final List<String> SCOPES = Collections.singletonList(SheetsScopes.SPREADSHEETS_READONLY);
private static final String CREDENTIALS_FILE_PATH = "/credentials.json";

private static Credential getCredentials(final NetHttpTransport HTTP_TRANSPORT, Context context) throws IOException {
    // Load client secrets.
    //InputStream in = GoogleSheetHelper.class.getResourceAsStream(CREDENTIALS_FILE_PATH);
    InputStream in = context.getAssets().open("credentials.json");;
    if (in == null) {
        throw new FileNotFoundException("Resource not found: " + CREDENTIALS_FILE_PATH);
    }
    GoogleClientSecrets clientSecrets = GoogleClientSecrets.load(JSON_FACTORY, new InputStreamReader(in));
    File tokenFolder = new File(Environment.getExternalStorageDirectory() +
            File.separator + TOKENS_DIRECTORY_PATH);
    if (!tokenFolder.exists()) {
        boolean success = tokenFolder.mkdirs();
        if( !success ){
            throw new RuntimeException("File Error in writing new folder");
        }
    }
    FileDataStoreFactory f = new FileDataStoreFactory(tokenFolder);
    // Build flow and trigger user authorization request.
    GoogleAuthorizationCodeFlow flow = new GoogleAuthorizationCodeFlow.Builder(
            HTTP_TRANSPORT, JSON_FACTORY, clientSecrets, SCOPES)
            .setDataStoreFactory(f)
            .setAccessType("offline")
            .build();
    //LocalServerReceiver receiver = new LocalServerReceiver.Builder().setPort(8888).build();
    return new AuthorizationCodeInstalledApp(flow, new LocalServerReceiver()).authorize("user");
}
public static void napravi(Context context) throws IOException, GeneralSecurityException {
    // Build a new authorized API client service.
    //final NetHttpTransport HTTP_TRANSPORT = GoogleNetHttpTransport.newTrustedTransport();
    final NetHttpTransport HTTP_TRANSPORT = new com.google.api.client.http.javanet.NetHttpTransport();
    final String spreadsheetId = "1BxiMVs0XRA5nFMdKvBdBZjgmUUqptlbs74OgvE2upms";
    final String range = "Class Data!A2:E";
    Sheets service = new Sheets.Builder(HTTP_TRANSPORT, JSON_FACTORY, getCredentials(HTTP_TRANSPORT, context))
            .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 {
        System.out.println("Name, Major");
        for (List row : values) {
            System.out.printf("%s, %s\n", row.get(0), row.get(4));
        }
    }
}

因为我在 MainActivity 中得到 NetworkOnMainThreadException,所以我在 Thread 中调用它:

new Thread(() -> {
        try {
            GoogleSheetHelper.napravi(getApplicationContext());
        } catch (IOException e) {
            e.printStackTrace();
        } catch (GeneralSecurityException e) {
            e.printStackTrace();
        }
        runOnUiThread(()->{
            // OnPostExecute stuff here
        });
    }).start();

但我现在得到了这个例外:

2020-11-26 06:50:06.447 30966-31002/hr.krkec.orchestrabarcodeapp E/AndroidRuntime: FATAL EXCEPTION: Thread-3
Process: hr.krkec.orchestrabarcodeapp, PID: 30966
java.lang.NoClassDefFoundError: Failed resolution of: Ljava/awt/Desktop;
    at com.google.api.client.extensions.java6.auth.oauth2.AuthorizationCodeInstalledApp.browse(AuthorizationCodeInstalledApp.java:129)
    at com.google.api.client.extensions.java6.auth.oauth2.AuthorizationCodeInstalledApp.onAuthorization(AuthorizationCodeInstalledApp.java:113)
    at com.google.api.client.extensions.java6.auth.oauth2.AuthorizationCodeInstalledApp.authorize(AuthorizationCodeInstalledApp.java:81)
    at hr.krkec.orchestrabarcodeapp.Helpers.GoogleSheetHelper.getCredentials(GoogleSheetHelper.java:75)
    at hr.krkec.orchestrabarcodeapp.Helpers.GoogleSheetHelper.napravi(GoogleSheetHelper.java:89)
    at hr.krkec.orchestrabarcodeapp.MainActivity.lambda$onCreate$1$MainActivity(MainActivity.java:112)
    at hr.krkec.orchestrabarcodeapp.-$$Lambda$MainActivity$dMONIKNVXAJxtq31-j2RI7GKpKk.run(Unknown Source:2)
    at java.lang.Thread.run(Thread.java:764)
 Caused by: java.lang.ClassNotFoundException: Didn't find class "java.awt.Desktop" on path: DexPathList[[zip file "/data/app/hr.krkec.orchestrabarcodeapp-DmJDmyzrsZ1Fz0c3Wtg9xg==/base.apk"],nativeLibraryDirectories=[/data/app/hr.krkec.orchestrabarcodeapp-DmJDmyzrsZ1Fz0c3Wtg9xg==/lib/x86, /data/app/hr.krkec.orchestrabarcodeapp-DmJDmyzrsZ1Fz0c3Wtg9xg==/base.apk!/lib/x86, /system/lib, /vendor/lib]]
    at dalvik.system.BaseDexClassLoader.findClass(BaseDexClassLoader.java:93)
    at java.lang.ClassLoader.loadClass(ClassLoader.java:379)
    at java.lang.ClassLoader.loadClass(ClassLoader.java:312)
    at com.google.api.client.extensions.java6.auth.oauth2.AuthorizationCodeInstalledApp.browse(AuthorizationCodeInstalledApp.java:129) 
    at com.google.api.client.extensions.java6.auth.oauth2.AuthorizationCodeInstalledApp.onAuthorization(AuthorizationCodeInstalledApp.java:113) 
    at com.google.api.client.extensions.java6.auth.oauth2.AuthorizationCodeInstalledApp.authorize(AuthorizationCodeInstalledApp.java:81) 
    at hr.krkec.orchestrabarcodeapp.Helpers.GoogleSheetHelper.getCredentials(GoogleSheetHelper.java:75) 
    at hr.krkec.orchestrabarcodeapp.Helpers.GoogleSheetHelper.napravi(GoogleSheetHelper.java:89) 
    at hr.krkec.orchestrabarcodeapp.MainActivity.lambda$onCreate$1$MainActivity(MainActivity.java:112) 
    at hr.krkec.orchestrabarcodeapp.-$$Lambda$MainActivity$dMONIKNVXAJxtq31-j2RI7GKpKk.run(Unknown Source:2) 
    at java.lang.Thread.run(Thread.java:764) 

我究竟做错了什么?

标签: androidgoogle-sheets

解决方案


如果您正在寻找一种通过 Android SDK 在您的 android 应用程序中使用 Google Sheets API 的方法,这可能会对您有所帮助。

为 Android 设置 Google Workspace API https://developers.google.com/gsuite/guides/android

先决条件:

  • 必须有一个谷歌帐户
  • Android Studio SDK 1.2 或更高版本
  • 适用于 API 23 或更高版本的 Android SDK 包

准备项目:

在您的 Android 项目中,包含一个带有以下依赖项的build.gradle文件:

dependencies {
    compile fileTree(dir: 'libs', include: ['*.jar'])
    compile 'com.android.support:appcompat-v7:25.0.1'
    compile 'com.google.android.gms:play-services-auth:15.0.1'
    compile 'pub.devrel:easypermissions:0.3.0'
    compile('com.google.api-client:google-api-client-android:1.23.0') {
        exclude group: 'org.apache.httpcomponents'
    }
    compile('com.google.apis:google-api-services-<API>-<VERSION>') {
        exclude group: 'org.apache.httpcomponents'
    }
}

请务必将APIVERSION替换为 Google Workspace API 和版本。例如,Google Sheets API 将使目标编译“ com.google.apis:google-api-services-sheets:v4-rev581-1.25.0

服务通过身份验证后,执行 API 调用与任何 G Suite Java 快速入门中所示的相同。

Java 快速入门过程总结:

  1. 开启 Google 表格 API
  2. 准备项目
  3. 设置示例
  4. 运行示例

有关 Java 快速入门的更多详细信息,请参阅此处: https ://developers.google.com/sheets/api/quickstart/java


推荐阅读