Android文件选择器[超级轻量级FilePicker测试没有问题][挣扎解决自带文件管理器获取不到绝对地址问题而是返回msf%3A1000038197]
超级轻量级FilePicker测试没有问题
本文摘录于:https://blog.csdn.net/gitblog_00365/article/details/141449437只是做学习备份之用,绝无抄袭之意,有疑惑请联系本人!
今天真的是发了疯的找文件管理器,因为调用系统自带的文件管理器老是有问题,所以越调越着急,最后发现还是FilePicker简单好用,代码仓库地址:https://gitcode.com/gh_mirrors/andr/android-filepicker/overview?utm_source=artical_gitcode&index=top&type=card&webUrl
步骤很简单,第一步添加依赖
首先,在你的项目的 build.gradle (Module) 文件中的 dependencies 块添加如下依赖:
implementation 'com.github.angads25:filepicker:1.1.0'
然后在代码黄总增加如下内容(原文内容):
import com.angads25.filepicker.model.FilePath;
import com.angads25.filepicker.view.FilePickerFragment;...// 在某个方法内启动FilePicker
private void chooseFile() {FilePickerFragment filePickerFragment = FilePickerFragment.newInstance();filePickerFragment.setFileType(FilePickerFragment.FILE_TYPE_ALL);filePickerFragment.setOnFilePathSelectedListener(new FilePickerFragment.OnFilePathSelectedListener() {@Overridepublic void onFilePathSelected(List<FilePath> filePaths) {// 处理选择的文件路径for (FilePath fp : filePaths) {Log.d("MyApp", "Selected Path: " + fp.getPath());}}});filePickerFragment.show(getSupportFragmentManager(), "FILE_PICKER");
}
我自己的代码如下:
public void onClickSelectFile(View view) {Toast.makeText(getApplicationContext(), "请选择bin格式文件", Toast.LENGTH_SHORT).show();DialogProperties properties = new DialogProperties();properties.selection_mode = DialogConfigs.SINGLE_MODE;properties.selection_type = DialogConfigs.FILE_SELECT;properties.root = new File("/sdcard");properties.error_dir = new File(DialogConfigs.DEFAULT_DIR);properties.offset = new File(DialogConfigs.DEFAULT_DIR);String[] extensions = {"bin",};properties.extensions = extensions;FilePickerDialog dialog = new FilePickerDialog(OTA_Active.this, properties);dialog.setTitle("请选择bin格式文件");dialog.setDialogSelectionListener(new DialogSelectionListener() {@Overridepublic void onSelectedFilePaths(String[] files) {// files数组包含了用户由应用程序选择的文件路径。String path=files[0];if(path!="") {int start = path.lastIndexOf("/");if (start != -1 ) {FileNameList.add(path.substring(start + 1));FilePathList.add(path);ArrayAdapter<String> array = new ArrayAdapter(OTA_Active.this, android.R.layout.simple_list_item_1, FileNameList);listview.setAdapter(array);OTA_Active.this.runOnUiThread(new Runnable() {@Overridepublic void run() {//此时已在主线程中,可以更新UI了AdapterView.OnItemClickListener onItemClickListener = listview.getOnItemClickListener();if(onItemClickListener!=null){onItemClickListener.onItemClick(listview,null,listview.getCount()-1,0);}}});}}}});dialog.show();}
本章节的源码可以从如下地址下载:https://download.csdn.net/download/chengdong1314/89943454
测试确实可行,使用起来完全没问题,视频操作演示如下:
选择文件操作
挣扎解决自带文件管理器获取不到绝对地址问题
非常无奈按照网上的方法调用系统自带的文件管理器选择文件的时候总会这样返回msf%3A1000038197之类的数据,比如如下:
content://com.android.providers.downloads.documents/document/msf%3A1000038197
本文摘录于:https://cloud.tencent.com/developer/article/2003648只是做学习备份之用,绝无抄袭之意,有疑惑请联系本人!
这里根据上面的文章调用如下函数:
public static File uriToFileApiQ(Uri uri, Context context) {File file = null;if (uri == null) return file;//android10以上转换if (uri.getScheme().equals(ContentResolver.SCHEME_FILE)) {file = new File(uri.getPath());} else if (uri.getScheme().equals(ContentResolver.SCHEME_CONTENT)) {//把文件复制到沙盒目录ContentResolver contentResolver = context.getContentResolver();String displayName = System.currentTimeMillis() + Math.round((Math.random() + 1) * 1000)+ "." + MimeTypeMap.getSingleton().getExtensionFromMimeType(contentResolver.getType(uri));try {InputStream is = contentResolver.openInputStream(uri);File cache = new File(context.getCacheDir().getAbsolutePath(), displayName);FileOutputStream fos = new FileOutputStream(cache);FileUtils.copy(is, fos);file = cache;fos.close();is.close();} catch (IOException e) {e.printStackTrace();}}return file;}
这样调用uriToFileApiQ函数:
protected void onActivityResult(int requestCode, int resultCode, Intent data) {super.onActivityResult(requestCode, resultCode, data);if (resultCode == Activity.RESULT_OK) {Uri uri = data.getData();if (Build.VERSION.SDK_INT > Build.VERSION_CODES.KITKAT) {//4.4以后File fi = uriToFileApiQ(this, uri);path=fi.getPath();} else {//4.4以下下系统调用方法path = getRealPathFromURI(uri);}int index = path.lastIndexOf('.');if (index > 0) {if(!("bin".equals(path.substring(index + 1))))return;}else return;if(path!="") {int start = path.lastIndexOf("/");if (start != -1 ) {FileNameList.add(path.substring(start + 1));FilePathList.add(path);ArrayAdapter<String> array = new ArrayAdapter(OTA_Active.this, android.R.layout.simple_list_item_1, FileNameList);listview.setAdapter(array);AdapterView.OnItemClickListener onItemClickListener = listview.getOnItemClickListener();if(onItemClickListener!=null){onItemClickListener.onItemClick(listview,null,listview.getCount()-1,0);}}}}}
onActivityResult是这样引起的:
public void onClickSelectFile(View view) {Toast.makeText(getApplicationContext(), "请选择bin格式文件", Toast.LENGTH_SHORT).show();Intent intent = new Intent(Intent.ACTION_GET_CONTENT);intent.setType("*/*");//无类型限制intent.addCategory(Intent.CATEGORY_OPENABLE);startActivityForResult(intent, 1);}
上面的uriToFileApiQ函数是有缺陷的,FileUtils.copy(is, fos);函数报错了,如果改成FileUtils.copy(is.tostring(), fos.tostring());确实编译没错了,但是拷贝到沙盒里面的文件大小是0,拷贝出错!
无奈啊,我这时候都放弃了,又去本文第一节去尝试了一圈,搞定了自定义文件管理器的问题,但是客户又说一定要自带的资源管理器,可以打开最近的文件,无奈只能够死磕这个问题!!!
最后找呀找,找到这篇文章:https://www.bytezonex.com/archives/b8w3-cvz.html
这里说明了原来的拷贝错误的原因:
Android 10 获取文件路径难题:/document/msf: 解决方案
许多开发者在 Android 10 设备上使用 Intent.ACTION_GET_CONTENT 获取文件路径时,都会遇到返回路径形如 /document/msf: 的情况,令人困惑不已。这并非应用本身的错误,而是 Android 10 为了加强隐私保护而采取的新策略。本文将深入剖析这一变化背后的原因,并提供一套完整的解决方案,帮助你绕过障碍,顺利获取目标文件。
从文件路径到 URI:Android 10 文件访问机制的转变
在 Android 10 之前,应用能够通过文件路径直接访问设备上的绝大多数文件,这种方式虽然便捷,但也存在着巨大的安全隐患,容易造成用户隐私泄露。为了提升系统安全性,Android 10 引入了分区存储机制,限制应用直接访问外部存储空间。
新的机制下,当应用使用 Intent.ACTION_GET_CONTENT 选择文件时,系统不再返回直接的文件路径,而是返回一个 content:// 格式的 URI。这个 URI 指向一个由 MediaStore 管理的中间层,应用无法直接从中获取文件路径,相当于在应用和真实文件之间建立了一道安全屏障。
神秘的 /document/msf: :特殊文件的安全处理
/document/msf: 正是 Android 10 返回的一种特殊 URI,它通常代表着应用选择的并非媒体文件(例如图片、视频),而是其他类型的文件。由于系统无法确定应用如何使用这些文件,为了最大程度地保护用户隐私,系统选择不直接提供文件路径,而是返回这个特殊的 URI,将文件访问权限牢牢掌握在自己手中。
ContentResolver 和 InputStream:突破封锁的利器
想要在 Android 10 上顺利获取文件内容,我们需要借助 Android 系统提供的 ContentResolver 和 InputStream 这两大利器。
操作步骤:
获取 ContentResolver: 通过 context.contentResolver 获取 ContentResolver 实例,相当于获取了与 MediaStore 通信的桥梁。
打开 InputStream: 使用 ContentResolver.openInputStream(uri) 方法,将获取的 content:// URI 传递进去,打开一个指向目标文件的 InputStream,相当于在安全屏障上打开了一条通道,文件内容将通过这条通道流向应用。
读取文件内容: 使用 InputStream 的 read() 方法,如同读取水流一般,将文件内容源源不断地读取出来,供应用使用。
整体思路就是通过InputStream 把数据从外部储存转写到沙盒来,最后修改uriToFileApiQ函数如下:
public static File uriToFileApiQ(Context context,Uri uri) {File file = null;if(uri == null) return file;//android10以上转换if (uri.getScheme().equals(ContentResolver.SCHEME_FILE)) {file = new File(uri.getPath());} else if (uri.getScheme().equals(ContentResolver.SCHEME_CONTENT)) {//把文件复制到沙盒目录ContentResolver contentResolver = context.getContentResolver();
// String displayName = System.currentTimeMillis()+ Math.round((Math.random() + 1) * 1000)
// +"."+ MimeTypeMap.getSingleton().getExtensionFromMimeType(contentResolver.getType(uri));// 注释掉的方法可以获取到原文件的文件名,但是比较耗时Cursor cursor = contentResolver.query(uri, null, null, null, null);String displayName="";if (cursor.moveToFirst()) {displayName = cursor.getString(cursor.getColumnIndex(OpenableColumns.DISPLAY_NAME));}try {InputStream in = contentResolver.openInputStream(uri);File cache = new File(context.getCacheDir().getAbsolutePath(), displayName);FileOutputStream out = new FileOutputStream(cache);//FileUtils.copy(in.toString(), out.toString());int len=-1;byte[] b=new byte[512*1024];while((len=in.read(b))!=-1){out.write(b,0,len);}file = cache;in.close();out.close();} catch (IOException e) {e.printStackTrace();}}return file;}
这里测试到拷贝过来的文件大小就对了,到此问题成功解决!
本章节的安卓源码从如下地址下载:https://download.csdn.net/download/chengdong1314/89943485
视频操作如下:
相关文章:

Android文件选择器[超级轻量级FilePicker测试没有问题][挣扎解决自带文件管理器获取不到绝对地址问题而是返回msf%3A1000038197]
超级轻量级FilePicker测试没有问题 本文摘录于:https://blog.csdn.net/gitblog_00365/article/details/141449437只是做学习备份之用,绝无抄袭之意,有疑惑请联系本人! 今天真的是发了疯的找文件管理器,因为调用系统自带的文件管理…...

【论文速读】| RED QUEEN: 保护大语言模型免受隐蔽多轮越狱攻击
基本信息 原文标题:RED QUEEN: Safeguarding Large Language Models against Concealed Multi-Turn Jailbreaking 原文作者:Yifan Jiang, Kriti Aggarwal, Tanmay Laud, Kashif Munir, Jay Pujara, Subhabrata Mukherjee 作者单位:Hippocr…...

39.第二阶段x86游戏实战2-HOOK实现主线程调用
免责声明:内容仅供学习参考,请合法利用知识,禁止进行违法犯罪活动! 本次游戏没法给 内容参考于:微尘网络安全 本人写的内容纯属胡编乱造,全都是合成造假,仅仅只是为了娱乐,请不要…...
wordpress argon主题美化方面
1、页面前端额外CSS: /*字体*/ font-face {font-family: myFont1; src:url(https://blog.yangmumu.com/css/fonts/Dancing.ttf) ;font-display: swap; } font-face {font-family: myFont2; src:url(https://blog.yangmumu.com/css/fonts/Regular.ttf) ;font-displa…...

qt QRadioButton详解
QRadioButton 是一个可以切换选中(checked)或未选中(unchecked)状态的选项按钮。单选按钮通常呈现给用户一个“多选一”的选择,即在一组单选按钮中,一次只能选中一个按钮。 重要方法 QRadioButton(QWidget…...
Qt 最小化,最大化,关闭窗口
Qt 最小化,最大化 在Qt中,你可以使用QWidget类提供的方法来实现窗口的最小化、最大化等操作。 最小化窗口 你可以使用QWidget的showMinimized()方法来最小化窗口。这将隐藏窗口并将其显示为系统托盘区域的图标。 connect(ui->btnMin,&QPushButton::click…...

【vue项目中添加告警音频提示音】
一、前提: 由于浏览器限制不能自动触发音频文件播放,所以实现此类功能时,需要添加触发事件,举例如下: 1、页面添加打开告警声音开关按钮 2、首次进入页面时添加交互弹窗提示:是否允许播放音频 以上两种方…...

百度SEO分析实用指南 提升网站搜索排名的有效策略
内容概要 在数字化时代,搜索引擎优化(SEO)已经成为提升网站曝光度的关键工具。本指南将带您了解SEO的基本知识,帮助您在复杂的网络环境中立足。我们将从关键词优化开始,重点讲解如何选择合适的关键词来提高搜索引擎排…...

高并发场景下的性能测试方法!
在现代互联网应用中,高并发场景下的性能测试显得尤为重要。无论是电商平台的秒杀活动,还是社交应用的突发流量,都需要确保系统能够在高并发情况下稳定运行。本文将详细介绍高并发场景下的性能测试方法,并提供具体的方案和实战演练…...

杂项——USB键盘与鼠标流量分析——BUUCTF——流量分析
第一次做USB键盘与鼠标流量分析的题目,现在来好好做一个总结 1. 基础知识 USB流量指的是USB设备接口的流量,攻击者能够通过监听usb接口流量获取键盘敲击键、鼠标移动与点击、存储设备的铭文传输通信、USB无线网卡网络传输内容等等。 在正式介绍 USB H…...
Java如何实现企业微信审批流程
大家好,我是 V 哥。最近的一个项目中,用到企业微信的审批流程,整理出来分享给大家。在企业微信中实现审批流程可以通过调用企业微信的开放API完成,企业微信提供了审批应用接口,用于创建审批模板、发起审批流程以及获取…...
GEE app:在地图上构建一个可以查看局部的小窗
目录 简介 函数 ee.Geometry.MultiLineString(coords, proj, geodesic, maxError) Arguments: Returns: Geometry.MultiLineString getBounds(asGeoJSON) Arguments: Returns: GeoJSONGeometry|List|String setControlVisibility(all, layerList, zoomControl, scaleC…...

leetcode71:简化路径
给你一个字符串 path ,表示指向某一文件或目录的 Unix 风格 绝对路径 (以 / 开头),请你将其转化为 更加简洁的规范路径。 在 Unix 风格的文件系统中规则如下: 一个点 . 表示当前目录本身。此外,两个点 ..…...
nodejs入门教程4:nodejs创建第一个应用
1. 安装 Node.js 首先,确保你的计算机上已经安装了 Node.js。如果还没有安装,可以从官方网站(https://nodejs.org)下载并安装最新的 LTS 版本。安装完成后,你可以在命令行或终端中运行以下命令来验证安装:…...

启用 iPhone 原生的五笔输入
聊聊如何在 iOS 中使用原生的五笔输入法 本文虽然介绍的是如何添加五笔键盘,其实其他键盘(双拼,外语键盘、第三方输入法)也是类似的添加方式。 使用原生的理由 虽然之前的文章列了不少第三方的五笔输入法,但其实…...

这个工具让你轻松开发一个带AI功能的Notion
这个工具让你轻松开发一个带AI功能的Notion Plate 是一款由 AI 加持的富文本编辑器,旨在帮助开发者创建功能强大的 WYSIWYG 文本编辑工具。本文将介绍 Plate 的基本信息、特点、以及如何快速上手使用。 软件简介 Plate 由 udecode 开发,基于 React 和 S…...

光耦合器的关键作用和创新---腾恩科技
光耦合器或光隔离器已成为电路中必不可少的器件,它允许信号在无需直接电接触的情况下跨不同电压域传输。这种隔离能力对于保护低压元件免受高压电路的潜在损坏至关重要。本文将仔细研究光耦合器在当今技术中发挥的独特作用,并探讨其在各种应用中不断扩展…...

穿越死锁的迷雾:pthread_mutex_lock的终极挑战与破解策略
穿越死锁的迷雾:pthread_mutex_lock的终极挑战与破解策略 一、死锁的基本概念二、pthread_mutex_lock 出现死锁的原因三、pthread_mutex_lock 出现死锁的表现四、处理pthread_mutex_lock 出现死锁的方法1. 避免死锁1.1 遵循锁的顺序原则1.2 使用定时锁1.3 使用尝试锁1.4 使用递…...
Dockerfile制作Oracle19c镜像
Dockerfile文件 cat > Dockerfile << EOF # 使用 Oracle Linux 8 作为基础镜像 FROM oraclelinux:8# 复制 Oracle 19c 安装包 COPY oracle-database-ee-19c-1.0-1.x86_64.rpm /tmp/# 安装 Oracle 19c 数据库和依赖 RUN yum localinstall -y /tmp/oracle-database-ee-…...

【时间之外】IT人求职和创业应知【23】
目录 新闻一:央行发布首个买断式逆回购交易公告 新闻二:2024CCF科技创业大赛报名截止 新闻三:BNB Chain将在迪拜主办第四届BNB孵化联盟(BIA) 认知决定你的赚钱能力。以下是今天可能影响你求职和创业的热点新闻: 今日关键字:TCL两连扳,已经跑了,我的认知就到此了 新…...
浏览器访问 AWS ECS 上部署的 Docker 容器(监听 80 端口)
✅ 一、ECS 服务配置 Dockerfile 确保监听 80 端口 EXPOSE 80 CMD ["nginx", "-g", "daemon off;"]或 EXPOSE 80 CMD ["python3", "-m", "http.server", "80"]任务定义(Task Definition&…...
Vue记事本应用实现教程
文章目录 1. 项目介绍2. 开发环境准备3. 设计应用界面4. 创建Vue实例和数据模型5. 实现记事本功能5.1 添加新记事项5.2 删除记事项5.3 清空所有记事 6. 添加样式7. 功能扩展:显示创建时间8. 功能扩展:记事项搜索9. 完整代码10. Vue知识点解析10.1 数据绑…...
论文解读:交大港大上海AI Lab开源论文 | 宇树机器人多姿态起立控制强化学习框架(二)
HoST框架核心实现方法详解 - 论文深度解读(第二部分) 《Learning Humanoid Standing-up Control across Diverse Postures》 系列文章: 论文深度解读 + 算法与代码分析(二) 作者机构: 上海AI Lab, 上海交通大学, 香港大学, 浙江大学, 香港中文大学 论文主题: 人形机器人…...

基于距离变化能量开销动态调整的WSN低功耗拓扑控制开销算法matlab仿真
目录 1.程序功能描述 2.测试软件版本以及运行结果展示 3.核心程序 4.算法仿真参数 5.算法理论概述 6.参考文献 7.完整程序 1.程序功能描述 通过动态调整节点通信的能量开销,平衡网络负载,延长WSN生命周期。具体通过建立基于距离的能量消耗模型&am…...
uniapp中使用aixos 报错
问题: 在uniapp中使用aixos,运行后报如下错误: AxiosError: There is no suitable adapter to dispatch the request since : - adapter xhr is not supported by the environment - adapter http is not available in the build 解决方案&…...

人机融合智能 | “人智交互”跨学科新领域
本文系统地提出基于“以人为中心AI(HCAI)”理念的人-人工智能交互(人智交互)这一跨学科新领域及框架,定义人智交互领域的理念、基本理论和关键问题、方法、开发流程和参与团队等,阐述提出人智交互新领域的意义。然后,提出人智交互研究的三种新范式取向以及它们的意义。最后,总结…...

无人机侦测与反制技术的进展与应用
国家电网无人机侦测与反制技术的进展与应用 引言 随着无人机(无人驾驶飞行器,UAV)技术的快速发展,其在商业、娱乐和军事领域的广泛应用带来了新的安全挑战。特别是对于关键基础设施如电力系统,无人机的“黑飞”&…...

Linux 中如何提取压缩文件 ?
Linux 是一种流行的开源操作系统,它提供了许多工具来管理、压缩和解压缩文件。压缩文件有助于节省存储空间,使数据传输更快。本指南将向您展示如何在 Linux 中提取不同类型的压缩文件。 1. Unpacking ZIP Files ZIP 文件是非常常见的,要在 …...

(一)单例模式
一、前言 单例模式属于六大创建型模式,即在软件设计过程中,主要关注创建对象的结果,并不关心创建对象的过程及细节。创建型设计模式将类对象的实例化过程进行抽象化接口设计,从而隐藏了类对象的实例是如何被创建的,封装了软件系统使用的具体对象类型。 六大创建型模式包括…...

Python 实现 Web 静态服务器(HTTP 协议)
目录 一、在本地启动 HTTP 服务器1. Windows 下安装 node.js1)下载安装包2)配置环境变量3)安装镜像4)node.js 的常用命令 2. 安装 http-server 服务3. 使用 http-server 开启服务1)使用 http-server2)详解 …...