4

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

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

4

2 回答 2

1

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

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

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

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

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

快乐的编码和好运

于 2014-03-15T12:53:53.267 回答
0

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

我从文档中引用:

“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

于 2016-12-29T03:58:41.883 回答