Android设备上获取照片裁剪图片压缩图片

Posted narkang

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Android设备上获取照片裁剪图片压缩图片相关的知识,希望对你有一定的参考价值。

前言

在做上一个项目时深深受到了图片上传的苦恼。图片上传主要分为两个部分,首先要获取图片,而获取图片可以分为从文件获取或者拍照获取。第二个部分才是上传图片,两个部分都是走了不少弯路。由于android系统的碎片化比较严重,我们可能出现在第一台机子上能获取图片,但是换一个机子就不能获取图片的问题,并且在Android6.0,7.0之后也要做一定的适配,这样对于开发者来说,无疑很蛋疼。由于也是初学者,很多东西没有考虑到,适配起来也是有点难度的。

这几天也是从github上找到了一个库(地址在这TakePhoto),经过简单的学习之后,发现用起来还是蛮简单的,并且在不同机型之间都能达到同样的效果。更重要的是可以根据不同配置达到不同的效果

接下来看下用法

获取图片

1) 获取TakePhoto对象

一) 通过继承的方式

  • 继承TakePhotoActivity、TakePhotoFragmentActivity、TakePhotoFragment三者之一。
  • 通过getTakePhoto()获取TakePhoto实例进行相关操作。
  • 重写以下方法获取结果
 void takeSuccess(TResult result);
 void takeFail(TResult result,String msg);
 void takeCancel();

这种方法使用起来虽然简单,但是感觉定制性不高,必须继承指定的Activity,而 有时我们已经封装好了BaseActivity,不想再改了。有时候通过继承无法满足实际项目的需求。

二) 通过组装的方式去使用

  • 实现TakePhoto.TakeResultListener,InvokeListener接口。
  • 在 onCreate,onActivityResult,onSaveInstanceState方法中调用TakePhoto对用的方法。
  • 重写onRequestPermissionsResult(int requestCode, String[] permissions, int[] grantResults),添加如下代码。
  @Override
    public void onRequestPermissionsResult(int requestCode, String[] permissions, int[] grantResults) {
        super.onRequestPermissionsResult(requestCode, permissions, grantResults);
        //以下代码为处理Android6.0、7.0动态权限所需
        TPermissionType type=PermissionManager.onRequestPermissionsResult(requestCode,permissions,grantResults);
        PermissionManager.handlePermissionsResult(this,type,invokeParam,this);
    }
  • 重写TPermissionType invoke(InvokeParam invokeParam)方法,添加如下代码:
 @Override
    public TPermissionType invoke(InvokeParam invokeParam) {
        TPermissionType type=PermissionManager.checkPermission(TContextWrap.of(this),invokeParam.getMethod());
        if(TPermissionType.WAIT.equals(type)){
            this.invokeParam=invokeParam;
        }
        return type;
    }
  • 添加如下代码获取TakePhoto实例:
   /**
     *  获取TakePhoto实例
     * @return
     */
    public TakePhoto getTakePhoto(){
        if (takePhoto==null){
            takePhoto= (TakePhoto) TakePhotoInvocationHandler.of(this).bind(new TakePhotoImpl(this,this));
        }
        return takePhoto;
    }    

2)自定义UI

不仅可以对于参数自定义,也可以对于UI的自定义,比如自定义相册,自定义Toolbar, 自定义状态栏,自定义提示文字,自定义裁切工具(需要使用自带的TakePhoto裁剪才行)。

3)通过TakePhoto对象获取图片

支持从相册获取,也支持拍照,相关Api

 * 从相机获取图片并裁剪
 * @param outPutUri 图片裁剪之后保存的路径
 * @param options 裁剪配置             
 */
void onPickFromCaptureWithCrop(Uri outPutUri, CropOptions options);
/**
 * 从相册中获取图片并裁剪
 * @param outPutUri 图片裁剪之后保存的路径
 * @param options 裁剪配置
 */
void onPickFromGalleryWithCrop(Uri outPutUri, CropOptions options);
/**
 * 从文件中获取图片并裁剪
 * @param outPutUri 图片裁剪之后保存的路径
 * @param options 裁剪配置
 */
void onPickFromDocumentsWithCrop(Uri outPutUri, CropOptions options);
/**
 * 图片多选,并裁切
 * @param limit 最多选择图片张数的限制
 * @param options  裁剪配置
 * */
void onPickMultipleWithCrop(int limit, CropOptions options);

4)裁剪配置

  • CropOptions 用于裁剪的配置类,可以对图片的裁剪比例,最大输出大小,以及是否使用TakePhoto自带的裁剪工具进行裁剪等,进行个性化配置。

  • 压缩图片 onEnableCompress(CompressConfig config,boolean showCompressDialog)

  • 指定压缩工具 takePhoto里面自带压缩算法,也可以通过第三方的Luban进行压缩

对于TakePhoto的二次封装

封装是对第二种方法的封装,主要参考了第一种的思想封装的。
关于TakePhoto的库代码全部封装到一个TakePhotoUtil工具类中,看代码:

public class TakePhotoUtil implements TakePhoto.TakeResultListener, InvokeListener {

    private static final String TAG = TakePhotoUtil.class.getName();
    private TakePhoto takePhoto;
    private InvokeParam invokeParam;
    private Activity activity;
    private Fragment fragment;

    public TakePhotoUtil(Activity activity){
        this.activity = activity;
    }

    public TakePhotoUtil(Fragment fragment){
        this.fragment = fragment;
    }

    /**
     *  获取TakePhoto实例
     * @return
     */
    public TakePhoto getTakePhoto(){
        if (takePhoto==null){
            takePhoto= (TakePhoto) TakePhotoInvocationHandler.of(this).bind(new TakePhotoImpl(activity,this));
        }
        return takePhoto;
    }

    public void onCreate(Bundle savedInstanceState){
        getTakePhoto().onCreate(savedInstanceState);
    }

    public void onSaveInstanceState(Bundle outState){
        getTakePhoto().onSaveInstanceState(outState);
    }

    public void onActivityResult(int requestCode, int resultCode, Intent data){
        getTakePhoto().onActivityResult(requestCode, resultCode, data);
    }

    public void onRequestPermissionsResult(int requestCode, String[] permissions, int[] grantResults) {
        PermissionManager.TPermissionType type=PermissionManager.onRequestPermissionsResult(requestCode,permissions,grantResults);
        PermissionManager.handlePermissionsResult(activity,type,invokeParam,this);
    }

    /**
     *
     * @param result
     */
    @Override
    public void takeSuccess(TResult result) {
        if(listener != null){
            listener.takeSuccess(result);
        }
//        deleteCachePic();
    }

    @Override
    public void takeFail(TResult result, String msg) {
        if(listener != null){
            listener.takeFail(result, msg);
        }
//        deleteCachePic();
    }

    @Override
    public void takeCancel() {
        if(listener != null){
            listener.takeCancel();
        }
    }

    public void deleteCachePic(){
        File file=new File(Environment.getExternalStorageDirectory(), "/takephoto/");
        if(!file.exists()) return;

        File[] files = file.listFiles();
        for (File f: files) {
            f.delete();
        }
    }

    public interface TakePhotoListener{
        void takeSuccess(TResult result);
        void takeFail(TResult result, String msg);
        void takeCancel();
    }

    public TakePhotoListener listener;

    public void setTakePhotoListener(SimpleTakePhotoListener listener){
        this.listener = listener;
    }

    public static class SimpleTakePhotoListener implements TakePhotoListener{

        @Override
        public void takeSuccess(TResult result) {

        }

        @Override
        public void takeFail(TResult result, String msg) {

        }

        @Override
        public void takeCancel() {

        }
    }

    @Override
    public PermissionManager.TPermissionType invoke(InvokeParam invokeParam) {
        PermissionManager.TPermissionType type=PermissionManager.checkPermission(TContextWrap.of(activity),invokeParam.getMethod());
        if(PermissionManager.TPermissionType.WAIT.equals(type)){
            this.invokeParam=invokeParam;
        }
        return type;
    }

    /**
     *
     * @param select_type
     */
    public void takePhoto(Select_type select_type, SimpleTakePhotoListener listener){
        takePhoto(select_type, null, listener);
    }

    public void takePhoto(Select_type select_type, PhotoConfigOptions cropOptions, SimpleTakePhotoListener listener){
        if (takePhoto == null){
            Toast.makeText(activity, "请先开启照片功能", Toast.LENGTH_SHORT).show();
            return;
        }

        setTakePhotoListener(listener);

        if(cropOptions == null){
            cropOptions = new PhotoConfigOptions();
        }

        cropOptions.configCompress();   //压缩配置
        cropOptions.configTakePhoto();  //拍照配置

        File file=new File(Environment.getExternalStorageDirectory(), "/takephoto/"+System.currentTimeMillis() + ".jpg");
        if (!file.getParentFile().exists())file.getParentFile().mkdirs();
        Uri imageUri = Uri.fromFile(file);

        switch (select_type){
            case PICK_BY_SELECT:  //从相册获取
                if(cropOptions.limit > 1){
                    if(cropOptions.crop == true){
                        takePhoto.onPickMultipleWithCrop(cropOptions.limit, cropOptions.getCropOptions());
                    }else {
                        takePhoto.onPickMultiple(cropOptions.limit);
                    }
                }
                if(cropOptions.chooseFromFile){
                    if(cropOptions.crop == true){
                        takePhoto.onPickFromDocumentsWithCrop(imageUri, cropOptions.getCropOptions());
                    }else {
                        takePhoto.onPickFromDocuments();
                    }
                }else {
                    if(cropOptions.crop == true){
                        takePhoto.onPickFromGalleryWithCrop(imageUri, cropOptions.getCropOptions());
                    }else {
                        takePhoto.onPickFromGallery();
                    }
                }
                break;
            case PICK_BY_TAKE:  //拍照获取
                if(cropOptions.crop == true){
                    takePhoto.onPickFromCaptureWithCrop(imageUri, cropOptions.getCropOptions());
                }else {
                    takePhoto.onPickFromCapture(imageUri);
                }
                break;
            default:
                break;
        }
    }

    /**
     * 图片的裁剪配置选项内部类
     */
    public class PhotoConfigOptions{
        //裁剪配置
        private boolean crop = true;  //是否裁剪
        private boolean withWonCrop = true;  //是否采用自带的裁剪工具,默认选取第三方的裁剪工具
        private boolean cropSize = true; //尺寸还是比例

        //压缩配置
        private boolean useOwnCompressTool = true;  //使用自带的压缩工具
        private boolean isCompress = true;  //是否压缩
        private boolean showProgressBar = true; //显示压缩进度条
//        private
        private int maxSize = 102400;

        //选择图片配置
        private boolean useOwnGallery = true; //选择使用自带的相册
        private boolean chooseFromFile = false;  //从文件获取图片
        private int limit = 1;  //选择最多图片的配置,选择多张图片会自动切换到TakePhoto自带相册

        //其它配置
        private boolean savePic = true;  //选择完之后是否保存图片
        private boolean correctTool = false; //纠正拍照的照片旋转角度

        private int height = 800;
        private int width = 800;

        /**
         * 裁剪相关配置
         * @return
         */
        public CropOptions getCropOptions(){
            if(crop == false) return null;

            CropOptions.Builder builder = new CropOptions.Builder();
            if(cropSize){
                builder.setOutputX(width).setOutputY(height);
            }else {
                builder.setAspectX(width).setAspectY(height);
            }
            builder.setWithOwnCrop(withWonCrop);  //默认采用第三方配置
            return builder.create();
        }

        /**
         *  图片压缩相关配置
         */
        public void configCompress(){
            if(isCompress == false) {
                takePhoto.onEnableCompress(null, false);
                return;
            }

            CompressConfig config;
            if(useOwnCompressTool){
                config = new CompressConfig.Builder()
                        .setMaxSize(maxSize)
                        .setMaxPixel(width>height?width:height)
                        .enableReserveRaw(savePic)
                        .create();
            }else {
                LubanOptions options = new LubanOptions.Builder()
                        .setMaxHeight(height)
                        .setMaxWidth(maxSize)
                        .create();
                config = CompressConfig.ofLuban(options);
                config.enableReserveRaw(savePic);
            }
            takePhoto.onEnableCompress(config, showProgressBar);
        }

        public void configTakePhoto(){
            TakePhotoOptions.Builder builder = new TakePhotoOptions.Builder();
            if(useOwnGallery){
                builder.setWithOwnGallery(true);
            }
            if(correctTool){
                builder.setCorrectImage(true);
            }
            takePhoto.setTakePhotoOptions(builder.create());
        }

        public void setCrop(boolean crop) {
            this.crop = crop;
        }

        public void setWithWonCrop(boolean withWonCrop) {
            this.withWonCrop = withWonCrop;
        }

        public void setCropSize(boolean cropSize) {
            this.cropSize = cropSize;
        }

        public void setUseOwnCompressTool(boolean useOwnCompressTool) {
            this.useOwnCompressTool = useOwnCompressTool;
        }

        public void setCompress(boolean compress) {
            isCompress = compress;
        }

        public void setShowProgressBar(boolean showProgressBar) {
            this.showProgressBar = showProgressBar;
        }

        public void setMaxSize(int maxSize) {
            this.maxSize = maxSize;
        }

        public void setUseOwnGallery(boolean useOwnGallery) {
            this.useOwnGallery = useOwnGallery;
        }

        public void setChooseFromFile(boolean chooseFromFile) {
            this.chooseFromFile = chooseFromFile;
        }

        public void setLimit(int limit) {
            this.limit = limit;
        }

        public void setSavePic(boolean savePic) {
            this.savePic = savePic;
        }

        public void setCorrectTool(boolean correctTool) {
            this.correctTool = correctTool;
        }

        public void setHeight(int height) {
            this.height = height;
        }

        public void setWidth(int width) {
            this.width = width;
        }
    }

    /**
     *  照片获取方式, 从相册获取或拍照处理
     */
    public enum Select_type{
        PICK_BY_SELECT, PICK_BY_TAKE
    }
}

封装了一个BaseTakePhotoActivity,里面的代码如下:


    protected TakePhotoUtil takePhotoUtil;

    @Override
    protected void onCreate(@Nullable Bundle savedInstanceState) {
        takePhotoUtil = new TakePhotoUtil(this);
        if(useTakePhoto()){
            takePhotoUtil.onCreate(savedInstanceState);
        }
        super.onCreate(savedInstanceState);
    }

    @Override
    protected void onSaveInstanceState(Bundle outState) {
        if(useTakePhoto()){
            takePhotoUtil.onSaveInstanceState(outState);
        }
        super.onSaveInstanceState(outState);
    }

    @Override
    protected void onActivityResult(int requestCode, int resultCode, Intent data) {
        if(useTakePhoto()){
            takePhotoUtil.onActivityResult(requestCode, resultCode, data);
        }
        super.onActivityResult(requestCode, resultCode, data);
    }

    @Override
    public void onRequestPermissionsResult(int requestCode, String[] permissions, int[] grantResults) {
        if(useTakePhoto()){
            takePhotoUtil.onRequestPermissionsResult(requestCode, permissions, grantResults);
        }
        super.onRequestPermissionsResult(requestCode, permissions, grantResults);
    }

    protected boolean useTakePhoto(){
        return false;
    }

其他对于业务的封装,可以再封装一个BaseActivity,继承自BaseTakePhotoActivity,这样就可以不影响BaseActivity的使用,如果我们在主Activity中使用获取图片的功能需要两步

  • 1)开启TakePhoto功能
@Override
    protected boolean useTakePhoto() {
        return true;
    }
  • 2 ) 获取图片
takePhotoUtil.takePhoto(TakePhotoUtil.Select_type.PICK_BY_TAKE, new TakePhotoUtil.SimpleTakePhotoListener(){
            @Override
            public void takeSuccess(TResult result) {
                String s = result.getImage().getCompressPath();
                Bitmap bitmap = BitmapFactory.decodeFile(s);
                iv.setImageBitmap(bitmap);
            }
        });

takePhoto()的第一个参数是一个枚举类型的参数,分别为从相册获取和拍照获取,第二个参数为获取成功失败监听,有三个回调,由于有些回调不是必须的,所以对Listener做了一个适配,只需要回调想要的方法即可,获取成功之后就可以通过TResult封装的参数获取想要的图片以及图片地址。对于获取到的图片地址就可以做一些上传处理。

图片上传

可以借助okhttp3实现上传功能

MultipartBody.Builder builder = new MultipartBody.Builder().setType(MultipartBody.FORM);

  RequestBody requestBody = RequestBody.create(MediaType.parse(MULTIPART_FORM_DATA), file);

  MultipartBody.Part part = MultipartBody.Part.createFormData("dir", file.getName(), requestBody);

  builder.addPart(part);

  Request.Builder builder1 = new Request.Builder().url(url).post(builder.build());

  Request request = builder1.build();

  HttpUtils.client.newCall(request).enqueue(new Callback() {
      @Override
      public void onFailure(Call call, IOException e) {

      }

      @Override
      public void onResponse(Call call, Response response) throws IOException {
          if(response.isSuccessful()){
              final String s = response.body().string();
              ((Activity)context).runOnUiThread(new Runnable() {
                  @Override
                  public void run() {


                  }
              });
          }
      }
  });

大致代码如上

最后

由于当时没有找到这个库,于是跑去问公司另一个做Android的,看了下他封装的代码,确实也是值得学习的,他的代码也是适配到了Android7.0,贴下它的代码,方便以后学习:

public class CameraUtil {
    private static final int REQUEST_CAPTURE_CAMERA = 1221;
    private static final int REQUEST_CROP = 1222;
    private static final int REQUEST_OPEN_ALBUM = 1223;
    private static final String TAG = "Camera";
    private static Uri mCacheUri;

    private CameraUtil() {
    }

    @RequiresPermission(allOf = {Manifest.permission.READ_EXTERNAL_STORAGE,Manifest.permission.WRITE_EXTERNAL_STORAGE, Manifest.permission.CAMERA})
    public static void getImageFromCamera(Activity activity) {
        if (checkExternalStorageState(activity)) {
            activity.startActivityForResult(getImageFromCamera(activity.getApplicationContext()), REQUEST_CAPTURE_CAMERA);
        }
    }

    @RequiresPermission(allOf = {Manifest.permission.READ_EXTERNAL_STORAGE,Manifest.permission.WRITE_EXTERNAL_STORAGE, Manifest.permission.CAMERA})
    @Deprecated
    public static void getImageFromCamera(Fragment fragment) {
        if (checkExternalStorageState(fragment.getContext())) {
            fragment.startActivityForResult(getImageFromCamera(fragment.getContext()), REQUEST_CAPTURE_CAMERA);
        }
    }

    private static Intent getImageFromCamera(Context context) {
        Intent getImageByCamera = new Intent(MediaStore.ACTION_IMAGE_CAPTURE);
        mCacheUri = getCachePhotoUri(context.getApplicationContext());
        getImageByCamera.putExtra(MediaStore.EXTRA_OUTPUT, mCacheUri);
        getImageByCamera.putExtra("outputFormat", Bitmap.CompressFormat.JPEG.toString());
        grantUriPermission(context, getImageByCamera, mCacheUri);
        return getImageByCamera;
    }

    private static boolean checkExternalStorageState(Context context) {
        if (TextUtils.equals(Environment.getExternalStorageState(), Environment.MEDIA_MOUNTED)) {
            return true;
        }
        Toast.makeText(context.getApplicationContext(), "请确认已经插入SD卡", Toast.LENGTH_LONG).show();
        return false;
    }

    @SuppressWarnings("ResultOfMethodCallIgnored")
    public static File getCachePhotoFile() {
        File file = new File(Environment.getExternalStorageDirectory(), "/lenso/cache/CameraTakePhoto" + System.currentTimeMillis() + ".jpg");
        if (!file.getParentFile().exists()) file.getParentFile().mkdirs();
        return file;
    }

    private static Uri getCachePhotoUri(Context context) {
        return FileProvider.getUriForFile(context, getAuthority(context), getCachePhotoFile());
    }

    private static Uri getCachePhotoUri(Context context, File file) {
        return FileProvider.getUriForFile(context, getAuthority(context), file);
    }

    public static void onActivityResult(Activity activity, int requestCode, int resultCode, Intent data, OnActivityResultListener listener) {
        onActivityResult(activity, null, requestCode, resultCode, data, listener);
    }

    /**
     * getCachePhotoFile().getParentFile().getAbsolutePath()
     * @param dir
     * @return
     */
    public static boolean deleteDir(File dir) {
        if (dir != null && dir.isDirectory()) {
            String[] children = dir.list();
            for (int i = 0; i < children.length; i++) {
                boolean success = deleteDir(new File(dir, children[i]));
                if (!success) {
                    return false;
                }
            }
        }
        return dir.delete();
    }

    public static File saveBitmap(Bitmap bitmap) {
        File file = getCachePhotoFile();
        if (bitmap == null || bitmap.isRecycled()) return file;
        FileOutputStream outputStream = null;
        try {
            outputStream = new FileOutputStream(file);
            bitmap.compress(Bitmap.CompressFormat.JPEG, 100, outputStream);
        } catch (FileNotFoundException e) {
            e.printStackTrace();
        } finally {
            if (outputStream != null)
                try {
                    outputStream.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            bitmap.recycle();
        }
        return file;
    }

    public static void copy(File file, File point) {
        if (!file.exists()) return;
        if (!point.getParentFile().exists()) point.getParentFile().mkdirs();
        BufferedInputStream inputStream = null;
        BufferedOutputStream outputStream = null;
        try {
            inputStream = new BufferedInputStream(new FileInputStream(file));
            outputStream = new BufferedOutputStream(new FileOutputStream(point));
            byte[] buff = new byte[1024 * 1024 * 2];
            int len;
            while ((len = inputStream.read(buff)) != -1) {
                outputStream.write(buff, 0, len);
                outputStream.flush();
            }
        } catch (FileNotFoundException e) {
            e.printStackTrace();
        } catch (IOException e) {
            e.printStackTrace();
        } finally {
            closeStream(inputStream);
            closeStream(outputStream);
        }
    }

    private static void closeStream(Closeable closeable) {
        if (closeable != null) try {
            closeable.close();
        } catch (IOException e) {
            e.printStackTrace();
        }
    }

    public static void onActivityResult(Activity activity, CropOption crop, int requestCode, int resultCode, Intent data, OnActivityResultListener listener) {

        if (resultCode == Activity.RESULT_CANCELED) return;
        Uri uri;
        switch (requestCode) {
            case REQUEST_OPEN_ALBUM:
                uri = data.getData();
                if (uri != null) {
                    mCacheUri = getCachePhotoUri(activity);
                    copy(new File(getRealFilePath(activity, uri)), new File(getRealFilePath(activity, mCacheUri)));
                } else {
                    Bitmap bitmap = data.getParcelableExtra("data");
                    File file = saveBitmap(bitmap);
                    mCacheUri = getCachePhotoUri(activity, file);
                }
            case REQUEST_CAPTURE_CAMERA:
                uri = mCacheUri;
                if (listener != null) {
                    listener.requestCaptureCamera(getRealFilePath(activity, uri), null);
                }
                if (crop == null) return;
                crop.setSource(uri);
                Intent intent = crop.create();
                grantUriPermission(activity, intent, crop.getOutput());
                activity.startActivityForResult(intent, REQUEST_CROP);
                break;
            case REQUEST_CROP:
                if (listener != null && data != null)
                {
                    listener.requestCrop(getRealFilePath(activity, mCacheUri), (Bitmap) data.getParcelableExtra("data"));
                }
                break;
        }
    }

    @RequiresPermission(allOf = {Manifest.permission.READ_EXTERNAL_STORAGE,Manifest.permission.WRITE_EXTERNAL_STORAGE})
    public static void getImageFromAlbum(Activity activity) {
        Intent intent = new Intent(Intent.ACTION_PICK);
        intent.setType("image/*");//相片类型
        activity.startActivityForResult(intent, REQUEST_OPEN_ALBUM);
    }

    @RequiresPermission(allOf = {Manifest.permission.READ_EXTERNAL_STORAGE,Manifest.permission.WRITE_EXTERNAL_STORAGE})
    @Deprecated
    public static void getImageFromAlbum(Fragment fragment) {
        Intent intent = new Intent(Intent.ACTION_PICK);
        intent.setType("image/*");//相片类型
        fragment.startActivityForResult(intent, REQUEST_OPEN_ALBUM);
    }

    public interface OnActivityResultListener {
        void requestCaptureCamera(String path, Bitmap bitmap);

        void requestCrop(String path, Bitmap bitmap);
    }

    /**
     * Try to return the absolute file path from the given Uri
     *
     * @param context context
     * @param uri     uri
     * @return the file path or null
     */
    public static String getRealFilePath(final Context context, final Uri uri) {
        if (null == uri) return null;
        String path = uri.toString();
        if (path.startsWith("content://" + getAuthority(context) + "/rc_external_path")) {
            return path.replace("content://" + getAuthority(context) + "/rc_external_path", Environment.getExternalStorageDirectory().getAbsolutePath());
        }
        final String scheme = uri.getScheme();
        String data = null;
        if (scheme == null)
            data = uri.getPath();
        else if (ContentResolver.SCHEME_FILE.equals(scheme)) {
            data = uri.getPath();
        } else if (ContentResolver.SCHEME_CONTENT.equals(scheme)) {
            Cursor cursor = context.getContentResolver().query(uri, new String[]{MediaStore.Images.ImageColumns.DATA}, null, null, null);
            if (null != cursor) {
                if (cursor.moveToFirst()) {
                    int index = cursor.getColumnIndex(MediaStore.Images.ImageColumns.DATA);
                    if (index > -1) {
                        data = cursor.getString(index);
                    }
                }
                cursor.close();
            }
        }
        return data;
    }

    private static String getAuthority(Context context) {
        return context.getPackageName() + ".FileProvider";
    }

    public static class CropOption {
        private int aspectX=1;//x比例
        private int aspectY=1;//y比例
        private boolean returnData = false;//是返回bitmap,否返回uri
        private String outputFormat;//输出流保存格式JPG PNG ...
        private int outputX=200;//返回的bitmap宽
        private int outputY=200;//返回的bitmap高
        private Uri output;//输出流保存路径
        private Uri source;//需要截图的图片uri
        private boolean noFaceDetection = true;//是否关闭人脸识别功能
// get和set方法省略

        private Intent create() {
            if (source == null)
                throw new NullPointerException("没有设置图片uri");
            Intent intent = new Intent("com.android.camera.action.CROP");
            intent.setDataAndType(source, "image/*");
            intent.putExtra("crop", "true");
            if (aspectX > 0)
                intent.putExtra("aspectX", aspectX);
            if (aspectY > 0)
                intent.putExtra("aspectY", aspectY);
            if (outputX > 0)
                intent.putExtra("outputX", outputX);
            if (outputY > 0)
                intent.putExtra("outputY", outputY);
            intent.putExtra("return-data", returnData);
            if (!returnData) {
                output = output == null ? source : output;
                outputFormat = outputFormat == null ? Bitmap.CompressFormat.JPEG.toString() : outputFormat;
                intent.putExtra(MediaStore.EXTRA_OUTPUT, output);
                intent.putExtra("outputFormat", outputFormat);
                intent.setType("image/*");
                intent.putExtra("noFaceDetection", noFaceDetection);
            }
            return intent;
        }
    }

    private static void grantUriPermission(Context context, Intent intent, Uri uri) {
        List<ResolveInfo> resInfoList = context.getPackageManager().queryIntentActivities(intent, PackageManager.MATCH_DEFAULT_ONLY);
        for (ResolveInfo resolveInfo : resInfoList) {
            String packageName = resolveInfo.activityInfo.packageName;
            context.grantUriPermission(packageName, uri, Intent.FLAG_GRANT_WRITE_URI_PERMISSION | Intent.FLAG_GRANT_READ_URI_PERMISSION);
        }
    }
}

//xml文件部分
<?xml version="1.0" encoding="utf-8"?>
<resources >
    <paths>
        <external-path path="" name="rc_external_path" />
    </paths>
</resources>
//清单文件注册部分
<provider
    android:name="android.support.v4.content.FileProvider"
    android:authorities="com.lenso.FileProvider"
    android:exported="false"
    android:grantUriPermissions="true">
    <meta-data
        android:name="android.support.FILE_PROVIDER_PATHS"
        android:resource="@xml/file_path" />
</provider>

也封装了从本地获取,以及拍照获取的相关功能,可以值得学习,毕竟不少坑。


以上是关于Android设备上获取照片裁剪图片压缩图片的主要内容,如果未能解决你的问题,请参考以下文章

android从相册选取图片裁剪,裁剪的时候图片变为黑色的,怎么解决???

图片上传

android 怎么裁剪drawable

从图片中拍摄的照片不会显示在 android 的科尔多瓦相机插件中的裁剪

前端压缩图片代码,支持移动端和pc 端,还有拍照后获取到的照片

Android 11 调用系统图片裁剪后,图片保存不了的解决方案