Android11图片和视频保存视频方案

一、简介

  • 软件都有着其生命周期,Android的更新换代也是很快的,每一年都会推出一个版本,AndroidQ与之前的版本有着比较大的改进,比如说文件存储强制要求使用沙盒模型,只能访问包名下的目录还有一些共享目录如Environment.DIRECTORY_DCIM、Environment.DIRECTORY_PICTURES、Environment.DIRECTORY_MOVIESD等(注:访问包名下的目录无需权限,共享目录需要权限),图片和视频的保存方式也发生了改变。

二、AndroidQ与其它版本图片和视频保存方式的差异

1、系统MediaStore ContentProvider数据存储字段的改变
  • 原来图片或视频的保存,存储的是图片的路径
values.put(ImageColumns.DATA, date);//图片或视频路径
  • AndroidQ以后则使用MediaColumns.RELATIVE_PATH(注:图片或视频存放的目录)
values.put(MediaColumns.RELATIVE_PATH, Environment.DIRECTORY_DCIM + File.separator + Constance.SYSTEM_CAMERA_FOLDER);//图片或视频保存的目录
2、AndroidQ只存储目录如何与图片视频文件相关联呢?
  • AndroidQ使用ContentResolver进行insert数据会返回uri,然后通过uri打开输出流再将图片或视频数据存入即可
uri = context.getContentResolver().insert(Images.Media.EXTERNAL_CONTENT_URI, values);
 if (null != uri) {
 	bitmap.compress(Bitmap.CompressFormat.JPEG, quality, context.getContentResolver().openOutputStream(uri));//使用uri打开输出流
  }

三、图片保存示例代码

  • AndroidQ保存图片示例
    public static void asynAddImageQ(final Context context, final Bitmap bitmap, final String path, final String fileName, final String mimeType,
                                     final long date, final Location location, final int quality, final int orientation
            , final int width, final int height,
                                     final OnScanCompletedListener listener) {
        QThreadExecutorProxy.getInstance().runOnAsyncThread(() -> {
            String title = fileName;
            if (title != null) {
                int index = title.lastIndexOf(".");
                if (index > 0) {
                    title = title.substring(0, index);
                }
            }
            ContentValues values = new ContentValues(9);
            values.put(ImageColumns.TITLE, title);
            values.put(ImageColumns.DISPLAY_NAME, fileName);
            values.put(ImageColumns.DATE_TAKEN, date);
            values.put(ImageColumns.MIME_TYPE, mimeType);
            values.put(ImageColumns.ORIENTATION, orientation);
            setImageSize(values, width, height);
            if (location != null) {
                values.put(ImageColumns.LATITUDE, location.getLatitude());
                values.put(ImageColumns.LONGITUDE, location.getLongitude());
            }
            values.put(MediaColumns.RELATIVE_PATH, Environment.DIRECTORY_DCIM + File.separator + Constance.SYSTEM_CAMERA_FOLDER);//AndroidQ存储目录
            Uri uri = null;
            try {
                uri = context.getContentResolver().insert(Images.Media.EXTERNAL_CONTENT_URI, values);
                if (null != uri) {
                    bitmap.compress(Bitmap.CompressFormat.JPEG, quality, context.getContentResolver().openOutputStream(uri));
                }
            } catch (Throwable th) {
                Log.e(TAG, "Failed to write MediaStore" + th);
            }
            if (listener != null) {
                listener.onScanCompleted(path + File.separator + fileName, uri, orientation);
            }
        });

    }

四、视频保存示例代码

  • AndroidQ保存视频示例
    public static void broadcastVideoFileQ(Context context, InputStream inputStream, String fileName, Location location,
                                           FolderHelper.OnScanCompletedListener listener) {
        try {
            long dateTaken = System.currentTimeMillis();
            ContentValues values = new ContentValues();
            values.put(Video.Media.TITLE, fileName);
            values.put(Video.Media.DISPLAY_NAME, fileName);
            values.put(Video.Media.DATE_TAKEN, dateTaken);
            values.put(Video.Media.DATE_MODIFIED, dateTaken / 1000);
            values.put(Video.Media.MIME_TYPE, "video/mp4");
            values.put(MediaStore.Video.Media.RELATIVE_PATH, Environment.DIRECTORY_DCIM + File.separator + Constance.SYSTEM_CAMERA_FOLDER);
            if (location != null) {
                values.put(Video.Media.LATITUDE, location.getLatitude());
                values.put(Video.Media.LONGITUDE, location.getLongitude());
            }
            Uri uri = context.getContentResolver()
                    .insert(Uri.parse(VIDEO_BASE_URI), values);
            if (uri != null) {
                try {
                    ParcelFileDescriptor pfd = context.getContentResolver().openFileDescriptor(uri, "rw", null);
                    //文件输出流
                    FileOutputStream outputStream = new FileOutputStream(pfd.getFileDescriptor());
                    int bufferSize = 1024;
                    byte[] buff = new byte[bufferSize];
                    int rc = 0;
                    try {
                        while ((rc = inputStream.read(buff, 0, bufferSize)) > 0) {
                            outputStream.write(buff, 0, rc);
                        }
                        outputStream.flush();
                        outputStream.close();
                        inputStream.close();
                    } catch (IOException e) {
                        e.printStackTrace();
                    }
                } catch (Exception e) {
                    e.printStackTrace();
                } finally {
                    if (listener != null) {
                        listener.onScanCompleted(FolderHelper.getOrCreateSaveLocation() + fileName, uri, 0);
                    }
                }
            } else {
                throw new RuntimeException();
            }

        } catch (Throwable tr) {
            tr.printStackTrace();
        }
    }

五、总结

1、 AndroidQ的图片视频保存其实只需要注意两点
  • MediaStore ContentProvider字段的改变原来是存储路径ImageColumns.DATA,现在是存储相对目录MediaColumns.RELATIVE_PATH
  • 使用ContentResolver进行insert生成uri后,在使用uri打开输出流,将图片或视频数据写入即可。
2、官方文档:访问共享存储空间中的媒体文件
  • 3
    点赞
  • 8
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值