上周在项目中遇到了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