通过uri获取文件路径手机适配

青铜版本

  return contentResolver.query(this, arrayOf(MediaStore.MediaColumns.DATA), null, null).let {if (it?.moveToFirst() == true) {val columnIndex = it.getColumnIndex(MediaStore.MediaColumns.DATA)val path = it.getString(columnIndex)it.close()return path}""}

在firebase上发现很多异常奔溃日志,部分手机获取到的 path 是空的,也就是说没有_data字段

其实有的手机通过选择图片或者文件后返回的uri并不一定是媒体uri,也可能是document uri,造成这个时候直接通过 uri查询,找不到_data字段,需要将 document uri中分离出类型和id,在拼凑成新的uri,在通过contentprovider查询,才可以查出 _data字段中真正的路径

//如果是Document类型的URI,需要进行转换
private fun getPathFromDocumentUri(uri: Uri): String? {val isDocumentUri = DocumentsContract.isDocumentUri(BaseApplication.instance, uri)if (isDocumentUri) {val docId = DocumentsContract.getDocumentId(uri)val split = docId.split(":".toRegex()).dropLastWhile { it.isEmpty() }.toTypedArray()val type = split[0] // "image"val id = split[1] // "1044024"var quaryUri: Uri? = nullif ("image".equals(type)) {quaryUri = MediaStore.Images.Media.EXTERNAL_CONTENT_URI;} else if ("video".equals(type)) {quaryUri = MediaStore.Video.Media.EXTERNAL_CONTENT_URI;} else if ("audio".equals(type)) {quaryUri = MediaStore.Audio.Media.EXTERNAL_CONTENT_URI;}LogUtils.d("linlian quaryUri=$quaryUri")quaryUri?.let {val projection = arrayOf(MediaStore.Images.Media.DATA,MediaStore.Images.Media._ID)BaseApplication.instance.contentResolver.query(quaryUri,projection,MediaStore.Images.Media._ID + "=?",arrayOf<String>(id),null)?.use {cursor ->val columnNames = cursor.columnNamesLogUtils.d("linlian ", "URI: $uri")LogUtils.d("linlian ", "Total columns: ${columnNames.size}")// 遍历每一行while (cursor.moveToNext()) {
//                    val rowData = StringBuilder()// 遍历每一列
//                    for (columnName in columnNames) {
//                        val columnIndex = cursor.getColumnIndex(columnName)
//                        if (columnIndex == -1) {
//                            rowData.append("$columnName: [COLUMN_NOT_FOUND]\n")
//                            continue
//                        }
//
//                        val value = when (cursor.getType(columnIndex)) {
//                            Cursor.FIELD_TYPE_NULL -> "NULL"
//                            Cursor.FIELD_TYPE_INTEGER -> cursor.getLong(columnIndex)
//                            Cursor.FIELD_TYPE_FLOAT -> cursor.getDouble(columnIndex)
//                            Cursor.FIELD_TYPE_STRING -> cursor.getString(columnIndex)
//                            Cursor.FIELD_TYPE_BLOB -> "BLOB (${cursor.getBlob(columnIndex)?.size ?: 0} bytes)"
//                            else -> "UNKNOWN_TYPE"
//                        }
//                        rowData.append("$columnName: $value\n")
//                    }
//                    LogUtils.d("linlian", "Row ${cursor.position}:\n$rowData")val index= cursor.getColumnIndex(MediaStore.Images.Media.DATA)if(index!=-1){val path = cursor.getString(index)LogUtils.d("linlian", "!!!!!!!!!!$path")return path}LogUtils.d("linlian", "!!!!!!!!!!$index")}return null}}}return null
}

但是根据文档其实Android 10 之后是有新的字段,但是手机厂商众多,实现方式不一,还是找不到path怎么办,官方是说可以从 RELATIVE_PATH获取路径

contentResolver.query(uri, projection, null, null, null).use { cursor ->if (cursor != null && cursor.moveToFirst()) {// 获取文件名val nameIndex: Int = cursor.getColumnIndex(if (isImage) MediaStore.Images.Media.DISPLAY_NAME else MediaStore.Video.Media.DISPLAY_NAME)val displayName: String? =if ((nameIndex != -1)) cursor.getString(nameIndex) else null// 获取相对路径(可能为 null)val pathIndex: Int = cursor.getColumnIndex(if (isImage) MediaStore.Images.Media.RELATIVE_PATH else MediaStore.Video.Media.RELATIVE_PATH)val relativePath: String? =if ((pathIndex != -1)) cursor.getString(pathIndex) else nullLogUtils.d("linlian getPathFromRelativeColumn displayName=$displayName,relativePath=$relativePath")// 生成最终路径return buildPathForAndroidQ(displayName, relativePath)}}

如果以上都找不到path 怎么办呢

那最后的方式是,通过uri拷贝一份文件到应用目录,不过用完记得删除

fun copyFileFromUri(context: Context, uri: Uri, destFileName: String): File? {return try {// 打开输入流val inputStream: InputStream? = context.contentResolver.openInputStream(uri)if (inputStream == null) {return null}// 目标文件:保存在 app 的 filesDir 目录val destFile = File(context.filesDir, destFileName)val outputStream: OutputStream = FileOutputStream(destFile)// 拷贝数据val buffer = ByteArray(4096)var bytesRead: Intwhile (inputStream.read(buffer).also { bytesRead = it } != -1) {outputStream.write(buffer, 0, bytesRead)}// 关闭流inputStream.close()outputStream.close()destFile} catch (e: Exception) {e.printStackTrace()null}
}

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/diannao/78744.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

vue模拟扑克效果

vue模拟扑克效果 效果图&#xff1a; step1:C:\Users\wangrusheng\PycharmProjects\untitled18\src\views\Home.vue <template><div class"poker-container"><!-- 使用复合数据对象实现双行显示 --><divv-for"(card, index) in POKER_…

基础数学:图论与信息论

微积分与概率论由此进&#xff1a;基础数学&#xff1a;微积分和概率与统计-CSDN博客 线代与优化理论由此进&#xff1a;基础数学&#xff1a;线性代数与优化理论-CSDN博客 数值分析与离散数学由此进&#xff1a;基础数学&#xff1a;数值分析与离散数学-CSDN博客 四、图论与…

构建智能期货交易策略分析应用:MCP与AI的无缝集成

引言 随着金融科技的快速发展&#xff0c;数据驱动的交易决策已成为期货交易领域的重要趋势。本文将深入探讨一个结合了Model Content Protocol (MCP)和AI技术的期货交易策略分析应用——Futures MCP。该应用不仅提供了丰富的技术分析工具&#xff0c;还通过MCP协议与大型语言…

0x02.Redis 集群的实现原理是什么?

回答重点 Redis 集群&#xff08;Redis cluster&#xff09;是通过多个 Redis 实例组成的&#xff0c;每个主节点实例负责存储部分的数据&#xff0c;并且可以有一个或多个从节点作为备份。 具体是采用哈希槽&#xff08;Hash Slot&#xff09;机制来分配数据&#xff0c;将整…

基本的DOS命令

一.打开CMD方式&#xff1a; winR 输入cmd 开始系统命令提示符 在任意文件夹下&#xff0c;shift&#xff0b;鼠标右击&#xff0c;在此处打开命令 资源管理器的地址栏前面输入cmd 以管理员身份打开cmd&#xff1a;选择以管理员方式运行 二.常用的Dos命令 #盘符切换 盘符…

深度剖析:架构评估的常用方法与应用

架构评估是确保系统架构满足需求、性能和质量等方面要求的重要环节&#xff0c;以下是一些常见的架构评估方法的详细介绍&#xff1a; 一、基于调查问卷或检查表的评估方法 1.方法概述&#xff1a;该方法通过设计一系列针对性的问题或检查项&#xff0c;形成问卷或检查表&…

代码随想录算法训练营第十六天

LeetCode题目: 530. 二叉搜索树的最小绝对差501. 二叉搜索树中的众数236. 二叉树的最近公共祖先3272. 统计好整数的数目(每日一题) 其他: 今日总结 往期打卡 530. 二叉搜索树的最小绝对差 跳转: 530. 二叉搜索树的最小绝对差 学习: 代码随想录公开讲解 问题: 给你一个二叉搜…

基于双闭环PID控制器的永磁同步电机控制系统匝间故障Simulink仿真

欢迎微♥关注“电击小子程高兴的MATLAB小屋”获取巨额优惠 1.模型简介 本仿真模型基于MATLAB/Simulink&#xff08;版本MATLAB 2013Rb&#xff09;软件。建议采用matlab2013 Rb及以上版本打开。&#xff08;若需要其他版本可联系代为转换&#xff0c;高于该版本的matlab均可正…

02-libVLC的视频播放器:播放音视频文件以及网络流

libvlc_new(0, nullptr)功能:创建并初始化libVLC的核心实例,是使用所有libVLC功能的前提。 参数:第一个参数:参数数量(通常设为0)第二个参数:参数列表(通常为nullptr,表示使用默认配置)返回值:成功返回libvlc_instance_t*指针,失败返回nullptr。注意事项:可通过参…

2025蓝桥杯省赛C++B组解题思路

由于题面还没出来&#xff0c;现在先口胡一下思路 填空题直接打表找规律或者乱搞一下就能出&#xff0c;从大题开始说。 1&#xff0c;题意&#xff1a; 给你一个数组&#xff0c;这个数组里有几个数可以被一个连续递增的数字区间求和得出 思路&#xff1a;诈骗题&#xff0c;显…

防止邮件伪造的策略 SPF 介绍

SPF是Sender Policy Framework的缩写&#xff0c;即发件人策略框架&#xff0c;是一种用于防止电子邮件伪造的技术&#xff0c;用来验证发件人邮箱域名的真实性。以下是关于它的详细说明&#xff1a; 1. 定义与作用 SPF是一种电子邮件验证系统&#xff0c;它通过在域名的DNS记…

JavaScript Symbol与BigInt

目录 Symbol类型 一、Symbol 的核心特性 1. 唯一性 2. 不可变性 3. 不可枚举性 二、创建 Symbol 1. 基础创建 2. 全局 Symbol 注册表 三、Symbol 作为对象属性 1. 定义 Symbol 属性 2. 遍历 Symbol 属性 四、内置 Symbol 值 五、实际应用场景 1. 避免属性名冲突 …

AI Agent工程师认证-学习笔记(3)——【多Agent】MetaGPT

学习链接:【多Agent】MetaGPT学习教程 源代码链接(觉得很好,star一下):GitHub - 基于MetaGPT的多智能体入门与开发教程 MetaGPT链接:GitHub - MetaGPT 前期准备 1、获取MetaGPT (1)使用pip获取MetaGPT pip install metagpt==0.6.6#或者在国内加速安装镜像 #pip in…

【leetcode hot 100 416】分割等和子集

解法一&#xff1a;&#xff08;动态规划&#xff09;①定义&#xff1a;dp[i]表示是否可以在nums找到元素之和为i&#xff0c;dp[sum/21] ②初始状态&#xff1a;dp[0]true;dp[i]false ③状态转移方程&#xff1a;dp[i] dp[i] || dp[i - num]; class Solution {public boole…

高中数学联赛模拟试题精选第2套几何题(改编)

在 △ A B C \triangle ABC △ABC 中, 点 M M M 是边 A C AC AC 的中点. 在线段 A M AM AM, C M CM CM 上分别取点 P P P, Q Q Q, 使得 P Q A C / 2 PQAC/2 PQAC/2. 设 △ A B Q \triangle ABQ △ABQ 的外接圆与边 B C BC BC 相交于点 X X X, △ B C P \triangle …

UWB双通道隧道人员定位方案

技术基础&#xff1a;UWB&#xff08;超宽带技术&#xff09; 定义&#xff1a;UWB&#xff08;Ultra-Wideband&#xff09;是一种通过纳秒级窄脉冲传输数据的无线通信技术&#xff0c;占用500MHz以上的超宽频段。 核心优势&#xff1a; 高精度定位&#xff1a;时间分辨率极高&…

Linux 入门八:Linux 多进程

一、概述 1.1 什么是进程&#xff1f; 在 Linux 系统中&#xff0c;进程是程序的一次动态执行过程。程序是静态的可执行文件&#xff0c;而进程是程序运行时的实例&#xff0c;系统会为其分配内存、CPU 时间片等资源。例如&#xff0c;输入 ls 命令时&#xff0c;系统创建进程…

MTCNN 人脸识别

前言 此处介绍强大的 MTCNN 模块&#xff0c;给出demo&#xff0c;展示MTCNN 的 OOP&#xff0c; 以及ROS利用 C 节点&#xff0c;命令行调用脚本执行实际工作的思路。 MTCNN Script import argparse import cv2 from mtcnn import MTCNN import osclass MTCNNProcessor:def…

01_核心系统下的技术原理解析

15年前&#xff0c;基本上国内的核心系统被C垄断&#xff0c;基本上是IBM的那套东西&#xff0c;场景也是比价复杂&#xff0c;这里不再赘述&#xff0c;TPS太过于庞大&#xff0c;技术上确实比较复杂。为此我这里抛砖引玉&#xff0c;说下对应的支付系统&#xff1a; &#x…

Python 实现最小插件框架

文章目录 Python 实现最小插件框架1. 基础实现项目结构plugin_base.py - 插件基类plugins/hello.py - 示例插件1plugins/goodbye.py - 示例插件2main.py - 主程序 2. 更高级的特性扩展2.1 插件配置支持2.2 插件依赖管理2.3 插件热加载 3. 使用 setuptools 的入口点发现插件3.1 …