首页 > 解决方案 > 如何使用 REST API 创建文件选择器以将文件保存到 Google Drive?

问题描述

现在 Google 正在弃用Google Drive Android API,我正在将我的代码迁移到 Drive REST API。

我几乎已经完成了所有工作,但我无法复制创建文件选择器的功能,允许用户选择他们想要将文件保存在 Google Drive 中的文件夹。我能够成功地将文件复制到用户的 Google Drive 的根文件夹中,但我更愿意创建一个选择器,允许用户将其放置在他们想要的位置。

我创建了一个文件选择器,用于使用 Google 提供的示例应用程序从 Google Drive中选择要下载的文件,但不幸的是,它们没有提供文件夹选择示例。此外,我还能够找到为 Web 应用程序创建文件选择器的文档,但不适用于 Android 应用程序

我知道我可以选择要插入文件的文件夹的名称,但是如何创建选择器以允许用户使用 REST API 选择文件夹(并命名文件)?这应该很容易,我想避免使用第三方库。

谢谢!

标签: androidgoogle-drive-api

解决方案


这个问题有点老了,所以你可能已经想通了。但我也遇到了同样的问题,所以也许其他人也有兴趣。

这里的问题是 Google Drive REST API 使用 ID 来识别文件和文件夹。API 不提供文件或目录选择器,这就是您使用 Android 的内置选择器的原因。例如,要允许用户为新文件选择名称和目标文件夹,您可以使用以下意图:

Intent createDirectoryPickerIntent(String fileName, String mimeType) {
    Intent intent = new Intent(Intent.ACTION_CREATE_DOCUMENT);
    intent.addCategory(Intent.CATEGORY_OPENABLE);
    intent.setType(mimeType);
    intent.putExtra(Intent.EXTRA_TITLE, fileName);
    return intent;
}

并在您的活动中创建它:

public void openDirectoryPicker() {
    if (mDriveServiceHelper != null) {
        Intent pickerIntent = mDriveServiceHelper.createDirectoryPickerIntent("fileName", "text/plain");
        startActivityForResult(pickerIntent, REQUEST_CODE_OPEN_DIR);
    }
}

(记得删除空文件,以防第二步写入实际内容失败。)

文件选择器通过 URI 识别文件,并且不知道任何关于文件 ID 的信息。按名称查询文件以获取新文件的 id 可能会失败,因为在另一个甚至同一个文件夹中可能存在重复项。这就是 Google 建议使用其他方式访问文件的原因:

对于使用 Android API 文件选择器的客户端(例如通过调用 DriveClient#newOpenFileActivityIntentSender),我们建议使用存储访问框架 (SAF),它访问 Drive Android 应用程序的内容提供程序。示例应用程序演示了如何启动文件选择器 Intent 并处理它返回的数据。(Google Drive Android API 弃用指南

如您所述,示例应用程序提供了一个读取openFileUsingStorageAccessFramework(...). 您可以对使用上述目录选择器创建的文件执行相同的操作。URI 由意图提供。

在您的活动中:

@Override
protected void onActivityResult(int requestCode, int resultCode, Intent resultData) {
    switch (requestCode) {
        case REQUEST_CODE_SIGN_IN:
            //...
        }
            break;
        case REQUEST_CODE_OPEN_DIR:
            if (resultCode == RESULT_OK && resultData != null) {
                Uri uri = resultData.getData();
                if (uri != null && mDriveServiceHelper != null) {
                    mDriveServiceHelper.writeToFileUsingStorageAccessFramework(this, getContentResolver(), uri, "some content")
                        .addOnSuccessListener(Void -> {
                            Log.v(TAG, "success");
                        })
                        .addOnFailureListener(exception -> {
                            Log.e(TAG, "Unable to write to file.", exception);
                        });
                }
            } else {
                Log.v(TAG, "Unable to write to file.");
            }
            break;
    }
    super.onActivityResult(requestCode, resultCode, resultData);
}

并且DriveServiceHelper与示例应用程序非常相似:

Task<Void> writeToFileUsingStorageAccessFramework(Context context, ContentResolver contentResolver, Uri uri, String content) {
    return Tasks.call(mExecutor, () -> {
        // Retrieve the document's display name from its metadata.
        String name;
        try (Cursor cursor = contentResolver.query(uri, null, null, null, null)) {
            if (cursor != null && cursor.moveToFirst()) {
                int nameIndex = cursor.getColumnIndex(OpenableColumns.DISPLAY_NAME);
                name = cursor.getString(nameIndex);
            } else {
                throw new IOException("Empty cursor returned for file.");
            }
        }

        // Write content to the file, e.g.
        try (OutputStream outputStream = contentResolver.openOutputStream(uri);) {
            if (outputStream != null) {
                outputStream.write(content.getBytes());
                outputStream.close();
            }
        }

        return null;
    });
}

推荐阅读