标签: storage-access-framework

使用KitKat存储访问框架后,打开Goog​​le云端硬盘文件内容URI

我正在使用Android 4.4的存储访问框架并打开文件选择器.

一切正常,除非从Google云端硬盘中选择文件,我只能弄清楚如何将其作为输入流打开,但我想获得一个java File对象.

返回的内容uri看起来像这样:content://com.google.android.apps.docs.storage/document/acc%3D4%3Bdoc%3D2279

其他类似的问题,但没有一个工作解决方案,允许我获取文件名,文件大小和内容:

我还研究了Paul Burke的FileChooser(https://github.com/iPaulPro/aFileChooser),这是该问题列表中最常见的问题.

如何从该内容获取文件?

我目前的解决方法是从输入流写出一个临时文件.

谢谢!

android google-drive-api storage-access-framework

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

使用SAF(存储访问框架)的Android SD卡写权限

关于如何在SD卡(android 5及以上版本)中编写(和重命名)文件的大量调查结果后,我认为android提供的新SAF需要获得用户写入SD卡文件的许可.

我在这个文件管理器应用程序ES文件资源管理器中看到,最初它采用以下方式读取和写入权限,如图片所示.

在此输入图像描述

图2

选择SD卡后,授予写入权限.

因此我尝试使用SAF的方式相同,但重命名文件失败了.我的代码:

@Override
protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.activity_main);

    rename = (Button) findViewById(R.id.rename);

    startActivityForResult(new Intent(Intent.ACTION_OPEN_DOCUMENT_TREE), 42);
}

@Override
public void onActivityResult(int requestCode,int resultCode,Intent resultData) {
    if (resultCode != RESULT_OK)
        return;
    Uri treeUri = resultData.getData();
    DocumentFile pickedDir = DocumentFile.fromTreeUri(this, treeUri);
    grantUriPermission(getPackageName(), treeUri, Intent.FLAG_GRANT_READ_URI_PERMISSION | Intent.FLAG_GRANT_WRITE_URI_PERMISSION);
    getContentResolver().takePersistableUriPermission(treeUri, Intent.FLAG_GRANT_READ_URI_PERMISSION | Intent.FLAG_GRANT_WRITE_URI_PERMISSION);
}

public void renameclick(View v) {
    File ff = new File("/storage/sdcard1/try1.jpg");
    try {
        ff.createNewFile();
    } catch (Exception e) {
        Log.d("error", "creating");
        e.printStackTrace();
    }
} …
Run Code Online (Sandbox Code Playgroud)

android android-sdcard storage-access-framework android-5.0-lollipop documentfile

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

找不到处理Intent的活动 - android.intent.action.OPEN_DOCUMENT

我正在尝试Android 4.4的存储访问框架

我开发了一个虚拟应用程序,它启动了活动开始的意图.

    Intent intent = new Intent(Intent.ACTION_OPEN_DOCUMENT);
    intent.addCategory(Intent.CATEGORY_OPENABLE);
    startActivityForResult(intent, READ_REQUEST_CODE);
Run Code Online (Sandbox Code Playgroud)

我还开发了另一个虚拟应用程序作为文件提供程序.

        <?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
    package="com.example.saf"
    android:versionCode="1"
    android:versionName="1.0" >
<uses-sdk
    android:minSdkVersion="19"
    android:targetSdkVersion="19" />

<uses-permission android:name="android.permission.MANAGE_DOCUMENTS"/>

<application
    android:allowBackup="true"
    android:icon="@drawable/ic_launcher"
    android:label="@string/app_name"
    android:theme="@style/AppTheme" >
    <activity
        android:name="com.example.saf.MainActivity"
        android:label="@string/app_name" >
        <intent-filter>
            <action android:name="android.intent.action.MAIN" />

            <category android:name="android.intent.category.LAUNCHER" />
        </intent-filter>
    </activity>

    <provider
        android:name="com.example.saf.MyFileProvider"
        android:authorities="com.example.saf.documents"
        android:exported="@bool/is_kitkat"
        android:enabled="@bool/is_kitkat"
        android:grantUriPermissions="@bool/is_kitkat"
        android:permission="android.permission.MANAGE_DOCUMENTS">
        <intent-filter>
            <action android:name="android.content.action.DOCUMENTS_PROVIDER" />
        </intent-filter>
    </provider>

</application>
Run Code Online (Sandbox Code Playgroud)

我已经实现了MyFileProvider类.

但是当我启动用户应用程序(触发意图的那个)时,我收到以下错误

android.content.ActivityNotFoundException: No Activity found to handle Intent { act=android.intent.action.OPEN_DOCUMENT cat=[android.intent.category.OPENABLE] }
Run Code Online (Sandbox Code Playgroud)

我只是关注android的开发者文档.我有什么想法可能做错了吗?

编辑:这是我最新的Manifest.我还需要MyFileProvider"扩展DocumentsProvider"的"正确"实现吗?我现在可以在函数中返回null吗?

android android-intent android-activity android-4.4-kitkat storage-access-framework

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

如何获得每个StorageVolume的免费和总大小?

背景

Google不幸地计划破坏存储权限,以使应用程序无法使用标准File API(和文件路径)访问文件系统。许多人反对它,因为它改变了应用程序访问存储的方式,并且在许多方面都是受限制的有限API。

因此,如果我们想处理各种问题,我们将需要在将来的某些Android版本上完全使用SAF(存储访问框架)(在Android Q上,我们至少可以暂时使用一个标志来使用常规存储权限)。存储卷并到达那里的所有文件。

因此,例如,假设您要制作一个文件管理器并显示设备的所有存储卷,并为每个文件显示有多少总字节和可用字节。这样的事情看起来非常合法,但是由于我找不到找到这种方法的方法。

问题

从API 24(此处)开始,我们终于可以列出所有存储卷,如下所示:

    val storageManager = getSystemService(Context.STORAGE_SERVICE) as StorageManager
    val storageVolumes = storageManager.storageVolumes
Run Code Online (Sandbox Code Playgroud)

事实是,此列表上的每个项目都没有功能来获取其大小和可用空间。

但是,以某种方式,Google的 Google提供的文件”应用程序设法获得了该信息,而没有获得任何形式的许可:

在此处输入图片说明

并在装有Android 8的Galaxy Note 8上进行了测试。甚至没有最新版本的Android。

因此,这意味着即使在Android 8上,也应该有一种无需任何许可即可获取此信息的方法。

我发现了什么

有一些类似于获得自由空间的东西,但是我不确定是否确实如此。虽然如此。这是它的代码:

    val storageManager = getSystemService(Context.STORAGE_SERVICE) as StorageManager
    val storageVolumes = storageManager.storageVolumes
    AsyncTask.execute {
        for (storageVolume in storageVolumes) {
            val uuid: UUID = storageVolume.uuid?.let { UUID.fromString(it) } ?: StorageManager.UUID_DEFAULT
            val allocatableBytes = storageManager.getAllocatableBytes(uuid)
            Log.d("AppLog", "allocatableBytes:${android.text.format.Formatter.formatShortFileSize(this,allocatableBytes)}")
        }
    }
Run Code Online (Sandbox Code Playgroud)

但是,我找不到类似的东西来获取每个StorageVolume实例的总空间。假设我对此是正确的,我已经在这里提出了要求。

您可以在我对此问题写的答案中找到更多我所找到的内容,但是目前,这是所有变通办法的结合,这些工作不是变通办法,而是在某些情况下有效。 …

android storage-access-framework

17
推荐指数
3
解决办法
587
查看次数

如何在android API 19(KitKat)中保留权限?

在我的应用程序中,我将图像路径存储在我的SQlite数据库中以供进一步使用.我得到的路径是

content://com.android.providers.media.documents/document/image%3A71964
Run Code Online (Sandbox Code Playgroud)

当我从数据库中检索此路径并尝试从该路径中检索图像时,机器人抛出

java.lang.SecurityException: Permission Denial: opening provider
com.android.providers.media.MediaDocumentsProvider 
from ProcessRecord{42c84ec8 23911:com.gots.gb/u0a248} (pid=23911, uid=10248) 
requires android.permission.MANAGE_DOCUMENTS or android.permission.MANAGE_DOCUMENTS
Run Code Online (Sandbox Code Playgroud)

根据https://developer.android.com/guide/topics/providers/document-provider.html#permissions我需要通过添加以下代码来保留权限

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

当我将此代码添加到我的ImageAdapter类时,它扩展了BaseAdapter android抛出

08-21 02:14:38.530: W/System.err(24452): java.lang.SecurityException:
No permission grant found for UID 10248 and Uri 
content://com.android.providers.media.documents/document/image:71964
Run Code Online (Sandbox Code Playgroud)

这是我的ImageAdapter代码的相关部分

public View getView(int position, View convertView, ViewGroup parent) {
    ImageView imageView ;


    if (convertView == null){
        imageView = new ImageView(mContext);
        imageView.setLayoutParams(new GridView.LayoutParams(185, 185));
        imageView.setScaleType(ImageView.ScaleType.CENTER_CROP);
        imageView.setPadding(8, …
Run Code Online (Sandbox Code Playgroud)

java sqlite android android-4.4-kitkat storage-access-framework

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

Android:使用Storage Access Framework获取的URI中的意向选择器打开文件

一开始,用户可以使用新的存储访问框架选择文件(假设应用程序是API> 19):

https://developer.android.com/guide/topics/providers/document-provider.html

然后通过保存URI来保存对所选文件的引用,如下所示:

content://com.android.providers.downloads.documments/document/745
Run Code Online (Sandbox Code Playgroud)

(在这种情况下,文件来自默认下载dir`).

稍后,我想让用户打开这些文件(例如,他们的名字显示在UI列表中,用户选择一个).

我想用Android着名的意图选择器功能做到这一点,我所拥有的只是上面的URI对象......

谢谢,

android android-intent android-file storage-access-framework android-afilechooser

14
推荐指数
1
解决办法
7092
查看次数

某些应用程序如何在没有 root 的情况下访问 Android 11 上“.../Android/...”子文件夹的内容?

背景

Android 10 和 11各种存储限制,其中还包括访问所有文件的新权限 ( MANAGE_EXTERNAL_STORAGE )(但它不允许访问真正的所有文件),而之前的存储权限已减少以仅授予对媒体的访问权限文件:

  1. 应用程序可以自由访问“媒体”子文件夹。
  2. 应用程序永远无法访问“数据”子文件夹,尤其是内容。
  3. 对于“obb”文件夹,如果应用程序被允许安装应用程序,它可以访问它(将文件复制到那里)。否则不能。
  4. 使用 USB 或 root,您仍然可以访问它们,作为最终用户,您可以通过内置的文件管理器应用程序“文件”访问它们。

问题

我注意到一个名为“ X-plore ”的应用程序以某种方式克服了这个限制(此处):一旦您进入“Android/data”文件夹,它会要求您授予对它的访问权限(直接使用 SAF,不知何故),并且当您授予它,您可以访问“Android”文件夹的所有文件夹中的所有内容。

这意味着可能仍然有一种方法可以达到它,但问题是由于某种原因,我无法制作具有相同效果的样本。

我发现并尝试过的

该应用程序似乎针对 API 29 (Android 10),并且它尚未使用新权限,并且它具有标志requestLegacyExternalStorage。我不知道他们在针对 API 30 时使用的相同技巧是否有效,但我可以说,在我的情况下,在 Pixel 4 和 Android 11 上运行,它工作正常。

所以我尝试做同样的事情:

  1. 我制作了一个针对 Android API 29 的示例 POC,已授予(各种)存储权限,包括遗留标志。

  2. 我试图请求直接访问“Android”文件夹(基于此处),但遗憾的是由于某种原因无法正常工作(一直转到 DCIM 文件夹,不知道为什么):

val androidFolderDocumentFile = DocumentFile.fromFile(File(primaryVolume.directory!!, "Android"))
val intent = Intent(Intent.ACTION_OPEN_DOCUMENT_TREE)
        .setFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION or Intent.FLAG_ACTIVITY_RESET_TASK_IF_NEEDED) 
        .putExtra(DocumentsContract.EXTRA_INITIAL_URI, androidFolderDocumentFile.uri)
startActivityForResult(intent, 1)
Run Code Online (Sandbox Code Playgroud)

我尝试了各种标志组合。

  1. 启动应用程序时,当我自己手动到达“Android”文件夹时,因为这不能正常工作,我授予了对该文件夹的访问权限,就像在其他应用程序上一样。

  2. 获取结果时,我尝试获取路径中的文件和文件夹,但无法获取它们:

override fun onActivityResult(requestCode: Int, resultCode: Int, …
Run Code Online (Sandbox Code Playgroud)

android storage-access-framework android-11

13
推荐指数
1
解决办法
3691
查看次数

如何检查我们可以访问哪些StorageVolume,我们不能访问哪些?

背景

Google不幸地计划破坏存储权限,以使应用程序无法使用标准File API(和文件路径)访问文件系统。许多人反对它,因为它改变了应用程序访问存储的方式,并且在许多方面都是受限制的有限API。

因此,如果我们想处理各种问题,我们将需要在将来的某些Android版本上完全使用SAF(存储访问框架)(在Android Q上,我们至少可以暂时使用一个标志来使用常规存储权限)。存储卷并到达那里的所有文件。

因此,例如,假设您要创建一个文件管理器并显示设备的所有存储卷,以显示用户可以授予访问权限的内容,并且如果您已经可以访问每个文件,则只需输入该文件即可。这样的事情看起来很合理,但是由于我找不到解决方法。

问题

从API 24(此处)开始,我们终于可以列出所有存储卷,如下所示:

    val storageManager = getSystemService(Context.STORAGE_SERVICE) as StorageManager
    val storageVolumes = storageManager.storageVolumes
Run Code Online (Sandbox Code Playgroud)

而且,这是有史以来第一次,我们可以有一个Intent请求访问storageVolume(在此)。因此,例如,如果我们要请求用户授予对主数据库的访问权限(实际上是从那里开始,实际上并没有真正询问任何内容),则可以使用以下方法:

startActivityForResult(storageManager.primaryStorageVolume.createOpenDocumentTreeIntent(), REQUEST_CODE__DIRECTORTY_PERMISSION)
Run Code Online (Sandbox Code Playgroud)

代替startActivityForResult(Intent(Intent.ACTION_OPEN_DOCUMENT_TREE), REQUEST_CODE__DIRECTORTY_PERMISSION),希望用户在那里选择正确的东西。

为了最终获得用户选择的内容,我们需要执行以下操作:

@TargetApi(Build.VERSION_CODES.KITKAT)
override fun onActivityResult(requestCode: Int, resultCode: Int, data: Intent?) {
    super.onActivityResult(requestCode, resultCode, data)
    if (requestCode == REQUEST_CODE__DIRECTORTY_PERMISSION && resultCode == Activity.RESULT_OK && data != null) {
        val treeUri = data.data ?: return
        contentResolver.takePersistableUriPermission(treeUri, Intent.FLAG_GRANT_READ_URI_PERMISSION or Intent.FLAG_GRANT_WRITE_URI_PERMISSION)
        val pickedDir = DocumentFile.fromTreeUri(this, treeUri)
        ...
Run Code Online (Sandbox Code Playgroud)

到目前为止,我们可以请求对各种存储卷的许可... …

android storage-access-framework

12
推荐指数
1
解决办法
710
查看次数

SAF(存储访问框架)是否解决了Android 4.4(KitKat)中的SD卡WRITE问题?

在Android 4.4中,来自Play商店的应用程序只能写入其应用程序特定目录(例如:/storage/extSdCar/Android/data/com.example.myapp/),并且不允许应用程序在micro SD卡中写入此目录以外的内容.所以我正在探索新的SAF API来检查我是否可以使用SAF写入除应用程序特定目录之外的micro SD卡.

我已经通过创建示例提供程序和客户端应用程序来实现SAF.在我的提供商中,我尝试通过在queryRoots中实现以下代码来显示SD卡的全部内容:

    row.add(Root.COLUMN_DOCUMENT_ID, getDocIdForFile(new File("/storage/extSdCard")));
    row.add(Root.COLUMN_FLAGS, Root.FLAG_SUPPORTS_CREATE | Root.FLAG_SUPPORTS_RECENTS | Root.FLAG_SUPPORTS_SEARCH);
Run Code Online (Sandbox Code Playgroud)

我在我的客户端创建了以下意图,我可以通过我的提供商从SAF的系统UI浏览SD卡的全部内容.

    Intent intent = new Intent(Intent.ACTION_CREATE_DOCUMENT);
    intent.addCategory(Intent.CATEGORY_OPENABLE);
    intent.setType("*/*");
    intent.putExtra(Intent.EXTRA_TITLE, "test.txt");
    startActivityForResult(intent, WRITE_REQUEST_CODE);
Run Code Online (Sandbox Code Playgroud)

当我单击保存按钮时,我收到Toast错误"无法保存文档".但是当我导航到我的提供者的App特定目录(/storage/extSdCar/Android/data/com.example.myprovider/)时系统UI,我能够保存文档.也没有意图,如Intent.CATEGORY_WRITABLE,所以我只能获得可以编辑的文档.请帮我解决以下几点:

似乎即使我们使用SAF,仍然对micro SD卡的WRITE限制保持不变.它是否正确?

2.有什么方法可以创建或删除或修改micro SD卡中我的App特定目录之外的已有文件?

3.谁为普通用户文件决定FLAG_SUPPORTS_WRITE标志,如照片,视频,音乐,文档等?

java android android-sdcard android-4.4-kitkat storage-access-framework

10
推荐指数
1
解决办法
7116
查看次数

如何向存储访问框架指示我不再​​需要加载动画?

我正在为Dropbox编写DocumentsProvider.我正在尝试遵循Google指南创建自定义提供程序,以及Ian Lake 在Medium发布的相同内容.

我试图在存储访问框架中包含该功能,其中一个表明有更多数据要加载.

queryChildDocuments()方法的相关部分如下所示:

@Override
public Cursor queryChildDocuments(final String parentDocumentId,
                                  final String[] projection,
                                  final String sortOrder)  {

    if (selfPermissionsFailed(getContext())) {
        // Permissions have changed, abort!
        return null;
    }

    // Create a cursor with either the requested fields, or the default projection if "projection" is null.
    final MatrixCursor cursor = new MatrixCursor(projection != null ? projection : getDefaultDocumentProjection()){
        // Indicate we will be batch loading
        @Override
        public Bundle getExtras() {
            Bundle bundle = new Bundle(); …
Run Code Online (Sandbox Code Playgroud)

storage android frameworks storage-access-framework dropbox-sdk-js

10
推荐指数
1
解决办法
277
查看次数