Android调起相册,拍照,裁剪+6.0权限适配大总结

以前研究过Android调用系统相机、相册、裁剪功能,写过demo。
上周在项目中遇到了Android图片裁剪的坑,于是带着不屑的态度去解bug,结果被狠狠的叮了一口。于是,眉头一皱,向上帝保证要把这块弄懂,并整成一个简单的工具类为公司项目而用。不扯废话,开始。


一、调用系统相机:

/**
 * 调用系统拍照
 *
 * @param activity 上下文
 * @param saveUri  保存路径
 */
public static void startCamera(Activity activity, Uri saveUri) {
	Intent intent = new Intent(MediaStore.ACTION_IMAGE_CAPTURE);
	//这是了此行代码,onActivityResult的intent == null
	intent.putExtra(MediaStore.EXTRA_OUTPUT, saveUri);
	activity.startActivityForResult(intent, CropUtils.REQUEST_CODE_CAMERA);
}

代码很简单,使用MediaStore.ACTION_IMAGE_CAPTURE就可以调起系统拍照界面。需要注意的是


//这是了此行代码,onActivityResult的intent == null
intent.putExtra(MediaStore.EXTRA_OUTPUT, saveUri);


如果设置了EXTRA_OUTPUT的保存路径,则在onActivityResult方法中,intent == null。
此时,你想获取图片去展示、裁剪等操作,需要用saveUri对象了。这么获取到bitmap对象:

public static Bitmap uriToBitmap(Activity activity, Uri uri) {
	if (activity == null || uri == null) {
		return null;
	}
	Bitmap bitmap = null;
	try {
		bitmap = BitmapFactory.decodeStream(activity.getContentResolver().openInputStream(uri));
	} catch (FileNotFoundException e) {
		e.printStackTrace();
	}
	return bitmap;
}

如果你没有设置这个EXTRA_OUTPUT,那拍照后的照片存到哪里去了?不急,拍照完后系统会回调你的Activity的onActivityResult方法,照片会在intent中返回,可以通过如下方法获取到拍照后返回的bitmap对象:

bitmap = intent.getExtras().get("data");
bitmap = intent.getExtras().getParcelable("data");
bitmap = intent.getParcelableExtra("data");
三种方法都试过,可用,等效。

二、调用系统相册:

/**
 * 调用系统相册
 *
 * @param activity 上下文
 */
public static void startAlbum(Activity activity) {
	Intent intent = new Intent(Intent.ACTION_PICK);//直接进相册
	//先进到文件夹选择界面,再选择相册
	//Intent intent = new Intent(Intent.ACTION_GET_CONTENT);
	intent.setDataAndType(MediaStore.Images.Media.EXTERNAL_CONTENT_URI, "image/*");
	activity.startActivityForResult(intent, CropUtils.REQUEST_CODE_ALBUM);
}

需要使用Intent.ACTION_PICK即可,直接进入到相册图片选择界面。
我还见过有人用Intent.ACTION_GET_CONTENT,经过测试后发现,这个action是会先进到选择文件夹界面(相册、文件夹、其他),选择完相册后才会进入到相册图片选择界面。


根据你的需求合理使用,不要盲目相信别人说的。拿到别人的代码,一定要动手实验,然后理解代码的含义和用法。不写这行 行不行?




调用系统相册应该和拍照一样,也可以设置输入目录,然后去展示或裁剪时用你保存的那个uri即可。
如果不设置,应该在onActivityResult的intent中可以获取到。跟相机一样。


三、图片裁剪:

/**
 * 图片裁剪两个大坑:<br/>
 * 1、intent.setDataAndType(sourceUri, "image/*");参数不要分开写,别问为什么 ,自己试。 <br/>
 * 2、intent.putExtra("return-data", true)时,可以在onActivityResult中获取bitmap。获取方法如下:<br/>
 * //bitmap = intent.getParcelableExtra("data");<br/>
 * //bitmap = intent.getExtras().getParcelable("data");<br/>
 * 直接在intent中通过"data"这个key获取bitmap对象。上面两种方法等效。<br/>
 * 且不需要设置//intent.putExtra(MediaStore.EXTRA_OUTPUT, saveUri);<br/>
 * 3、intent.putExtra("return-data", false)时,可以在onActivityResult中获取裁剪后保存的uri。获取方法如下:<br/>
 * Uri uri = intent.getData();<br/>
 * 如果此时设置了//intent.putExtra(MediaStore.EXTRA_OUTPUT, saveUri);<br/>
 * 则intent.getData()、intent.getParcelableExtra("data")、intent.getExtras().getParcelable("data")全部为null<br/>
 * 裁剪的uri保存到saveUri中了。切记这点。<br/>
 *
 * @param activity    上下文对象
 * @param sourceUri   待裁剪的uri
 * @param requestCode 裁剪请求码
 */
public static void startCrop(Activity activity, Uri sourceUri, int requestCode) {
	//saveUri不要加null判断,上面有重载的方法没传递saveUri
	if (sourceUri == null || activity == null) {
		return;
	}
	//是否以bitmap的形式返回
	boolean isBitmap = false;
	if (requestCode == REQUEST_CODE_CROP_OF_BITMAP) {
		isBitmap = true;
	} else if (requestCode == REQUEST_CODE_CROP_OF_URI) {
		isBitmap = false;
	}
	Intent intent = new Intent("com.android.camera.action.CROP");
	//***此参数,不能分开写***
	intent.setDataAndType(sourceUri, "image/*");
	intent.putExtra("scale", true);//去黑边
	intent.putExtra("crop", "true");//是否可以裁剪
	intent.putExtra("circleCrop", "true");//圆形裁剪区域
	intent.putExtra("aspectX", 1);// 设置剪切框1:1比例
	intent.putExtra("aspectY", 1);// 设置剪切框1:1比例
	intent.putExtra("outputX", 200);//输出图片宽
	intent.putExtra("outputY", 200);//输出图片高
	intent.putExtra("noFaceDetection", false); //是否使用人脸识别
	intent.putExtra("return-data", isBitmap);//是否将数据保留在Bitmap中返回
	/*if (!isBitmap && saveUri != null) {
		//裁剪后图片的保存路径
		//设置了此行代码后intent.getData() == null
		intent.putExtra(MediaStore.EXTRA_OUTPUT, saveUri);
	}*/
	intent.putExtra("outputFormat", Bitmap.CompressFormat.JPEG.toString());
	activity.startActivityForResult(intent, requestCode);
}

图片裁剪的代码也封装好了,每行代码都有注释,尤其看下方法头部的文档说明。
我想总结的一点是:
我们在使用自功能时,会在某些机型上碰到崩溃,是因为裁剪后返回的是bitmap,占用内存过大,导致系统崩溃。那该怎么办呢?
1、继续让系统返回bitmp对象,在onActivityResult中intent中获取bitmap。
但是需要修改:
outputX和outputY参数不要太大;
确保return-data值为true;
不要设置MediaStore.EXTRA_OUTPUT。


2、不这么玩了,使用uri返回,避免直接加载bitmap导致内存崩溃。
需要注意设置:
outputX和outputY可以根据自己的需要设置,但是要考虑到后续加载uri时会不会又崩溃呢?
确保return-data值为false。
此方法到此即可。但是我在某些机型上测试,发现在onActivityResult中的intent为null,很是费解,于是同时设置了intent.putExtra(MediaStore.EXTRA_OUTPUT, saveUri)。在后续要处理裁剪后的图片时,用我保存的路径saveUri即可,而不要去关心intent中的各种值了。


很麻烦?没有。
一个原则:
1、不论是系统相机、相册、裁剪,只要设置了intent.putExtra(MediaStore.EXTRA_OUTPUT, saveUri),则在onActivityResult中要操作图片时,值接用自己的saveUri。不用去关心返回的intent是否有数据和怎么获取。同时还可以避免bitmap导致内存崩溃。
2、如果没有设置了,那系统很可能直接返回了bitmap对象,在onActivityResult中的intent中获取。
3、如果是图片裁剪,return-data值为false时,没有设置intent.putExtra(MediaStore.EXTRA_OUTPUT, saveUri),系统也有可能会返回uri,在onActivityResult的intent中,使用intent.getData()方法获取。但是部分手机获取不到,万一获取不到那就还是设置个intent.putExtra(MediaStore.EXTRA_OUTPUT, saveUri)吧,兼容性高。




四、简单封装工具类,调用简单:

以上是我对基础知识的理解分析。接下来我提供一个自己封装的工具类和用法。

package com.dk.photoviewcrop;

import android.app.Activity;
import android.content.Intent;
import android.content.res.Resources;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.graphics.drawable.BitmapDrawable;
import android.graphics.drawable.Drawable;
import android.net.Uri;
import android.provider.MediaStore;
import android.text.TextUtils;

import java.io.FileNotFoundException;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.Locale;

/**
 * @Author: duke
 * @DateTime: 2017-05-27 16:21
 * @Description: 系统拍照、选择相册、裁剪工具类
 */
public class CropUtils {
    public static final int REQUEST_CODE_CAMERA = 0xF1;
    public static final int REQUEST_CODE_ALBUM = 0xF2;
    public static final int REQUEST_CODE_CROP_OF_BITMAP = 0xF3;
    public static final int REQUEST_CODE_CROP_OF_URI = 0xF4;

    /**
     * 调用系统拍照
     *
     * @param activity 上下文
     * @param saveUri  保存路径
     */
    public static void startCamera(Activity activity, Uri saveUri) {
        Intent intent = new Intent(MediaStore.ACTION_IMAGE_CAPTURE);
        //这是了此行代码,onActivityResult的intent == null
        intent.putExtra(MediaStore.EXTRA_OUTPUT, saveUri);
        activity.startActivityForResult(intent, CropUtils.REQUEST_CODE_CAMERA);
    }

    /**
     * 调用系统相册
     *
     * @param activity 上下文
     */
    public static void startAlbum(Activity activity) {
        Intent intent = new Intent(Intent.ACTION_PICK);//直接进相册
        //先进到文件夹选择界面,再选择相册
        //Intent intent = new Intent(Intent.ACTION_GET_CONTENT);
        intent.setDataAndType(MediaStore.Images.Media.EXTERNAL_CONTENT_URI, "image/*");
        activity.startActivityForResult(intent, CropUtils.REQUEST_CODE_ALBUM);
    }

    public static void startCrop(Activity activity, Intent intent, Uri saveUri, int requestCode) {
        if (intent == null || activity == null) {
            return;
        }
        startCrop(activity, intent.getData(), saveUri, requestCode);
    }

    /**
     * 图片裁剪两个大坑:<br/>
     * 1、intent.setDataAndType(sourceUri, "image/*");参数不要分开写,别问为什么 ,自己试。 <br/>
     * 2、intent.putExtra("return-data", true)时,可以在onActivityResult中获取bitmap。获取方法如下:<br/>
     * //bitmap = intent.getParcelableExtra("data");<br/>
     * //bitmap = intent.getExtras().getParcelable("data");<br/>
     * 直接在intent中通过"data"这个key获取bitmap对象。上面两种方法等效。<br/>
     * 且不需要设置//intent.putExtra(MediaStore.EXTRA_OUTPUT, saveUri);<br/>
     * 3、intent.putExtra("return-data", false)时,可以在onActivityResult中获取裁剪后保存的uri。获取方法如下:<br/>
     * Uri uri = intent.getData();<br/>
     * 如果此时设置了//intent.putExtra(MediaStore.EXTRA_OUTPUT, saveUri);<br/>
     * 则intent.getData()、intent.getParcelableExtra("data")、intent.getExtras().getParcelable("data")全部为null<br/>
     * 裁剪的uri保存到saveUri中了。切记这点。<br/>
     *
     * @param activity    上下文对象
     * @param sourceUri   待裁剪的uri
     * @param saveUri     裁剪结果uri
     * @param requestCode 裁剪请求码
     */
    public static void startCrop(Activity activity, Uri sourceUri, Uri saveUri, int requestCode) {
        //saveUri不要加null判断,上面有重载的方法没传递saveUri
        if (sourceUri == null || activity == null) {
            return;
        }
        //是否以bitmap的形式返回
        boolean isBitmap = false;
        if (requestCode == REQUEST_CODE_CROP_OF_BITMAP) {
            isBitmap = true;
        } else if (requestCode == REQUEST_CODE_CROP_OF_URI) {
            isBitmap = false;
        }
        Intent intent = new Intent("com.android.camera.action.CROP");
        //***此参数,不能分开写***
        intent.setDataAndType(sourceUri, "image/*");
        intent.putExtra("scale", true);//去黑边
        intent.putExtra("crop", "true");//是否可以裁剪
        intent.putExtra("circleCrop", "true");//圆形裁剪区域
        intent.putExtra("aspectX", 1);// 设置剪切框1:1比例
        intent.putExtra("aspectY", 1);// 设置剪切框1:1比例
        intent.putExtra("outputX", 200);//输出图片宽
        intent.putExtra("outputY", 200);//输出图片高
        intent.putExtra("noFaceDetection", false); //是否使用人脸识别
        intent.putExtra("return-data", isBitmap);//是否将数据保留在Bitmap中返回
        if (!isBitmap && saveUri != null) {
            //裁剪后图片的保存路径
            //设置了此行代码后intent.getData() == null
            intent.putExtra(MediaStore.EXTRA_OUTPUT, saveUri);
        }
        intent.putExtra("outputFormat", Bitmap.CompressFormat.JPEG.toString());
        activity.startActivityForResult(intent, requestCode);
    }

    public static Bitmap onActivityResult(int requestCode, int resultCode, Intent data, Uri cameraUri, Activity activity) {
        return onActivityResult(requestCode, resultCode, data, cameraUri, activity, null);
    }

    /**
     * 裁剪回调
     *
     * @param requestCode 请求码
     * @param resultCode  结果码
     * @param data        结果intent(从相册选择会走这里返回数据)
     * @param cameraUri   拍照结果保存路径(相机拍照的返回设置到这里了)
     * @param activity    上下文
     * @param listener    回调函数
     */
    public static Bitmap onActivityResult(int requestCode, int resultCode, Intent data, Uri cameraUri, Activity activity, OnCropReturnListener listener) {
        if (requestCode != CropUtils.REQUEST_CODE_CAMERA
                && requestCode != CropUtils.REQUEST_CODE_ALBUM
                && requestCode != CropUtils.REQUEST_CODE_CROP_OF_BITMAP
                && requestCode != CropUtils.REQUEST_CODE_CROP_OF_URI) {
            return null;
        }
        if (activity == null) {
            return null;
        }
        //测试了红米4手机,6.0系统,resultCode貌似等于RESULT_CANCELED
        /*if (resultCode != Activity.RESULT_OK) {
            return null;
        }*/
        Bitmap bitmap = null;
        switch (requestCode) {
            case CropUtils.REQUEST_CODE_CAMERA:
                //拍照返回,开始裁剪图片
                if (cameraUri == null) {
                    if (data != null) {
                        //拍照时设置了MediaStore.EXTRA_OUTPUT,则此时data == null
                        cameraUri = data.getData();
                    }
                }
                /**
                 * 裁剪结果继续放到cameraUri中
                 */
                CropUtils.startCrop(activity, cameraUri, cameraUri, CropUtils.REQUEST_CODE_CROP_OF_URI);
                break;
            case CropUtils.REQUEST_CODE_ALBUM:
                //选择相册返回,开始裁剪图片
                /**
                 * 裁剪结果继续放到cameraUri中
                 */
                CropUtils.startCrop(activity, data, cameraUri, CropUtils.REQUEST_CODE_CROP_OF_URI);
                break;
            case CropUtils.REQUEST_CODE_CROP_OF_URI:
            case CropUtils.REQUEST_CODE_CROP_OF_BITMAP:
                //裁剪结果
                bitmap = CropUtils.getCropBitmap(activity, data, cameraUri, requestCode);
                if (listener != null) {
                    listener.onCropReturn(bitmap);
                }
                break;
        }
        return bitmap;
    }

    /**
     * 获取裁剪后的图片
     *
     * @param activity    上下文
     * @param intent      裁剪返回的intent
     * @param requestCode 裁剪请求码
     * @return bitmap
     */
    public static Bitmap getCropBitmap(Activity activity, Intent intent, int requestCode) {
        return getCropBitmap(activity, intent, null, requestCode);
    }

    /**
     * 获取裁剪后的图片
     *
     * @param activity    上下文
     * @param intent      裁剪返回的intent
     * @param saveUri     裁剪返回图片保存路径
     * @param requestCode 裁剪请求码
     * @return bitmap
     */
    public static Bitmap getCropBitmap(Activity activity, Intent intent, Uri saveUri, int requestCode) {
        //saveUri不要加null判断,上面有重载的方法没传递saveUri
        if (activity == null) {
            return null;
        }
        Bitmap bitmap = null;
        if (requestCode == REQUEST_CODE_CROP_OF_BITMAP) {
            //此行代码与intent.getExtras().getParcelable("data");等效
            if (intent == null) {
                return null;
            }
            bitmap = intent.getParcelableExtra("data");
            if (bitmap != null) {
                return bitmap;
            }
            //intent.getExtras().get("data");
            bitmap = intent.getExtras().getParcelable("data");
            if (bitmap != null) {
                return bitmap;
            }
        } else if (requestCode == REQUEST_CODE_CROP_OF_URI) {
            if (saveUri != null) {
                bitmap = uriToBitmap(activity, saveUri);
                if (bitmap != null) {
                    return bitmap;
                }
            }
            //intent.putExtra(MediaStore.EXTRA_OUTPUT, saveUri);
            //如果裁剪时设置了MediaStore.EXTRA_OUTPUT,则intent.getData() == null
            if (intent == null) {
                return null;
            }
            Uri uri = intent.getData();
            if (uri != null) {
                bitmap = uriToBitmap(activity, uri);
                if (bitmap != null) {
                    return bitmap;
                }
            }
        }
        return bitmap;
    }

    public static Bitmap uriToBitmap(Activity activity, Uri uri) {
        if (activity == null || uri == null) {
            return null;
        }
        Bitmap bitmap = null;
        try {
            bitmap = BitmapFactory.decodeStream(activity.getContentResolver().openInputStream(uri));
        } catch (FileNotFoundException e) {
            e.printStackTrace();
        }
        return bitmap;
    }

    public static Drawable bitmap2Drawable(Resources resources, Bitmap bitmap) {
        if (resources == null || bitmap == null) {
            return null;
        }
        return new BitmapDrawable(resources, bitmap);
    }

    public static String getRandomFileName() {
        Date date = new Date(System.currentTimeMillis());
        SimpleDateFormat dateFormat = new SimpleDateFormat("yyyyMMdd_HHmmss", Locale.CHINESE);
        return "IMG_" + dateFormat.format(date) + ".jpg";
    }

    public static String getRandomFileName(String basePath) {
        if (TextUtils.isEmpty(basePath)) {
            return getRandomFileName();
        }
        if (!basePath.endsWith("/")) {
            basePath += "/";
        }
        return basePath + getRandomFileName();
    }

    public interface OnCropReturnListener {
        void onCropReturn(Bitmap bitmap);
    }
}

其实也没啥,三个功能的调用代码都在里面,注意各个功能的请求码。
试想下,如果一个项目中三个都有,都自己调用,都在onActivityResult中处理,逻辑是不是会增加?是。
于是我封装了onActivityResult函数,把所有与相机、相册、裁剪的回调封装到了工具类中。

/**
 * 裁剪回调
 *
 * @param requestCode 请求码
 * @param resultCode  结果码
 * @param data        结果intent
 * @param cameraUri   拍照结果保存路径
 * @param activity    上下文
 * @param listener    回调函数
 */
public static Bitmap onActivityResult(int requestCode, int resultCode, Intent data, Uri cameraUri, Activity activity, OnCropReturnListener listener) {
	if (requestCode != CropUtils.REQUEST_CODE_CAMERA
			&& requestCode != CropUtils.REQUEST_CODE_ALBUM
			&& requestCode != CropUtils.REQUEST_CODE_CROP_OF_BITMAP
			&& requestCode != CropUtils.REQUEST_CODE_CROP_OF_URI) {
		return null;
	}
	if (activity == null) {
		return null;
	}
	if (resultCode != Activity.RESULT_OK) {
		return null;
	}
	Bitmap bitmap = null;
	switch (requestCode) {
		case CropUtils.REQUEST_CODE_CAMERA:
			//拍照返回,开始裁剪图片
			Uri sourceUti = null;
			if (data != null) {
				//拍照时设置了MediaStore.EXTRA_OUTPUT,则此时data == null
				sourceUti = data.getData();
			}
			if (sourceUti == null && cameraUri != null) {
				sourceUti = cameraUri;
			}
			CropUtils.startCrop(activity, sourceUti, CropUtils.REQUEST_CODE_CROP_OF_URI);
			break;
		case CropUtils.REQUEST_CODE_ALBUM:
			//选择相册返回,开始裁剪图片
			CropUtils.startCrop(activity, data, CropUtils.REQUEST_CODE_CROP_OF_URI);
			break;
		case CropUtils.REQUEST_CODE_CROP_OF_URI:
		case CropUtils.REQUEST_CODE_CROP_OF_BITMAP:
			//裁剪结果
			bitmap = CropUtils.getCropBitmap(activity, data, cameraUri, requestCode);
			if (listener != null) {
				listener.onCropReturn(bitmap);
			}
			break;
	}
	return bitmap;
}

如果是相机、相册、裁剪功能,会被上面这个方法拦截处理。相机、相册返回后继续调用裁剪的方法。裁剪结束后会去处理bitmap,把得到的bitmap直接返回和回调返回。供调用者显示到UI上。


通过相机、相册、裁剪功能区获取bitmap,有可能是在intent中,intent有时还可能为null,有可能是自己定义的uri中。很麻烦?对。
于是我封装了一个工具方法:

/**
 * 获取裁剪后的图片
 *
 * @param activity    上下文
 * @param intent      裁剪返回的intent
 * @param saveUri     裁剪返回图片保存路径
 * @param requestCode 裁剪请求码
 * @return bitmap
 */
public static Bitmap getCropBitmap(Activity activity, Intent intent, Uri saveUri, int requestCode) {
	//saveUri不要加null判断,上面有重载的方法没传递saveUri
	if (activity == null || intent == null) {
		return null;
	}
	Bitmap bitmap = null;
	if (requestCode == REQUEST_CODE_CROP_OF_BITMAP) {
		//此行代码与intent.getExtras().getParcelable("data");等效
		bitmap = intent.getParcelableExtra("data");
		if (bitmap != null) {
			return bitmap;
		}
		//intent.getExtras().get("data");
		bitmap = intent.getExtras().getParcelable("data");
		if (bitmap != null) {
			return bitmap;
		}
	} else if (requestCode == REQUEST_CODE_CROP_OF_URI) {
		//intent.putExtra(MediaStore.EXTRA_OUTPUT, saveUri);
		//如果裁剪时设置了MediaStore.EXTRA_OUTPUT,则intent.getData() == null
		Uri uri = intent.getData();
		if (uri != null) {
			bitmap = uriToBitmap(activity, uri);
			if (bitmap != null) {
				return bitmap;
			}
		}
		if (saveUri != null) {
			bitmap = uriToBitmap(activity, saveUri);
			if (bitmap != null) {
				return bitmap;
			}
		}
	}
	return bitmap;
}


无论什么时候,统统给我intent和人为定义的uri(确实没有就给null)。我自己根据你裁剪的要求去获取bitmap。
REQUEST_CODE_CROP_OF_BITMAP,是裁剪时要求返回bitmap的,即return-data=true。
REQUEST_CODE_CROP_OF_URI,是裁剪时要求返回uri,并设置了MediaStore.EXTRA_OUTPUT。
两种不同的情况,获取处理后的bitmap方式不一样,不过你不用关心,我都干了。


方便吧?!


五、关键来看工具类的用法:

public class MainActivity extends AppCompatActivity {
	private Button btn1 = null;
	private Button btn2 = null;
	private ImageView imageView = null;
	private String basePath = Environment.getExternalStoragePublicDirectory(Environment.DIRECTORY_PICTURES).getAbsolutePath();
	private Uri cameraUri = Uri.fromFile(new File(CropUtils.getRandomFileName(basePath)));

	@Override
	protected void onCreate(Bundle savedInstanceState) {
		super.onCreate(savedInstanceState);
		setContentView(R.layout.activity_main);

		btn1 = (Button) findViewById(btnTake1);
		btn2 = (Button) findViewById(btnTake2);
		imageView = (ImageView) findViewById(lblImage);

		btn1.setOnClickListener(new View.OnClickListener() {
			@Override
			public void onClick(View v) {
				//相册中选择图片的action
				CropUtils.startAlbum(MainActivity.this);
			}
		});
		btn2.setOnClickListener(new View.OnClickListener() {

			@Override
			public void onClick(View v) {
				// 指定调用相机拍照后照片的储存路径
				CropUtils.startCamera(MainActivity.this, cameraUri);
			}
		});
	}

	protected void onActivityResult(int requestCode, int resultCode, Intent data) {
		super.onActivityResult(requestCode, resultCode, data);
		/*CropUtils.onActivityResult(requestCode, resultCode, data, cameraUri, this, new CropUtils.OnCropReturnListener() {
			@Override
			public void onCropReturn(Bitmap bitmap) {
				imageView.setImageBitmap(bitmap);
			}
		});*/
		/**
		 * 参数说明(请求码,结果码,intent对象,拍照uri,Activity,callback回调)
		 */
		Bitmap bitmap = CropUtils.onActivityResult(requestCode, resultCode, data, cameraUri, this);
		if (bitmap != null) {
			imageView.setImageBitmap(bitmap);
		}
	}
}



封装为的是什么?简单好用


注意看btn1、btn2两个按钮对相机、相册的调用代码。
注意看onActivityResult中对相机、相册、裁剪的处理。


对于6.0的系统需要注意Manifest.permission.WRITE_EXTERNAL_STORAGE, Manifest.permission.CAMERA两个动态权限。
对于小米手机,重要注意这个坑:
//测试了红米手机,6.0系统,resultCode貌似等于RESULT_CANCELED
/*if (resultCode != Activity.RESULT_OK) {
return null;
}*/

请注意清单文件注册权限
关于6.0权限,可以参考我的文章:
http://blog.csdn.net/fesdgasdgasdg/article/details/70540329


完事了。不多说,出去散步了。

demo下载地址:

http://download.csdn.net/detail/fesdgasdgasdg/9855448


  • 1
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值