Frage

This issue has been bugging me since the inception of the new Google Drive Android Api (GDAA). First discussed here, I hoped it would go away in later releases, but it is still there (as of 2014/03/19). The user-trashed (referring to the 'Remove' action in 'drive.google.com') files/folders keep appearing in both the

  Drive.DriveApi.query(_gac, query), and  
  DriveFolder.queryChildren(_gac, query)

as well as

  DriveFolder.listChildren(_gac)

methods, even if used with

  Filters.eq(SearchableField.TRASHED, false)

query qualifier, or if I use a filtering construct on the results

for (Metadata md : result.getMetadataBuffer()) {
  if ((md == null) || (!md.isDataValid()) || md.isTrashed()) continue;
  dMDs.add(new DrvMD(md));
}

Using

  Drive.DriveApi.requestSync(_gac);

has no impact. And the time elapsed since the removal varies wildly, my last case was over 12 HOURS. And it is completely random.

What's worse, I can't even rely on EMPTY TRASH in 'drive.google.com', it does not yield any predictable results. Sometime the file status changes to 'isTrashed()' sometimes it disappears from the result list.

As I kept fiddling with this issue, I ended up with the following superawfulhack:

find file with TRASH status equal FALSE 
if (file found and is not trashed) {
  try to write content
  if ( write content fails)
    create a new file
}

Not even this helps. The file shows up as healthy even if the file is in the trash (and it's status was double-filtered by query and by metadata test). It can even be happily written into and when inspected in the trash, it is modified.

The conclusion here is that a fix should get higher priority, since it renders multi-platform use of Drive unreliable. It will be discovered by developers right away in the development / debugging process, steering them away.

War es hilfreich?

Lösung

While waiting for any acknowledgement from the support team, I devised a HACK that allows a workaround for this problem. Using the same principle as in SO 22295903, the logic involves falling back to RESTful API. Basically, dropping the LIST / QUERY functionality of GDAA.

The high level logic is:

  1. query the RESTful API to retrieve the ID/IDs of file(s) in question
  2. use retrieved ID to get GDAA's DriveId via 'fetchDriveId()'

here are the code snippets to document the process:

1/ initialize both GDAA's 'GoogleApiClient' and RESTful's 'services.drive.Drive'

GoogleApiClient _gac;
com.google.api.services.drive.Drive _drvSvc;

void init(Context ctx, String email){
  // build GDAA  GoogleApiClient
  _gac = new GoogleApiClient.Builder(ctx).addApi(com.google.android.gms.drive.Drive.API)
    .addScope(com.google.android.gms.drive.Drive.SCOPE_FILE).setAccountName(email)
    .addConnectionCallbacks(ctx).addOnConnectionFailedListener(ctx).build();
  // build RESTFul (DriveSDKv2) service to fall back to  
  GoogleAccountCredential crd = GoogleAccountCredential
  .usingOAuth2(ctx, Arrays.asList(com.google.api.services.drive.DriveScopes.DRIVE_FILE));
  crd.setSelectedAccountName(email);
  _drvSvc = new com.google.api.services.drive.Drive.Builder(
                       AndroidHttp.newCompatibleTransport(), new GsonFactory(), crd).build();
}

2/ method that queries the Drive RESTful API, returning GDAA's DriveId to be used by the app.

String qry = "title = 'MYFILE' and mimeType = 'text/plain' and trashed = false";
DriveId findObject(String qry) throws Exception {
  DriveId dId = null;
  try {
    final FileList gLst = _drvSvc.files().list().setQ(query).setFields("items(id)").execute();
    if (gLst.getItems().size() == 1) {
      String sId = gLst.getItems().get(0).getId();
      dId = Drive.DriveApi.fetchDriveId(_gac, sId).await().getDriveId();
    } else if (gLst.getItems().size() > 1)
      throw new Exception("more then one folder/file found");
  } catch (Exception e) {}
  return dId;
}

The findObject() method above (again I'm using the 'await()' flavor for simplicity) returns the the Drive objects correctly, reflecting the trashed status with no noticeable delay (implement in non-UI thread).

Again, I would strongly advice AGAINST leaving this in code longer than necassary since it is a HACK with unpredictable effect on the rest of the system.

Lizenziert unter: CC-BY-SA mit Zuschreibung
Nicht verbunden mit StackOverflow
scroll top