Google Drive Android API: 删除的文件夹在查询中仍然存在

Google Drive Android API: Deleted folder still exists in query

运行 下面的代码,我在平板电脑上用 Google Drive Android API 创建了一个文件夹。几秒钟后,从 PC 上的远程位置删除该文件夹。当我重新 运行 代码时,API 仍然认为 'MyFolder' 存在,即使它已被删除并且在平板电脑上的 Google 云端硬盘应用程序中不可见。一段时间后文件夹持久性终于消失,代码按预期工作。这是云驱动器的预期行为吗?

Query query = new Query.Builder()
        .addFilter(Filters.and(Filters.eq(
                SearchableField.TITLE, "MyFolder"),
                Filters.eq(SearchableField.TRASHED, false)))
        .build();
Drive.DriveApi.query(getGoogleApiClient(), query)
        .setResultCallback(new ResultCallback<DriveApi.MetadataBufferResult>() {
    @Override
    public void onResult(DriveApi.MetadataBufferResult result) {
        if (!result.getStatus().isSuccess()) {
            showMessage("Cannot create folder in the root.");
        } else {
            boolean isFound = false;
            for(Metadata m : result.getMetadataBuffer()) {
                if(!isFound) {
                    if (m.getTitle().equals("MyFolder")) {
                        showMessage("Folder exists");
                        isFound = true;
                    }
                }
            }
            if(!isFound) {
                showMessage("Folder not found; creating it.");
                MetadataChangeSet changeSet = new MetadataChangeSet.Builder()
                        .setTitle("MyFolder")
                        .build();
                Drive.DriveApi.getRootFolder(getGoogleApiClient())
                        .createFolder(getGoogleApiClient(), changeSet)
                        .setResultCallback(new ResultCallback<DriveFolder.DriveFolderResult>() {
                    @Override
                    public void onResult(DriveFolder.DriveFolderResult result) {
                        if (!result.getStatus().isSuccess()) {
                            showMessage("Error while trying to create the folder");
                        } else {
                            mThwingAlbertFolderId = result.getDriveFolder().getDriveId();
                            showMessage("Created a folder: " + mThwingAlbertFolderId);
                        }
                    }
                });
            }
        }
    }
});

您看到的是 GDAA, that can be explained if you look closer at the 'Lifecycle of a Drive file' 图的 'normal' 行为(警告:我从未见过源代码,只是根据我观察到的假设)。

看,GDAA 与 REST Api, creates a layer that does its best to create caching and network traffic optimization. So, when you manipulate the file/folder from the 'outside' (like the web app), the GDAA layer has no knowledge of the fact until it initiates synchronization, controlled by it's own logic. I myself originally assumed that GooDrive has this under control by dispatching some kind of notification back to the GDAA, but it apparently is not the case. Also, some Googlers mentioned 'requestSync()' as a cure 不同,但我从未成功地让它发挥作用。

您认为您正在做的是轮询 GooDrive。但实际上,您正在轮询其 DriveId 仍然有效(未更新)的 GDAA(本地 GooPlaySvcs),这与已经消失的真实 GooDrive 对象不同。

这是文档中没有明确说明的一件事。 GDAA 不是最好的 Api for EVERY application。它的缓存机制非常适合透明管理 online/offline 状态、网络流量优化。电池寿命,......但是在你的情况下,你 可能 使用 REST Api 会更好,因为你得到的响应反映了当前的 GooDrive 状态。

我自己也遇到过类似的情况,不得不从 GDAA 切换回 REST(并用基于私有 GCM 的通知系统替换轮询)。不用说,通过使用 REST Api,您的应用会变得更加复杂,通常需要同步适配器/服务来进行数据同步、管理网络状态,... GDAA 免费为您提供的所有东西)。 =27=] 如果您想并排使用 2 个 api,可以在 Github.

上使用 (GDAA, REST) 两个相同的 CRUD 实现

祝你好运

正如 Sean 提到的,Drive Android API 在本地缓存元数据以减少带宽和电池使用。

当您在设备上执行某项操作时,例如创建一个文件夹,我们尝试尽快在服务器上应用该操作。虽然可能会因操作依赖性和内容传输而出现延迟,但您通常会很快看到服务器上反映的结果。

在服务器上执行操作时,例如通过 Web 客户端删除文件夹,此操作会在下次 Drive Android API 同步时反映在设备上。为了节省电池和带宽,同步频率取决于 API 的使用方式,因为这是用户的优先事项。

如果您需要保证已发生同步,您可以使用 DriveApi.requestSync() 明确请求同步并等待结果。目前速率限制为每分钟 1 次,这在测试期间经常发生,但对实际使用情况的影响应该小得多。

如果此同步行为导致您的用例出现问题,请通过我们的 issue tracker 告知我们,以便我们调查解决方案。

Google 驱动器 api 不会立即同步,这就是删除的文件夹仍在显示的原因,因此您必须使用 requestSync()[= 强制 google 驱动器同步12=]

Drive.DriveApi.requestSync(mGoogleApiClient).await();

我在这里找到了一个示例片段: http://wiki.workassis.com/android-google-drive-api-deleted-folder-still-exists-in-query/

Google 驱动器为驱动器 api 使用自己的生命周期并管理缓存中的所有内容,这就是为什么如果您删除某些文件或文件夹并尝试使用 google 驱动器 apis 它仍然可用,因为它存储在缓存中,因此您需要为此显式调用 requestSync() 方法,然后缓存将被更新并为您提供未找到的文件夹或文件。 下面是代码:

Drive.DriveApi.requestSync(mGoogleApiClient).setResultCallback(new ResultCallback<Status>() {
        @Override
        public void onResult(@NonNull Status status) {
            Log.e("sync_status", status.toString());
            if (status.getStatus().isSuccess()) {
                setRootFolderDriveId();
            }
        }
    });

并且不要调用 Drive.DriveApi.requestSync(mGoogleApiClient).await(),因为您的主线程会阻塞,因此会崩溃。使用上面的方法,在获得成功回调后,您可以在 google 驱动器上进行操作,因为它已更新。

我遇到了同样的问题,使用 "Drive.DriveApi.requestSync" 成功了。 我还建议看一下 https://github.com/francescocervone/RxDrive,因为您可以使用 rxandroid 将同步连接到其他驱动器操作。 例如,这变成了删除和同步操作:

Observable<Boolean> deleteFile = rxDrive.delete(file);
Observable<Void> syncDrive = rxDrive.sync();
Observable.concat(deleteFile, syncDrive);

你可以在主线程中完成:

 Drive.DriveApi.requestSync(mGoogleApiClient).setResultCallback(new ResultCallback<com.google.android.gms.common.api.Status>() {
    @Override
    public void onResult(com.google.android.gms.common.api.Status status) {
        if (!status.getStatus().isSuccess()) {
            Log.e("SYNCING", "ERROR" + status.getStatusMessage());
        } else {
            Log.e("SYNCING", "SUCCESS");
            // execute your code to interact with Google Drive

        }
    }
});

您从查询中列出已删除文件的原因是 Google 驱动器有一个“可搜索”的“垃圾箱”文件夹。您需要先清空垃圾箱。