适配7.0,Android 打开相册、拍照、裁剪图片的用法、细节处理

关于Android 7.0所需要做的权限适配

Android 7.0 之后对读取文件操作做了限制,如果不处理一个应用获取file://格式的URI的话,应用会抛出FileUriExposedException。这时我们需要用到Fileprovider,关于Fileprovider的用法 参考 这篇文章
  Android 7.0 Uri适配:

Uri uri;
if (Build.VERSION.SDK_INT >= 24) {
   uri = FileProvider.getUriForFile(context, "com.hjl.android7.fileprovider", file);
} else {
   uri = Uri.fromFile(file);
}

调用系统摄像头关键代码

imageUri: 需要传入适配后的Uri 这个Uri 保存拍照后的照片,可以在Activity 里面直接调用此方法,并且在 onActivityResult 回调方法中对Uri里的照片进行操作

public static void takePicture(Activity activity, Uri imageUri, int requestCode) {
   //调用系统相机  imageUri: 需要传入适配后的Uri 这个Uri 保存拍照后的照片 
   Intent intentCamera = new Intent();
   if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N) {
     intentCamera.addFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION); 
     //添加这一句表示对目标应用临时授权该Uri所代表的文件
   }
   intentCamera.setAction(MediaStore.ACTION_IMAGE_CAPTURE);
   
    //将拍照结果保存至photo_file的Uri中,不保留在相册中 
   intentCamera.putExtra(MediaStore.EXTRA_OUTPUT, imageUri);
   if (activity!=null){
      activity.startActivityForResult(intentCamera, requestCode);
   }
}

调用系统摄像头关键代码

public static void openPic(Activity activity, int requestCode) {
     Intent albumIntent = new Intent(Intent.ACTION_PICK, null);
     albumIntent.setDataAndType(MediaStore.Images.Media.EXTERNAL_CONTENT_URI, "image/*");  
     activity.startActivityForResult(albumIntent, requestCode);
 }

onActivityResult 回调方法中得到选取的图片Uri:

protected void onActivityResult(int requestCode, int resultCode, @Nullable Intent data) {
        Uri uri = data.getData();
        ... //拿到uri后就可以进行相应的处理了
}

拿到uri后就可以进行相应的处理了,例如转换成bitmap对象并缓存到本地:

File file = new File(FileUtils.getSDCachePath(),"test.png");
//缓存文件路径
try {
     OutputStream fos = new FileOutputStream(file);
     Bitmap bitmap = BitmapFactory.decodeStream(getContentResolver().openInputStream( data.getData() ));
     bitmap.compress(Bitmap.CompressFormat.PNG,100,fos);
     fos.flush();
     fos.close();
} catch (FileNotFoundException e) {
     e.printStackTrace();
}

裁剪图片关键代码

/**
* @param activity 当前activity
* @param orgUri 剪裁原图的Uri
* @param desUri 剪裁后的图片的Uri
* @param aspectX X方向的比例
* @param aspectY Y方向的比例
* @param width 剪裁图片的宽度
* @param height 剪裁图片高度
* @param requestCode 剪裁图片的请求码
*/
public static void cropImageUri(Activity activity, Uri orgUri, Uri desUri, int aspectX, int aspectY, int width, int height, int requestCode) {
   Intent intent = new Intent("com.android.camera.action.CROP");
   if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N) {
   intent.addFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION);
   }
   intent.setDataAndType(orgUri, "image/*");
   intent.putExtra("crop", "true");
   intent.putExtra("aspectX", aspectX);
   intent.putExtra("aspectY", aspectY);
   intent.putExtra("outputX", width);
   intent.putExtra("outputY", height);
   intent.putExtra("scale", true);
   //将剪切的图片保存到目标Uri中
   intent.putExtra(MediaStore.EXTRA_OUTPUT, desUri);
   intent.putExtra("return-data", false);
   intent.putExtra("outputFormat", Bitmap.CompressFormat.PNG.toString());
   intent.putExtra("noFaceDetection", true);
   intent.putExtra("scaleUpIfNeeded", true);//去除黑边
   activity.startActivityForResult(intent, requestCode);
}

注意:

  • 第一个坑:
    desUri 保存裁剪后的图片: 这个desUri是要使用Uri.fromFile(file)生成的,而不是使用 FileProvider.getUriForFile,否则会显示:“无法保存经过裁剪的图片”
    并且设置 intent.putExtra(MediaStore.EXTRA_OUTPUT, desUri); 输出的Uri之后,在onActivityResult 里通过 data.getData() 获取的Uri 会为空
  • 第二个坑:
    如果裁剪的图片像素过低,会出现黑边,解决方法:在上面的调用裁剪方法中加上下面两句
裁剪图片后出现黑边:
intent.putExtra("scale", true);//去除黑边
intent.putExtra("scaleUpIfNeeded", true);//去除黑边

附:Android 缓存本地文件各个路径小结

Android 缓存本地文件各个路径小结

参考文章

发布了27 篇原创文章 · 获赞 6 · 访问量 1667

猜你喜欢

转载自blog.csdn.net/weixin_41802023/article/details/90602450