Android 11 拍照+录制视频保存到外部共享区域

Posted 我不勤奋v

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Android 11 拍照+录制视频保存到外部共享区域相关的知识,希望对你有一定的参考价值。

本文是 Android 11 从外部存储读取文件到应用沙盒存储  和 Android 11 从沙盒拷贝文件到外部共享存储区域 实践篇。

 项目中我们有拍摄图片或者录制视频保存到外部共享存储区域的需求。

android 10之前,我们可以直接new File的形式访问外部存储区域的任意路径。

Android 10后,Google推出了沙盒机制,应用通过new File形式访问只能访问自己沙盒下路径;可以通过ContentResolver访问外部共享存储区域。

外部共享存储区域:主要是指Enviromnent下的 如

    Environment.DIRECTORY_DCIM
    Environment.DIRECTORY_DOCUMENTS
    Environment.DIRECTORY_DOWNLOADS
    Environment.DIRECTORY_MOVIES
    Environment.DIRECTORY_PICTURES
    Environment.DIRECTORY_MUSIC

等。
 

本文是关于调用系统拍照+录制视频并且保存到外部共享存储区域的demo,效果:

核心实现: 

 1. 调用系统拍照和录制视频的方法requestWriteImage()和requestWriteVideo()

 2. 拍照和录制视频保存到外部共享存储,android Q以上 需要通过ContentResolver获取uri :getImageUriAboveQ()和getVideoUriAboveQ()

public void requestWriteImage() 
        Intent intent = new Intent();
        intent.setAction(MediaStore.ACTION_IMAGE_CAPTURE);
        Uri mediaUri = null;
        if(Build.VERSION.SDK_INT >= Build.VERSION_CODES.Q) 
            mediaUri = getImgeUriAboveQ(mFragment.getActivity(), "Image_" + System.currentTimeMillis());
         else 
            File dicmFile = Environment.getExternalStoragePublicDirectory(Environment.DIRECTORY_DCIM);
            File mediaFile = new File(dicmFile.getAbsoluteFile() + "Image_" +  System.currentTimeMillis() +".jpg");
            mediaUri = Uri.fromFile(mediaFile);
        
        intent.putExtra(MediaStore.EXTRA_OUTPUT, mediaUri);
        mFragment.startActivityForResult(intent, REQUEST_CODE_WRITE_IMAGE);
    

    public void requestWriteVideo() 
        Intent intent = new Intent();
        intent.setAction("android.media.action.VIDEO_CAPTURE");
        intent.addCategory("android.intent.category.DEFAULT");
        Uri mediaUri = null;
        if(Build.VERSION.SDK_INT >= Build.VERSION_CODES.Q) 
            mediaUri = getVideoUriAboveQ(mFragment.getActivity(), "Video_" + System.currentTimeMillis());
         else 
            File dicmFile = Environment.getExternalStoragePublicDirectory(Environment.DIRECTORY_DCIM);
            File mediaFile = new File(dicmFile.getAbsoluteFile() + "Video_" +  System.currentTimeMillis() +".mp4");
            mediaUri = Uri.fromFile(mediaFile);
        
        intent.putExtra(MediaStore.EXTRA_OUTPUT, mediaUri);
        mFragment.startActivityForResult(intent, REQUEST_CODE_WRITE_VIDEO);
    

    private Uri getImgeUriAboveQ(Context context, String imageName) 
        if(Build.VERSION.SDK_INT < Build.VERSION_CODES.Q) 
            return null;
        
        Uri imageUri = null;
        ContentResolver resolver = context.getContentResolver();
        ContentValues values = new ContentValues();
        values.put(MediaStore.Images.Media.DISPLAY_NAME, imageName);//图片名
        values.put(MediaStore.Images.Media.DESCRIPTION, imageName); //描述
        values.put(MediaStore.Images.Media.MIME_TYPE, "image/jpeg");//类型
        values.put(MediaStore.Images.Media.RELATIVE_PATH, Environment.DIRECTORY_DCIM);//保存路径
        Uri externalUri = MediaStore.Images.Media.EXTERNAL_CONTENT_URI;
        imageUri = resolver.insert(externalUri, values);
        return imageUri;
    

    private Uri getVideoUriAboveQ(Context context, String videoName) 
        if(Build.VERSION.SDK_INT < Build.VERSION_CODES.Q) 
            return null;
        
        Uri videoUri = null;
        ContentResolver resolver = context.getContentResolver();
        ContentValues values = new ContentValues();
        values.put(MediaStore.Video.Media.DISPLAY_NAME, videoName);//视频名
        values.put(MediaStore.Video.Media.DESCRIPTION, videoName); //描述
        values.put(MediaStore.Images.Media.MIME_TYPE, "video/mp4");//类型
        values.put(MediaStore.Video.Media.RELATIVE_PATH, Environment.DIRECTORY_DCIM);//保存路径
        Uri externalUri = MediaStore.Video.Media.EXTERNAL_CONTENT_URI;
        videoUri = resolver.insert(externalUri, values);
        return videoUri;
    

3. 弹BottomSheetDialog调用requestWriteImage()和requestWriteVideo()

 public void showBottomSheetDialog() 
        bottomSheetDialog = new BottomSheetDialog(mFragment.getActivity());
        View dialogView= LayoutInflater.from(mFragment.getActivity())
                .inflate(R.layout.layout_bottom_sheet_image_video, null);
        TextView pictureTv= (TextView) dialogView.findViewById(R.id.picture_tv);
        TextView videoTv= (TextView) dialogView.findViewById(R.id.video_tv);
        TextView cancelTv= (TextView) dialogView.findViewById(R.id.cancel_tv);
        pictureTv.setOnClickListener(new View.OnClickListener() 
            @Override
            public void onClick(View v) 
                requestWriteImage();
                bottomSheetDialog.dismiss();
            
        );
        videoTv.setOnClickListener(new View.OnClickListener() 
            @Override
            public void onClick(View v) 
                requestWriteVideo();
                bottomSheetDialog.dismiss();
            
        );

        cancelTv.setOnClickListener(new View.OnClickListener() 
            @Override
            public void onClick(View v) 
                bottomSheetDialog.dismiss();
            
        );

        bottomSheetDialog.setContentView(dialogView);
        bottomSheetDialog.show();
    

Demo地址:

CODING | 一站式软件研发管理平台

以上是关于Android 11 拍照+录制视频保存到外部共享区域的主要内容,如果未能解决你的问题,请参考以下文章

Android 使用CameraX实现预览/拍照/录制视频/图片分析/对焦/缩放/切换摄像头等操作

Android20.3 拍照和视频录制

Android拍照丶录制视频功能实现

JCameraView 仿微信拍照Android控件(点击拍照,长按录小视频)

在 Android 上录制视频时拍照

Android拍照,录制视频,相机简单功能实现