Android保存照片到相册

前言

随着Android系统的不断升级 从最初的第一个版本 更新到现在 Android 11.0 Beta都出炉了 Android 11.0也即将面试 系统的不断更新完善 用户体验也是蹭蹭蹭的 隐私安全方面也是越来越给力了 这对用户当然是一级棒 对于开发者 简直无力吐槽 因为碎片化问题 加上版本更新迭代 废弃淘汰一堆 API 脑瓜子疼。

正文

这几天刚刚需要保存视频到相册 发现 我去 以前的方法好像不太给力了,磨了 我好久。。因为我手机是Android 10 版本 从用户隐私加强了 最大的变化就是 存储权限

Android 10 在外部存储设备中为每个应用提供了一个“隔离存储沙盒”(例如 /sdcard)。任何其他应用都无法直接访问您应用的沙盒文件。由于文件是您应用的私有文件,因此您不再需要任何权限即可在外部存储设备中访问和保存自己的文件。此变更可让您更轻松地保证用户文件的隐私性,并有助于减少应用所需的权限数量。

所以就是说我们不能直接访问 根目录 了? 其实 在Android 10 上还不是完全杜绝你使用的 你还是可以兼容低版本 那怎么做呢

<application...android:requestLegacyExternalStorage="true">
</application>

只需要在 你的AndroidManifest.xml 文件中 加入这行代码 意思就是申请旧版本的外部存储 那么你还是可与愉快玩耍的

可是旧版本的外部存储权限都已经废弃了 这样做是可以解决当前的问题 但是在Android 11 上 讲严格执行沙盒存储方式 也就是说 这样的代码在Android 11 上已经无法兼容了 并且的 10 的系统兼容也不够

撸码环节

那么开始撸代码把

/***保存bitmap*/
fun saveBitmap2Gallery(context: Context, bitmap: Bitmap): Boolean {val name=System.currentTimeMillis().toString()val photoPath=Environment.DIRECTORY_DCIM + "/Camera"val contentValues = ContentValues().apply {put(MediaStore.MediaColumns.DISPLAY_NAME,name )put(MediaStore.Images.Media.MIME_TYPE, "image/jpeg")put(MediaStore.MediaColumns.RELATIVE_PATH, photoPath)//保存路径put(MediaStore.MediaColumns.IS_PENDING, true)}if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.Q) {//返回出一个URIval insert = context.contentResolver.insert(MediaStore.Images.Media.EXTERNAL_CONTENT_URI,contentValues) ?: return false //为空的话 直接失败返回了//这个打开了输出流  直接保存图片就好了context.contentResolver.openOutputStream(insert).use {it ?: return falsebitmap.compress(Bitmap.CompressFormat.JPEG, 100, it)}return true} else {MediaStore.Images.Media.insertImage(context.contentResolver, bitmap, "title", "desc")return true}}

就上面的代码 可以直接保存了 如果不挑剔 应该是可以使用的了 但是发现一个问题 除了Android 10以上的 用 MediaStore 提示是废弃的 蒙蔽 为什么废弃呢 我们进入文档看看

inserting of images should be performed using {@link MediaColumns#IS_PENDING}, which offers richer control over lifecycle.

一看文档一脸懵逼 没看懂什么 各种查阅资料 百度一堆都是废弃的API。。。Android 这么难吗 保存个图片 都没有一个兼容的 完美的解决方案 或者 API 经过漫长的查询 种算看到眉目了 改良后的代码是这样的

 fun saveBitmap2Gallery2(context: Context, bitmap: Bitmap): Boolean {val name = System.currentTimeMillis().toString()val photoPath = Environment.DIRECTORY_DCIM + "/Camera"val contentValues = ContentValues().apply {put(MediaStore.MediaColumns.DISPLAY_NAME, name)put(MediaStore.Images.Media.MIME_TYPE, "image/jpeg")if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.Q) {put(MediaStore.MediaColumns.RELATIVE_PATH, photoPath)//保存路径put(MediaStore.MediaColumns.IS_PENDING, true)}}val insert = context.contentResolver.insert(MediaStore.Images.Media.EXTERNAL_CONTENT_URI,contentValues) ?: return false //为空的话 直接失败返回了//这个打开了输出流  直接保存图片就好了context.contentResolver.openOutputStream(insert).use {it ?: return falsebitmap.compress(Bitmap.CompressFormat.JPEG, 100, it)}if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.Q) {contentValues.put(MediaStore.MediaColumns.IS_PENDING, false)}return true}

是简单了好多 发现 在Android 10一下 只需要屏蔽 RELATIVE_PATHIS_PENDING 就可以了

但是发现一个问题 在Android 默认是保持在 /sdCard/Pictures/ 虽说也存放图片的地方 但是不是 /sdCard/DCIM/Camera小米 OV 等手机上 不能直接显示在照片里 而是在相册 中的 Pictures里 或者在全部照片也可以查到 这个问题我还是不知道怎么解决 因为 在使用 ContentValues 时 10.0以下的系统是不能设置路径的 那怎么办 可能还是的用废弃的 API 了 这里方法提供了 2种 自行选择最适合自己的 如果知道怎么保存到DCIM 欢迎评论区解答下

最后需要注意的是 在Android 10 中 保存到相册是不需要存储权限的 在6 - 9的版本中 需要存储权限

整合放出代码

object PhotoUtils {fun saveBitmap2Gallery(context: Context, bitmap: Bitmap): Boolean {if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.Q) {//返回出一个URIval insert = context.contentResolver.insert(MediaStore.Images.Media.EXTERNAL_CONTENT_URI,/*这里如果不写的话 默认是保存在 /sdCard/DCIM/Pictures*/ContentValues()//这里可以啥也不设置 保存图片默认就好了) ?: return false //为空的话 直接失败返回了//这个打开了输出流  直接保存图片就好了context.contentResolver.openOutputStream(insert).use {it ?: return falsebitmap.compress(Bitmap.CompressFormat.JPEG, 100, it)}return true} else {MediaStore.Images.Media.insertImage(context.contentResolver, bitmap, "title", "desc")return true}}fun saveFile2Gallery(context: Context, url: String): Boolean {if (true) {//返回出一个URIval insert = context.contentResolver.insert(MediaStore.Images.Media.EXTERNAL_CONTENT_URI,/*这里可以默认不写 默认保存在*/ContentValues()) ?: return false //为空的话 直接失败返回了//这个打开了输出流  直接保存图片就好了context.contentResolver.openOutputStream(insert).use { os ->os ?: return falsevar x = download(url, os)return x}return false} else {val externalFilesDir =context.getExternalFilesDir(Environment.DIRECTORY_DCIM) ?: return falsevar name = "${System.currentTimeMillis()}.jpg"val file = File(externalFilesDir, name)//下载文件到应用目录download(url, file.outputStream())MediaStore.Images.Media.insertImage(context.contentResolver,file.absolutePath,name,"desc")//刷新相册context.sendBroadcast(Intent(Intent.ACTION_MEDIA_SCANNER_SCAN_FILE,Uri.fromFile(File(file.getPath()))))return true}}fun saveFile2Gallery2(context: Context, url: String): Boolean {val name = System.currentTimeMillis().toString()val photoPath = Environment.DIRECTORY_DCIM + "/Camera"val contentValues = ContentValues().apply {put(MediaStore.MediaColumns.DISPLAY_NAME, name)put(MediaStore.Images.Media.MIME_TYPE, "image/jpeg")if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.Q) {put(MediaStore.MediaColumns.RELATIVE_PATH, photoPath)//保存路径put(MediaStore.MediaColumns.IS_PENDING, true)}}//返回出一个URIval insert = context.contentResolver.insert(MediaStore.Images.Media.EXTERNAL_CONTENT_URI,contentValues) ?: return false//这个打开了输出流  直接保存图片就好了context.contentResolver.openOutputStream(insert).use { os ->os ?: return falsevar x = download(url, os)if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.Q) {contentValues.put(MediaStore.MediaColumns.IS_PENDING, false)}return x}return false}fun saveBitmap2Gallery2(context: Context, bitmap: Bitmap): Boolean {val name = System.currentTimeMillis().toString()val photoPath = Environment.DIRECTORY_DCIM + "/Camera"val contentValues = ContentValues().apply {put(MediaStore.MediaColumns.DISPLAY_NAME, name)put(MediaStore.Images.Media.MIME_TYPE, "image/jpeg")if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.Q) {put(MediaStore.MediaColumns.RELATIVE_PATH, photoPath)//保存路径put(MediaStore.MediaColumns.IS_PENDING, true)}}val insert = context.contentResolver.insert(MediaStore.Images.Media.EXTERNAL_CONTENT_URI,contentValues) ?: return false //为空的话 直接失败返回了//这个打开了输出流  直接保存图片就好了context.contentResolver.openOutputStream(insert).use {it ?: return falsebitmap.compress(Bitmap.CompressFormat.JPEG, 100, it)}if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.Q) {contentValues.put(MediaStore.MediaColumns.IS_PENDING, false)}return true}private fun download(url: String, os: OutputStream): Boolean {val url = URL(url)(url.openConnection() as HttpURLConnection).also { conn ->conn.requestMethod = "GET"conn.connectTimeout = 5 * 1000if (conn.responseCode == 200) {conn.inputStream.use { ins ->val buf = ByteArray(2048)var len: Intwhile (ins.read(buf).also { len = it } != -1) {os.write(buf, 0, len)}os.flush()}return true} else {return false}}}}

Android保存照片到相册相关推荐

  1. React Native Android 保存网络图片到相册

    最近项目有个需求:保存网络图片到相册,IOS用CameraRoll很容易就实现了,Android稍微要麻烦点,思路是用库react-native-fetch-blob(版本0.10.8,也可以用其它库 ...

  2. Android 保存bitmap到相册

    安卓原生的保存相册方法可以用但是可调参数很少,对三星这样的手机支持不好,图片的创建时间一般为1970.1.1,可以通过复写android原生的方法来添加相关参数,比如照片创建时间和gps位置信息什么的 ...

  3. Android开发 拍照+读取相册+保存到本地

    Android Studio 新建项目,Minimum SDK选择API 28: android 9.0(Pie),在华为Mate20 Pro 测试通过. AndroidManifest.xml中添加 ...

  4. Android 中拍照、相册选择、裁剪照片

    一个多月没总结知识点了,差点连博客账号都忘了...好了,步入正题,在 Android 中调用摄像头拍照获取图片或者是从相册中选取图片是很常见的功能,比如某些 APP 上传头像的功能就是一个例子. ** ...

  5. android 地图相册,android开发实现view转bitmap保存到手机相册

    android开发实现view转bitmap保存到手机相册 直接贴代码,可以根据代码自行测试 //view转bitmap: public void SaveBitmapFromView(View vi ...

  6. 保存照片和视频到相册显示

    照片和视频保存到本地的方法大致都是通过流的方式写入文件里面就可以达到保存到文件夹的目的,但是你保存到文件夹的资源却不一定能够在相册显示出来,只能翻看文件管理. 怎么能够将保存到本地的照片视频显示在系统 ...

  7. 这4种照片千万不能保存在手机相册里,必须重视,避免损失

    在日常生活中,虽然手机给我们带来了很大的方便,但如果稍有不注意,也会有可能造成不必要的麻烦和损失,所以大家一定要切记手机里千万不要保存以下几种照片. 1.身份证照片 很多人出门办事为了图方便,会把身份 ...

  8. android拍照保存照片方向,Android:Camera2开发详解(上):实现预览、拍照、保存照片等功能...

    android.jpg 前言 在前几篇文章中介绍了如何调用系统相机拍照和使用Camera1的实现自定义相机拍照.人脸检测等功能 文章传送门: 接下来的几篇文章中,我将给大家介绍如何使用Camera2实 ...

  9. android 相册 恢复,Android手机照片恢复一例

    最近接到一部手机,需要恢复手机中删除的照片.手机型号为vivo X5Max+,系统为Funtouch OS 2.0(基于Android 4.4.4).尝试获取ROOT权限失败,尝试使用DC-4501工 ...

  10. android发广播更新相册,安卓保存视频和图片之后相册不刷新的问题总结

    最近在做项目中遇到保存照片和视频,本地已经保存而在相册和项目中不能找到,这里做一个简单的总结 在本地保存之后需要吧文件发送到本地或者广播的方式刷新相册 1.照片发送到相册 //把文件插入到系统图库 / ...

最新文章

  1. Web服务器的工作原理
  2. 本周学习进度表及时间安排(2018-1-7~2018-1-13)
  3. 2021-01-20 Matlab画图技巧与实例:堆叠图stackedplot
  4. scrapy-redis
  5. [css] style标签写在body前和body后的区别是什么?
  6. Python基础知识学习笔记——Matplotlib绘图
  7. 4核处理器_买电脑选4核、6核还是8核,从业是十年的专家终于讲清楚了差异
  8. Linux学习笔记009---Centos7安装vim ifconfig wget tree等基础命令
  9. 从数据库中导出数据库文档(新增了索引及表的描述信息)
  10. 本地远程查看服务器tomcat 上虚拟机信息
  11. dw怎么打开html模板,Dreamweaver怎样使用网页模板及修改模板
  12. css中iconfont图标旋转
  13. 为什么电脑屏幕会横过来_电脑屏幕倒过来了怎么办?电脑屏幕横过来了怎么办?...
  14. 2021年岳阳市高考成绩查询,2021年岳阳高考状元名单公布,岳阳文理科状元是谁多少分...
  15. python精灵和精灵组_Pygame精灵和精灵组
  16. 分水岭算法--语义分割
  17. Chrome浏览器更新
  18. DDNS动态域名解析IPv6地址
  19. php 加密解密方法,php加密方法与解密方法
  20. 加密狗突破之移花接木

热门文章

  1. 云计算与云原生 — ETCD 数据库完全解析
  2. 计算机专业基础820考什么,820计算机专业基础考纲
  3. asc和desc全称_MySQL数据排序asc、desc
  4. Spark安装与配置(单机版)(保姆级教程)
  5. linux服务器离线安装python第三方库
  6. 易语言之编译后图标模糊的处理方案
  7. 三次样条曲线拟合算法c语言,关于三次样条曲线拟合法
  8. 在Windows上将Ctrl+C信号发送到Python subprocess子进程
  9. 数字电路基础知识——时序逻辑电路之存储器(SRAM、DRAM、ROM)
  10. 高中物理知识补充——电容电感充放电极性判断