在Java中使用Google Spreadsheet API在Google Drive中创建电子表格

17

我曾经创建了一些工具来填充谷歌电子表格。 自从今天起,它已经运行了1年,并且一直正常工作,但现在出现了错误。

Exception in thread "main" com.google.gdata.util.AuthenticationException: Error authenticating (check service name)
at com.google.gdata.client.GoogleAuthTokenFactory.getAuthException(GoogleAuthTokenFactory.java:688)
at com.google.gdata.client.GoogleAuthTokenFactory.getAuthToken(GoogleAuthTokenFactory.java:560)
at com.google.gdata.client.GoogleAuthTokenFactory.setUserCredentials(GoogleAuthTokenFactory.java:397)
at com.google.gdata.client.GoogleService.setUserCredentials(GoogleService.java:364)
at com.google.gdata.client.GoogleService.setUserCredentials(GoogleService.java:319)
at com.google.gdata.client.GoogleService.setUserCredentials(GoogleService.java:303)

这是连接Gmail的代码部分:

String USERNAME = "usename@........com"; ->of course I'm using proper username and password
    String PASSWORD = "*******";
    SpreadsheetService service
            = new SpreadsheetService("SandboxCheck");
    service.setUserCredentials(USERNAME, PASSWORD);

我不知道如何连接Gmail,我尝试通过oAuth来完成这个任务,但是我不知道该如何做。在https://developers.google.com/google-apps/spreadsheets/authorize的例子中,只提供了.NET的代码。


我怀疑你遇到了两个问题。1)OpenAuth 1 / Client Login 不再受支持,2)Documents List API 已经过时,因此您需要迁移到Drive API来创建电子表格。不幸的是,我没有Java方面的示例供您参考。 - daryl
看起来客户端登录已不再受支持。我希望他们能更新Spreed API页面并提供如何在Java中使用它的示例。 - Skwarosz
同样的问题,我也遇到了,从昨天开始!他们是否停止支持应用程序密码身份验证? - Dimitris Sfounis
3个回答

18

在此链接的帮助下,我最终成功创建了这样的连接。一切都像以前一样正常工作。
以下是您需要完成的步骤:

  1. https://console.developers.google.com上注册
  2. 创建新项目
  3. 在API和授权->凭据->为服务帐户创建新的客户端ID下
  4. 生成P12密钥后,您必须使用生成的客户端ID。
  5. 下面的代码中需要用到客户端ID,电子邮件地址是您需要共享您的电子表格的地址。

以下是可行的代码:

import com.google.api.client.googleapis.auth.oauth2.GoogleCredential;
import com.google.api.client.http.HttpTransport;
import com.google.api.client.http.javanet.NetHttpTransport;
import com.google.api.client.json.jackson.JacksonFactory;
import com.google.gdata.client.spreadsheet.SpreadsheetService;
import com.google.gdata.data.spreadsheet.SpreadsheetEntry;
import com.google.gdata.data.spreadsheet.SpreadsheetFeed;
import com.google.gdata.util.ServiceException;
import java.io.File;
import java.io.IOException;
import java.net.MalformedURLException;
import java.net.URL;
import java.security.GeneralSecurityException;
import java.util.Arrays;
import java.util.List;
public class OAuthIntegration{
    public static void main(String[] args) throws MalformedURLException, GeneralSecurityException, IOException, ServiceException {
        URL SPREADSHEET_FEED_URL;
        SPREADSHEET_FEED_URL = new URL("https://spreadsheets.google.com/feeds/spreadsheets/private/full");

        File p12 = new File("./key.p12");

        HttpTransport httpTransport = new NetHttpTransport();
        JacksonFactory jsonFactory = new JacksonFactory();
        String[] SCOPESArray = {"https://spreadsheets.google.com/feeds", "https://spreadsheets.google.com/feeds/spreadsheets/private/full", "https://docs.google.com/feeds"};
        final List SCOPES = Arrays.asList(SCOPESArray);
        GoogleCredential credential = new GoogleCredential.Builder()
                .setTransport(httpTransport)
                .setJsonFactory(jsonFactory)
                .setServiceAccountId("cliend_ID")
                .setServiceAccountScopes(SCOPES)
                .setServiceAccountPrivateKeyFromP12File(p12)
                .build();

        SpreadsheetService service = new SpreadsheetService("Test");

        service.setOAuth2Credentials(credential);
        SpreadsheetFeed feed = service.getFeed(SPREADSHEET_FEED_URL, SpreadsheetFeed.class);
        List<SpreadsheetEntry> spreadsheets = feed.getEntries();

        if (spreadsheets.size() == 0) {
            System.out.println("No spreadsheets found.");
        }

         SpreadsheetEntry spreadsheet = null;
        for (int i = 0; i < spreadsheets.size(); i++) {
            if (spreadsheets.get(i).getTitle().getPlainText().startsWith("ListOfSandboxes")) {
                spreadsheet = spreadsheets.get(i);
                System.out.println("Name of editing spreadsheet: " + spreadsheets.get(i).getTitle().getPlainText());
                System.out.println("ID of SpreadSheet: " + i);
            }
        }

    }

}

我希望这将有助于解决我遇到的问题。 以下是我使用的jar清单:

guava-11.0.2.jar
gdata-spreadsheet-3.0.jar
gdata-maps-2.0.jar
gdata-core-1.0.jar
jackson-core-asl-1.9.11.jar
jackson-core-2.1.3.jar
google-oauth-client-1.20.0.jar
google-http-client-jackson2-1.20.0.jar
google-http-client-jackson-1.20.0.jar
google-http-client-1.20.0.jar
google-api-client-1.20.0.jar

2
谢谢Skwarsz。对于其他人,有一个小澄清。在第4步中,控制台将提供“客户端ID”和“电子邮件地址”。(a)您需要“电子邮件地址”来在setServiceAccountId()方法调用中使用(而不是ID,尽管方法名称中包含ID)。(b)您需要与相同的电子邮件地址共享您的电子表格。 - AndrewL
2
谢谢Skwarsz。不过有一个小问题:我认为你需要使用gdata-core-1.47.1.jar而不是你正在使用的gdata-core-1.0.jar。版本1.0无法识别SpreadsheetService类的setOAuth2Credentials()方法。 - davak
1
在哪里保存p12密钥文件? - John
我该如何获取P12密钥文件? - Sumeet Vishwas
你好Sumeet,我看到console.developers.google.com的界面发生了变化。为了获取密钥,您需要进入Service Accounts,然后在右侧有3个点,点击它们并选择Create Key,然后选择p12。 - Skwarosz
显示剩余5条评论

4

Google刚刚停止支持OAuth1.0,需要使用OAuth2。要进行切换,请先前往Google开发人员控制台,创建一个项目并设置凭据。然后更新您的代码,类似于以下Java代码:

private void createSpreadSheetService() throws GeneralSecurityException, IOException, ServiceException {
   HttpTransport httpTransport = new NetHttpTransport();
   JacksonFactory jsonFactory = new JacksonFactory();
   String [] SCOPESArray= {"https://spreadsheets.google.com/feeds", "https://docs.google.com/feeds"};
   final List SCOPES = Arrays.asList(SCOPESArray);
   GoogleCredential credential = new GoogleCredential.Builder()
     .setTransport(httpTransport)
     .setJsonFactory(jsonFactory)
     .setServiceAccountId(SERVICE_ACCOUNT_EMAIL)
     .setServiceAccountScopes(SCOPES)
     .setServiceAccountPrivateKeyFromP12File(SERVICE_ACCOUNT_PKCS12_FILE)
     .build();

   SPREADSHEETSERVICE = new SpreadsheetService("data");
   SPREADSHEETSERVICE.setOAuth2Credentials(credential);

您需要两个库:google-api-client和google-http-client-jackson。如果您使用Maven,请在pom.xml中包含以下依赖项。

 <dependency>
  <groupId>com.google.api-client</groupId>
  <artifactId>google-api-client</artifactId>
  <version>1.19.0</version>
  <type>jar</type>
 </dependency>
 <dependency>
  <groupId>com.google.http-client</groupId>
  <artifactId>google-http-client-jackson</artifactId>
  <version>1.19.0</version>
  <type>jar</type>
 </dependency>

你从哪里导入 JacksonFactory - Dimitris Sfounis
1
需要哪些库才能运行createSpreadSheetService - Skwarosz
高灿,请问您用了哪些库来使这段代码工作?我总是面临各种异常和其他错误。 - Skwarosz

1

我尝试了Gao的解决方案,但是在使用库时遇到了一个问题。我正在使用NetBeans,项目没有错误构建,但是当我尝试执行它时,出现了以下错误:

 Exception in thread "main" java.lang.NoClassDefFoundError: org/codehaus/jackson/JsonFactory
at com.google.api.client.json.jackson.JacksonFactory.<init>(JacksonFactory.java:38)
at SandboxCheck.main(SandboxCheck.java:48) 

我发现类路径有问题,但不知道如何在netbeans上修复它,我认为当添加库时它应该自动处理。我已经添加了以下这些库:google-oauth-client-1.16.0-rc.jar google-oauth-client-1.16.0-rc-sources.jar google-api-client-1.8.0-beta-sources.jar google-api-client-1.4.1-beta.jar google-api-client-1.19.1.jar 我不确定是否添加了太多的库,但是如果我删除例如google-api-client-1.4.1-beta.jar,它就无法查看JacksonFactory类。

这里也有完全相同的问题。 - Dimitris Sfounis
更新:通过 import com.fasterxml.jackson.core.*; 成功解决了。我不知道自己在做什么或发生了什么。 - Dimitris Sfounis
Dimitris是如何通过这个导入使其工作的呢?因为它使用的是JsonFactory而不是JacksonFactory,我仍然有这个问题。 - Skwarosz
JsonFactory 是一个抽象超类,你的问题出在 JacksonFactory 无法找到定义。将 jackson-core-2.1.3.jar 包含到你的项目库中并导入我写的内容。这样应该就可以通过了。 - Dimitris Sfounis
我在 SpreadsheetFeed feed = service.getFeed(SPREADSHEET_FEED_URL, SpreadsheetFeed.class); 遇到了 Exception in thread "main" java.lang.AbstractMethodError: com.google.api.client.json.JsonFactory.createJsonGenerator(Ljava/io/OutputStream;Ljava/nio/charset/Charset;)Lcom/google/api/client/json/JsonGenerator; 的异常。 - Skwarosz
我知道现在可能太晚了,但我尝试了上述方法。我已经从钥匙串访问中获取了生成.p12文件所需的密钥,并请注意,我只是使用了公司提供的笔记本电脑上的密钥。然后将它们导出到桌面上,但现在我得到了这个错误信息:java.io.IOException: failed to decrypt safe contents entry: javax.crypto.BadPaddingException: Given final block not properly padded。这是因为我正在使用来自我的办公笔记本电脑的p12,并使用为Google应用程序中的不同电子邮件生成的客户端ID吗? - ApJo

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接