本文是?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 | 一站式软件研发管理平台
|