现在的应用,很多时候都会用到拍照,例如上传个头像什么的,而现在安卓已经8都出来了,并且在7.0之后有一些权限都列为了危险权限,所以有些变动,做个记录
首先写个CameraUtils的工具类,用于返回uri
public class CameraUtils {
private static final String TAG = "CameraUtils";
private static CameraUtils cu;
private static Context mContext;
private static Uri uri;
public static CameraUtils getInstance(Context c){
if (null == cu){
synchronized (CameraUtils.class){
if (null == cu){
cu = new CameraUtils(c);
}
}
}
return cu;
}
private CameraUtils(Context context){
mContext = context;
}
/**
* 拍照
* @param authority 在manifest中的对应一致
* @return
*/
public Uri takePhotos(String authority){
if (TextUtils.isEmpty(authority)){
Log.e(TAG, "takePhotos: authority is null");
return null;
}
//创建file对象,用于存储拍照的图片 (应用关联缓存目录,6.0后,读取sd卡列为危险权限)
File outputImg = new File(mContext.getExternalCacheDir(),"take_img.jpg");
try {
if (outputImg.exists()){
outputImg.delete();
}
outputImg.createNewFile();
} catch (IOException e) {
e.printStackTrace();
}
//7.0之后使用本地真实路径的uri被认为是不安全的,会报异常,所以用FileProvider这个内容提供器来做
if (Build.VERSION.SDK_INT >= 24){
uri = FileProvider.getUriForFile(mContext, authority, outputImg);
}else{
uri = Uri.fromFile(outputImg);
}
return uri;
}
}
然后记得要在manifest中注册,如下
<!--这里的authorities和takephotos的参数对应一致
用meta-data他来指定uri的共享路径
exported 是否支持其他应用调用控件-->
<provider
android:name="android.support.v4.content.FileProvider"
android:authorities="com.example.magic.myapplication.provider"
android:grantUriPermissions="true"
android:exported="false"
>
<meta-data
android:name="android.support.FILE_PROVIDER_PATHS"
android:resource="@xml/file_path"
/>
</provider>
这里的resource中的这个xml文件是没有,所以需要我们自己创建
<?xml version="1.0" encoding="utf-8"?>
<!--external-path用来指定uri共享的.name随便填写 path表示共享路径,这里设置空表示整个sd进行共享-->
<paths xmlns:android="http://schemas.android.com/apk/res/android">
<external-path name="my_img" path=""/>
</paths>
用到了读写权限,在6.0后就可以不用写了,但是为了兼容低版的,所以记得添加权限
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE"/>
最后就是在Activity中使用了
btn_take_pic.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View view) {
uri = CameraUtils.getInstance(MainActivity.this).takePhotos("com.example.magic.myapplication.provider");
Intent intent = new Intent("android.media.action.IMAGE_CAPTURE");
intent.putExtra(MediaStore.EXTRA_OUTPUT,uri);
startActivityForResult(intent,1);
}
});
@Override
protected void onActivityResult(int requestCode, int resultCode, Intent data) {
super.onActivityResult(requestCode, resultCode, data);
switch (requestCode){
case 1:
if (resultCode == RESULT_OK){
try {
Bitmap bitmap = BitmapFactory.decodeStream(getContentResolver().openInputStream(uri));
iv_showpic.setImageBitmap(bitmap);
} catch (FileNotFoundException e) {
e.printStackTrace();
}
}
break;
}
}
当然有拍照就会有从本地相册选择图片
首先还是在CameraUtils的工具类中添加 如下:
/**
* 4.4版本以上 从相册获取照片
* @param data
*/
@TargetApi(Build.VERSION_CODES.KITKAT)
public Bitmap getImageOnKitKat(Intent data){
String imagePath = null;
Uri dataUri = data.getData();
if (DocumentsContract.isDocumentUri(mContext,dataUri)){
//如果是document类型的Uri,则通过document id处理
String docId = DocumentsContract.getDocumentId(dataUri);
if ("com.android.providers.media.documents".equals(dataUri.getAuthority())){
String id = docId.split(":")[1];
String selection = MediaStore.Images.Media._ID + "=" + id;
imagePath = getImagePath(MediaStore.Images.Media.EXTERNAL_CONTENT_URI,selection);
}else if("com.android.providers.downloads.documents".equals(dataUri.getAuthority())){
Uri contentUri = ContentUris.withAppendedId(Uri.parse("content://downloads/public_downloads"), Long.valueOf(docId));
imagePath = getImagePath(contentUri,null);
}
}else if ("content".equalsIgnoreCase(dataUri.getScheme())){
imagePath = getImagePath(dataUri,null);
}else if("file".equalsIgnoreCase(dataUri.getScheme())){
imagePath = dataUri.getPath();
}
//根据路径来显示图片
return displayImage(imagePath);
}
/**
* 4.4之前从相册选图片
*/
public Bitmap getImageBeforeKitKat(Intent data){
Uri dataUri = data.getData();
String imagePath = getImagePath(dataUri,null);
return displayImage(imagePath);
}
private String getImagePath(Uri uris,String selection){
String path = null;
//通过uris和selection来获取真实的图片路径
Cursor cursor = mContext.getContentResolver().query(uris, null, selection, null, null);
if (null != cursor){
if (cursor.moveToFirst()){
path = cursor.getString(cursor.getColumnIndex(MediaStore.Images.Media.DATA));
}
cursor.close();
}
return path;
}
private Bitmap displayImage(String path){
Bitmap bitmap;
if (null != path){
bitmap = BitmapFactory.decodeFile(path);
}else{
return null;
}
return bitmap;
}
在Activity中使用,这里加了权限的检查,因为在7.0后读取sd列为危险权限,否则会崩,如下
btn_get_pic.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View view) {
if (ContextCompat.checkSelfPermission(MainActivity.this, Manifest.permission.WRITE_EXTERNAL_STORAGE)!= PackageManager.PERMISSION_GRANTED){
ActivityCompat.requestPermissions(MainActivity.this,new String[]{Manifest.permission.WRITE_EXTERNAL_STORAGE},1);
}else{
openAlbum();
}
}
});
}
/**
* 打开相册
*/
private void openAlbum() {
Intent intent = new Intent("android.intent.action.GET_CONTENT");
intent.setType("image/*");
startActivityForResult(intent,2);
}
@Override
public void onRequestPermissionsResult(int requestCode, @NonNull String[] permissions, @NonNull int[] grantResults) {
super.onRequestPermissionsResult(requestCode, permissions, grantResults);
switch(requestCode){
case 1:
if (grantResults.length > 0 && grantResults[0] == PackageManager.PERMISSION_GRANTED){
openAlbum();
}else{
MyToastUtils.show(MainActivity.this,"没有权限,请开启权限");
}
break;
}
}
@Override
protected void onActivityResult(int requestCode, int resultCode, Intent data) {
super.onActivityResult(requestCode, resultCode, data);
switch (requestCode){
case 1:
if (resultCode == RESULT_OK){
try {
Bitmap bitmap = BitmapFactory.decodeStream(getContentResolver().openInputStream(uri));
iv_showpic.setImageBitmap(bitmap);
} catch (FileNotFoundException e) {
e.printStackTrace();
}
}
break;
case 2:
if(resultCode == RESULT_OK){
Bitmap bitmap;
//4.4以上
if (Build.VERSION.SDK_INT >= 19){
bitmap = CameraUtils.getInstance(MainActivity.this).getImageOnKitKat(data);
Log.i(TAG, "1 onActivityResult: "+Build.VERSION.SDK_INT);
}else{
bitmap = CameraUtils.getInstance(MainActivity.this).getImageBeforeKitKat(data);
Log.i(TAG, "2 onActivityResult: "+Build.VERSION.SDK_INT);
}
iv_showpic.setImageBitmap(bitmap);
}
break;
}
}