Android Google DriveApi возвращает разные идентификаторы DriveID для одного и того же заголовка на разных устройствах

Итак, во-первых, я знаю, что DriveID для каждого файла/папки зависит от устройства, НО resourceId является постоянным, и это действительно то, что я использую для проверки того, одинаковы ли элементы (кроме названия, конечно).

Проблема

Я пытаюсь синхронизировать папки в своей папке AppFolder на разных устройствах, однако я получаю разные файлы/папки на каждом устройстве, несмотря на то, что перед тем, как что-либо делать, запрашиваю заголовок. Итак, некоторый код:

Как настроить клиент API

 mGoogleApiClient = new GoogleApiClient.Builder(context.getApplicationContext())
                .addApi(Drive.API)
                .addApi(Plus.API)//used for logout process
                .addScope(Drive.SCOPE_APPFOLDER)
                .addConnectionCallbacks(OnConnection)
                .addOnConnectionFailedListener(OnFailedListener)
                .build();

Как настроить appFolder

appFolder = Drive.DriveApi.getAppFolder(mGoogleApiClient);

Я убедился, что получаю один и тот же идентификатор ресурса для AppFolder на обоих устройствах.

Как я создаю/получаю папки

private static DriveFolder CheckForOrCreateDriveFolder(DriveFolder appFolder, String folder) {
    MetadataBuffer metadataBuffer = appFolder.queryChildren(mGoogleApiClient, new Query.Builder().addFilter(Filters.eq(SearchableField.TITLE, folderName)).build()).await().getMetadataBuffer();
    if(metadataBuffer != null&&metadataBuffer.getCount()>0) {
        Log.v(TAG,"Found "+metadataBuffer.getCount()+" existing folders");
        Metadata metadata = metadataBuffer.get(0);
        if (metadata != null && metadata.isFolder()) {
            Log.v(TAG,"Returning existing folder");
            return Drive.DriveApi.getFolder(mGoogleApiClient, metadata.getDriveId());
        }else{
            Log.v(TAG,"Returning created folder even though we found meta data");
            return appFolder.createFolder(mGoogleApiClient, new MetadataChangeSet.Builder().setTitle(folderName).build()).await().getDriveFolder();
        }
    }else{
        Log.v(TAG,"Returning created folder");
        return appFolder.createFolder(mGoogleApiClient, new MetadataChangeSet.Builder().setTitle(folderName).build()).await().getDriveFolder();
    }
}

На этом я всегда получаю ожидаемый результат. т.е. Found 1 existing folders, а затем Returning existing folder. Кроме того, прежде чем вы упомянете об использовании await(), я выделяю свои собственные потоки, и это НИКОГДА не вызывается в потоке пользовательского интерфейса, так что не беспокойтесь.

Тестовый код

Я заметил, что sqlite db не копировался, что позволило мне выяснить, что даже папки не пересекались, поэтому я написал еще один тест:

DriveApi.MetadataBufferResult metadataBufferResult = appFolder.listChildren(mGoogleApiClient).await();
Log.v(TAG,"AppFolder Contents:");
for (Metadata metadata : metadataBufferResult.getMetadataBuffer()) {
    Log.v(TAG,"MD:"+metadata.getTitle()+" : "+metadata.getDriveId().getResourceId()+" - "+(metadata.isFolder()?"is a folder":"is a file"));
}

Что для одного устройства возвращает:

AppFolder Contents:
MD:itemImage : 1eFvDS6cWmCbgblahblahblahblahblah - is a folder
MD:itemAudio : 1c86N8AGRV8Bblahblahblahblahblah - is a folder
MD:userImage : 1LnsgFneT-l3ZYzMbblahblahblahblah - is a folder
MD:db.sqlite : 1DH4QfUfrsxDScblahblahblahblah - is a file

и для другого:

AppFolder Contents:
MD:itemAudio : 1CqeVASm_Gjjblahblahblahblahblah - is a folder
MD:itemImage : 1Djs059FYGSfOblahblahblahblahblah - is a folder
MD:userImage : 1U5c5yCw-XdfCblahblahblahblahblah - is a folder
MD:db.sqlite : 15qR3WLmvT3Nn2Ztblahblahblahblahblah - is a file

Я проверил 4 или более раз, что эти устройства используют одну и ту же учетную запись Google. Если есть какой-либо другой код или информация, которую я мог бы дать вам, пожалуйста, дайте мне знать! Любая помощь в поиске ответа на этот вопрос будет принята с благодарностью ^^ Спасибо!


person Matthew Clark    schedule 31.10.2014    source источник
comment
Так что у ваших двух устройств разный взгляд на реальность. Что думает Драйв? Попробуйте использовать developers.google.com/drive/v2/reference/ files/get#try-it или clevernote.co/app/drivecrud.html или даже drive.google.com, чтобы посмотреть, что находится на сервере. Идентификатор ресурса — это то, что остальная часть Диска называет идентификатором файла. Суть в том, что если файл имеет два идентификатора ресурса, то на самом деле это два отдельных файла. Воспроизводима ли бифуркация? Я спрашиваю, потому что это может быть побочным эффектом общих проблем с Диском в последнее время.   -  person pinoyyid    schedule 31.10.2014
comment
@pinoyyid Спасибо за вопрос! Я думаю, что основная проблема заключается в том, что, поскольку я использую AppFolder, только приложение может видеть содержимое ... и ссылка разработчика, которую вы дали, похоже, не видит appFolder (или что-либо под ним). Версия Clevernote потребует, чтобы я добавил к ней общедоступный веб-API... и, поскольку на данный момент это приложение только для Android, я хотел бы держаться подальше от него как можно дольше. И поскольку это appFolder, пользователь не может просмотреть его через Google Drive. Вот почему я сделал функцию тестового списка... любые другие сайты/проспекты? Мне нравится идея проверить это!   -  person Matthew Clark    schedule 03.11.2014
comment
когда вы говорите только приложение, это должно быть только приложение. Таким образом, вы должны иметь возможность запрашивать содержимое папки приложений с помощью Oauth Playground. Убедитесь, что вы включили область googleapis.com/auth/drive.appfolder.   -  person pinoyyid    schedule 04.11.2014
comment
Я могу ошибаться, но у меня сложилось впечатление, что для этого требуется приложение, созданное с правильным идентификатором пакета, а также подписанное с правильным кодовым знаком. Я добавляю инициализацию клиента к приведенной выше информации, чтобы вы могли видеть большую ее часть ^^   -  person Matthew Clark    schedule 04.11.2014
comment
Вы вполне можете быть правы. Я никогда не использовал appdata из-за этой самой непрозрачности в случае возникновения проблемы.   -  person pinoyyid    schedule 05.11.2014


Ответы (3)


К сожалению, я заблудился в объяснении вашего конкретного случая, но если я прочитаю только заголовок, я могу дать вам некоторые подсказки, так как я столкнулся с той же проблемой.

Для каждого объекта (папки или файла) в GDAA (Google Drive Android Api) есть 2 идентификатора: DRIVE_ID и RESOURCE_ID.

Идентификатор DRIVE_ID специфичен для вашего конкретного устройства, поэтому, если вы используете его на другом устройстве, это ничего не значит. RESOURCE_ID уникален для разных устройств, поэтому его нужно использовать для любого типа синхронизации. См. SO 22841237.

Если вы создаете файл/папку с помощью GDAA, RESOURCE_ID может быть недоступен сразу, поскольку GDAA необходимо «зафиксировать» объект, чтобы получить его. См. SO 22432431.

НЕ ИСПОЛЬЗУЙТЕ заголовок (имя) файла/папки вообще, так как это не основной идентификатор в мире Google Диска. Вы можете иметь несколько объектов Диска в одной и той же области с одним и тем же заголовком (именем).

Кроме того, имейте в виду, что добавление GDAA в уравнение (в отличие от использования простого RESTful API), вы добавляете слой с собственной задержкой, которую вы не можете контролировать. «ChangeEvent Listener» и «requestSync()» также не помогают. См. SO 23073474.

Просто чтобы дать вам подсказку, потратив несколько месяцев на борьбу с теми же проблемами, я вернулся к RESTful API с поставщиком данных и адаптером синхронизации, опрашивая Диск на наличие изменений. Следующим шагом будет добавление синхронизации на основе GCM. Я надеялся, что синхронизация (с использованием GCM) будет встроена в GDAA. Но это, видимо, не так. И вы еще не пытались удалить файлы/папки, вот где начинается настоящее веселье.

Удачи.

person seanpj    schedule 31.10.2014
comment
Спасибо за ваши комментарии! Я понял, что resourceId был фактическим идентификатором методом проб и ошибок (именно это я пытался объяснить в своем первом предложении). Я использовал DriveID в заголовке исключительно потому, что если бы я искал этот вопрос, я бы использовал это слово, но, возможно, мне также следует указать в заголовке resourceId. Что касается остального из того, что вы сказали ... Мне было весело с входом / выходом, я надеюсь, что смогу заставить это работать с не слишком большой работой ... то, что вы описываете, было бы довольно огромным переписыванием. Скрещенные пальцы. О, и я запрашиваю только заголовки, не использую их ни для чего другого ^^ - person Matthew Clark; 31.10.2014
comment
Это не отвечает на ваш вопрос, но с учетом довольно большого переписывания... Я бы посоветовал, чтобы все, что вы делаете с Диском, было полностью инкапсулировано в модуль с вашими собственными интерфейсами к нему. В настоящее время существует 4 различных способа, которыми приложение может общаться с Диском, и кто знает, сколько их появится в будущем. Нет никаких причин, по которым DropBox или даже Microsoft не могли бы придумать эквивалент GDAA, на который вы, возможно, захотите переключиться в какой-то момент. - person pinoyyid; 31.10.2014
comment
Да, довольно большое переписывание. Это то, чем я занимаюсь. Мне удалось уловить все причуды GDAA, но все же случайная задержка в конце меня убила. Даже если все остальное работает. Службы Google Play были слишком непредсказуемы. GDAA может быть полезен для некоторых приложений, но я считаю, что синхронизация объектов Диска между разными устройствами не является одним из них. Как я прокомментировал в другом месте, мне удалось создать файл в несуществующей папке (удален, корзина очищена) в течение 3 часов. Попробуйте создать приложение вокруг этого. - person seanpj; 31.10.2014
comment
Например, если вы удалите что-либо на устройстве A (вы должны использовать RESTful, поскольку в GDAA нет удаления), устройство B будет видеть эту чертову вещь в течение нескольких часов через GDAA (даже с использованием RESOURCE_ID). Таким образом, вы можете работать с несуществующим объектом Drive. И «удаление» GDAA «входит в следующий выпуск» с февраля. - person seanpj; 31.10.2014
comment
К счастью, я использую это только для резервного копирования, поэтому не нужно удалять. Я надеюсь, что нужно просто подождать достаточно долго и найти способ не дублировать/не перезаписывать тем временем... в худшем случае. Что касается перезаписи, код резервной копии инкапсулирован, однако он написан с использованием GDAA в качестве основы с пониманием того, что на сервисы Play можно положиться... посмотрим, как он выдержит. - person Matthew Clark; 31.10.2014
comment
Тем не менее, даже без DELETE вы будете бороться со случайными задержками. Например, если вы записываете/обновляете что-либо с помощью устройства A, вы можете некоторое время не видеть изменения на устройстве B, поскольку GDAA предоставит вам его кешированную версию, даже если вы используете RESOURCE_ID. Таким образом, для опроса RESTful более надежен (заметьте, окончательным решением по-прежнему является система уведомлений на основе GCM). Что касается инкапсуляции, лучшее место для нее — «ContentProvider» (по крайней мере, в моем случае). Если вы сделаете это там, легко использовать «AbstractThreadedSyncAdapter» для выполнения опроса/синхронизации. - person seanpj; 31.10.2014
comment
... и я не ругаю GDAA, возможность записи в него без подключения к сети - это здорово. Но эта возможность с кэшированием и задержкой делает его плохим выбором для приложения, которому нужно видеть, что другие устройства делают с файлами на Диске. Как я уже сказал, я надеялся, что они встроят в него синхронизацию на основе GCM, но ее нет. Кто-нибудь знает о планах??? - person seanpj; 31.10.2014

Помогает ли такая настройка appFolder?

String appFolder = Drive.DriveApi.getAppFolder(mGoogleApiClient()).getDriveId().getResourceId().toString();
person berkley    schedule 25.11.2014

У меня была такая же проблема (дублированные папки), и я решил использовать requestSync ПЕРЕД запуском поискового запроса:

Drive.DriveApi.requestSync(getGoogleApiClient()).await();
person Marco C.    schedule 19.07.2016
comment
Спасибо за ответ! Надеюсь, скоро сможем протестировать и принять его! - person Matthew Clark; 20.07.2016