一.使用系统相机拍照:
private void openCamera() {
File outputImage = new File(getExternalCacheDir(), "output_image.jpg");//获取应用关联文件缓存目录
try{
if(outputImage.exists()) {
outputImage.delete();//判断如果当前文件存在,则删除
}
outputImage.createNewFile();//创建新的文件
}catch (Exception e) {
e.printStackTrace();
}//这段逻辑相当于每次更新缓存文件
if(Build.VERSION.SDK_INT >= 24) {
//检查版本7.0以上,需要使用 FileProvider,否则会报FileUriException异常
imageUri = FileProvider.getUriForFile(this, "com.itcast.myopencamera.fileprovider", outputImage);
}else {
imageUri = Uri.fromFile(outputImage);//将文件转换成uri格式
}
Intent intent = new Intent("android.media.action.IMAGE_CAPTURE");//从已存在的相机应用中请求一个图片
intent.putExtra(MediaStore.EXTRA_OUTPUT,imageUri);//保存图像的路径和文件名
startActivityForResult(intent, 1);
}
private void getCameraPics(Intent data) {
try {
Logger.d(imageUri+"..."+path);
Bitmap bitmap = BitmapFactory.decodeStream(getContentResolver().openInputStream(imageUri));
imageView.setImageBitmap(bitmap);
} catch (FileNotFoundException e) {
e.printStackTrace();
}
}
@Override
protected void onActivityResult(int requestCode, int resultCode, Intent data) {
super.onActivityResult(requestCode, resultCode, data);
switch (requestCode) {
case 1:
if(resultCode == RESULT_OK) {
getCameraPics(data);
}
break;
}
}
先要指定相机拍照后,图片存放的位置。判断手机android版本,如果是7.0及以上系统,需要使用FileProvider来封装文件转换成Uri格式,否则系统会报FileUriException异常。如果是7.0以下的直接使用Uri.fromFile()来转换成Uri格式。调用系统相机,需要传递数据,用MediaStore.EXTRA_OUTPUT标识来保存设置的图片存放的路径和文件名。当拍照完并保存后,会回调onActivityResult()方法,使用BitmapFactory工厂将图片保存的文件直接转换成一个Bitmap对象,直接显示到ImageView控件上。
二.从相册中获取图片:
private void openPics() {
// //打开系统相册一:如果按下面的方式打开,图片uri地址不会被封装
// Intent intent = new Intent(Intent.ACTION_PICK, android.provider.MediaStore.Images.Media.EXTERNAL_CONTENT_URI);
// startActivityForResult(intent,0);
//打开系统相册方法二
Intent intent = new Intent("android.intent.action.GET_CONTENT");
intent.setType("image/*");
startActivityForResult(intent,0);
}
@RequiresApi(api = Build.VERSION_CODES.KITKAT)
private void handleImageOnKitKat(Intent data) {
String imagePath = null;
Uri uri = data.getData();
Logger.d(uri);//-----content://com.android.providers.media.documents/document/image%3A659
if(DocumentsContract.isDocumentUri(this,uri)) {
//如果是document类型的Uri,则通过document ID处理
String docId = DocumentsContract.getDocumentId(uri);
Logger.d(docId);//----- image:662
if("com.android.providers.media.documents".equals(uri.getAuthority())) {
Logger.d(uri.getAuthority());//----- com.android.providers.media.documents
String id = docId.split(":")[1];//解析出数字格式的id
Logger.d(id);//----662
String selection = MediaStore.Images.Media._ID + "=" + id;
Logger.d(selection);// -----_id=662
imagePath = getImagePath(MediaStore.Images.Media.EXTERNAL_CONTENT_URI,selection);
Logger.d(imagePath+"-----media.documents");//-----/storage/emulated/0/Pictures/04 慢速快门.jpg
}else if("com.android.providers.downloads.document".equals(uri.getAuthority())) {
Uri contentUri = ContentUris.withAppendedId(uri.parse("content://downloads/public_downloads"), Long.valueOf(docId));
imagePath = getImagePath(contentUri,null);
Logger.d(imagePath+"-----downloads.document");
}
}else if("content".equalsIgnoreCase(uri.getScheme())) {
//如果是content类型的uri,则使用普通方式处理
imagePath = getImagePath(uri,null);
}else if("file".equalsIgnoreCase(uri.getScheme())) {
//如果是file类型的uri,直接获取图片的路径即可
imagePath = uri.getPath();
}
displayImage(imagePath);
}
private void handleImageBeforeKitKat(Intent data) {
Uri uri = data.getData();//获取Android默认的Uri地址,地址格式为:/storage/emulated/0/Pictures/07 绚彩夜拍.jpg
String imagePath = getImagePath(uri, null);
Logger.d(imagePath);
displayImage(imagePath);
}
private String getImagePath(Uri uri,String selection) {
String path = null;
Cursor cursor = getContentResolver().query(uri, null, selection, null, null);
if(cursor != null) {
if(cursor.moveToFirst()) {
path = cursor.getString(cursor.getColumnIndex(MediaStore.Images.Media.DATA));
}
cursor.close();
}
return path;
}
private void displayImage(String imagePath) {
if(imagePath != null) {
Bitmap bitmap = BitmapFactory.decodeFile(imagePath);
imageView.setImageBitmap(bitmap);
}else {
Toast.makeText(this,"不存在图片",Toast.LENGTH_SHORT).show();
}
}
@Override
protected void onActivityResult(int requestCode, int resultCode, Intent data) {
super.onActivityResult(requestCode, resultCode, data);
switch (requestCode) {
case 0:
if(resultCode == RESULT_OK) {
if(Build.VERSION.SDK_INT < 19) {
handleImageBeforeKitKat(data);//4.4版本以下处理图片的uri地址
}else {
handleImageOnKitKat(data);//4.4版本以上处理图片的uri地址
}
}
break;
}
}
直接从相册中获取图片有2中方式,一个方式是以“
ACTION_PICK”行为打开的相册,它在任何Android版本下,图片的Uri地址都是真实的绝对路径,不需要解析它的地址,直接调用getImagePath()方法就能获取到图片的地址。另一种方式是以“GET_CONTENT”行为打开的相册,如果以这种方式开启,需要对Android版本进行判断,因为在Android4.4版本以上,相册中的图片地址都进行过封装的,Uri地址格式为:
content://com.android.providers.media.documents/document/image%3A659
而在Android4.4版本以下,相册的图片地址没进行封装,Uri地址格式为:
/storage/emulated/0/Pictures/07 绚彩夜拍.jpg
Android4.4版本及以上图片Uri解析,需要先判断Uri是否是Document类型的,如果是获取Document的ID来处理。如果不是的话,就使用普通方式的来解析Uri地址。另外,如果Uri的Authority是media类型的,需要再一次解析,通过字符串的分割获取到数字格式的id,然后将id封装成选择条件与新构建的Uri传入到getImagePath()方法中,这样才能获取到图片的真实地址。而Android4.4版本以下,直接使用内容解析者遍历图库的数据库查找,找到将图片的真实地址直接返回。