标签: storage-access-framework

ContentResolver.openFileDescriptor() 不调用 ContentProvider.openFIle

我实现了一个ContentProvider重写openFile(...)方法。然后我用ContentResolver.openFileDescriptor(...)方法测试了一下。根据 javadoc 中的指定,openFileDescriptor假设调用ContentProvider.openFile

“...打开原始文件描述符以访问 URI 下的数据。这类似于openAssetFileDescriptor(Uri, String),但使用底层openFile(Uri, String) ContentProvider.openFile()方法...”

问题是该openFile()方法从未被调用。相反,我观察到它openAssetFile()被称为相反。我用android 4.1.2r1测试过。当我查看 android 类 ContentResolver (4.1.2) 的源代码时,我发现它openFileDescriptor()只会调用openAssetFileDescriptor(),并且我根本找不到任何ContentProvider.openFile()会被调用的执行路径。

有人知道我错在哪里吗?- 谢谢

这是我的测试方法调用:

context.getContentResolver().openFileDescriptor(bitmapUri, "r").getFileDescriptor();
Run Code Online (Sandbox Code Playgroud)

我的bitmapUri是这样的“content://com.myprovider.authority/filename”

android android-contentprovider storage-access-framework

6
推荐指数
1
解决办法
1万
查看次数

Android OPEN_DOCUMENT_TREE意图根位置

我正在使用Android 5.0(API级别21)中引入的目录选择 API,以便用户选择一个目录来保存文件.

要选择我构建的目录并发送ACTION_OPEN_DOCUMENT_TREE意图,如下面的代码所示:

Intent intent = new Intent(Intent.ACTION_OPEN_DOCUMENT_TREE);
startActivityForResult(intent, REQUEST_CODE_OPEN_DIRECTORY);
Run Code Online (Sandbox Code Playgroud)

我得到以下弹出窗口:

在此输入图像描述

但是,如果我让用户使用ACTION_OPEN_DOCUMENT意图选择一个文件:

Intent intent = new Intent(Intent.ACTION_OPEN_DOCUMENT);
intent.addCategory(Intent.CATEGORY_OPENABLE);
intent.setType("*/*");
startActivityForResult(intent, FILE_CHOOSER_ACTIVITY_REQUEST_CODE);
Run Code Online (Sandbox Code Playgroud)

然后,我得到以下弹出窗口:

在此输入图像描述

我在我的Android 5.0.1 Nexus Tab 10中测试它.为什么我使用ACTION_OPEN_DOCUMENT_TREE和ACTION_OPEN_DOCUMENT获得不同的根位置?也许只有内部存储文档提供程序实例支持子树选择?

我还希望允许用户使用ACTION_OPEN_DOCUMENT_TREE选择Google云端硬盘目录.

ACTION_OPEN_DOCUMENT_TREE和ACTION_OPEN_DOCUMENT引用都说:

调用时,系统将显示设备上安装的各种DocumentsProvider实例,让用户浏览它们.

非常感谢你提前

android-intent google-drive-api storage-access-framework android-5.0-lollipop

6
推荐指数
1
解决办法
2039
查看次数

Storage Access Framework获取正确的Uri路径删除/编辑/获取文件

TL:DR; 我解释了如何使用DocumentFile使用创建文件夹和子文件夹以及如何删除使用此类创建的文件。从onActvityResult()和documentFile.getUri.toString()返回的Uri不相同。我的问题是如何在不使用SAF UI的情况下获得有效的Uri来操作文件夹和文件,如果可能的话,不使用hack也不行。

让我分享到目前为止我学到的知识并提出我的问题。如果要获取文件夹的Uri并对其进行处理,则应使用Intentwith ACTION_OPEN_DOCUMENT_TREE获取一个Uri来访问文件夹并为该uri设置W / R权限。

通过以下方式授予 onActivityResult的持久权限

final int takeFlags = data.getFlags() & (Intent.FLAG_GRANT_READ_URI_PERMISSION | Intent.FLAG_GRANT_WRITE_URI_PERMISSION);
// Check for the freshest data.
getContentResolver().takePersistableUriPermission(treeUri, takeFlags);
Run Code Online (Sandbox Code Playgroud)

如果选择设备的主文件夹:

Uri treeUri = data.getData();
treeUri.toString()
Run Code Online (Sandbox Code Playgroud)

返回:content://com.android.externalstorage.documents/tree/primary:

File mediaStorageDir = new File(Environment.getExternalStorageDirectory(), "");
Run Code Online (Sandbox Code Playgroud)

返回值:存储/模拟/ 0

new File(treeUri.toString()).getAbsolutePath();
Run Code Online (Sandbox Code Playgroud)

返回值:内容:/com.android.externalstorage.documents/tree/primary:

如果使用DocumentFile类获取主文件夹的路径,则会得到

DocumentFile saveDir = null;
saveDir = DocumentFile.fromFile(Environment.getExternalStorageDirectory());
String uriString = saveDir.getUri().toString();
Run Code Online (Sandbox Code Playgroud)

返回值:file:/// storage / emulated / 0

我的第一个问题是如何使用DocumentFile类获取带有内容的Uri。

我正在构建一个摄影应用程序,默认情况下,我想使用DocumentFile类为图像设置初始文件夹。

 @TargetApi(19)
protected DocumentFile getSaveDirMainMemory() {
    DocumentFile …
Run Code Online (Sandbox Code Playgroud)

android storage-access-framework documentfile

6
推荐指数
1
解决办法
1051
查看次数

如何更好地控制 Android SAF UI(例如 ACTION_OPEN_DOCUMENT)?

我希望 SAF 在指定文档中\xe2\x80\x9claunch 导航器(如果它是文件夹\xe2\x80\x9d)(他们在文档中这么称呼它)。

\n\n

这不起作用,所以我还想知道是否可以将存储快捷方式添加到 SAF UI。请参阅此链接中的图片:https://i.stack.imgur.com/adINm.jpg

\n\n

但我认为更有可能在特定文件夹中启动 SAF UI,因此我暂时可能会采用这种方法。我已经在 - 方法中尝试过onCreate(...)

\n\n
String pathAsString = Environment.getExternalStorageDirectory() + "/myscientificapp/measurements/";\nFile pathAsFile = new File(pathAsString);\n\nif (pathAsFile.exists()) { Log.d(TAG, "pathAsFile exists!"); } //This is printed in Logcat\n\nandroid.net.Uri pathAsUri = Uri.fromFile(pathAsFile);\nIntent intent = new Intent(Intent.ACTION_OPEN_DOCUMENT);\nintent.addCategory(Intent.CATEGORY_OPENABLE);\nintent.setType("*/*");\nintent.putExtra(DocumentsContract.EXTRA_INITIAL_URI, pathAsUri); //Does not make effect\nstartActivityForResult(intent, REQUEST_OPEN_DOCUMENT);\n
Run Code Online (Sandbox Code Playgroud)\n\n

问题是它不起作用..或者我不知道该怎么做。:/

\n\n

我读过一些关于这些地方的内容。例如在Medium.com上,一位开发人员说:

\n\n
\n

当使用 ACTION_CREATE_DOCUMENT 选择保存文件的位置或打开文档时,新的 EXTRA_INITIAL_URI 允许您使用自己的自定义起始位置覆盖默认初始位置(用户选择的最后位置)。

\n
\n\n

在 Android 文档中,我们可以阅读有关EXTRA_INITIAL_URI的信息:

\n\n
\n

调用者可以通过 DocumentsContract#EXTRA_INITIAL_URI 设置文档 URI 来指示文档导航器的初始位置。如果指定文档是文件夹,系统将尽力在指定文档中启动导航器;如果不是,则在包含指定文档的文件夹中启动导航器。

\n …

android android-intent android-contentprovider storage-access-framework

6
推荐指数
1
解决办法
3520
查看次数

如何解决Android 10的存储混乱

由于Android在有关文件访问的不同主要版本之间非常不一致,因此我感到有些失落。我尝试尽可能简单地描述问题:

我的公司使用商业本地DRM保护我们提供的其他本地库。我们有一个许可应用程序,该应用程序调用了一些Voodoo来结束/ sdcard / companyname / LicenseContainer /中的许可文件。其他受保护的应用程序以本机代码查看此目录,检查用户是否具有有效的许可证。

但是,Android 10更新仅提供,使该工作流程完全无效scoped storage access。我们可以使用一种方法Storage Manager来授予访问权限,不幸的是,现在也已弃用该方法。

所以我的问题是:一个应用程序如何将文件保存到/ sdcard / FOLDER上的某个位置

  1. 应用删除后未删除
  2. 其他应用可使用本机代码访问

对于所有可能的解决方案(SAF,FileProvider等),我有点不知所措,这些解决方案通常会调用一个应用程序将权限授予另一个应用程序的权限。但是,如果没有安装的第一个应用程序将文件放到那里,则应该可以访问这些文件。

我知道必须有解决方案,因为最近的FileManagers(即Files by Google)可以访问整个/sdcard/目录。

在不调用“黑客”之类的情况下,最简单,最适合未来的路线是什么 android:requestLegacyExternalStorage="true"

android file android-fileprovider storage-access-framework scoped-storage

6
推荐指数
1
解决办法
134
查看次数

在Android OS 10中,如何获取“下载”文件夹中的所有文件?

我正在使用Raspberry Pi和Android设备。Pi硬件将某些文件转储到Android设备外部存储的“下载”文件夹中(使用MTP)。路径是: /storage/emulated/0/Download

我开发了一个应用程序,该应用程序读取Pi转储的该文件夹中的所有文件(名称中具有预先确定的前缀)并进行处理。我的应用程序适用于在Android OS 9及更低版本上运行的设备。

从Android 10开始,到明年强制使用SAF(又名存储访问框架),我想升级我的解决方案以使其适应未来。尽管围绕此主题有太多关于SO的问题和答案,但我一直未能找到适合我要求的正确解决方案。

因此,这确实是我要问的问题:是否可以安全地假设上述(/storage/emulated/0/Download)路径可供Pi使用,以将文件转储到运行Android 10的设备中?如果是,请提出一种方法,以编程方式读取Android 10中该路径中存在的所有文件?如果否,请提出另一种方法来实现整个过程?

android storage-access-framework

6
推荐指数
0
解决办法
61
查看次数

如何提示内容管理器选择器直接在 ACTION_OPEN_DOCUMENT_TREE 的可选位置上打开

当您ACTION_OPEN_DOCUMENT_TREE在 Android 11 中选择存储文件的路径的权限时,默认的 Android 内容管理器默认会在最近使用的路径上打开,并且由于某种原因“使用此文件夹”按钮根本不会出现,即使此路径是可访问路径,除非用户手动移动路径以转到合适的位置(或者返回默认打开的路径,如果这是可选位置,则移动到目录)。

例如,假设用户使用的最新路径是Documents。当我要求用户选择允许应用程序保存文件的路径时,

Intent i = new Intent(Intent.ACTION_OPEN_DOCUMENT_TREE);
i.addCategory(Intent.CATEGORY_DEFAULT);
Run Code Online (Sandbox Code Playgroud)

这就是出现的情况:

在此输入图像描述

正如您所看到的,没有“使用此文件夹”蓝色按钮。

现在,如果用户从此处选择超级文件夹路径并在文档中再次输入,这就是他所看到的:

在此输入图像描述

现在“使用此文件夹”按钮可用。

这是完全没有意义的,而且对用户体验来说非常糟糕,许多用户最终肯定会感到烦恼和困惑地卸载该应用程序。

难道我做错了什么?是否可以向意图传递一些提示,以便直接在所有 Android 设备存储(例如DocumentsACTION_OPEN_DOCUMENT_TREE )中可用的特定路径中打开内容管理器视图,并在打开选择器时使用“使用此文件夹”按钮?

android storage-access-framework android-11

6
推荐指数
0
解决办法
531
查看次数

Android 11 SAF - 本机 fdopendir + readdir 不显示完整文件列表

在我的应用程序中,我使用本机函数fdopendir。从java我得到文件描述符,并将其放入这个函数中。使用它的结果我可以读取目录的内容。在 android 11 上,列出目录时我只看到媒体文件。如何使用存储访问框架获取完整文件列表?

这是我的代码:

在本机代码中,我使用readdir迭代目录条目。dirp 是我自己的结构,其中包含指向标准 DIR 结构的指针。

struct dirent* dentry = readdir(dirp->dir);
Run Code Online (Sandbox Code Playgroud)

为了获得 DIR 结构,我跳转到 Java 来获取文件描述符

DIR *AndroidStorage_OpenDir(const char *folder) {
    jstring string = jvmEnv->NewStringUTF(folder);
    int fd = jvmEnv->CallIntMethod( jvmCallbackThread, JavaOpenDir, string);
    jvmEnv->DeleteLocalRef(string);
    return fdopendir(fd);
}
Run Code Online (Sandbox Code Playgroud)

在Java中,我使用SAF方法来获取整数文件描述符,然后将其返回给C++

public static int openDir(String path) {
        Uri uri = uriCache.get(path);
        if (uri == null) {
            uri=getUri(path);
            uriCache.put(path, uri);
        }
    return resolver.openFileDescriptor(uri, "r").detachFd();
}
Run Code Online (Sandbox Code Playgroud)

在 Android 10 及更低版本上,它运行良好。我应该在 android 11 上做什么来获取目录中的所有文件?用户使用Intent.ACTION_OPEN_DOCUMENT_TREE授予我对此文件夹的完全访问权限

编辑:我在谷歌的跟踪器上打开了问题,因为在我看来这似乎是一个错误。您可以找到用于复制的小应用程序。您可以给这个问题加注星标,这样谷歌就可以更快地查看这个问题。

c++ directory android android-ndk storage-access-framework

6
推荐指数
0
解决办法
469
查看次数

Android 12 - 存储访问框架/范围存储不再工作

Android 12最近在一些手机上发布,一些用户开始抱怨存储访问:他们无法再向应用程序授予对特定文件夹的访问权限(例如“下载”文件夹)。

该消息表示:“无法使用此文件夹。为了保护您的隐私,请选择其他文件夹”。

这个问题很容易重现,我花了一些时间寻找解决方案,但找不到一个简单的解决方案。

问题图片

似乎唯一的解决方法是要求完全存储访问(但这不是我想要做的,这很糟糕)或要求用户创建一个新文件夹,这将是用户体验的绝对痛苦。

我不明白的是:Google 是否在没有任何文档的情况下就在 Android 12 上弃用了 SAF?这是一个错误还是一个功能?我真的很困惑那里。Android 11 的迁移已经很痛苦了,现在恐怕 12 会变得更加痛苦。

这是代码,但没什么特别的:

    /*
    * Requests Scoped Storage access authorization
    */
    @RequiresApi(Build.VERSION_CODES.Q)
    @JvmStatic
    fun requestScopedStorageAccess(activity: Activity, requestCode: Int) {
        val storageManager = activity.getSystemService(Context.STORAGE_SERVICE) as StorageManager
        val intent = storageManager.primaryStorageVolume.createOpenDocumentTreeIntent()
        activity.startActivityForResult(intent, requestCode)
    }
Run Code Online (Sandbox Code Playgroud)

我认为值得注意的是,一切都在 Android 10 和 11 上完美运行,因此问题确实与 Android 12 有关。

storage android storage-access-framework scoped-storage android-12

6
推荐指数
1
解决办法
5120
查看次数

存储访问框架不适用于 Android 电视

我正在开发一个针对 Android 电视的 Android 应用程序,应用程序的部分要求是用户需要将文件保存在 SD 卡上。为了访问文件系统,我尝试使用存储访问框架(SAF)。为了使用 SAF 进行测试,我创建了一个示例活动。这是我用来启动文件浏览器活动的代码:

Intent intent = new Intent(Intent.ACTION_OPEN_DOCUMENT);
        intent.addCategory(Intent.CATEGORY_OPENABLE);
        intent.setType("*/*");
        startActivityForResult(i, REQUEST_CODE);
Run Code Online (Sandbox Code Playgroud)

然后在该onActivityResult方法中,我显示一个简单的 toast,仅用于测试目的。这是方法

    @Override
    public void onActivityResult(int requestCode, int resultCode,
                                 Intent resultData) {

        if (resultCode == Activity.RESULT_OK && requestCode == REQUEST_CODE) {

            Uri uri = null;
            if (resultData != null) {
                uri = resultData.getData();
            }
            Toast.makeText(this, "Path: " + uri.getPath(), Toast.LENGTH_LONG).show();
       }
Run Code Online (Sandbox Code Playgroud)

当在我的手机(Android 5.0)上测试具有上述代码的示例活动时,它可以成功运行。但是,在 android 电视盒和 android 电视模拟器(均为 Android 6.0)上测试它时,出现以下异常:

android.content.ActivityNotFoundException:找不到处理 Intent 的 Activity { act=android.intent.action.OPEN_DOCUMENTtyp= / }

Android 电视不支持存储访问框架吗?我该怎么做才能解决这个问题

android storage-access-framework android-tv

5
推荐指数
0
解决办法
6246
查看次数