【问题标题】:DriveFolder.listChildren() not showing all its childrenDriveFolder.listChildren() 未显示其所有子项
【发布时间】:2014-03-14 14:59:30
【问题描述】:

我正在制作一个适用于谷歌驱动器的应用程序。

我需要获取文件夹中所有文件的列表,但似乎不可能:当我调用 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);
}



}

显然,我创建了一个名为“Neewie”的文件夹,并在其中创建了一个文件。我有一个指向 Neewie 文件夹的 DriveFolder,但是当 listChildren 它时,我收到一个计数为 0 的 MetadataBuffer。

我需要做些什么来列出所有文件吗? gms 库有问题吗?

【问题讨论】:

    标签: android google-drive-api google-play-services google-drive-android-api


    【解决方案1】:

    我需要很长时间才能重新运行您的示例,但我可能有几点可以让您领先。

    首先,由于 Google Drive Android API 中还没有 DELETE 功能,您可能指的是 Web Drive 界面中的“删除”操作。状态 Metadata.isTrashed() 未正确反映状态为discussed here。并且使用 requestSync() 并没有帮助。但是我让这个问题消失了,因为我希望他们通过在 GDAA 中实现 DELETE 来解决它。更多关于 DELETE 的信息请见here

    其次,我在测试环境中使用“等待”版本的调用(包装在 AsyncTask 中)来测试事物。一步一步要容易得多。我曾经经历过一些“奇怪”的行为,但无法确定。由clearing the Google Play Services cache 修复。

    第三,这段代码中有一个Google Api Client wrapper class GooApiClnt(在底部),它似乎产生了稳定的结果——你可以试试。您可以测试“findAll”(即 DriveApi.query)版本而不是“listAll”(即 listChildren),因为它允许您预先过滤 TRASHED 状态。顺便说一句,我注意到您没有在示例中记录 Metadata.isTrashed() 状态。它将更好地查看哪些文件被删除。但同样,它只会确认同步延迟问题。

    最后一个小问题——我不知道它是否已经在 GDAA 级别上修复了——“getMetadataBuffer”的释放/关闭。它导致我的代码中的资源泄漏。同样,请参阅上面引用的 Github 代码,grep 'mdb.close()'。

    编码愉快,祝你好运

    【讨论】:

    • 好吧,我已经尝试过 GooApiClnt 类... findAll() 和 listAll() 会给出相同的文件 ID。但是,GDrive 上仍有一些文件不在给定的 ArrayList 中 :( 我认为列表中的唯一文件是我的应用程序上传的文件......太奇怪了
    • 一般来说,GDAA 还没有为黄金时段做好准备,我遇到了各种我通常无法复制的异常问题(比如今天,createFolder() 创建了 3 个同名文件夹) .存在时间问题,例如 SO 22381649,“删除”时间问题,......但我想它会变得更好。注意,我经常修改 GooApiClnt,只是添加了删除/垃圾箱,请参阅 SO 22295903。
    • 对不起,SO 22295903 = stackoverflow.com/questions/22295903/…
    • 好吧,最后还是用老API吧……看来Google Drive Android API应该还没发布吧……
    • 这是一个两难的选择,毫无疑问它最终会优于旧的。我并不急于开发,我可能需要足够长的时间才能最终与最终的 GDAA 合并。
    【解决方案2】:

    我尝试过这种方法,还发现并非所有文件都返回。不幸的是,这种行为是故意的 =(

    我从文档中引用:

    “Google Drive Android API 目前仅支持 drive.file 和 drive.appfolder”

    drive.file (Drive.SCOPE_FILE) 表示:“按文件访问应用程序创建或打开的文件”

    “这意味着只有用户使用您的应用程序打开或创建的文件才能被查询匹配”

    见:

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

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

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多