Състоянието на изтритите файлове е ненадеждно докладвано в новия API на Google Диск за Android (GDAA)

Този проблем ме тормози от създаването на новия Android API на Google Drive (GDAA). Първо обсъдено тук, надявах се да изчезне в следващите версии, но е все още там (от 2014/03/19). Изхвърлените от потребителя файлове/папки (отнасяйки се до действието „Премахване“ в „drive.google.com“) продължават да се появяват и в двете

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

както и

  DriveFolder.listChildren(_gac)

методи, дори ако се използват с

  Filters.eq(SearchableField.TRASHED, false)

квалификатор на заявка или ако използвам конструкция за филтриране на резултатите

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

Използвайки

  Drive.DriveApi.requestSync(_gac);

няма влияние. И времето, изминало от премахването, варира много, последният ми случай беше над 12 ЧАСА. И това е напълно случайно.

Което е по-лошо, дори не мога да разчитам на EMPTY TRASH в „drive.google.com“, то не дава никакви предвидими резултати. Понякога състоянието на файла се променя на „isTrashed()“, понякога изчезва от списъка с резултати.

Докато продължавах да се занимавам с този проблем, стигнах до следния супер ужасен хак:

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
}

Дори това не помага. Файлът се показва като здрав, дори ако файлът е в кошчето (и състоянието му е двойно филтрирано чрез заявка и чрез тест за метаданни). Може дори да се запише щастливо и когато се провери в кошчето, се променя.

Заключението тук е, че корекцията трябва да получи по-висок приоритет, тъй като прави мултиплатформеното използване на Drive ненадеждно. Той ще бъде открит от разработчиците веднага в процеса на разработка / отстраняване на грешки, като ги отклони.


person seanpj    schedule 19.03.2014    source източник
comment
Има потвърждение за този проблем в SO: stackoverflow.com/questions/21713482/ (отговорът на Джейкъб).   -  person seanpj    schedule 20.03.2014
comment
requstSync().await() реши проблема за мен.   -  person Yaroslav Mytkalyk    schedule 15.04.2014


Отговори (1)


Докато чаках потвърждение от екипа за поддръжка, създадох HACK, който позволява заобиколно решение за това проблем. Използване на същия принцип като в SO 22295903, логиката включва връщане към RESTful API. По принцип премахване на функционалността СПИСЪК / ЗАЯВКА на GDAA.

Логиката на високо ниво е:

  1. направете заявка към RESTful API, за да извлечете идентификатора/идентификаторите на въпросния файл(ове).
  2. използвайте извлечения ID, за да получите DriveId на GDAA чрез 'fetchDriveId()'

ето кодовите фрагменти за документиране на процеса:

1/ инициализирайте 'GoogleApiClient' на GDAA и 'services.drive.Drive' на RESTful

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/ метод, който прави запитване към Drive RESTful API, връщайки DriveId на GDAA, който да се използва от приложението.

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;
}

Методът findObject() по-горе (отново използвам варианта „await()“ за простота) връща правилно обектите на Диск, отразявайки състоянието на кошчето без забележимо забавяне (имплементиране в нишка, която не е UI).

Отново силно препоръчвам ДА НЕ оставяте това в кода по-дълго от необходимото, тъй като това е HACK с непредсказуем ефект върху останалата част от системата.

person seanpj    schedule 22.03.2014