targetSdkVersion > 30 如何将下载的网络视频 保存到手机相册里更新
在 targetSdkVersion 31 中,将下载的网络视频保存到手机相册中涉及几个关键步骤。由于 Android 12(API 级别 31)引入了更多的隐私和安全限制,特别是作用域存储(Scoped Storage),因此你需要遵循这些限制来保存文件。
以下是将下载的网络视频保存到手机相册的步骤:
- 请求必要的权限:
- 对于网络下载,你可能需要
INTERNET权限。 - 对于保存到外部存储,你需要考虑作用域存储的限制。如果你的应用面向的是 Android 10(API 级别 29)及以上版本,并且你的应用没有声明
requestLegacyExternalStorage属性为true,则你需要使用MediaStoreAPI 来保存文件,并且不需要WRITE_EXTERNAL_STORAGE权限。
- 对于网络下载,你可能需要
- 下载视频文件:
- 使用适当的网络库(如 OkHttp, Retrofit, Volley 等)从网络下载视频文件。
- 将下载的视频文件保存到应用的私有目录(例如,使用
getExternalFilesDir(null)或getCacheDir())。
- 使用 MediaStore 保存视频到相册:
- 创建一个
ContentValues对象来存储视频文件的元数据。 - 使用
MediaStore.Video.Media.getExternalContentUri(MediaStore.VOLUME_EXTERNAL_PRIMARY)获取外部存储中视频内容的 URI。 - 调用
ContentResolver.insert()方法来创建一个新的视频条目。 - 使用
ContentResolver.openOutputStream()获取输出流,并将下载的视频文件数据写入该输出流。
- 创建一个
- 更新媒体数据库:
- 在视频文件写入后,你可能需要通知媒体扫描器扫描该文件,以便它出现在相册中。这可以通过发送一个
Intent来实现,使用MediaScannerConnection.SCAN_FILE_ACTION。
- 在视频文件写入后,你可能需要通知媒体扫描器扫描该文件,以便它出现在相册中。这可以通过发送一个
下面是一个简化的代码示例,展示了如何实现这一过程:
// 假设你已经从网络下载了视频,并且将其保存在了 privateDir 路径下
File videoFile = new File(privateDir, "downloaded_video.mp4"); // 使用 MediaStore API 保存视频到外部存储
ContentValues values = new ContentValues();
values.put(MediaStore.Video.Media.DISPLAY_NAME, videoFile.getName());
values.put(MediaStore.Video.Media.MIME_TYPE, "video/mp4");
values.put(MediaStore.Video.Media.RELATIVE_PATH, Environment.DIRECTORY_MOVIES); Uri collection = MediaStore.Video.Media.getExternalContentUri(MediaStore.VOLUME_EXTERNAL_PRIMARY);
Uri videoUri = getContentResolver().insert(collection, values); try (OutputStream outputStream = getContentResolver().openOutputStream(videoUri)) { Files.copy(videoFile.toPath(), outputStream);
} catch (IOException e) { e.printStackTrace();
} // 通知媒体扫描器扫描新文件
MediaScannerConnection.scanFile(this, new String[]{videoFile.toString()}, new String[]{"video/*"}, null);
请注意,由于作用域存储的限制,你可能无法直接将文件保存到公共目录(如 Environment.DIRECTORY_MOVIES)。如果你的应用没有请求 MANAGE_EXTERNAL_STORAGE 权限,或者用户没有授予该权限,你可能需要将文件保存到应用的私有目录,并通过 MediaStore 创建一个指向该文件的引用。
此外,始终确保你的应用遵循最新的 Android 存储最佳实践,并考虑到用户隐私和数据安全。
另外
在 Android 10(API 级别 29)及以上版本,由于作用域存储(Scoped Storage)的引入,直接获取文件在外部存储的完整路径变得不再直接可行。相反,您应该使用 ContentResolver 和 ContentValues 将文件保存到 MediaStore,并通过返回的 Uri 来引用它。这样,视频文件就可以被其他应用(如相册)访问,而不需要知道其实际存储路径。
以下是一个示例,展示了如何将下载的视频保存到 MediaStore 并获取其 Uri:
private Uri saveVideoToMediaStore(Context context, File videoFile) throws IOException { // 创建一个 ContentValues 对象来存储视频文件的元数据 ContentValues values = new ContentValues(); values.put(MediaStore.Video.Media.DISPLAY_NAME, videoFile.getName()); values.put(MediaStore.Video.Media.MIME_TYPE, "video/mp4"); values.put(MediaStore.Video.Media.RELATIVE_PATH, Environment.DIRECTORY_MOVIES); // 获取外部存储中视频内容的 Uri Uri collection = MediaStore.Video.Media.getExternalContentUri(MediaStore.VOLUME_EXTERNAL_PRIMARY); // 使用 ContentResolver 插入一个新的视频条目到 MediaStore Uri videoUri = context.getContentResolver().insert(collection, values); // 使用 ContentResolver 打开一个输出流来写入视频文件 try (OutputStream outputStream = context.getContentResolver().openOutputStream(videoUri)) { Files.copy(videoFile.toPath(), outputStream); } // 通知媒体扫描器扫描新文件,使其出现在相册中 MediaScannerConnection.scanFile(context, new String[]{videoFile.getAbsolutePath()}, new String[]{"video/*"}, null); return videoUri;
}
在这个示例中,videoUri 就是您需要的 Uri,它代表了保存在 MediaStore 中的视频文件。您可以使用这个 Uri 来在其他地方引用该视频,例如在一个 Intent 中传递给相册应用。
请注意,由于作用域存储的限制,您无法直接从这个 Uri 获取文件的完整路径。如果您需要这个路径用于某些特定的操作(比如在其他应用中分享文件),您可能需要使用 FileProvider 来创建一个临时访问权限的 Uri。
如果您确实需要获取视频文件的路径用于某些特殊情况(比如备份到云存储),您可以使用 ContentResolver 和 openFileDescriptor 方法来获取一个 ParcelFileDescriptor,然后从中获取文件描述符,并最终转换为 File 对象。但请注意,这样做可能会违反 Android 的隐私政策,因此应该谨慎使用,并确保您的应用遵循了所有的最佳实践和隐私指南。
如果您的应用需要兼容低版本的 Android(低于 API 级别 29),您可能需要采用不同的方法来保存视频到外部存储,因为作用域存储(Scoped Storage)在这些版本上不可用。在这种情况下,您可能需要请求 WRITE_EXTERNAL_STORAGE 权限,并将文件直接保存到公共目录(如 /sdcard/DCIM/Camera/)中。
以下是一个兼容低版本的示例,展示如何保存视频到外部存储并获取其路径:
private String saveVideoToExternalStorage(Context context, File videoFile) { // 确保有写入外部存储的权限 if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.Q) { if (ContextCompat.checkSelfPermission(context, Manifest.permission.WRITE_EXTERNAL_STORAGE) != PackageManager.PERMISSION_GRANTED) { // 请求写入外部存储的权限 ActivityCompat.requestPermissions( (Activity) context, new String[]{Manifest.permission.WRITE_EXTERNAL_STORAGE}, MY_PERMISSIONS_REQUEST_WRITE_EXTERNAL_STORAGE); // 等待用户授权 return null; } } else { // 对于低于 Android 10 的版本,您可以在 AndroidManifest.xml 中声明权限 } // 获取外部存储的目录 File externalStorageDir = Environment.getExternalStoragePublicDirectory(Environment.DIRECTORY_MOVIES); if (!externalStorageDir.exists()) { if (!externalStorageDir.mkdirs()) { Log.e("VideoSave", "Failed to create directory"); return null; } } // 将视频文件复制到外部存储的目录 File destinationFile = new File(externalStorageDir, videoFile.getName()); try { Files.copy(videoFile.toPath(), destinationFile.toPath()); return destinationFile.getAbsolutePath(); } catch (IOException e) { e.printStackTrace(); return null; }
}
在这个示例中,我们首先检查应用是否有写入外部存储的权限。如果没有,我们会请求这个权限。一旦获得权限,我们就将视频文件复制到外部存储的 /sdcard/Movies/ 目录下,并返回文件的绝对路径。
请注意,从 Android 10(API 级别 29)开始,推荐的做法是使用 MediaStore API,因为它提供了更好的隐私控制和兼容性。如果您的应用需要支持 Android 10 及更高版本,强烈建议使用 MediaStore 方法。如果您的应用需要兼容低版本,并且您确定您的用户主要使用这些低版本设备,那么您可以使用上述方法。但请记住,随着时间的推移,低版本设备的用户群体可能会逐渐减少,因此最好尽可能使用最新的 API 和实践。
相关文章:
targetSdkVersion > 30 如何将下载的网络视频 保存到手机相册里更新
在 targetSdkVersion 31 中,将下载的网络视频保存到手机相册中涉及几个关键步骤。由于 Android 12(API 级别 31)引入了更多的隐私和安全限制,特别是作用域存储(Scoped Storage),因此你需要遵循这…...
C#,无监督的K-Medoid聚类算法(K-Medoid Algorithm)与源代码
1 K-Medoid算法 K-Medoid(也称为围绕Medoid的划分)算法是由Kaufman和Rousseeuw于1987年提出的。中间点可以定义为簇中的点,其与簇中所有其他点的相似度最小。 K-medoids聚类是一种无监督的聚类算法,它对未标记数据中的对象进行聚…...
宏定义中#与##的注意事项
1. #是字符串化操作符。它的作用是将宏参数转换成字符串 2. ##是标记粘贴操作符。它的作用是将两个标记连接起来形成一个新的标记 #define TEST1(a) #a #define TEST2(a) b##a/***********************************************************/ 举例:TEST1(hello) 会…...
Java函数式编程
Java函数式编程 Java函数式编程(Functional Programming in Java)是指使用函数式编程范式来编写Java代码的一种编程方式。函数式编程是一种编程范式,它强调使用函数作为基本构建块,并将计算视为数学上的函数求值,避免…...
【深度优先搜索】【树】【C++算法】2003. 每棵子树内缺失的最小基因值
作者推荐 动态规划的时间复杂度优化 本文涉及知识点 深度优先搜索 LeetCode2003. 每棵子树内缺失的最小基因值 有一棵根节点为 0 的 家族树 ,总共包含 n 个节点,节点编号为 0 到 n - 1 。给你一个下标从 0 开始的整数数组 parents ,其中…...
电脑开机显示器没有信号而且键盘鼠标不亮怎么解决?
大家在使用电脑的过程,开机没有反应是比较经常遇到的问题,就有用户反映说自己的电脑启动之后,显示器无信号,键盘鼠标灯也不亮,怎么操作都没有效果。对开机有影响的硬件主要是内存条,内存条是非常容易松动的,而且金手指如果氧化了,都会导致开不了机 大家在使用电脑的过程…...
RLWE同态加密编码打包——系数打包
RLWE同态加密的明文域 RLWE的加密方案,如BGV、BFV,加密的对象,实际上是分圆多项式环上的一个整系数多项式。而我们在平时接触到的需要加密的数据,如图像或者工资,通常是一个数。所以,在使用RLWE同态加密时…...
Codeforces Round 930 (Div. 2 ABCDEF题) 视频讲解
A. Shuffle Party Problem Statement You are given an array a 1 , a 2 , … , a n a_1, a_2, \ldots, a_n a1,a2,…,an. Initially, a i i a_ii aii for each 1 ≤ i ≤ n 1 \le i \le n 1≤i≤n. The operation swap ( k ) \texttt{swap}(k) swap(k) for an…...
【LeetCode-中等】209.长度最小的子数组-双指针/滑动窗口
力扣题目链接 1. 暴力解法 这道题的暴力解法是两层嵌套for循环,第一层循环从 i 0 开始遍历至数组末尾,第二层循环从 j i 开始遍历至找到总和大于等于 target 的连续子数组,并将该连续子数组的长度与之前找到的子数组长度相比较࿰…...
MACOS/LINUX/WINDOWS C++ 获取当前可执行程序的完整路径
依赖本人写的多平台编译器宏判断: C/C MACOS、Windows、Linux、HarmonyOS 平台宏判断-CSDN博客 MACOS头文件依赖: #if defined(_MACOS) #include <libproc.h> #endif #include <mach-o/dyld.h> 只需要链接 libSystem.dylib 就行了&#…...
【Nginx笔记02】通过Nginx服务器转发客户端的WebSocket接口到后端服务
这篇文章,主要介绍如何通过Nginx服务器转发客户端的WebSocket接口到后端服务【知识星球】。 目录 一、Nginx配置WebSocket 1.1、Nginx配置内容 1.2、客户端请求地址 1.3、创建WebSocket测试工程 1.4、启动测试 1.5、WebSocket超时问题 1.5.1、设置超时时间 …...
关于高德地图及其APP获取地图数据的研究
刚过完春节没几天,有个客户提出要获取高德地图的数据。 我看了下,回复说:这不是很简单嘛,高德有公开的开放平台,有足够的API支持用户获取数据,开发自己基于高德数据库的应用。 客户回复说:他的要…...
【Python入门教程】Python实现鸡兔同笼
今天跟大家分享一下很久之前自己做的鸡兔同笼求解问题的小游戏,使用公式和基本的判断语句即可实现,可以用来当练手或者消磨时间用。 大家在编代码的时候最重要就是先理清逻辑思路,例如应该套几层循环、分几个模块等等。然后在编码时可以先随意…...
微信小程序,h5端自适应登陆方式
微信小程序端只显示登陆(获取opid),h5端显示通过账户密码登陆 例如: 通过下面的变量控制: const isWeixin ref(false); // #ifdef MP-WEIXIN isWeixin.value true; // #endif...
物体检测-系列教程20:YOLOV5 源码解析10 (Model类前向传播、forward_once函数、_initialize_biases函数)
😎😎😎物体检测-系列教程 总目录 有任何问题欢迎在下面留言 本篇文章的代码运行界面均在Pycharm中进行 本篇文章配套的代码资源已经上传 点我下载源码 14、Model类 14.2 前向传播 def forward(self, x, augmentFalse, profileFalse):if augm…...
贪吃蛇(C语言)步骤讲解
一:文章大概 使用C语言在windows环境的控制台中模拟实现经典小游戏 实现基本功能: 1.贪吃蛇地图绘制 2.蛇吃食物的功能(上,下,左,右方向控制蛇的动作) 3.蛇撞墙死亡 4.计算得分 5.蛇身加…...
MySQL 数据库表设计和优化
一、数据结构设计 正确的数据结构设计对数据库的性能是非常重要的。 在设计数据表时,尽量遵循一下几点: 将数据分解为合适的表,每个表都应该有清晰定义的目的,避免将过多的数据存储在单个表中。使用适当的数据类型来存储数据&…...
JavaScript进阶-高阶技巧
文章目录 高阶技巧深浅拷贝浅拷贝深拷贝 异常处理throw抛异常try/caych捕获异常debugger 处理thisthis指向改变this 性能优化防抖节流 高阶技巧 深浅拷贝 只针对引用类型 浅拷贝 拷贝对象后,里面的属性值是简单数据类型直接拷贝值,如果属性值是引用数…...
C语言中“#“和“##“的用法
1. 前言 # :把宏参数变为一个字符串, ##:把两个宏参数贴合在一起. 2. 一般用法 #include<stdio.h> #define toString(str) #str //转字符串 #define conStr(a,b) (a##b)//连接 int main() { printf(toString(12345)): //输出字符串&q…...
Linux命令-clock命令(用于调整 RTC 时间)
说明 clock命令用于调整 RTC 时间。 RTC 是电脑内建的硬件时间,执行这项指令可以显示现在时刻,调整硬件时钟的时间,将系统时间设成与硬件时钟之时间一致,或是把系统时间回存到硬件时钟。 语法 clock [--adjust][--debug][--dir…...
【Python】 -- 趣味代码 - 小恐龙游戏
文章目录 文章目录 00 小恐龙游戏程序设计框架代码结构和功能游戏流程总结01 小恐龙游戏程序设计02 百度网盘地址00 小恐龙游戏程序设计框架 这段代码是一个基于 Pygame 的简易跑酷游戏的完整实现,玩家控制一个角色(龙)躲避障碍物(仙人掌和乌鸦)。以下是代码的详细介绍:…...
Linux 文件类型,目录与路径,文件与目录管理
文件类型 后面的字符表示文件类型标志 普通文件:-(纯文本文件,二进制文件,数据格式文件) 如文本文件、图片、程序文件等。 目录文件:d(directory) 用来存放其他文件或子目录。 设备…...
java调用dll出现unsatisfiedLinkError以及JNA和JNI的区别
UnsatisfiedLinkError 在对接硬件设备中,我们会遇到使用 java 调用 dll文件 的情况,此时大概率出现UnsatisfiedLinkError链接错误,原因可能有如下几种 类名错误包名错误方法名参数错误使用 JNI 协议调用,结果 dll 未实现 JNI 协…...
什么是库存周转?如何用进销存系统提高库存周转率?
你可能听说过这样一句话: “利润不是赚出来的,是管出来的。” 尤其是在制造业、批发零售、电商这类“货堆成山”的行业,很多企业看着销售不错,账上却没钱、利润也不见了,一翻库存才发现: 一堆卖不动的旧货…...
Psychopy音频的使用
Psychopy音频的使用 本文主要解决以下问题: 指定音频引擎与设备;播放音频文件 本文所使用的环境: Python3.10 numpy2.2.6 psychopy2025.1.1 psychtoolbox3.0.19.14 一、音频配置 Psychopy文档链接为Sound - for audio playback — Psy…...
ardupilot 开发环境eclipse 中import 缺少C++
目录 文章目录 目录摘要1.修复过程摘要 本节主要解决ardupilot 开发环境eclipse 中import 缺少C++,无法导入ardupilot代码,会引起查看不方便的问题。如下图所示 1.修复过程 0.安装ubuntu 软件中自带的eclipse 1.打开eclipse—Help—install new software 2.在 Work with中…...
多模态大语言模型arxiv论文略读(108)
CROME: Cross-Modal Adapters for Efficient Multimodal LLM ➡️ 论文标题:CROME: Cross-Modal Adapters for Efficient Multimodal LLM ➡️ 论文作者:Sayna Ebrahimi, Sercan O. Arik, Tejas Nama, Tomas Pfister ➡️ 研究机构: Google Cloud AI Re…...
tree 树组件大数据卡顿问题优化
问题背景 项目中有用到树组件用来做文件目录,但是由于这个树组件的节点越来越多,导致页面在滚动这个树组件的时候浏览器就很容易卡死。这种问题基本上都是因为dom节点太多,导致的浏览器卡顿,这里很明显就需要用到虚拟列表的技术&…...
Fabric V2.5 通用溯源系统——增加图片上传与下载功能
fabric-trace项目在发布一年后,部署量已突破1000次,为支持更多场景,现新增支持图片信息上链,本文对图片上传、下载功能代码进行梳理,包含智能合约、后端、前端部分。 一、智能合约修改 为了增加图片信息上链溯源,需要对底层数据结构进行修改,在此对智能合约中的农产品数…...
Python基于历史模拟方法实现投资组合风险管理的VaR与ES模型项目实战
说明:这是一个机器学习实战项目(附带数据代码文档),如需数据代码文档可以直接到文章最后关注获取。 1.项目背景 在金融市场日益复杂和波动加剧的背景下,风险管理成为金融机构和个人投资者关注的核心议题之一。VaR&…...
