Android 10之前版本主要步骤

  1. 请求读写权限
  2. 图片/视频下载到/storage/emulated/0/Android/data/包名/xxx
  3. 复制到系统相册目录下
  4. 扫描媒体库

Android 10及以上版本主要步骤

  1. 请求读写权限
  2. 图片/视频下载到/storage/emulated/0/Android/data/包名/xxx
  3. 创建ContentValues,写入要保存的信息
  4. 调用ContentResolver插入ContentValues到相册中,此时会返回新创建的相册uri
  5. 将原先的文件复制到该uri中(android11及以上必须这么干)
  6. 发送广播,扫描媒体库

关键代码:

public class SaveUtils {private static final String TAG = "SaveUtils";/*** 将图片文件保存到系统相册*/public static boolean saveImgFileToAlbum(Context context, String imageFilePath) {Log.d(TAG, "saveImgToAlbum() imageFile = [" + imageFilePath + "]");try {Bitmap bitmap = BitmapFactory.decodeFile(imageFilePath);return saveBitmapToAlbum(context, bitmap);} catch (Exception e) {e.printStackTrace();return false;}}/*** 将bitmap保存到系统相册*/public static boolean saveBitmapToAlbum(Context context, Bitmap bitmap) {if (bitmap == null) return false;if (Build.VERSION.SDK_INT < Build.VERSION_CODES.Q) {return saveBitmapToAlbumBeforeQ(context, bitmap);} else {return saveBitmapToAlbumAfterQ(context, bitmap);}}@RequiresApi(api = Build.VERSION_CODES.Q)private static boolean saveBitmapToAlbumAfterQ(Context context, Bitmap bitmap) {Uri contentUri;if (Environment.getExternalStorageState().equals(Environment.MEDIA_MOUNTED)) {contentUri = MediaStore.Images.Media.EXTERNAL_CONTENT_URI;} else {contentUri = MediaStore.Images.Media.INTERNAL_CONTENT_URI;}ContentValues contentValues = getImageContentValues(context);Uri uri = context.getContentResolver().insert(contentUri, contentValues);if (uri == null) {return false;}OutputStream os = null;try {os = context.getContentResolver().openOutputStream(uri);bitmap.compress(Bitmap.CompressFormat.JPEG, 50, os);
//            if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
//                Files.copy(bitmapFile.toPath(), os);
//            }contentValues.clear();contentValues.put(MediaStore.MediaColumns.IS_PENDING, 0);context.getContentResolver().update(uri, contentValues, null, null);return true;} catch (Exception e) {context.getContentResolver().delete(uri, null, null);e.printStackTrace();return false;} finally {try {if (os != null) {os.close();}} catch (IOException e) {e.printStackTrace();}}}private static boolean saveBitmapToAlbumBeforeQ(Context context, Bitmap bitmap) {File picDir = Environment.getExternalStoragePublicDirectory(Environment.DIRECTORY_DCIM);File destFile = new File(picDir, context.getPackageName() + File.separator + System.currentTimeMillis() + ".jpg");
//            FileUtils.copy(imageFile, destFile.getAbsolutePath());OutputStream os = null;boolean result = false;try {if (!destFile.exists()) {destFile.getParentFile().mkdirs();destFile.createNewFile();}os = new BufferedOutputStream(new FileOutputStream(destFile));result = bitmap.compress(Bitmap.CompressFormat.JPEG, 50, os);if (!bitmap.isRecycled()) bitmap.recycle();} catch (IOException e) {e.printStackTrace();} finally {try {if (os != null) {os.close();}} catch (IOException e) {e.printStackTrace();}}MediaScannerConnection.scanFile(context,new String[]{destFile.getAbsolutePath()},new String[]{"image/*"},(path, uri) -> {Log.d(TAG, "saveImgToAlbum: " + path + " " + uri);// Scan Completed});return result;}/*** 获取图片的ContentValue** @param context*/@RequiresApi(api = Build.VERSION_CODES.Q)public static ContentValues getImageContentValues(Context context) {ContentValues contentValues = new ContentValues();contentValues.put(MediaStore.Images.Media.DISPLAY_NAME, System.currentTimeMillis() + ".jpg");contentValues.put(MediaStore.Images.Media.MIME_TYPE, "image/*");contentValues.put(MediaStore.Images.Media.RELATIVE_PATH, Environment.DIRECTORY_DCIM + File.separator + context.getPackageName());contentValues.put(MediaStore.MediaColumns.IS_PENDING, 1);contentValues.put(MediaStore.Images.Media.DATE_TAKEN, System.currentTimeMillis());contentValues.put(MediaStore.Images.Media.DATE_MODIFIED, System.currentTimeMillis());contentValues.put(MediaStore.Images.Media.DATE_ADDED, System.currentTimeMillis());return contentValues;}/*** 将视频保存到系统相册*/public static boolean saveVideoToAlbum(Context context, String videoFile) {Log.d(TAG, "saveVideoToAlbum() videoFile = [" + videoFile + "]");if (Build.VERSION.SDK_INT < Build.VERSION_CODES.Q) {return saveVideoToAlbumBeforeQ(context, videoFile);} else {return saveVideoToAlbumAfterQ(context, videoFile);}}private static boolean saveVideoToAlbumAfterQ(Context context, String videoFile) {try {ContentResolver contentResolver = context.getContentResolver();File tempFile = new File(videoFile);ContentValues contentValues = getVideoContentValues(context, tempFile, System.currentTimeMillis());Uri uri = contentResolver.insert(MediaStore.Video.Media.EXTERNAL_CONTENT_URI, contentValues);copyFileAfterQ(context, contentResolver, tempFile, uri);contentValues.clear();contentValues.put(MediaStore.MediaColumns.IS_PENDING, 0);context.getContentResolver().update(uri, contentValues, null, null);context.sendBroadcast(new Intent(Intent.ACTION_MEDIA_SCANNER_SCAN_FILE, uri));return true;} catch (Exception e) {e.printStackTrace();return false;}}private static boolean saveVideoToAlbumBeforeQ(Context context, String videoFile) {File picDir = Environment.getExternalStoragePublicDirectory(Environment.DIRECTORY_DCIM);File tempFile = new File(videoFile);File destFile = new File(picDir, context.getPackageName() + File.separator + tempFile.getName());FileInputStream ins = null;BufferedOutputStream ous = null;try {ins = new FileInputStream(tempFile);ous = new BufferedOutputStream(new FileOutputStream(destFile));long nread = 0L;byte[] buf = new byte[1024];int n;while ((n = ins.read(buf)) > 0) {ous.write(buf, 0, n);nread += n;}MediaScannerConnection.scanFile(context,new String[]{destFile.getAbsolutePath()},new String[]{"video/*"},(path, uri) -> {Log.d(TAG, "saveVideoToAlbum: " + path + " " + uri);// Scan Completed});return true;} catch (Exception e) {e.printStackTrace();return false;} finally {try {if (ins != null) {ins.close();}if (ous != null) {ous.close();}} catch (IOException e) {e.printStackTrace();}}}private static void copyFileAfterQ(Context context, ContentResolver localContentResolver, File tempFile, Uri localUri) throws IOException {if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.Q &&context.getApplicationInfo().targetSdkVersion >= Build.VERSION_CODES.Q) {//拷贝文件到相册的uri,android10及以上得这么干,否则不会显示。可以参考ScreenMediaRecorder的save方法OutputStream os = localContentResolver.openOutputStream(localUri);Files.copy(tempFile.toPath(), os);os.close();tempFile.delete();}}/*** 获取视频的contentValue*/public static ContentValues getVideoContentValues(Context context, File paramFile, long timestamp) {ContentValues localContentValues = new ContentValues();if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.Q) {localContentValues.put(MediaStore.Video.Media.RELATIVE_PATH, Environment.DIRECTORY_DCIM+ File.separator + context.getPackageName());}localContentValues.put(MediaStore.Video.Media.TITLE, paramFile.getName());localContentValues.put(MediaStore.Video.Media.DISPLAY_NAME, paramFile.getName());localContentValues.put(MediaStore.Video.Media.MIME_TYPE, "video/mp4");localContentValues.put(MediaStore.Video.Media.DATE_TAKEN, timestamp);localContentValues.put(MediaStore.Video.Media.DATE_MODIFIED, timestamp);localContentValues.put(MediaStore.Video.Media.DATE_ADDED, timestamp);localContentValues.put(MediaStore.Video.Media.SIZE, paramFile.length());return localContentValues;}}

android 11及以上保存图片视频到相册相关推荐

  1. Android webView长按保存图片到本地相册(队列下载实现)

    前言 自己写的app中 有大量的webView 在加载的过程中 新增了许多功能 比如 加载H5链接时 遇到有趣的图片 想长按保存下来是否可以呢 答案:"肯定是可以的" 网上有很多例 ...

  2. android应用开发实验报告_聚焦 Android 11: Android 11 应用兼容性

    作者 / Android 产品经理 Diana Wong在往期 #11WeeksOfAndroid 系列文章中我们介绍了联系人和身份.隐私和安全,本期将聚焦 Android 11 兼容性.我们将为大家 ...

  3. android照片视频备份,Android 保存图片或视频到相册并刷新相册

    在做项目时,有时会有这样的需求,需要将用户保存的图片和视频文件,能及时在相册中展示和查看,此时如果没有通知相册更新,就不会及时查看到相册中保存的这种图片.那么我们的应用程序如何通知相册刷新并且用户可以 ...

  4. android 视频相册,安卓11版本保存视频到相册,提示保存成功,相册里没有视频...

    安卓11版本,下载视频uni.downloadFile并保存到相册uni.saveImageToPhotosAlbum提示成功,但相册里没有视频 其他安卓版本和iphone,可以正常保存 save(v ...

  5. Android开发之刷新图片到相册 | 刷新视频到相册的方法区分发广播刷新方法

    我们很多app会有保存图片和保存视频,保存成功后一般在最近文件或者相册就能看到了,这个需要我们在保存文件后自行刷新到相册中,以前老版本方法通过广播刷新方法在API29中已经废弃了无法使用,咱们提供了新 ...

  6. 兼容Android 11 相机拍照,从相册中选择,裁剪图片

    由于android 11对存储空间进行了更新,导致无法进入裁剪或者裁剪后无法保存,返回路径等问题. android 10以下可以参考:android 相机拍照,从相册中选择,裁剪图片 前面部分和之前的 ...

  7. android 系统相册 多远,【系统相册】Android 保存图片到系统相册

    保存完图片后,可以在内存设备的文件系统相册目录下看到对应图片(以小米手机为例,系统相册的路径为:/storage/emulated/0/DCIM/Camera).但是,使用系统图库无法马上看到该图片, ...

  8. 直播视频app源码,保存图片到系统相册

    直播视频app源码,保存图片到系统相册相关的代码 public static void saveImageToGallery(Context context, Bitmap bmp) {// 首先保存 ...

  9. android 6.0获取图片地址,Android应用开发Android 保存图片到系统相册(三星6.0有效)...

    Android   保存图片到系统相册(三星6.0有效).今天要做一个保存图片到系统图库的功能,自身能力较浅,所以只能搜索了但发现网上的方法有几处bug,所以自己总结一下防止以后忘掉也想和大家分享一下 ...

最新文章

  1. 第十节 范围操作符(Range Operators)
  2. HAproxy七层负载均衡——环境搭建及实现过程详解
  3. 【项目管理】人力资源管理
  4. 需求分析的定义(转)
  5. java 中 的 字节流!
  6. java jvm调优_(第2部分,共3部分):有关性能调优,Java中的JVM,GC,Mechanical Sympathy等的文章和视频的摘要...
  7. carplant_mxnet
  8. 普通人有必要学新媒体吗?
  9. vue 调用移动录像_vue调用摄像头拍照 (移动)2020-11-18
  10. abb机器人编程指令写字_ABB 机器人编程指令.pdf
  11. Windows10-查询电脑mac地址
  12. 酷睿i3 10105参数 i3 10105功耗 i310105怎么样
  13. 【Linux 性能优化】利用perf和CPU使用率定位异常函数
  14. ffmpeg读取rtsp并保存到mp4文件
  15. js实现京东商城导航
  16. 小爱触屏音响用php接口,小米小爱触屏音箱:这个“闹钟”不简单
  17. 【微信小程序】自定义加载动画3
  18. 手把手带你实现第三方应用登录
  19. [ C语言 ] 结构体成员定义
  20. Day600601.马踏棋盘算法 -数据结构和算法Java

热门文章

  1. lodop设置html字体大小无效,LODOP设置纸张无效问题
  2. 新增商品(商品维护模块)
  3. 如何运用VR3d模型线上展示构建博物馆展厅与展馆
  4. 安装centos7.0时电脑进入黑屏的解决方法
  5. 【高德地图API】绘制大地线 Geodesic/Great Circles
  6. 各类文件的文件头标志[转]
  7. Windows之内存映射文件
  8. Android 升级/刷机攻略(Google原生系统Pixel)
  9. MySQL学习之路(一):使用命令行登录mysql的方式
  10. Rtos的调研分析报告