使用 AppIdentityService 进行身份验证时未找到电子表格

No spreadsheets found when using AppIdentityService to authenticate

我可以使用 AppIdentityService 成功验证我的 App Engine 应用程序。但是,当我执行 SpreadsheetService.getEntries 时,我没有收到任何条目。

这是我的代码:

SpreadsheetService service = new SpreadsheetService("Spreadsheet editing");
String[] SCOPESArray = { "https://spreadsheets.google.com/feeds" };
final List SCOPES = Arrays.asList(SCOPESArray);
AppIdentityService appIdentity = AppIdentityServiceFactory.getAppIdentityService();
AppIdentityService.GetAccessTokenResult accessToken = appIdentity.getAccessToken(SCOPES);

Credential creds = new Credential(BearerToken.authorizationHeaderAccessMethod());
creds.setAccessToken(accessToken.getAccessToken());    
service.setOAuth2Credentials(creds);

SpreadsheetFeed feed = service.getFeed(new URL("https://spreadsheets.google.com/feeds/spreadsheets/private/full"), SpreadsheetFeed.class);

List spreadsheets = feed.getEntries();

此时,电子表格是一个空列表。

我通过在电子表格的 "share" 框中输入服务帐户电子邮件与我的应用程序共享了电子表格 - 这是表单中的电子邮件:xxx@developer.gserviceaccount.com.

我是不是误解了这里的权限? "sharing" 包含服务帐户的电子表格是否不足以使服务帐户 "see" 成为电子表格?

我发现 Google Docs 上的共享效果不佳,即 "Shared with me" 文件夹相当不完整。 Drive 似乎改善了这一点,但电子表格 API 很古老...

我所做的是与 App Engine 服务帐户共享包含电子表格的文件夹,并使用云端硬盘 API 列出这些文件夹中的电子表格。使用其密钥访问文件夹。这允许我为单元测试、测试和生产配置不同的文件夹。

下面是一些从文件夹中获取电子表格的示例代码:

public enum MimeType { //
  SPREADSHEET ("application/vnd.google-apps.spreadsheet"),
  EXCEL ("application/vnd.openxmlformats-officedocument.spreadsheetml.sheet");

  private String type;
  MimeType(String type) {this.type = type;}

  public String getType() {
    return type;
  }
}

/**
 * Get a list of files of a given type from a folder 
 * 
 * @param folderId The Id of the folder
 * @param type The mime type of the files
 * @return a {@link FileList} containing the desired files
 * @throws IOException
 */
public FileList getFolderItems(String folderId, MimeType type) throws IOException {
    QueryBuilder query = new QueryBuilder();
    query.addParent(folderId).setMimeType(type);
    FileList list = drive.files().list().setQ(query.getQuery()).execute();
    return list;
}

然后您可以使用 File.getId() 检索文件密钥以用于电子表格 API。

顺便说一句,我建议不要使用 App Engine 中的电子表格 API。当从 GAE 调用时,API 经常遇到超时和其他异常。我不得不将我的处理转移到一个排队的任务中,不幸的是它没有像承诺的那样更长的 URLFetch 超时(参见 issue 10470),但至少,请求没有被取消。

我围绕大多数电子表格 API 调用编写了包装器,以便在出现异常时重试调用。而且我会不断添加更多包装器。

目前我认为使用来自 Google App Engine 的表格 API 进行更新时 AppIdentity 不受支持。

似乎可以进行身份​​验证,但 SpreadsheetEntry 的列表始终为空。

相反,通过在 GoogleCredential 实例中指定凭据,使用来自 Google App Engine 的服务帐户:

GoogleCredential creds = new GoogleCredential.Builder()
    .setTransport(GoogleNetHttpTransport.newTrustedTransport())
    .setJsonFactory(JacksonFactory.getDefaultInstance())
    .setServiceAccountId(serviceAccountEmailAddress)
    .setServiceAccountPrivateKeyFromP12File(p12FileFromCredentials)
    .setServiceAccountScopes(SCOPES)
    .build();


service.setOAuth2Credentials(creds);