DriveFolder.listChildren() не показывает всех своих дочерних элементов

Я делаю приложение, которое работает с Google Drive.

Мне нужно получить список ВСЕХ файлов внутри папки, но кажется, что это невозможно: когда я вызываю метод listFiles(), я не могу получить все файлы внутри DriveFolder. Но не только это, в списке файлов, которые я получаю, есть некоторые файлы, которые я удалил ранее.

Я читал, что это может быть вызвано задержкой синхронизации из-за сервисов Google Play, но я выбрал параметр «Синхронизировать сейчас» в настройках своей учетной записи, поэтому я думаю, что проблема не вызвана этой задержкой.

Это метод, о котором я говорю http://developer.android.com/reference/com/google/android/gms/drive/DriveFolder.html#listChildren(com.google.android.gms.common.api.GoogleApiClient)

И это код, который я написал:

public class ServicePull extends IntentService implements
    GoogleApiClient.ConnectionCallbacks,
    GoogleApiClient.OnConnectionFailedListener{

private GoogleApiClient mApiClient;

public static void startPull(Context context) {
    Intent intent = new Intent(context, ServicePull.class);
    context.startService(intent);
}

public ServicePull() {
    super("ServicePull");
}

@Override
protected void onHandleIntent(Intent intent) {
    mApiClient = new GoogleApiClient.Builder(this)
            .addApi(Drive.API)
            .addScope(Drive.SCOPE_FILE)
            .addConnectionCallbacks(this)
            .addOnConnectionFailedListener(this)
            .build();

    mApiClient.connect();
}



@Override
public void onConnected(Bundle bundle) {
    NotificationStatus.notify(this, "On Connected", "mApiClient Connected");
    DriveFolder driveFolder = Drive.DriveApi.getRootFolder(mApiClient);
    driveFolder.listChildren(mApiClient).setResultCallback(rootFolderCallback);
}

@Override
public void onConnectionSuspended(int i) {
    NotificationStatus.notify(this, "On Suspended", "mApiClient Suspended");
}

@Override
public void onConnectionFailed(ConnectionResult connectionResult) {
    NotificationStatus.notify(this, "On failed", "mApiClient failed");
}

final private ResultCallback<DriveApi.MetadataBufferResult> rootFolderCallback =
        new ResultCallback<DriveApi.MetadataBufferResult>() {
            @Override
            public void onResult(DriveApi.MetadataBufferResult metadataBufferResult) {
                log("got root folder");
                MetadataBuffer buffer = metadataBufferResult.getMetadataBuffer();
                log("Buffer count  " + buffer.getCount());
                for(Metadata m : buffer){
                    log("Metadata name  " + m.getTitle() + "(" + (m.isFolder() ? "folder" : "file") + ")");
                    if (m.isFolder() && m.getTitle().equals("Neewie"))
                        Drive.DriveApi.getFolder(mApiClient, m.getDriveId())
                                .listChildren(mApiClient)
                                .setResultCallback(fileCallback);
                }
            }
};

final private ResultCallback<DriveApi.MetadataBufferResult> fileCallback =
        new ResultCallback<DriveApi.MetadataBufferResult>() {
            @Override
            public void onResult(DriveApi.MetadataBufferResult metadataBufferResult) {
                log("got file children");
                MetadataBuffer buffer = metadataBufferResult.getMetadataBuffer();
                //for(Metadata m : buffer){
                log("Buffer count  " + buffer.getCount());
                for(int i =0;i<buffer.getCount();i++){
                    Metadata m = buffer.get(i);
                    log(m.toString());
                    Drive.DriveApi.getFile(mApiClient, m.getDriveId())
                            .openContents(mApiClient, DriveFile.MODE_READ_ONLY,
                                    new DriveFile.DownloadProgressListener() {
                                        @Override
                                        public void onProgress(long bytesDownloaded, long bytesExpected) {
                                            // Update progress dialog with the latest progress.
                                            int progress = (int) (bytesDownloaded * 100 / bytesExpected);
                                            Log.wtf("TAG", String.format("Loading progress: %d percent", progress));
                                        }
                                    }
                            )
                            .setResultCallback(contentsCallback);
                }
            }
};


final private ResultCallback<DriveApi.ContentsResult> contentsCallback =
        new ResultCallback<DriveApi.ContentsResult>() {
            @Override
            public void onResult(DriveApi.ContentsResult contentsResult) {
                log("got file contents");
                File file = new File("storage/emulated/0/Downtests/tessing.txt");
                file.mkdirs();
                try {
                    InputStream input = contentsResult.getContents().getInputStream();
                    OutputStream output = new FileOutputStream(file);
                    byte[] buf = new byte[1024];
                    int len;
                    while ((len = input.read(buf)) > 0) {
                        output.write(buf, 0, len);
                    }
                    input.close();
                    output.close();
                } catch (FileNotFoundException e) {
                    e.printStackTrace();
                } catch (IOException e) {
                    e.printStackTrace();
                }


            }
        };

private void log(String s){
    Log.wtf("ServicePull", s);
}



}

Очевидно, я создал папку под названием «Неви» и внутри нее файл. У меня есть DriveFolder, указывающий на папку Neewie, но когда я перечисляю ее, я получаю MetadataBuffer со счетчиком 0.

Нужно ли мне что-то делать, чтобы перечислить ВСЕ файлы? Что-то не так с библиотекой gms?


person BamsBamx    schedule 14.03.2014    source источник


Ответы (2)


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

Во-первых, поскольку в Android API Google Диска пока нет функции DELETE, вы, вероятно, имеете в виду действие «удалить» в интерфейсе веб-диска. Статус Metadata.isTrashed() неправильно отражает статус, как описано здесь . Использование requestSync() не помогло. Но я оставил эту проблему, так как я ожидаю, что они исправят ее с реализацией DELETE в GDAA. Подробнее об DELETE можно узнать здесь< /а>.

Во-вторых, я использую «ожидающую» версию вызовов в моей тестовой среде (обернутой в AsyncTask) для тестирования. Пройти его намного проще. Однажды я испытал некоторое «странное» поведение, но не мог точно его определить. Исправлено с помощью очистки Google Кэш сервисов Play.

В-третьих, существует класс-оболочка Google Api Client GooApiClnt. в этом коде (внизу), который, кажется, дает стабильные результаты — вы можете попробовать. Вы можете протестировать версии «findAll» (т. е. DriveApi.query) вместо «listAll» (т. е. listChildren), поскольку это позволяет заранее отфильтровать состояние TRASHED. Кстати, я заметил, что вы не регистрируете статус Metadata.isTrashed() в своем примере. Это дало бы лучшее представление о том, какие файлы были удалены. Но опять же, это только подтвердило бы проблемы с задержкой синхронизации.

Последняя, ​​незначительная проблема — и я не знаю, не была ли она уже исправлена ​​на уровне GDAA — выпуск/закрытие 'getMetadataBuffer'. Это вызывало утечку ресурсов в моем коде. Опять же, см. код Github, указанный выше, grep 'mdb.close()'.

Удачного кодирования и удачи

person seanpj    schedule 15.03.2014
comment
Что ж, я пробовал класс GooApiClnt... findAll() и listAll() давали бы одинаковые идентификаторы файлов. Однако на GDrive все еще есть некоторые файлы, которых нет в данном ArrayList :( Я думаю, что в списке есть только те файлы, которые были загружены моим приложением... Это так странно - person BamsBamx; 16.03.2014
comment
В общем, GDAA не совсем готов к прайм-тайму, я получаю всякие необычные загвоздки (например, сегодня, createFolder() создал 3 папки с одинаковыми именами), которые я обычно не могу воспроизвести. Есть проблемы с синхронизацией, такие как SO 22381649, проблема с синхронизацией «удалить», ... Но, я думаю, это станет лучше. Осторожно, я довольно часто изменяю GooApiClnt, просто добавил удаление/корзину, см. SO 22295903. - person seanpj; 16.03.2014
comment
Извините, SO 22295903 = stackoverflow.com/questions/22295903/ - person seanpj; 16.03.2014
comment
Ну наконец-то я буду использовать старый API.... Кажется, Google Drive Android API еще не должен был быть выпущен... - person BamsBamx; 16.03.2014
comment
Это дилемма, нет сомнений, что в конце концов он будет лучше старого. Я не тороплюсь со своей разработкой, просто мне может понадобиться достаточно много времени, чтобы в конце слиться с окончательным GDAA. - person seanpj; 16.03.2014

Я попробовал этот подход и обнаружил, что возвращаются не все файлы. К сожалению, такое поведение является преднамеренным =(

Цитирую из документации:

«API Google Диска Android в настоящее время поддерживает только drive.file и drive.appfolder»

drive.file (Drive.SCOPE_FILE) означает: «Пофайловый доступ к файлам, созданным или открытым приложением».

«Это означает, что только файлы, которые пользователь открыл или создал с помощью вашего приложения, могут быть сопоставлены по запросу»

Видеть:

https://developers.google.com/drive/android/auth

https://developers.google.com/drive/android/queries

person Bleifuss    schedule 29.12.2016