如何创建文件选择器以使用 REST API 将文件保存到 Google Drive?

2024-03-02

现在谷歌是不赞成 https://developers.google.com/drive/android/deprecationGoogle Drive Android API,我正在将代码迁移到 Drive REST API。

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

我创建了一个文件选择器来选择一个文件download从 Google 云端硬盘使用示例应用程序 https://github.com/gsuitedevs/android-samples/tree/master/drive/deprecation谷歌提供了,但不幸的是他们没有提供文件夹选择的示例。另外,我还找到了文档 https://developers.google.com/picker/docs/用于为 Web 应用程序创建文件选择器,但不适用于 Android 应用程序。

我知道我可以选择文件夹名称 https://developers.google.com/drive/api/v3/folder#inserting_a_file_in_a_folder将文件插入其中,但如何创建一个选择器以允许用户使用 REST API 选择文件夹(并命名文件)?这should很简单,我想避免使用第三方库。

谢谢你!


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

这里的问题是 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 弃用指南 https://developers.google.com/drive/android/deprecation#file_picker_ui)

The 示例应用程序 https://github.com/gsuitedevs/android-samples/tree/master/drive/deprecation正如您所说,提供了一个读取文件的示例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;
    });
}
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

如何创建文件选择器以使用 REST API 将文件保存到 Google Drive? 的相关文章

随机推荐

  • 如何将 HTML 代码添加到 JSF FacesMessage

    默认情况下 每个 JSFFacesMessage以单行形式呈现 我想添加 HTML 换行符 br 消息本身 以便消息显示整齐 我尝试过如下 message new FacesMessage test br test 然而 它被 JSF 转义
  • 如何在另一个方法中的方法中使用局部变量?

    private void UserYoutubeService var youtubeService new YouTubeService new BaseClientService Initializer HttpClientInitia
  • 如何在 Node.js 中向子进程发送“CTRL+C”?

    I tried to spawn child process vvp https linux die net man 1 vvp https linux die net man 1 vvp At the certain time I nee
  • vTigerCRM 7 - 除非手动触发,否则调度程序不会运行任何 cron 作业

    我正在运行 vTiger 7 0 我注意到在这个月的第一天 我没有创建任何发票 然后我查看了调度程序 注意到 上次扫描开始 和 上次扫描结束 字段显示几天内没有任何 cron 作业被触发 cron 作业计划以 15 分钟的间隔触发一次 但
  • PyAPN 和发送之间睡眠的需要

    我正在使用 PyAPN 向 iOS 设备发送通知 我经常一次发送多组通知 如果任何令牌因任何原因损坏 该过程将停止 因此 我使用增强的设置和以下方法 apns gateway server register response listene
  • 为脚本语言设置 Maven?

    Maven 用于构建和管理任何基于 Java 的项目 但是如果项目使用脚本语言会发生什么呢 maven 现在对 TCL 能做的就是复制文件并将它们放在目标目录中的正确位置 我的问题如下 代码在 TCL 中 gt 需要解释器而不是编译器 它看
  • 如何通过 Android API 关闭所有声音和振动

    我正在构建一个 Android 应用程序 我试图在应用程序启动时禁用设备的所有声音和振动 我是新手 所以我找不到如何做到这一点 任何想法 提前致谢 谢谢 我自己回复以完成答案 AudioManager aManager AudioManag
  • apache prefork/mod_wsgi 产生的进程计数似乎过去的配置[关闭]

    Closed 这个问题是无关 help closed questions 目前不接受答案 在生产环境中运行 nginx 反转回 apache mpm prefork mod wsgi 我看到90apache 子进程 当我期望 40 是最大值
  • Apache http 基本身份验证?

    是否有一些简单的代码可以添加到 htaccess文件或我的虚拟主机文件来强制执行 http 基本身份验证 那这个呢 AuthUserFile my derectory htpasswd Require valid user AuthName
  • HTML CSS DIV 面板

    I want to make something like this 到目前为止我所做的 谁能告诉我如何实现这一目标 谢谢 提前 See jsFiddle http jsfiddle net SanaBukhari DAFW9 代码如下 H
  • 每个 Android 应用程序的网络流量监控

    我想知道我是否可以对每个 Android 应用程序进行网络流量监控 基本上看看哪个应用程序正在接收 发送多少数据 我知道有很多应用程序已经做到了这一点 但我想知道如何做到这一点 嗯 你当然可以 一个非常简单的方法是使用交通统计 http d
  • PostgreSQL 和 ActiveRecord 子选择竞争条件

    我在 ActiveRecord 和 PostgreSQL 中遇到竞争条件 我正在读取一个值 然后递增它并插入一条新记录 num Foo where bar id 42 maximum number Foo create bar id 42
  • jedi-vim 和 YouCompleteMe 冲突吗?

    YouCompleteMe YCM 和 jedi vim 是两个提供自动补全功能的 vim 插件 并且都在 Python 下使用 jedi 不过 两者兼得是件好事 因为 jedi vim 除了文档之外还提供了一些有用的功能 例如 转到定义
  • 访客模式中的泛型杀伤力过大

    我正在开发一个项目 将十年前编写的旧 java 1 2 代码转换为 java 7 该项目大量 过度 使用特定访问者 为了使事情在概念上简单 我们假设访问者是这样的 public interface RobotVisitor public O
  • Google Chrome 调试器跳过断点

    我目前正在尝试在 chrome 中调试 js 脚本 我在脚本中放置了一个断点 当我仅使用一个选项卡时 它会正确中断 但在第二个选项卡上 即使我在代码中看到断点 它也不会中断 查看源代码时是否使用了漂亮的打印选项 我注意到格式化的副本可能会不
  • 有非官方的 Flash .FLA 规范吗?

    是否有非官方规范解释如何对 Flash FLA 文件进行逆向工程 我对创建一个应用程序特别感兴趣 该应用程序可以通过编程方式 自动场景规划 Flash 文档 从其他文件中提取内容 将该内容排列到图层中 而无需打开 Flash IDE 然后动
  • 使用 IB 将分段控件添加到导航栏

    我目前正在创建一个UISegmentedControl以编程方式在视图控制器中viewDidLoad方法并将其分配给视图控制器的导航栏self navigationItem titleView 这很简单 但我也希望能够在 Interface
  • 与 pypi.org 的连接超时

    无法 pip 安装 3rd 方软件包 venv pip install django Collecting django Retrying Retry total 4 connect None read None redirect None
  • 使用 R Lubridate 提取会计年度

    我将创建几个日期 library lubridate x lt ymd c 2012 03 26 2012 05 04 2012 09 23 2012 12 31 我可以从中提取年份和季度x values quarter x with ye
  • 如何创建文件选择器以使用 REST API 将文件保存到 Google Drive?

    现在谷歌是不赞成 https developers google com drive android deprecationGoogle Drive Android API 我正在将代码迁移到 Drive REST API 我几乎已经完成了