Android - 获取对 SD 卡上任何文件路径具有写访问权限的 DocumentFile(已获得 SD 卡权限)

2024-01-21

在我的应用程序中,我使用以下意图获得 SD 卡写入权限。如果用户从系统文件资源管理器中选择 SD 卡文件夹,则我具有 SD 卡写入权限。

Intent intent = new Intent(Intent.ACTION_OPEN_DOCUMENT_TREE);
intent.putExtra("android.content.extra.SHOW_ADVANCED", true);
startActivityForResult(intent, 42);

之后,我可以使用 DocumentFile 类修改 SD 卡中的文件。但我在获取随机文件路径的 DocumentFile 时遇到问题。

Document.fromFile(new File(path));
Document.fromSingleUri(Uri.fromFile(new File(path)));

两者都返回一个 DocumentFile 对象,该对象在 .canWrite() 上返回 false。即使我已经有SD卡权限。

因此,我编写了问题末尾发布的方法,以获取在 .canWrite() 上返回 true 的 DocumentFile。但这很慢……而且还感觉很不对劲!必须有更好的方法来做到这一点。我还编写了一个返回与以下内容相同的字符串的方法

String docFileUriString = docFile.getUri().toString(); 

对于任何文件,其中 docFile 是由以下方法返回的 DocumentFile。但

DocumentFile.fromTreeUri(Uri.parse(docFileUriString ));

返回一个指向 sd 卡根目录的 DocumentFile,而不是 DocumentFile 路径。这很奇怪。有人可以建议一个更优雅的解决方案吗?

public static DocumentFile getDocumentFileIfAllowedToWrite(File file, Context con){ 

    List<UriPermission> permissionUris = con.getContentResolver().getPersistedUriPermissions();

    for(UriPermission permissionUri:permissionUris){

        Uri treeUri = permissionUri.getUri();
        DocumentFile rootDocFile = DocumentFile.fromTreeUri(con, treeUri);
        String rootDocFilePath = FileUtil.getFullPathFromTreeUri(treeUri, con);

        if(file.getAbsolutePath().startsWith(rootDocFilePath)){

            ArrayList<String> pathInRootDocParts = new ArrayList<String>();
            while(!rootDocFilePath.equals(file.getAbsolutePath())){
                pathInRootDocParts.add(file.getName());
                file = file.getParentFile();
            } 

            DocumentFile docFile = null;  

            if(pathInRootDocParts.size()==0){ 
                docFile = DocumentFile.fromTreeUri(con, rootDocFile.getUri()); 
            }
            else{
                for(int i=pathInRootDocParts.size()-1;i>=0;i--){
                    if(docFile==null){docFile = rootDocFile.findFile(pathInRootDocParts.get(i));}
                    else{docFile = docFile.findFile(pathInRootDocParts.get(i)); }  
                }
            }
            if(docFile!=null && docFile.canWrite()){ 
                return docFile; 
            }else{
                return null;
            }

        }
    }
    return null; 
}

Document.fromFile(File)在最近的设备上似乎无法正常工作

这是答案的链接,我获得了有关该问题的最多信息https://stackoverflow.com/a/26765884/971355 https://stackoverflow.com/a/26765884/971355

关键步骤是:

  1. 获取对 SD 卡的写入权限并使其在手机重启后保持不变

    公共无效onActivityResult(int requestCode,int resultCode,Intent resultData){

    ...

    getContentResolver().takePersistableUriPermission(treeUri, Intent.FLAG_GRANT_READ_URI_PERMISSION | Intent.FLAG_GRANT_READ_URI_PERMISSION | Intent.FLAG_GRANT_WRITE_URI_PERMISSION);

    }

  2. 之后,您可以访问文件和文件夹,无论它们嵌套的深度如何,但您必须了解必须处理的复杂 URL。

如果你像我一样是一个 Linux 爱好者,并且曾经认为一切都是文件并且一切都很简单。这次不是。 例如,SD 卡上的文件/storage/13E5-2604/testDir/test.txt where 13E5-2604您的 SD 卡根文件夹将是:

content://com.android.externalstorage.documents/tree/13E5-2604%3A/document/13E5-2604%3A%2FtestDir%2Ftest.txt

in the 新现实。为什么他们做得如此复杂 - 是另一个问题......

我不知道有一种 API 方法可以透明且轻松地将正常的 linux 路径转换为此新现实-小路。但是当你完成之后(%3A是:和%2F是/参见https://www.w3schools.com/tags/ref_urlencode.ASP https://www.w3schools.com/tags/ref_urlencode.ASP供参考)您可以创建一个实例DocumentFile easily:

DocumentFile txtFile = DocumentFile.fromSingleUri(context,
Uri.parse("content://com.android.externalstorage.documents/tree/13E5-2604%3A/document/13E5-2604%3A%2FtestDir%2Ftest.txt"));

并写信给它。

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

Android - 获取对 SD 卡上任何文件路径具有写访问权限的 DocumentFile(已获得 SD 卡权限) 的相关文章

  • 如何清除所有WebView存储的信息?

    我有一个 Android 浏览器 我可以选择清除缓存 存储 cookie 等 代码如下所示 webView clearCache true webView clearFormData webView clearHistory webView
  • 如何对这个字符串进行子串化

    我想得到这个字符串的 4 个部分 String string 10 trillion 896 billion 45 million 56873 我需要的4个部分是 10万亿 8960亿 4500万 和 56873 我所做的是删除所有空格 然
  • 使用workmanager时Firestore脱机持久性错误

    我正在使用一个WorkManger定期从我的中检索信息Firestore当应用程序处于后台和前台时的数据库 此信息用于根据状态更新 UI 因此不同的状态会添加或删除 UI 的不同部分 第一次运行时效果很好 但是 一旦应用程序处于后台并且Wo
  • Sqlite数据库生命周期?关闭应用程序后它会被删除吗?

    我正在遵循一个简单的教程 该教程创建一个从 SQLiteOpenHelper 扩展的类 并创建一个包含一个表和 5 行的数据库 好的 但我需要更多地了解 android Sqlite 数据库 例如 如果应用程序关闭或手机关机会发生什么 数据
  • android中向sqlite中插入大量数据

    目前 我必须一次向我的 Android 中插入超过 100 亿条数据 然而 内存不足的问题会使程序崩溃 sqlite 插入测试非常简单 只需使用 for 循环生成 sql 插入命令并通过 开始 和 提交 进行包装 private Array
  • 卸载后 Web 应用程序不显示“添加到主屏幕”

    这是我第一次创建网络应用程序 我设法解决了这个问题 所以我得到了实际的 chrome 提示 将其添加到主屏幕 然后我从手机上卸载了该网络应用程序 因为我想将其展示给我的同事 但是 屏幕上不再出现提示 问题 这是有意为之的行为还是我的应用程序
  • 如何在android中获取Camera2 API的当前曝光

    In android hardware Camera旧的 我使用下面的代码获取当前曝光并获取它Camera Camera Parameters param mCamera getParameters currentExposure para
  • 在画布上绘图

    我正在编写一个 Android 应用程序 它可以在视图的 onDraw 事件上直接绘制到画布上 我正在绘制一些涉及单独绘制每个像素的东西 为此我使用类似的东西 for int x 0 x lt xMax x for int y 0 y lt
  • Android 模拟器插件无法初始化后端 EGL 显示

    我在 Cloudbees 上设置了 Jenkins 作业 并且可以在那里成功签出并编译我的 Android 项目 现在我想在 android 模拟器中运行一些 JUnit 测试并添加 Android 模拟器插件 我将 显示模拟器窗口 选项设
  • CollapsingToolBarLayout - 状态栏稀松布颜色不改变

    几天前我更新了我的 android studio 并开始使用 CoordinatorLayout 和 CollapsingToolbarLayout 只是尝试一些东西 工具栏稀松布颜色似乎覆盖了状态栏初始颜色和状态栏稀松布颜色 从 xml
  • 带有 EditText 和 Spinner 的对话框

    我有一个按钮 单击后会弹出一个对话框 我希望对话框有一个EditText and a Spinner对话框内 我不知道如何设置它的视图 我有一个代码AlertDialog它有效 只是EditText and Spinner我需要将其放入其中
  • 发布android后更改应用内购买项目的价格

    在 Google Play 上发布后 是否可以更改应用内购买商品的价格 我假设该应用程序也已发布 完整的在线文档位于http developer android com http developer android com也http sup
  • 原色(有时)变得透明

    我正在使用最新的 SDK 版本 API 21 和支持库 21 0 2 进行开发 并且在尝试实施新的材料设计指南时遇到了麻烦 材料设计说我需要有我的primary color and my accent color并将它们应用到我的应用程序上
  • Google 云端硬盘身份验证异常 - 需要许可吗? (v2)

    我一直在尝试将 Google Drive v2 添加到我的 Android 应用程序中 但无法获得授权 我收到 UserRecoverableAuthIOException 并显示消息 NeedPermission 我感觉 Google A
  • 我想实现下面的布局,按钮应该在屏幕底部,当惰性列被填充时,按钮不应该出去

    顶部有惰性列 惰性列下方有输入电话号码布局并从电话簿布局添加联系人 我希望当未添加联系人时此布局位于顶部 当我添加大量联系人时输入电话号码并添加电话簿布局中的联系人会随着惰性列滚动并移出屏幕 我不让他们走出屏幕 当接触较多时 它们必须粘在底
  • 如何根据 gradle 风格设置变量

    我想传递一个变量test我为每种风格设置了不同的值作为 NDK 的定义 但出于某种原因 他总是忽略了最后味道的价值 这是 build gradle apply plugin com android library def test andr
  • Android:膨胀布局时出现 StackOverFlowError 和 InvokingTargetException

    首先 对不起我的英语 我在膨胀布局时有一个问题 我有一个自定义视图 从 LinearLayout 扩展而来 称为按钮帮助 我在名为的布局上使用该视图加载活动 我的以下代码在所有设备和模拟器上都能完美运行 但具有 QVGA 屏幕 例如 Sam
  • 一次显示两条Toast消息?

    我希望在一个位置显示一条 Toast 消息 并在另一位置同时显示另一条 Toast 消息 多个 Toast 消息似乎总是按顺序排队和显示 是否可以同时显示两条消息 是否有一种解决方法至少可以提供这种外观并且不涉及扰乱活动布局 Edit 看来
  • 捕获的图像分辨率太大

    我在做什么 我允许用户捕获图像 将其存储到 SD 卡中并上传到服务器 但捕获图像的分辨率为宽度 4608 像素和高度 2592 像素 现在我想要什么 如何在不影响质量的情况下获得小分辨率图像 例如我可以获取或设置捕获的图像分辨率为原始图像分
  • 如何将 google+ 登录集成到我的 Android 应用程序中?

    大家好 实际上我需要通过我的应用程序从 google 登录人们 现在我阅读了 google 上的文档 其中指出 要允许用户登录 请将 Google Sign In 集成到您的应用中 初始化 GoogleApiClient 对象时 请求 PL

随机推荐

  • sqlalchemy 强制所有连接关闭 mysql

    我们在一些复杂的单元测试中使用sqlalchemy 在每次测试结束时 我们完全使用以下命令拆除数据库drop all 有时 有人会忘记关闭嵌入单元测试深处的会话 然后 我们必须花费大量时间试图找出问题所在 并最终关闭 sqlalchemy
  • 单击 LinkBut​​ton 上的动态文本框

    我通过单击 LinkBut ton 在页面中创建动态文本框 但是 之后 如果提交页面 我找不到动态创建的项目 因此无法将信息发送到数据库 protected void lbAddTag Click object sender EventAr
  • JQGrid 获取特定列的所有值,而不考虑分页

    我正在使用 json 从数据库中提取数据 如何获取特定列的所有值 我想获取 PrimarySkill 列的所有值 全套值 无论分页如何 var texts listTableSupply jqGrid getCol PrimarySkill
  • 如何从 C# 更改 PowerPoint 中 TextRange 的字体颜色?

    我使用 C 创建了一个 PowerPoint 演示文稿 PowerPoint Application powerpointApplication PowerPoint Presentation pptPresentation PowerPo
  • Junit 与 new Date()

    当我有以下方法时 junit 测试会是什么 Override public void saveLastSuccesfullLogin final User user gebruiker setLastLogin new Date store
  • 在网页上,如何为特定部分设置滚动条?

    在获得的背面这个问题 https stackoverflow com questions 21159136 on a web page how can i create a horizontal scroll instead of havi
  • 如何使用 javascript 显示 PNG 图像的动画图像? [ 如 Gmail ]

    First of all check out this image Gmail uses this image to display the animated emoticon How can we show such animation
  • 启动应用程序的第二个实例的小部件

    当我点击小部件时 我在从小部件启动应用程序时遇到问题 这是一些代码的剪辑 Create an Intent to launch activity Intent intent new Intent context Entry MainTabV
  • 如何在Python中使用正则表达式排除特定字符串?

    我想匹配如下字符串 45 meters 45 meters 45 45 但不是像这样的字符串 45 meters you 45 you 45 and you 在这两种情况下 问号都必须位于末尾 所以 本质上我想排除所有包含 you 这个词的
  • 如何在构造函数中初始化 Objective-C 结构体?

    我在 Objective C 上使用一个结构来存储一些数据 如下所示 interface Interface NSObject my Data struct Data unsafe unretained BOOL isInit unsafe
  • 真正的 CTE 递归?

    我今天下午刚刚发现了 CTE 在享受了 2 个小时之后 我意识到它们并没有像我们在任何其他语言中学到的那样执行常见的递归 我的意思是 我总是将递归视为树搜索 所以我原以为 CTE 会一路下降到它发现的第一片叶子 但没有 他的工作是分层进行的
  • Power Query 列名称作为参数

    亲爱的巫师们 我正在尝试创建一个可以使用输入的搜索功能 1 搜索表 2 该表中将运行搜索的列 3 在2指定的列中搜索的值 该函数如下所示 mTbl as table mColName as text mColValue as text gt
  • 如何在 RDBMS 中表示预定事件?

    我必须存储可以每周 每天或每月组织的预定活动 例如上课时间 例如 事件可以在每周一和周三或每月的第二个周四发生 有没有办法将这些信息存储在遵循 3NF 的 RDBMS 中 编辑 这不是家庭作业 我正在和一个朋友一起构建一些东西来启发我们自己
  • MVC 提交带有部分视图的表单

    抱歉 如果之前已经回答过这个问题 我找不到任何与我的问题相符的内容 我有一个视图 其中包含一个部分视图 并且在提交视图时 部分视图中的数据不会发送到控制器 我知道如果我使用编辑器模板 这应该可以工作 但我无法使用它 因为我需要来自部分内部主
  • 如何从列表中显示 ng-templates

    我有一个AppComponent其中包含一个列表ShapeComponents 我实现了一些扩展的组件ShapeComponent like LineComponent CircleComponent RectangleComponent
  • 序列化时仅使用@JsonIgnore,反序列化时不使用@JsonIgnore

    我有一个与服务器发送和接收的用户对象 当我发送用户对象时 我不想将哈希密码发送给客户端 所以 我添加了 JsonIgnore在密码属性上 但这也阻止了它被反序列化为密码 这使得当用户没有密码时很难注册用户 我怎样才能只得到 JsonIgno
  • urllib2 SSL3_CHECK_CERT_AND_ALGORITHM:dh 密钥太小

    尝试使用发送 SOAP 请求suds 我在用着Python 2 7 6 我不太熟悉安全性 我相信我的机器或服务器机器上的安全密钥太小 我不知道如何解决 我是否生成一些新密钥并创建自定义开启器 任何帮助 指导都会有帮助 堆栈跟踪 Traceb
  • TFS 尽管构建是绿色的,但并非所有测试都运行

    由于某种原因 我们大约四分之一的测试没有在 TFS 上运行 构建最终显示为绿色 但仅报告 3 4 表示所有测试均已通过 我猜问题出在一些经过测试的异步代码中 这些代码可能会导致测试运行程序崩溃或继续自行运行 在 VS 本地 所有测试都顺利通
  • 用 Cpp 或其他快速语言反转大型哈希表

    我正在寻找高效的 C 或其他快速 来反转一个巨大的哈希表 哈希键的数量约为200 000 000个 每个哈希键中可能的元素数量约为 100 000 个 我想知道 有效地 反转此类表的好方法是什么 这样现在元素就是键 键就是元素 现在 我将硬
  • Android - 获取对 SD 卡上任何文件路径具有写访问权限的 DocumentFile(已获得 SD 卡权限)

    在我的应用程序中 我使用以下意图获得 SD 卡写入权限 如果用户从系统文件资源管理器中选择 SD 卡文件夹 则我具有 SD 卡写入权限 Intent intent new Intent Intent ACTION OPEN DOCUMENT