public class Constants {
    public static final int REQUEST_CODE = 2000;

    public static final int FETCH_STARTED = 2001;
    public static final int FETCH_COMPLETED = 2002;
    public static final int PERMISSION_GRANTED = 2003;
    public static final int PERMISSION_DENIED = 2004;
    public static final int ERROR = 2005;

    public static final int PERMISSION_REQUEST_READ_EXTERNAL_STORAGE = 23;

    public static final String INTENT_EXTRA_ALBUM = "album";
    public static final String INTENT_EXTRA_IMAGES = "images";
    public static final String INTENT_EXTRA_LIMIT = "limit";
    public static final int DEFAULT_LIMIT = 10;

    //Maximum number of images that can be selected at a time
    public static int limit;
} public class CompressConfig implements Serializable {

    /**
     * 长或宽不超过的最大像素,单位px
     */
    private int maxPixel=1200;
    /**
     * 压缩到的最大大小，单位B
     */
    private int maxSize=100*1024;

    /**
     * 是否启用像素压缩
     */
    private boolean enablePixelCompress=true;
    /**
     * 是否启用质量压缩
     */
    private boolean enableQualityCompress=true;

    /**
     * 是否保留原文件
     */
    private boolean enableReserveRaw = true;

    /**
     * Luban压缩配置
     */
    private LubanOptions lubanOptions;
    public static CompressConfig ofDefaultConfig(){
        return new CompressConfig();
    }
    public static CompressConfig ofLuban(LubanOptions options){
        return new CompressConfig(options);
    }
    private CompressConfig(){}
    private CompressConfig(LubanOptions options){
        this.lubanOptions=options;
    }

    public LubanOptions getLubanOptions() {
        return lubanOptions;
    }

    public int getMaxPixel() {
        return maxPixel;
    }
    public CompressConfig setMaxPixel(int maxPixel) {
        this.maxPixel = maxPixel;
        return this;
    }
    public int getMaxSize() {
        return maxSize;
    }
    public void setMaxSize(int maxSize) {
        this.maxSize = maxSize;
    }

    public boolean isEnablePixelCompress() {
        return enablePixelCompress;
    }

    public void enablePixelCompress(boolean enablePixelCompress) {
        this.enablePixelCompress = enablePixelCompress;
    }

    public boolean isEnableQualityCompress() {
        return enableQualityCompress;
    }

    public void enableQualityCompress(boolean enableQualityCompress) {
        this.enableQualityCompress = enableQualityCompress;
    }

    public boolean isEnableReserveRaw() {
        return enableReserveRaw;
    }
    public void enableReserveRaw(boolean enableReserveRaw) {
        this.enableReserveRaw = enableReserveRaw;
    }
    public static class Builder{
        private CompressConfig config;
        public Builder() {
            config=new CompressConfig();
        }
        public Builder setMaxSize(int maxSize) {
            config.setMaxSize( maxSize);
            return this;
        }
        public Builder setMaxPixel(int maxPixel) {
            config.setMaxPixel(maxPixel);
            return this;
        }
        public Builder enablePixelCompress(boolean enablePixelCompress) {
            config.enablePixelCompress(enablePixelCompress);
            return this;
        }
        public Builder enableQualityCompress(boolean enableQualityCompress) {
            config.enableQualityCompress(enableQualityCompress);
            return this;
        }
        public Builder enableReserveRaw(boolean enableReserveRaw) {
            config.enableReserveRaw(enableReserveRaw);
            return this;
        }
        public CompressConfig create(){
            return config;
        }
    }
} public interface CompressImage {
    void compress();

    /**
     * 压缩结果监听器
     */
    interface CompressListener {
        /**
         * 压缩成功
         * @param images 已经压缩图片
         */
        void onCompressSuccess(ArrayList <TImage> images);

        /**
         * 压缩失败
         * @param images 压缩失败的图片
         * @param msg 失败的原因
         */
        void onCompressFailed(ArrayList <TImage> images,String msg);
    }
} public class CompressImageImpl implements CompressImage {
    private CompressImageUtil compressImageUtil;
    private ArrayList<TImage> images;
    private CompressImage.CompressListener listener;

    public static CompressImage of(Context context,CompressConfig config, ArrayList<TImage> images, CompressImage.CompressListener listener) {
        return new CompressImageImpl(context,config,images,listener);
    }
    private CompressImageImpl(Context context,CompressConfig config, ArrayList<TImage> images, CompressImage.CompressListener listener){
        compressImageUtil = new CompressImageUtil(context,config);
        this.images = images;
        this.listener = listener;
    }

    @Override
    public void compress() {
        if(images==null||images.isEmpty())listener.onCompressFailed(images," images is null");
        for(TImage image:images){
            if(image==null){
                listener.onCompressFailed(images," There are pictures of compress  is null.");
                return;
            }
        }
        compress(images.get(0));
    }

    private void compress(final TImage image) {
        if (TextUtils.isEmpty(image.getOriginalPath())){
            continueCompress(image,false);
            return;
        }

        File file = new File(image.getOriginalPath());
        if (file == null || !file.exists() || !file.isFile()){
            continueCompress(image,false);
            return;
        }

        compressImageUtil.compress(image.getOriginalPath(), new CompressImageUtil.CompressListener() {
            @Override
            public void onCompressSuccess(String imgPath) {
                image.setCompressPath(imgPath);
                continueCompress(image,true);
            }

            @Override
            public void onCompressFailed(String imgPath, String msg) {
                continueCompress(image,false,msg);
            }
        });
    }

    private void continueCompress(TImage image,boolean preSuccess,String...message){
        image.setCompressed(preSuccess);
        int index=images.indexOf(image);
        boolean isLast=index== images.size() - 1;
        if (isLast) {
            handleCompressCallBack(message);
        }else {
            compress(images.get(index+1));
        }
    }
    private void handleCompressCallBack(String...message){
        if(message.length>0){
            listener.onCompressFailed(images,message[0]);
            return;
        }

        for(TImage image:images){
            if(!image.isCompressed()){
                listener.onCompressFailed(images,image.getCompressPath()+" is compress failures");
                return;
            }
        }
        listener.onCompressSuccess(images);
    }
} public class CropOptions implements Serializable{
    /**使用TakePhoto自带的裁切工具进行裁切*/
    private boolean withOwnCrop;
    private int aspectX;
    private int aspectY;
    private int outputX;
    private int outputY;
    private CropOptions(){}

    public int getAspectX() {
        return aspectX;
    }

    public void setAspectX(int aspectX) {
        this.aspectX = aspectX;
    }

    public int getAspectY() {
        return aspectY;
    }

    public void setAspectY(int aspectY) {
        this.aspectY = aspectY;
    }

    public int getOutputX() {
        return outputX;
    }

    public void setOutputX(int outputX) {
        this.outputX = outputX;
    }

    public int getOutputY() {
        return outputY;
    }

    public void setOutputY(int outputY) {
        this.outputY = outputY;
    }

    public boolean isWithOwnCrop() {
        return withOwnCrop;
    }

    public void setWithOwnCrop(boolean withOwnCrop) {
        this.withOwnCrop = withOwnCrop;
    }

    public static class Builder{
        private CropOptions options;

        public Builder() {
            options=new CropOptions();
        }

        public Builder setAspectX(int aspectX) {
            options.setAspectX(aspectX);
            return this;
        }

        public Builder setAspectY(int aspectY) {
            options.setAspectY(aspectY);
            return this;
        }

        public Builder setOutputX(int outputX) {
            options.setOutputX(outputX);
            return this;
        }

        public Builder setOutputY(int outputY) {
            options.setOutputY(outputY);
            return this;
        }

        public Builder setWithOwnCrop(boolean withOwnCrop) {
            options.setWithOwnCrop(withOwnCrop);
            return this;
        }
        public CropOptions create(){
            return options;
        }
    }
} public class MultipleCrop {
    private ArrayList<Uri> uris;
    private ArrayList<Uri> outUris;
    private ArrayList<TImage>tImages;
    private TImage.FromType fromType;
    public boolean hasFailed;//是否有裁切失败的标识
    public static MultipleCrop of(ArrayList<Uri> uris,Activity activity, TImage.FromType fromType) throws TException {
        return new MultipleCrop(uris,activity, fromType);
    }
    public static MultipleCrop of(ArrayList<Uri> uris,ArrayList<Uri>outUris, TImage.FromType fromType){
        return new MultipleCrop(uris,outUris, fromType);
    }
    private MultipleCrop(ArrayList<Uri> uris,Activity activity, TImage.FromType fromType) throws TException {
        this.uris=uris;
        ArrayList<Uri>outUris=new ArrayList<>();
        for (Uri uri:uris){
            outUris.add(Uri.fromFile(TImageFiles.getTempFile(activity,uri)));//生成临时裁切输出路径
        }
        this.outUris=outUris;
        this.tImages= TUtils.getTImagesWithUris(outUris, fromType);
        this.fromType = fromType;
    }
    private MultipleCrop(ArrayList<Uri> uris,ArrayList<Uri>outUris, TImage.FromType fromType) {
        this.uris=uris;
        this.outUris=outUris;
        this.tImages= TUtils.getTImagesWithUris(outUris, fromType);
        this.fromType = fromType;
    }

    public ArrayList<Uri> getUris() {
        return uris;
    }

    public void setUris(ArrayList<Uri> uris) {
        this.uris = uris;
    }

    public ArrayList<Uri> getOutUris() {
        return outUris;
    }

    public void setOutUris(ArrayList<Uri> outUris) {
        this.outUris = outUris;
    }

    public ArrayList<TImage> gettImages() {
        return tImages;
    }

    public void settImages(ArrayList<TImage> tImages) {
        this.tImages = tImages;
    }

    /**
     * 为被裁切的图片设置已被裁切的标识
     * @param uri 被裁切的图片
     * @return 该图片是否是最后一张
     */
    public Map setCropWithUri(Uri uri,boolean cropped){
        if(!cropped)hasFailed=true;
        int index=outUris.indexOf(uri);
        tImages.get(index).setCropped(cropped);
        Map result=new HashMap();
        result.put("index",index);
        result.put("isLast",index==outUris.size()-1? true:false);
        return result;
    }
} public class TContextWrap {
    private Activity activity;
    private Fragment fragment;
    public static TContextWrap of(Activity activity){
        return new TContextWrap(activity);
    }
    public static TContextWrap of(Fragment fragment){
        return new TContextWrap(fragment);
    }
    private TContextWrap(Activity activity) {
        this.activity = activity;
    }

    private TContextWrap(Fragment fragment) {
        this.fragment = fragment;
        this.activity=fragment.getActivity();
    }

    public Activity getActivity() {
        return activity;
    }

    public void setActivity(Activity activity) {
        this.activity = activity;
    }

    public Fragment getFragment() {
        return fragment;
    }

    public void setFragment(Fragment fragment) {
        this.fragment = fragment;
    }
} public enum TExceptionType {
    TYPE_NOT_IMAGE("选择的文件不是图片"),
    TYPE_WRITE_FAIL("保存选择的的文件失败"),
    TYPE_URI_NULL("所选照片的Uri 为null"),
    TYPE_URI_PARSE_FAIL("从Uri中获取文件路径失败"),
    TYPE_NO_MATCH_PICK_INTENT("没有匹配到选择图片的Intent"),
    TYPE_NO_MATCH_CROP_INTENT("没有匹配到裁切图片的Intent"),
    TYPE_NO_CAMERA("没有相机"),
    TYPE_NO_FIND("选择的文件没有找到");

    String stringValue;
    TExceptionType(String stringValue) {
        this.stringValue=stringValue;
    }
    public String getStringValue() {
        return stringValue;
    }
} public class TImage implements Serializable{
    private String originalPath;
    private String compressPath;
    private FromType fromType;
    private boolean cropped;
    private boolean compressed;
    public static TImage of(String path, FromType fromType){
        return new TImage(path, fromType);
    }
    public static TImage of(Uri uri, FromType fromType){
        return new TImage(uri, fromType);
    }
    private TImage(String path, FromType fromType) {
        this.originalPath = path;
        this.fromType = fromType;
    }
    private TImage(Uri uri, FromType fromType) {
        this.originalPath = uri.getPath();
        this.fromType = fromType;
    }

    public String getOriginalPath() {
        return originalPath;
    }

    public void setOriginalPath(String originalPath) {
        this.originalPath = originalPath;
    }

    public String getCompressPath() {
        return compressPath;
    }

    public void setCompressPath(String compressPath) {
        this.compressPath = compressPath;
    }

    public FromType getFromType() {
        return fromType;
    }

    public void setFromType(FromType fromType) {
        this.fromType = fromType;
    }

    public boolean isCropped() {
        return cropped;
    }

    public void setCropped(boolean cropped) {
        this.cropped = cropped;
    }

    public boolean isCompressed() {
        return compressed;
    }

    public void setCompressed(boolean compressed) {
        this.compressed = compressed;
    }

    public enum FromType {
        CAMERA, OTHER
    }
} public class TIntentWap {
    private Intent intent;
    private int requestCode;

    public TIntentWap() {
    }

    public TIntentWap(Intent intent, int requestCode) {
        this.intent = intent;
        this.requestCode = requestCode;
    }

    public Intent getIntent() {
        return intent;
    }

    public void setIntent(Intent intent) {
        this.intent = intent;
    }

    public int getRequestCode() {
        return requestCode;
    }

    public void setRequestCode(int requestCode) {
        this.requestCode = requestCode;
    }
} public class TResult {
    private  ArrayList<TImage> images;
    private TImage image;
    public static TResult of(TImage image){
        ArrayList<TImage> images=new ArrayList<>(1);
        images.add(image);
        return new TResult(images);
    }
    public static TResult of(ArrayList<TImage> images){
        return new TResult(images);
    }
    private TResult(ArrayList<TImage> images) {
        this.images = images;
        if(images!=null&&!images.isEmpty())this.image=images.get(0);
    }

    public ArrayList<TImage> getImages() {
        return images;
    }

    public void setImages(ArrayList<TImage> images) {
        this.images = images;
    }

    public TImage getImage() {
        return image;
    }

    public void setImage(TImage image) {
        this.image = image;
    }
} public class TakePhotoOptions implements Serializable {
    /**
     * 是否使用TakePhoto自带的相册进行图片选择，默认不使用，但选择多张图片会使用
     */
    private boolean withOwnGallery;
    /**
     * 是对拍的照片进行旋转角度纠正
     */
    private boolean correctImage;

    private TakePhotoOptions() {
    }

    public boolean isWithOwnGallery() {
        return withOwnGallery;
    }

    public void setWithOwnGallery(boolean withOwnGallery) {
        this.withOwnGallery = withOwnGallery;
    }

    public boolean isCorrectImage() {
        return correctImage;
    }

    public void setCorrectImage(boolean correctImage) {
        this.correctImage = correctImage;
    }

    public static class Builder {
        private TakePhotoOptions options;

        public Builder() {
            this.options = new TakePhotoOptions();
        }

        public Builder setWithOwnGallery(boolean withOwnGallery) {
            options.setWithOwnGallery(withOwnGallery);
            return this;
        }
        public Builder setCorrectImage(boolean isCorrectImage) {
            options.setCorrectImage(isCorrectImage);
            return this;
        }
        public TakePhotoOptions create(){
            return options;
        }
    }
} public class PermissionManager {
    public enum TPermission {
        STORAGE(Manifest.permission.WRITE_EXTERNAL_STORAGE),
        CAMERA(Manifest.permission.CAMERA);
        String stringValue;

        TPermission(String stringValue) {
            this.stringValue = stringValue;
        }

        public String stringValue() {
            return stringValue;
        }
    }

    public enum TPermissionType {
        GRANTED("已授权"),
        DENIED("未授权"),
        WAIT("等待授权"),
        NOT_NEED("无需授权"),
        ONLY_CAMERA_DENIED("没有拍照权限"),
        ONLY_STORAGE_DENIED("没有读写SD卡权限");
        String stringValue;

        TPermissionType(String stringValue) {
            this.stringValue = stringValue;
        }

        public String stringValue() {
            return stringValue;
        }
    }
    private final static String []methodNames={
            "onPickFromCapture",
            "onPickFromCaptureWithCrop",
            "onPickMultiple",
            "onPickMultipleWithCrop",
            "onPickFromDocuments",
            "onPickFromDocumentsWithCrop",
            "onPickFromGallery",
            "onPickFromGalleryWithCrop",
            "onCrop"
    };
    /**
     * 检查当前应用是否被授予相应权限
     *
     * @param contextWrap
     * @param method
     * @return
     */
    public static TPermissionType checkPermission(@NonNull TContextWrap contextWrap, @NonNull Method method) {
        String methodName = method.getName();
        boolean contain=false;
        for(int i=0,j=methodNames.length;i<j;i++){
            if(TextUtils.equals(methodName,methodNames[i])){
                contain=true;
                break;
            }
        }
        if(!contain)return TPermissionType.NOT_NEED;

        boolean cameraGranted = true, storageGranted = ContextCompat.checkSelfPermission(contextWrap.getActivity(), TPermission.STORAGE.stringValue()) == PackageManager.PERMISSION_GRANTED ? true : false;

        if (TextUtils.equals(methodName, "onPickFromCapture") || TextUtils.equals(methodName, "onPickFromCaptureWithCrop")) {
            cameraGranted = ContextCompat.checkSelfPermission(contextWrap.getActivity(), TPermission.CAMERA.stringValue()) == PackageManager.PERMISSION_GRANTED ? true : false;
        }

        boolean granted = storageGranted && cameraGranted;
        if (!granted) {
            ArrayList<String> permissions = new ArrayList<>();
            if (!storageGranted) permissions.add(TPermission.STORAGE.stringValue());
            if (!cameraGranted) permissions.add(TPermission.CAMERA.stringValue());
            requestPermission(contextWrap,permissions.toArray(new String[permissions.size()]));
        }
        return granted ? TPermissionType.GRANTED : TPermissionType.WAIT;
    }

    public static void requestPermission(@NonNull TContextWrap contextWrap, @NonNull String[] permissions) {
        if(contextWrap.getFragment()!=null){
            contextWrap.getFragment().requestPermissions(permissions, TConstant.PERMISSION_REQUEST_TAKE_PHOTO);
        }else{
            ActivityCompat.requestPermissions(contextWrap.getActivity(), permissions, TConstant.PERMISSION_REQUEST_TAKE_PHOTO);
        }
    }

    public static TPermissionType onRequestPermissionsResult(int requestCode, String[] permissions, int[] grantResults) {
        if (requestCode == TConstant.PERMISSION_REQUEST_TAKE_PHOTO) {
            boolean cameraGranted = true, storageGranted = true;
            for (int i = 0, j = permissions.length; i < j; i++) {
                if (grantResults[i] != PackageManager.PERMISSION_GRANTED) {
                    if (TextUtils.equals(TPermission.STORAGE.stringValue(),permissions[i])) {
                        storageGranted = false;
                    } else if (TextUtils.equals(TPermission.CAMERA.stringValue(),permissions[i])) {
                        cameraGranted = false;
                    }
                }
            }
            if (cameraGranted && storageGranted) return TPermissionType.GRANTED;
            if (!cameraGranted && storageGranted) return TPermissionType.ONLY_CAMERA_DENIED;
            if (!storageGranted && cameraGranted) return TPermissionType.ONLY_STORAGE_DENIED;
            if(!storageGranted&&!cameraGranted)return TPermissionType.DENIED;
        }
        return TPermissionType.WAIT;
    }
    public static void handlePermissionsResult(Activity activity, TPermissionType type, InvokeParam invokeParam, TakePhoto.TakeResultListener listener){
                String tip=null;
                switch (type){
                    case DENIED:
                        listener.takeFail(null,tip=activity.getResources().getString(R.string.tip_permission_camera_storage));
                        break;
                    case ONLY_CAMERA_DENIED:
                        listener.takeFail(null,tip=activity.getResources().getString(R.string.tip_permission_camera));
                        break;
                    case ONLY_STORAGE_DENIED:
                        listener.takeFail(null,tip=activity.getResources().getString(R.string.tip_permission_storage));
                        break;
                    case GRANTED:
                        try {
                            invokeParam.getMethod().invoke(invokeParam.getProxy(),invokeParam.getArgs());
                        } catch (Exception e) {
                            e.printStackTrace();
                            listener.takeFail(null,tip=activity.getResources().getString(R.string.tip_permission_camera_storage));
                        }
                        break;
            default:
                break;
        }
        if(tip!=null)Toast.makeText(activity,tip,Toast.LENGTH_LONG).show();

    }
} public class ImageRotateUtil {

    public static ImageRotateUtil of(){
        return new ImageRotateUtil();
    }

    private ImageRotateUtil() {
    }

    /**
     * 纠正照片的旋转角度
     * @param path
     */
    public void correctImage(Context context,Uri path){

        String imagePath=TUriParse.parseOwnUri(context,path);
        int degree;
        if((degree=getBitmapDegree(imagePath))!=0){
            Bitmap bitmap= BitmapFactory.decodeFile(imagePath);
            if(bitmap==null)return;
            Bitmap resultBitmap=rotateBitmapByDegree(bitmap,degree);
            if(resultBitmap==null)return;
            try {
                resultBitmap.compress(Bitmap.CompressFormat.JPEG,100,new FileOutputStream(new File(imagePath)));
            } catch (FileNotFoundException e) {
                e.printStackTrace();
            }catch (OutOfMemoryError e){
                e.printStackTrace();
            }
        }
    }

    /**
     * 读取图片的旋转的角度
     *
     * @param path 图片绝对路径
     * @return 图片的旋转角度
     */
    private int getBitmapDegree(String path) {
        int degree = 0;
        try {
            // 从指定路径下读取图片，并获取其EXIF信息
            ExifInterface exifInterface = new ExifInterface(path);
            // 获取图片的旋转信息
            int orientation = exifInterface.getAttributeInt(ExifInterface.TAG_ORIENTATION,
                    ExifInterface.ORIENTATION_NORMAL);
            switch (orientation) {
                case ExifInterface.ORIENTATION_ROTATE_90:
                    degree = 90;
                    break;
                case ExifInterface.ORIENTATION_ROTATE_180:
                    degree = 180;
                    break;
                case ExifInterface.ORIENTATION_ROTATE_270:
                    degree = 270;
                    break;
            }
        } catch (IOException e) {
            e.printStackTrace();
        }
        return degree;
    }

    /**
     * 将图片按照某个角度进行旋转
     *
     * @param bm     需要旋转的图片
     * @param degree 旋转角度
     * @return 旋转后的图片
     */
    private Bitmap rotateBitmapByDegree(Bitmap bm, int degree) {
        Bitmap returnBm = null;

        // 根据旋转角度，生成旋转矩阵
        Matrix matrix = new Matrix();
        matrix.postRotate(degree);
        try {
            // 将原始图片按照旋转矩阵进行旋转，并得到新的图片
            returnBm = Bitmap.createBitmap(bm, 0, 0, bm.getWidth(), bm.getHeight(), matrix, true);
        } catch (OutOfMemoryError e) {
        }
        if (returnBm == null) {
            returnBm = bm;
        }
        if (bm != returnBm) {
            bm.recycle();
        }
        return returnBm;
    }
} public class IntentUtils {
    private static final String TAG = IntentUtils.class.getName();

    /**
     *  获取图片多选的Intent
     * @param limit 最多选择图片张数的限制
     * */
    public static Intent getPickMultipleIntent(TContextWrap contextWrap, int limit){
        Intent intent = new Intent(contextWrap.getActivity(), AlbumSelectActivity.class);
        intent.putExtra(Constants.INTENT_EXTRA_LIMIT, limit>0? limit:1);
        return intent;
    }

    /**
     * 获取裁剪照片的Intent
     * @param targetUri 要裁剪的照片
     * @param outPutUri 裁剪完成的照片
     * @param options 裁剪配置
     * @return
     */
    public static Intent getCropIntentWithOtherApp(Uri targetUri, Uri outPutUri, CropOptions options) {
        boolean isReturnData = TUtils.isReturnData();
        Log.w(TAG, "getCaptureIntentWithCrop:isReturnData:" + (isReturnData ? "true" : "false"));
        Intent intent = new Intent("com.android.camera.action.CROP");
        intent.addFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION);
        intent.setDataAndType(targetUri, "image/*");
        intent.putExtra("crop", "true");
        if (options.getAspectX()*options.getAspectY()>0){
            intent.putExtra("aspectX", options.getAspectX());
            intent.putExtra("aspectY", options.getAspectY());
        }
        if (options.getOutputX()*options.getOutputY()>0){
            intent.putExtra("outputX", options.getOutputX());
            intent.putExtra("outputY", options.getOutputY());
        }
        intent.putExtra("scale", true);
        intent.putExtra(MediaStore.EXTRA_OUTPUT, outPutUri);
        intent.putExtra("return-data", isReturnData);
        intent.putExtra("outputFormat", Bitmap.CompressFormat.JPEG.toString());
        intent.putExtra("noFaceDetection", true); // no face detection
        return intent;
    }

    /**
     * 获取拍照的Intent
     * @return
     */
    public static Intent getCaptureIntent(Uri outPutUri) {
        Intent intent = new Intent();
        intent.addFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION);
        intent.setAction(MediaStore.ACTION_IMAGE_CAPTURE);//设置Action为拍照
        intent.putExtra(MediaStore.EXTRA_OUTPUT, outPutUri);//将拍取的照片保存到指定URI
        return intent;
    }
    /**
     * 获取选择照片的Intent
     * @return
     */
    public static Intent getPickIntentWithGallery() {
        Intent intent = new Intent();
        intent.setAction(Intent.ACTION_PICK);//Pick an item from the data
        intent.setType("image/*");//从所有图片中进行选择
        return intent;
    }
    /**
     * 获取从文件中选择照片的Intent
     * @return
     */
    public static Intent getPickIntentWithDocuments() {
        Intent intent = new Intent(Intent.ACTION_GET_CONTENT);
        intent.setType("image/*");
        return intent;
    }
} public class TConstant {


    /**
     * request Code 裁剪照片
     **/
    public final static int RC_CROP = 1001;
    /**
     * request Code 从相机获取照片并裁剪
     **/
    public final static int RC_PICK_PICTURE_FROM_CAPTURE_CROP = 1002;
    /**
     * request Code 从相机获取照片不裁剪
     **/
    public final static int RC_PICK_PICTURE_FROM_CAPTURE = 1003;
    /**
     * request Code 从文件中选择照片
     **/
    public final static int RC_PICK_PICTURE_FROM_DOCUMENTS_ORIGINAL = 1004;
    /**
     * request Code 从文件中选择照片并裁剪
     **/
    public final static int RC_PICK_PICTURE_FROM_DOCUMENTS_CROP = 1005;
    /**
     * request Code 从相册选择照
     **/
    public final static int RC_PICK_PICTURE_FROM_GALLERY_ORIGINAL = 1006;
    /**
     * request Code 从相册选择照片并裁剪
     **/
    public final static int RC_PICK_PICTURE_FROM_GALLERY_CROP = 1007;
    /**
     * request Code 选择多张照片
     **/
    public final static int RC_PICK_MULTIPLE = 1008;


    /**
     * requestCode 请求权限
     **/
    public final static int PERMISSION_REQUEST_TAKE_PHOTO = 2000;

    public final static String getFileProviderName(Context context){
        return context.getPackageName()+".fileprovider";
    }
 } public class TException extends Exception{
    String detailMessage;
    public TException(TExceptionType exceptionType) {
        super(exceptionType.getStringValue());
        this.detailMessage=exceptionType.getStringValue();
    }
    public String getDetailMessage() {
        return detailMessage;
    }
} public class TFileUtils {
    private static final String TAG="TFileUtils";
    private static String DEFAULT_DISK_CACHE_DIR = "takephoto_cache";
    public static File getPhotoCacheDir(Context context, File file) {
        File cacheDir = context.getCacheDir();
        if (cacheDir != null) {
            File mCacheDir = new File(cacheDir,DEFAULT_DISK_CACHE_DIR);
            if (!mCacheDir.mkdirs() && (!mCacheDir.exists() || !mCacheDir.isDirectory())) {
                return file;
            }else {
                return new File(mCacheDir, file.getName());
            }
        }
        if (Log.isLoggable(TAG, Log.ERROR)) {
            Log.e(TAG, "default disk cache dir is null");
        }
        return file;
    }

    public static void delete(String path) {
        try {
            if(path == null) {
                return ;
            }
            File file = new File(path);
            if(!file.delete()) {
                file.deleteOnExit();
            }
        } catch (Exception e) {
            e.printStackTrace();
        }
    }
} public class TImageFiles {
    private static final String TAG = IntentUtils.class.getName();
    /**
     * 将bitmap写入到文件
     *
     * @param bitmap
     */
    public static void writeToFile(Bitmap bitmap, Uri imageUri) {
        if (bitmap == null) return;
        File file = new File(imageUri.getPath());
        ByteArrayOutputStream bos = new ByteArrayOutputStream();
        bitmap.compress(Bitmap.CompressFormat.JPEG, 100, bos);
        FileOutputStream fos = null;
        try {
            fos = new FileOutputStream(file);
            fos.write(bos.toByteArray());
            bos.flush();
            fos.flush();
        } catch (java.io.IOException e) {
            e.printStackTrace();
        } finally {
            if (fos != null) try {
                fos.close();
                if (bos != null) bos.close();
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
    }
    /**
     * InputStream 转File
     * */
    public static void inputStreamToFile(InputStream is, File file) throws TException {
        if (file==null){
            Log.i(TAG,"inputStreamToFile:file not be null");
            throw new TException(TExceptionType.TYPE_WRITE_FAIL);
        }
        FileOutputStream fos = null;
        try {
            fos = new FileOutputStream(file);
            byte[] buffer = new byte[1024 * 10];
            int i;
            while ((i = is.read(buffer)) != -1) {
                fos.write(buffer, 0, i);
            }
        } catch (IOException e) {
            Log.e(TAG,"InputStream 写入文件出错:"+e.toString());
            throw new TException(TExceptionType.TYPE_WRITE_FAIL);
        } finally {
            try {
                fos.flush();
                fos.close();
                is.close();
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
    }

    /**
     * 获取临时文件
     * @param context
     * @param photoUri
     * @return
     */
    public static File getTempFile(Activity context, Uri photoUri)throws TException {
        String minType=getMimeType(context, photoUri);
        if (!checkMimeType(context,minType))throw new TException(TExceptionType.TYPE_NOT_IMAGE);
        File filesDir=context.getExternalFilesDir(Environment.DIRECTORY_PICTURES);
        if (!filesDir.exists())filesDir.mkdirs();
        File photoFile = new File(filesDir, UUID.randomUUID().toString() + "." +minType );
        return photoFile;
    }

    /**
     * 检查文件类型是否是图片
     * @param minType
     * @return
     */
    public static boolean checkMimeType(Context context,String minType) {
        boolean isPicture=TextUtils.isEmpty(minType)?false:".jpg|.gif|.png|.bmp|.jpeg|.webp|".contains(minType.toLowerCase())?true:false;
        if (!isPicture)Toast.makeText(context,context.getResources().getText(R.string.tip_type_not_image),Toast.LENGTH_SHORT).show();
        return isPicture;
    }

    /**
     * To find out the extension of required object in given uri
     * Solution by http://stackoverflow.com/a/36514823/1171484
     */
    public static String getMimeType(Activity context, Uri uri) {
        String extension;
        //Check uri format to avoid null
        if (ContentResolver.SCHEME_CONTENT.equals(uri.getScheme())) {
            //If scheme is a content
            extension = MimeTypeMap.getSingleton().getExtensionFromMimeType(context.getContentResolver().getType(uri));
            if (TextUtils.isEmpty(extension))extension=MimeTypeMap.getFileExtensionFromUrl(Uri.fromFile(new File(uri.getPath())).toString());
        } else {
            //If scheme is a File
            //This will replace white spaces with %20 and also other special characters. This will avoid returning null values on file name with spaces and special characters.
            extension = MimeTypeMap.getFileExtensionFromUrl(Uri.fromFile(new File(uri.getPath())).toString());
            if (TextUtils.isEmpty(extension))extension=MimeTypeMap.getSingleton().getExtensionFromMimeType(context.getContentResolver().getType(uri));
        }
        if(TextUtils.isEmpty(extension)){
            extension=getMimeTypeByFileName(TUriParse.getFileWithUri(uri,context).getName());
        }
        return extension;
    }
    public static String getMimeTypeByFileName(String fileName){
        return fileName.substring(fileName.lastIndexOf("."),fileName.length());
    }
 } public class TUriParse {
    private static final String TAG = IntentUtils.class.getName();

    /**
     * 将scheme为file的uri转成FileProvider 提供的content uri
     * @param context
     * @param uri
     * @return
     */
    public static Uri convertFileUriToFileProviderUri(Context context,Uri uri){
        if(uri==null)return null;
        if(ContentResolver.SCHEME_FILE.equals(uri.getScheme())){
            return getUriForFile(context,new File(uri.getPath()));
        }
        return uri;

    }

    /**
     * 获取一个临时的Uri, 文件名随机生成
     * @param context
     * @return
     */
    public static Uri getTempUri(Context context){
        String timeStamp = new SimpleDateFormat("yyyyMMdd_HHmmss", Locale.getDefault()).format(new Date());
        File file=new File(Environment.getExternalStorageDirectory(), "/images/"+timeStamp + ".jpg");
        if (!file.getParentFile().exists())file.getParentFile().mkdirs();
        return getUriForFile(context,file);
    }

    /**
     * 获取一个临时的Uri, 通过传入字符串路径
     *
     * @param context
     * @param path
     * @return
     */
    public static Uri getTempUri(Context context, String path) {
        File file = new File(path);
        return getTempUri(context, file);
    }

    /**
     * 获取一个临时的Uri, 通过传入File对象
     * @param context
     * @return
     */
    public static Uri getTempUri(Context context, File file){
        if (!file.getParentFile().exists())file.getParentFile().mkdirs();
        return getUriForFile(context,file);
    }

    /**
     * 创建一个用于拍照图片输出路径的Uri (FileProvider)
     * @param context
     * @return
     */
    public static Uri getUriForFile(Context context, File file) {
        return FileProvider.getUriForFile(context,TConstant.getFileProviderName(context), file);
    }

    /**
     * 将TakePhoto 提供的Uri 解析出文件绝对路径
     * @param uri
     * @return
     */
    public static String parseOwnUri(Context context,Uri uri){
        if(uri==null)return null;
        String path;
        if(TextUtils.equals(uri.getAuthority(),TConstant.getFileProviderName(context))){
            path=new File(uri.getPath().replace("camera_photos/","")).getAbsolutePath();
        }else {
            path=uri.getPath();
        }
        return path;
    }
    /**
     * 通过URI获取文件的路径
     * @param uri
     * @param activity
     * @return
     * Author JPH
     * Date 2016/6/6 0006 20:01
     */
    public static String getFilePathWithUri(Uri uri, Activity activity)throws TException {
        if(uri==null){
            Log.w(TAG,"uri is null,activity may have been recovered?");
            throw new TException(TExceptionType.TYPE_URI_NULL);
        }
        File picture=getFileWithUri(uri,activity);
        String picturePath=picture==null? null:picture.getPath();
        if (TextUtils.isEmpty(picturePath))throw new TException(TExceptionType.TYPE_URI_PARSE_FAIL);
        if (!TImageFiles.checkMimeType(activity,TImageFiles.getMimeType(activity,uri)))throw new TException(TExceptionType.TYPE_NOT_IMAGE);
        return picturePath;
    }
    /**
     * 通过URI获取文件
     * @param uri
     * @param activity
     * @return
     * Author JPH
     * Date 2016/10/25
     */
    public static File getFileWithUri(Uri uri, Activity activity) {
        String picturePath = null;
        String scheme=uri.getScheme();
        if (ContentResolver.SCHEME_CONTENT.equals(scheme)){
            String[] filePathColumn = {MediaStore.Images.Media.DATA};
            Cursor cursor = activity.getContentResolver().query(uri,
                    filePathColumn, null, null, null);//从系统表中查询指定Uri对应的照片
            cursor.moveToFirst();
            int columnIndex = cursor.getColumnIndex(filePathColumn[0]);
            if(columnIndex>=0){
                picturePath = cursor.getString(columnIndex);  //获取照片路径
            }else if(TextUtils.equals(uri.getAuthority(),TConstant.getFileProviderName(activity))){
                picturePath=parseOwnUri(activity,uri);
            }
            cursor.close();
        }else if (ContentResolver.SCHEME_FILE.equals(scheme)){
            picturePath=uri.getPath();
        }
        return TextUtils.isEmpty(picturePath)? null:new File(picturePath);
    }
    /**
     * 通过从文件中得到的URI获取文件的路径
     * @param uri
     * @param activity
     * @return
     * Author JPH
     * Date 2016/6/6 0006 20:01
     */
    public static String getFilePathWithDocumentsUri(Uri uri,Activity activity) throws TException {
        if(uri==null){
            Log.e(TAG,"uri is null,activity may have been recovered?");
            return null;
        }
        if (ContentResolver.SCHEME_CONTENT.equals(uri.getScheme())&&uri.getPath().contains("document")){
            File tempFile = TImageFiles.getTempFile(activity,uri);
            try {
                TImageFiles.inputStreamToFile(activity.getContentResolver().openInputStream(uri),tempFile);
                return tempFile.getPath();
            } catch (FileNotFoundException e) {
                e.printStackTrace();
                throw new TException(TExceptionType.TYPE_NO_FIND);
            }
        }else {
            return getFilePathWithUri(uri,activity);
        }
    }
} public class TUtils {
    private static final String TAG = IntentUtils.class.getName();


    /**
     * 将Image集合转换成Uri集合
     * @param images
     * @return
     */
    public static ArrayList<Uri> convertImageToUri(Context context,ArrayList<Image>images) throws TException {
        ArrayList<Uri>uris=new ArrayList();
        for(Image image:images){
            uris.add(FileProvider.getUriForFile(context,TConstant.getFileProviderName(context), new File(image.path)));
        }
        return uris;
    }
    /**
     * 将Image集合转换成TImage集合
     * @param images
     * @return
     */
    public static ArrayList<TImage> getTImagesWithImages(ArrayList<Image>images, TImage.FromType fromType){
        ArrayList<TImage>tImages=new ArrayList();
        for(Image image:images){
            tImages.add(TImage.of(image.path, fromType));
        }
        return tImages;
    }
    /**
     * 将Uri集合转换成TImage集合
     * @param uris
     * @return
     */
    public static ArrayList<TImage> getTImagesWithUris(ArrayList<Uri>uris, TImage.FromType fromType){
        ArrayList<TImage>tImages=new ArrayList();
        for(Uri uri:uris){
            tImages.add(TImage.of(uri, fromType));
        }
        return tImages;
    }
    /**
     * @param contextWrap
     * @param intentWap
     */
    public static void startActivityForResult(TContextWrap contextWrap,TIntentWap intentWap){
        if (contextWrap.getFragment()!=null){
            contextWrap.getFragment().startActivityForResult(intentWap.getIntent(),intentWap.getRequestCode());
        }else {
            contextWrap.getActivity().startActivityForResult(intentWap.getIntent(),intentWap.getRequestCode());
        }
    }
    /**
     * 安全地发送Intent
     * @param contextWrap
     * @param intentWapList 要发送的Intent以及候选Intent
     * @param defaultIndex 默认发送的Intent
     * @param isCrop 是否为裁切照片的Intent
     * @throws TException
     */
    public static void sendIntentBySafely(TContextWrap contextWrap, List<TIntentWap> intentWapList, int defaultIndex, boolean isCrop)throws TException{
        if (defaultIndex+1>intentWapList.size())throw new TException(isCrop? TExceptionType.TYPE_NO_MATCH_PICK_INTENT:TExceptionType.TYPE_NO_MATCH_CROP_INTENT);
        TIntentWap intentWap=intentWapList.get(defaultIndex);
        List result=contextWrap.getActivity().getPackageManager().queryIntentActivities(intentWap.getIntent(),PackageManager.MATCH_ALL);
        if (result.isEmpty()){
            sendIntentBySafely(contextWrap,intentWapList,++defaultIndex,isCrop);
        }else {
            startActivityForResult(contextWrap,intentWap);
        }
    }
    /**
     * 拍照前检查是否有相机
     **/
    public static void captureBySafely(TContextWrap contextWrap,TIntentWap intentWap)throws TException{
        List result=contextWrap.getActivity().getPackageManager().queryIntentActivities(intentWap.getIntent(),PackageManager.MATCH_ALL);
        if (result.isEmpty()){
            Toast.makeText(contextWrap.getActivity(),contextWrap.getActivity().getResources().getText(R.string.tip_no_camera),Toast.LENGTH_SHORT).show();
            throw new TException(TExceptionType.TYPE_NO_CAMERA);
        }else {
            startActivityForResult(contextWrap,intentWap);
        }
    }
    /**
     * 通过第三方工具裁切照片，当没有第三方裁切工具时，会自动使用自带裁切工具进行裁切
     * @param contextWrap
     * @param imageUri
     * @param outPutUri
     * @param options
     */
    public static void cropWithOtherAppBySafely(TContextWrap contextWrap, Uri imageUri, Uri outPutUri, CropOptions options){
        Intent nativeCropIntent=IntentUtils.getCropIntentWithOtherApp(imageUri, outPutUri,options);
        List result=contextWrap.getActivity().getPackageManager().queryIntentActivities(nativeCropIntent,PackageManager.MATCH_ALL);
        if (result.isEmpty()){
            cropWithOwnApp(contextWrap,imageUri,outPutUri,options);
        }else {
//            try {
//                imageUri=Uri.fromFile(new File(TUriParse.getFilePathWithDocumentsUri(imageUri,contextWrap.getActivity())));
//            } catch (TException e) {
//                e.printStackTrace();
//            }
            startActivityForResult(contextWrap,new TIntentWap(IntentUtils.getCropIntentWithOtherApp(imageUri, outPutUri,options), TConstant.RC_CROP));
        }
    }
    /**
     * 通过TakePhoto自带的裁切工具裁切图片
     * @param contextWrap
     * @param imageUri
     * @param outPutUri
     * @param options
     */
    public static void cropWithOwnApp(TContextWrap contextWrap, Uri imageUri, Uri outPutUri, CropOptions options){
        if (options.getAspectX()*options.getAspectY()>0){
            if (contextWrap.getFragment()!=null){
                Crop.of(imageUri, outPutUri).withAspect(options.getAspectX(),options.getAspectY()).start(contextWrap.getActivity(),contextWrap.getFragment());
            }else {
                Crop.of(imageUri, outPutUri).withAspect(options.getAspectX(),options.getAspectY()).start(contextWrap.getActivity());
            }
        }else if (options.getOutputX()*options.getOutputY()>0){
            if (contextWrap.getFragment()!=null){
                Crop.of(imageUri, outPutUri).withMaxSize(options.getOutputX(),options.getOutputY()).start(contextWrap.getActivity(),contextWrap.getFragment());
            }else {
                Crop.of(imageUri, outPutUri).withMaxSize(options.getOutputX(),options.getOutputY()).start(contextWrap.getActivity());
            }
        }else {
            if (contextWrap.getFragment()!=null){
                Crop.of(imageUri, outPutUri).asSquare().start(contextWrap.getActivity(),contextWrap.getFragment());
            }else {
                Crop.of(imageUri, outPutUri).asSquare().start(contextWrap.getActivity());
            }
        }
    }
    /**
     * 是否裁剪之后返回数据
     **/
    public static boolean isReturnData() {
        String release= Build.VERSION.RELEASE;
        int sdk= Build.VERSION.SDK_INT;
        Log.i(TAG,"release:"+release+"sdk:"+sdk);
        String manufacturer = android.os.Build.MANUFACTURER;
        if (!TextUtils.isEmpty(manufacturer)) {
            if (manufacturer.toLowerCase().contains("lenovo")) {//对于联想的手机返回数据
                return true;
            }
        }
//        if (sdk>=21){//5.0或以上版本要求返回数据
//            return  true;
//        }
        return false;
    }
    /**
     * 显示圆形进度对话框
     *
     * @author JPH
     * Date 2014-12-12 下午7:04:09
     * @param activity
     * @param progressTitle
     *            显示的标题
     * @return
     */
    public static ProgressDialog showProgressDialog(final Activity activity,
                                                    String... progressTitle) {
        if(activity==null||activity.isFinishing())return null;
        String title = activity.getResources().getString(R.string.tip_tips);
        if (progressTitle != null && progressTitle.length > 0)
            title = progressTitle[0];
        ProgressDialog progressDialog = new ProgressDialog(activity);
        progressDialog.setTitle(title);
        progressDialog.setCancelable(false);
        progressDialog.show();
        return progressDialog;
    }
}
import android.app.Activity;
import android.app.ProgressDialog;
import android.content.Intent;
import android.graphics.Bitmap;
import android.net.Uri;
import android.os.Build;
import android.os.Bundle;
import android.widget.Toast;
import androidx.fragment.app.Fragment;
import com.darsh.multipleimageselect.helpers.Constants;
import com.darsh.multipleimageselect.models.Image;
import com.jph.takephoto.R;
import com.jph.takephoto.compress.CompressConfig;
import com.jph.takephoto.compress.CompressImage;
import com.jph.takephoto.compress.CompressImageImpl;
import com.jph.takephoto.model.CropOptions;
import com.jph.takephoto.model.MultipleCrop;
import com.jph.takephoto.model.TContextWrap;
import com.jph.takephoto.model.TExceptionType;
import com.jph.takephoto.model.TImage;
import com.jph.takephoto.model.TIntentWap;
import com.jph.takephoto.model.TResult;
import com.jph.takephoto.model.TakePhotoOptions;
import com.jph.takephoto.permission.PermissionManager;
import com.jph.takephoto.uitl.ImageRotateUtil;
import com.jph.takephoto.uitl.IntentUtils;
import com.jph.takephoto.uitl.TConstant;
import com.jph.takephoto.model.TException;
import com.jph.takephoto.uitl.TFileUtils;
import com.jph.takephoto.uitl.TImageFiles;
import com.jph.takephoto.uitl.TUriParse;
import com.jph.takephoto.uitl.TUtils;
import com.soundcloud.android.crop.Crop;
import java.io.File;
import java.util.ArrayList;
import java.util.Map;
                    }
                } else {
                    listener.takeCancel();
                }
                break;
            case TConstant.RC_PICK_PICTURE_FROM_CAPTURE_CROP://拍取照片,并裁剪
                if (resultCode == Activity.RESULT_OK) {
                    if(takePhotoOptions!=null&&takePhotoOptions.isCorrectImage())ImageRotateUtil.of().correctImage(contextWrap.getActivity(), tempUri);
                    try {
                        onCrop(tempUri, Uri.fromFile(new File(TUriParse.parseOwnUri(contextWrap.getActivity(), outPutUri))), cropOptions);
                    } catch (TException e) {
                        takeResult(TResult.of(TImage.of(outPutUri, fromType)), e.getDetailMessage());
                        e.printStackTrace();
                    }
                } else {
                    listener.takeCancel();
                }
                break;
            case TConstant.RC_PICK_PICTURE_FROM_CAPTURE://拍取照片
                if (resultCode == Activity.RESULT_OK) {
                    if(takePhotoOptions!=null&&takePhotoOptions.isCorrectImage())ImageRotateUtil.of().correctImage(contextWrap.getActivity(), outPutUri);
                    try {
                        takeResult(TResult.of(TImage.of(TUriParse.getFilePathWithUri(outPutUri, contextWrap.getActivity()), fromType)));
                    } catch (TException e) {
                        takeResult(TResult.of(TImage.of(outPutUri, fromType)), e.getDetailMessage());
                        e.printStackTrace();
                    }
                } else {
                    listener.takeCancel();
                }
                break;
            case TConstant.RC_CROP://裁剪照片返回结果
            case Crop.REQUEST_CROP://裁剪照片返回结果
                if (resultCode == Activity.RESULT_OK) {
                    if (multipleCrop != null) {
                        cropContinue(true);
                    } else {
                        try {
                            TImage image = TImage.of(TUriParse.getFilePathWithUri(outPutUri, contextWrap.getActivity()), fromType);
                            image.setCropped(true);
                            takeResult(TResult.of(image));
                        } catch (TException e) {
                            takeResult(TResult.of(TImage.of(outPutUri.getPath(), fromType)), e.getDetailMessage());
                            e.printStackTrace();
                        }
                    }
                } else if (resultCode == Activity.RESULT_CANCELED) {//裁剪的照片没有保存
                    if (multipleCrop != null) {
                        if (data != null) {
                            Bitmap bitmap = data.getParcelableExtra("data");//获取裁剪的结果数据
                            TImageFiles.writeToFile(bitmap, outPutUri);//将裁剪的结果写入到文件
                            cropContinue(true);
                        } else {
                            cropContinue(false);
                        }
                    } else {
                        if (data != null) {
                            Bitmap bitmap = data.getParcelableExtra("data");//获取裁剪的结果数据
                            TImageFiles.writeToFile(bitmap, outPutUri);//将裁剪的结果写入到文件

                            TImage image = TImage.of(outPutUri.getPath(), fromType);
                            image.setCropped(true);
                            takeResult(TResult.of(image));
                        } else {
                            listener.takeCancel();
                        }
                    }
                } else {
                    if (multipleCrop != null) {
                        cropContinue(false);
                    } else {
                        listener.takeCancel();
                    }
                }
                break;
            case TConstant.RC_PICK_MULTIPLE://多选图片返回结果
                if (resultCode == Activity.RESULT_OK && data != null) {
                    ArrayList<Image> images = data.getParcelableArrayListExtra(Constants.INTENT_EXTRA_IMAGES);
                    if (cropOptions != null) {
                        try {
                            onCrop(MultipleCrop.of(TUtils.convertImageToUri(contextWrap.getActivity(), images), contextWrap.getActivity(), fromType), cropOptions);
                        } catch (TException e) {
                            cropContinue(false);
                            e.printStackTrace();
                        }
                    } else {
                        takeResult(TResult.of(TUtils.getTImagesWithImages(images, fromType)));
                    }

                } else {
                    listener.takeCancel();
                }
                break;
            default:
                break;
        }
    }

    @Override
    public void onPickMultiple(int limit) {
        if (PermissionManager.TPermissionType.WAIT.equals(permissionType)) return;
        TUtils.startActivityForResult(contextWrap, new TIntentWap(IntentUtils.getPickMultipleIntent(contextWrap, limit), TConstant.RC_PICK_MULTIPLE));
    }

    @Override
    public void onPickMultipleWithCrop(int limit, CropOptions options) {
        this.fromType = TImage.FromType.OTHER;
        onPickMultiple(limit);
        this.cropOptions = options;
    }

    /**
     * -----crop------
     **/
    @Override
    public void onCrop(Uri imageUri, Uri outPutUri, CropOptions options) throws TException {
        if (PermissionManager.TPermissionType.WAIT.equals(permissionType)) return;
        this.outPutUri = outPutUri;
        if (!TImageFiles.checkMimeType(contextWrap.getActivity(), TImageFiles.getMimeType(contextWrap.getActivity(), imageUri))) {
            Toast.makeText(contextWrap.getActivity(), contextWrap.getActivity().getResources().getText(R.string.tip_type_not_image), Toast.LENGTH_SHORT).show();
            throw new TException(TExceptionType.TYPE_NOT_IMAGE);