1200字范文,内容丰富有趣,写作的好帮手!
1200字范文 > 兼容Android 11 相机拍照 从相册中选择 裁剪图片

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

时间:2018-08-26 18:07:54

相关推荐

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

由于android 11对存储空间进行了更新,导致无法进入裁剪或者裁剪后无法保存,返回路径等问题.

android 10以下可以参考:android 相机拍照,从相册中选择,裁剪图片

前面部分和之前的一样.

一,兼容android 7.0 在AndroidManifest.xml中先申请临时访问权限,样式和activity同级

<providerandroid:name="android.support.v4.content.FileProvider"android:authorities="${applicationId}.fileProvider"android:exported="false"android:grantUriPermissions="true"><meta-dataandroid:name="android.support.FILE_PROVIDER_PATHS"android:resource="@xml/file_paths"/></provider>

二,申请权限

<uses-permission android:name="android.permission.CAMERA" />

三,打开相机需要动态申请权限

1,可使用google提供的权限库easypermissions动态权限库:/googlesamples/easypermissions

详细用法自行百度,google

打开相机/相册

//mImagePath是保存图片的路径,建议放缓存路径,不用权限:getExternalCacheDir()private Uri photoOutputUri = FileProvider7.getUriForFile(this, new File(mImagePath));/*** 打开相机*/private void openCamera() {Intent intent = new Intent(MediaStore.ACTION_IMAGE_CAPTURE);intent.addFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION);//拍照图片保存到指定的路径intent.putExtra(MediaStore.EXTRA_OUTPUT, photoOutputUri);startActivityForResult(intent, 2);}/*** 打开相册*/private void openPhoto() {//调用android的图库Intent i = new Intent(Intent.ACTION_PICK, MediaStore.Images.Media.EXTERNAL_CONTENT_URI);startActivityForResult(i, 3);}

/*** 兼容android 7.0以上获取uri异常的工具类*/public class FileProvider7 {/*** 获取uri** @param context* @param file* @return*/public static Uri getUriForFile(Context context, File file) {Uri fileUri = null;try {if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.R) {ContentValues contentValues = new ContentValues();contentValues.put(MediaStore.Images.Media.DATA, file.getAbsolutePath());contentValues.put(MediaStore.Images.Media.DISPLAY_NAME, file.getName());contentValues.put(MediaStore.Images.Media.MIME_TYPE, "image/jpeg");fileUri = context.getContentResolver().insert(MediaStore.Images.Media.EXTERNAL_CONTENT_URI, contentValues);} else if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N) {fileUri = getUriForFile24(context, file);} else {fileUri = Uri.fromFile(file);}} catch (Exception e) {e.printStackTrace();}return fileUri;}/*** android 7.0以上获取uri的方法** @param context* @param file* @return*/private static Uri getUriForFile24(Context context, File file) {Uri fileUri = FileProvider.getUriForFile(context, BuildConfig.APPLICATION_ID + ".fileProvider", file);return fileUri;}/*** uri转Sting** @param context Context* @param uriUri* @param path 文件路径*/public static void getFilePathString(Context context, Uri uri, String path) {try {InputStream is = context.getContentResolver().openInputStream(uri);if (is == null) {return;}File file = new File(path);file.createNewFile();FileOutputStream fos = null;if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.R) {fos = new FileOutputStream(file);FileUtils.copy(is, fos);} else {ByteArrayOutputStream arrayOutputStream = new ByteArrayOutputStream();byte[] buffer = new byte[1024 * 10];while (true) {int len = is.read(buffer);if (len == -1) {break;}arrayOutputStream.write(buffer, 0, len);}arrayOutputStream.close();byte[] dataByte = arrayOutputStream.toByteArray();if (dataByte.length > 0) {fos = new FileOutputStream(file);fos.write(dataByte);}}if (fos != null)fos.close();if (is != null)is.close();} catch (IOException e) {e.printStackTrace();}}/*** 安装app的操作,兼容7.0** @param context* @param intent* @param type执行的意图(application/vnd.android.package-archive-->安装app)* @param file* @param writeAble 是否需要写操作*/public static void setIntentDataAndType(Context context, Intent intent, String type, File file, boolean writeAble) {if (Build.VERSION.SDK_INT >= 24) {intent.setDataAndType(getUriForFile(context, file), type);intent.addFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION);if (writeAble) {intent.addFlags(Intent.FLAG_GRANT_WRITE_URI_PERMISSION);}} else {intent.setDataAndType(Uri.fromFile(file), type);}}}

核心部分:android 11获取uri的方式通过ContentValues转换

拍照/相册成功后返回

@Overrideprotected void onActivityResult(int requestCode, int resultCode, Intent data) {super.onActivityResult(requestCode, resultCode, data);Intent intent;if (resultCode == RESULT_OK) {switch (requestCode) {//拍照完成,去裁剪case 2:if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.R) {intent = PhotoUtils.startPhotoZoom(photoOutputUri, photoOutputUri, 100);} else {intent = PhotoUtils.startPhotoZoom(photoOutputUri, mImagePath, 100);}startActivityForResult(intent, 4);break;//相册完成,去裁剪case 3:if (null != data) {if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.R) {intent = PhotoUtils.startPhotoZoom(data.getData(), photoOutputUri, 100);} else {intent = PhotoUtils.startPhotoZoom(data.getData(), mImagePath, 100);}startActivityForResult(intent, 4);}break;//裁剪完成,保存,上传case 4:new Thread(() -> {FileProvider7.getFilePathString(mContext, photoOutputUri, mImagePath);mHandler.sendEmptyMessage(UPDATA_MSG);}).start();break;default:break;}}}

public class PhotoUtils {/*** 调用系统裁剪** @param uri 需要裁剪的图片路径* @param mImagePath 图片输出路径* @param size 裁剪框大小*/public static Intent startPhotoZoom(Uri uri, Uri mImagePath, int size) {return startPhotoZoom(uri, mImagePath, size, size);}public static Intent startPhotoZoom(Uri uri, String mImagePath, int size) {return startPhotoZoom(uri, Uri.fromFile(new File(mImagePath)), size, size);}/*** 调用系统裁剪<br>* 注:华为手机默认** @param uri 需要裁剪的图片路径* @param mImagePath 图片输出路径* @param sizeX裁剪x* @param sizeY裁剪y*/public static Intent startPhotoZoom(Uri uri, Uri mImagePath, int sizeX, int sizeY) {Intent intent = new Intent("com.android.camera.action.CROP");if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N) {//添加这一句表示对目标应用临时授权该Uri所代表的文件intent.addFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION);//intent.addFlags(Intent.FLAG_GRANT_WRITE_URI_PERMISSION);}//裁剪后输出路径intent.putExtra(MediaStore.EXTRA_OUTPUT, mImagePath);//输入图片路径intent.setDataAndType(uri, "image/*");intent.putExtra("crop", "true");// intent.putExtra("circleCrop", "true");intent.putExtra("aspectX", 9998);///5/8 修复华为手机默认为圆角裁剪的问题intent.putExtra("aspectY", 9999);//intent.putExtra("outputX", sizeX);intent.putExtra("outputY", sizeY);intent.putExtra("scale", true);intent.putExtra("scaleUpIfNeeded", true);intent.putExtra("outputFormat", pressFormat.JPEG.toString());intent.putExtra("return-data", false);return intent;}}

裁剪完成返回的是uri,如果只是用于显示可以直接使用uri显示.如果需要上传,需要本地路径,就需要通过转换一下.

FileProvider7.getFilePathString(mContext, photoOutputUri, mImagePath);

mImagePath就是图片本地路径,可以用于显示,上传,保存等操作,由于进行了IO操作,建议在子线程处理.

笔记备忘, 请多指教

本内容不代表本网观点和政治立场,如有侵犯你的权益请联系我们处理。
网友评论
网友评论仅供其表达个人看法,并不表明网站立场。