好久没有坐下来安安静静的写博客了 ,上一篇写的是自定义相机 ,以前项目中用过一些第三方的库 ,万物归终今天找个时间总结一下 ,做开发几年了 。随着android studio的运用,开源资源越来越多,越来越好用 ,但是使用第三方的开源代码,越来越不爽 ,很多库渐渐的丢下了 ,比如说EventBus ,刚开始的时候觉得好像神奇 ,用多了 。感觉代码不是很直观 ,就慢慢不用了 ,还是觉得自己写的回调接口好用。
好了,不说废话了 ,一直以来开发平台都是RK芯片 5.0系统的,有时候也做一些APK ,上次出现的androdi7.0的问题,今天整理下 。拍照,选中本地图片,切割,老生常谈,无论使用开源,还是自定义 ,现在发现还是android系统提供的好用,毕竟androi d都8.0了,越来越好用 。
android7.0 ,拍照,选择图片,不能和以前一样使用了 ,增加了权限的管理 ,直接看代码 。 相对以前的使用区别还是挺明显的
0:先贴一个常量类,一会后边要使用
public class AppConstant { /*** * 拍照返回图片的 */ public static final String cameralSavePath = ApInfo.IMAGE_URL + "/camera.jpg"; public static final String CACHE_IMAGE = ApInfo.IMAGE_URL + "/cache.jpg"; public static final String authorities = "com.mirrormobile.fileprovider"; public static final int CAMERA_IMAGE_BACK = 5612; public static final int CUT_IMAGE_BACK = 23456; public static final int IMAGE_CUT_BACK = 5617; /*** * 选择本地图库 */ public static final int LOCAL_FILE_BACK = 56452; public static final String TAG_LOCALFILE_BACK = "TAG_LOCALFILE_BACK";}
1:res中新建 xml 文件夹,在xml中新建file_paths.xml
patH后边的路径是包名
<?xml version="1.0" encoding="utf-8"?> <paths> <external-path name="files_root" path="Android/data/com.mirrormobile/" /> <external-path name="external_storage_root" path="." /> </paths>
2:在清单文件中注册 :com.mirrormobile 是包名
resource中是刚才新建的xml的路径
<provider android:name="android.support.v4.content.FileProvider" android:authorities="com.mirrormobile.fileprovider" android:exported="false" android:grantUriPermissions="true"> <meta-data android:name="android.support.FILE_PROVIDER_PATHS" android:resource="@xml/file_paths" /> </provider>
3:新建工具类 : ImageCutUtil,用来拍照,本地选择,切割图片
android 6.0 以后使用隐私的权限,需要申请权限,这里我用的是HiPermission ,大家可以去github去看,使用还是挺方便的,这里就只贴代码了 ,Buid.gradle中引用一下
//hipermission compile 'me.weyye.hipermission:library:1.0.7'
去请求相机权限 ,通过后去调用系统
/*** * 检查相机权限 */ public void checkCameraPermission() { List<PermissionItem> permissions = new ArrayList<PermissionItem>(); permissions.add( new PermissionItem(Manifest.permission.CAMERA, "SD卡读取权限", R.drawable.permission_ic_phone)); HiPermission.create(context).title(context.getString(R.string.permission_cus_title)).permissions( permissions).msg(context.getString(R.string.permission_cus_msg)).animStyle(R.style.PermissionAnimModal).style( R.style.PermissionDefaultBlueStyle).checkMutiPermission(new PermissionCallback() { @Override public void onClose() { Log.e("main", "====onClose===="); } @Override public void onFinish() { try { takeCameraPhoto(); } catch (Exception e) { MyToastView.getInstance().Toast(context, e.toString()); Log.e("main", "====打开相机异常====" + e.toString()); } } @Override public void onDeny(String permission, int position) { Log.e("main", "====打开相机异常===="); MyToastView.getInstance().Toast(context, "您拒绝了" + permission + "权限,请手动打开"); } @Override public void onGuarantee(String permission, int position) { Log.e("main", "====onGuarantee===="); } }); }
/*** * 拍照返回 */ public void takeCameraPhoto() { try { FileUtils.creatFileNotExciet(); File file = new File(AppConstant.cameralSavePath); if (file.exists()) { file.delete(); } file.createNewFile(); if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N) { //7.0执行该方法 Uri imageUri = FileProvider.getUriForFile(context, AppConstant.authorities, file); Intent intent = new Intent(); //添加这一句表示对目标应用临时授权该Uri所代表的文件 intent.addFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION); intent.setAction(MediaStore.ACTION_IMAGE_CAPTURE);//设置Action为拍照 intent.putExtra(MediaStore.EXTRA_OUTPUT, imageUri);//将拍取的照片保存到指定URI context.startActivityForResult(intent, AppConstant.CAMERA_IMAGE_BACK); } else { //7.0以下手机系统执行这个方法 Intent getPhoto = new Intent(MediaStore.ACTION_IMAGE_CAPTURE); Uri uri = Uri.fromFile(file); getPhoto.putExtra(MediaStore.EXTRA_OUTPUT, uri);//根据uri保存照片 getPhoto.putExtra(MediaStore.EXTRA_VIDEO_QUALITY, 1);//保存照片的质量 context.startActivityForResult(getPhoto, AppConstant.CAMERA_IMAGE_BACK);//启动相机拍照 } } catch (Exception e) { MyToastView.getInstance().Toast(context, e.toString()); } }拍照的时候,判断一下当前的系统版本,7.0以前使用的url .7.0以后是使用FileProvider来访问本地图片
选择本地的图片 ,同理,需要分系统来操作
接下来就是图片切割了 ,7.0的使用方法相比以前的要稍微复杂一点,但是系统的切割用着舒服 ,简单的调用,如果觉得界面不好看,那就智能自己去想办法了 ,去引用第三方 ,或者自己写 ,注释比较清楚,不解释了
/*** * 裁切图片 * @param inputUrl * 裁切图片的url * @param outputUrl * 保存的图片的url */ public void cutImage(String inputUrl, String outputUrl) { try { File file_out = new File(outputUrl); if (file_out.exists()) { file_out.delete(); } file_out.createNewFile(); cropPicture(inputUrl, outputUrl); } catch (Exception e) { Log.e(TAG, "====裁切图片异常=--" + e.toString()); MyToastView.getInstance().Toast(context, e.toString()); } } /** * 调用系统剪裁功能 */ public void cropPicture(String inputUrl, String output) { File fileinput = new File(inputUrl); Uri imageUri; Uri outputUri; Intent intent = new Intent("com.android.camera.action.CROP"); if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N) { intent.addFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION); imageUri = FileProvider.getUriForFile(context, AppConstant.authorities, fileinput); outputUri = Uri.fromFile(new File(output)); } else { imageUri = Uri.fromFile(fileinput); outputUri = Uri.fromFile(new File(output)); } intent.setDataAndType(imageUri, "image/*"); intent.putExtra("crop", "true"); //设置宽高比例 intent.putExtra("aspectX", 1); intent.putExtra("aspectY", 2); //设置裁剪图片宽高 // intent.putExtra("outputX", 300); // intent.putExtra("outputY", 300); intent.putExtra("scale", true); intent.putExtra(MediaStore.EXTRA_OUTPUT, outputUri); intent.putExtra("outputFormat", Bitmap.CompressFormat.JPEG.toString()); intent.putExtra("noFaceDetection", true); context.startActivityForResult(intent, AppConstant.IMAGE_CUT_BACK); }
界面调用初始化这个工具类 ,然后直接调用权限的方法就可以了,我们看一下OnActivityForResult()这个方法
String updatePath = ""; @Override protected void onActivityResult(int requestCode, int resultCode, Intent data) { super.onActivityResult(requestCode, resultCode, data); if (requestCode == AppConstant.CAMERA_IMAGE_BACK) { //拍照返回的数据 imageCutUtil.cutImage(AppConstant.cameralSavePath, AppConstant.CACHE_IMAGE); } else if (requestCode == AppConstant.LOCAL_FILE_BACK) { String filePath = data.getStringExtra(AppConstant.TAG_LOCALFILE_BACK); imageCutUtil.cutImage(filePath, AppConstant.CACHE_IMAGE); } else if (requestCode == AppConstant.IMAGE_CUT_BACK) { //切割之后返回的数据 Bitmap bitmap = BitmapFactory.decodeFile(AppConstant.CACHE_IMAGE); iv_show_image.setImageBitmap(bitmap); updatePath = AppConstant.CACHE_IMAGE; } }
选择本地也就简单了,结合上边的代码 ,处理起来比较简单,检查权限,打开本地图库
public void checkSdImagePermiss() { List<PermissionItem> permissions = new ArrayList<PermissionItem>(); permissions.add(new PermissionItem(Manifest.permission.READ_EXTERNAL_STORAGE, "SD卡读取权限", R.drawable.permission_ic_phone)); permissions.add(new PermissionItem(Manifest.permission.WRITE_EXTERNAL_STORAGE, "SD卡读取权限", R.drawable.permission_ic_phone)); HiPermission.create(context).title(context.getString(R.string.permission_cus_title)).permissions( permissions).msg(context.getString(R.string.permission_cus_msg)).animStyle(R.style.PermissionAnimModal).style( R.style.PermissionDefaultBlueStyle).checkMutiPermission(new PermissionCallback() { @Override public void onClose() { Log.i(TAG, "用户拒绝我们的权限"); } @Override public void onFinish() { try { Intent intent = new Intent(Intent.ACTION_GET_CONTENT); intent.addCategory(Intent.CATEGORY_OPENABLE); intent.setType("image/*"); context.startActivityForResult(intent, AppConstant.LOCAL_FILE_BACK); // Intent intent = new Intent(context, LoImgChooiceActivity.class); // context.startActivityForResult(intent, AppConstant.LOCAL_FILE_BACK); } catch (Exception e) { Log.e("main", "====打开相机异常====" + e.toString()); } }
界面的onActivityForResult(),接受到数据,直接吧数据丢给Util去处理
String updatePath = ""; @Override protected void onActivityResult(int requestCode, int resultCode, Intent data) { super.onActivityResult(requestCode, resultCode, data); if (requestCode == AppConstant.CAMERA_IMAGE_BACK) { //拍照返回的数据 imageCutUtil.cutImage(AppConstant.cameralSavePath, AppConstant.CACHE_IMAGE); } else if (requestCode == AppConstant.LOCAL_FILE_BACK) { //本地图片选择 imageCutUtil.cutImageLocal(data); // String filePath = data.getStringExtra(AppConstant.TAG_LOCALFILE_BACK); // imageCutUtil.cutImage(filePath, AppConstant.CACHE_IMAGE); } else if (requestCode == AppConstant.IMAGE_CUT_BACK) { //切割之后返回的数据 Bitmap bitmap = BitmapFactory.decodeFile(AppConstant.CACHE_IMAGE); iv_show_image.setImageBitmap(bitmap); updatePath = AppConstant.CACHE_IMAGE; } }
/*** * 本地图片选择器 * @param data */ public void cutImageLocal(Intent data) { Uri imageUri = data.getData(); String url_out = AppConstant.CACHE_IMAGE; File file_out = new File(AppConstant.CACHE_IMAGE); if (file_out.exists()) { file_out.delete(); } Uri outputUri = Uri.fromFile(new File(url_out)); cutImage(imageUri, outputUri); }直接获取图片的URI ,然后直接去裁切 。下面贴上全部代码 ;
package com.mirror.mobile.util.image; import android.Manifest; import android.app.Activity; import android.content.Intent; import android.database.Cursor; import android.graphics.Bitmap; import android.net.Uri; import android.os.Build; import android.provider.MediaStore; import android.support.v4.content.FileProvider; import android.util.Log; import com.cdl.dialog.toast.MyToastView; import com.mirror.mobile.test.LoImgChooiceActivity; import com.mirror.mobile.util.FileUtils; import com.mirror.mobile.util.updatepic.AppConstant; import com.mirrormobile.R; import java.io.File; import java.util.ArrayList; import java.util.List; import me.weyye.hipermission.HiPermission; import me.weyye.hipermission.PermissionCallback; import me.weyye.hipermission.PermissionItem; /*** * 图片裁剪工具类 */ public class ImageCutUtil { Activity context; private static final String TAG = "MAIN"; public ImageCutUtil(Activity context) { this.context = context; } //=============================================================================================================================== /*** * 本地图片选择器 * @param data */ public void cutImageLocal(Intent data) { Uri imageUri = data.getData(); String url_out = AppConstant.CACHE_IMAGE; File file_out = new File(AppConstant.CACHE_IMAGE); if (file_out.exists()) { file_out.delete(); } Uri outputUri = Uri.fromFile(new File(url_out)); cutImage(imageUri, outputUri); } //============================================================================================================================================ public void cutImage(String inputUrl, String output) { try { File file_out = new File(output); if (file_out.exists()) { file_out.delete(); } file_out.createNewFile(); File fileinput = new File(inputUrl); Uri imageUri; Uri outputUri; if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N) { imageUri = FileProvider.getUriForFile(context, AppConstant.authorities, fileinput); outputUri = Uri.fromFile(new File(output)); } else { imageUri = Uri.fromFile(fileinput); outputUri = Uri.fromFile(new File(output)); } cutImage(imageUri, outputUri); } catch (Exception e) { } } public void cutImage(Uri imageUri, Uri outputUri) { try { Intent intent = new Intent("com.android.camera.action.CROP"); if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N) { intent.addFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION); } intent.setDataAndType(imageUri, "image/*"); intent.putExtra("crop", "true"); //设置宽高比例 intent.putExtra("aspectX", 1); intent.putExtra("aspectY", 2); intent.putExtra("scale", true); intent.putExtra(MediaStore.EXTRA_OUTPUT, outputUri); intent.putExtra("outputFormat", Bitmap.CompressFormat.JPEG.toString()); intent.putExtra("noFaceDetection", true); context.startActivityForResult(intent, AppConstant.IMAGE_CUT_BACK); } catch (Exception e) { } } // public void cutImage(String inputUrl, String output) { // try { // File file_out = new File(output); // if (file_out.exists()) { // file_out.delete(); // } // file_out.createNewFile(); // File fileinput = new File(inputUrl); // Uri imageUri; // Uri outputUri; // Intent intent = new Intent("com.android.camera.action.CROP"); // if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N) { // intent.addFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION); // imageUri = FileProvider.getUriForFile(context, AppConstant.authorities, fileinput); // outputUri = Uri.fromFile(new File(output)); // } else { // imageUri = Uri.fromFile(fileinput); // outputUri = Uri.fromFile(new File(output)); // } // intent.setDataAndType(imageUri, "image/*"); // intent.putExtra("crop", "true"); // //设置宽高比例 // intent.putExtra("aspectX", 1); // intent.putExtra("aspectY", 2); // //设置裁剪图片宽高 // // intent.putExtra("outputX", 300); // // intent.putExtra("outputY", 300); // intent.putExtra("scale", true); // intent.putExtra(MediaStore.EXTRA_OUTPUT, outputUri); // intent.putExtra("outputFormat", Bitmap.CompressFormat.JPEG.toString()); // intent.putExtra("noFaceDetection", true); // context.startActivityForResult(intent, AppConstant.IMAGE_CUT_BACK); // } catch (Exception e) { // } // } public void checkSdImagePermiss() { List<PermissionItem> permissions = new ArrayList<PermissionItem>(); permissions.add(new PermissionItem(Manifest.permission.READ_EXTERNAL_STORAGE, "SD卡读取权限", R.drawable.permission_ic_phone)); permissions.add(new PermissionItem(Manifest.permission.WRITE_EXTERNAL_STORAGE, "SD卡读取权限", R.drawable.permission_ic_phone)); HiPermission.create(context).title(context.getString(R.string.permission_cus_title)).permissions( permissions).msg(context.getString(R.string.permission_cus_msg)).animStyle(R.style.PermissionAnimModal).style( R.style.PermissionDefaultBlueStyle).checkMutiPermission(new PermissionCallback() { @Override public void onClose() { Log.i(TAG, "用户拒绝我们的权限"); } @Override public void onFinish() { try { Intent intent = new Intent(Intent.ACTION_GET_CONTENT); intent.addCategory(Intent.CATEGORY_OPENABLE); intent.setType("image/*"); context.startActivityForResult(intent, AppConstant.LOCAL_FILE_BACK); // Intent intent = new Intent(context, LoImgChooiceActivity.class); // context.startActivityForResult(intent, AppConstant.LOCAL_FILE_BACK); } catch (Exception e) { Log.e("main", "====打开相机异常====" + e.toString()); } } @Override public void onDeny(String permission, int position) { MyToastView.getInstance().Toast(context, "您拒绝了" + permission + "权限,请手动打开"); Log.i(TAG, "用户禁止了权限" + permission); } @Override public void onGuarantee(String permission, int position) { Log.i(TAG, "onGuarantee"); } }); } /*** * 检查相机权限 */ public void checkCameraPermission() { List<PermissionItem> permissions = new ArrayList<PermissionItem>(); permissions.add( new PermissionItem(Manifest.permission.CAMERA, "SD卡读取权限", R.drawable.permission_ic_phone)); HiPermission.create(context).title(context.getString(R.string.permission_cus_title)).permissions( permissions).msg(context.getString(R.string.permission_cus_msg)).animStyle(R.style.PermissionAnimModal).style( R.style.PermissionDefaultBlueStyle).checkMutiPermission(new PermissionCallback() { @Override public void onClose() { Log.e("main", "====onClose===="); } @Override public void onFinish() { try { takeCameraPhoto(); } catch (Exception e) { MyToastView.getInstance().Toast(context, e.toString()); Log.e("main", "====打开相机异常====" + e.toString()); } } @Override public void onDeny(String permission, int position) { Log.e("main", "====打开相机异常===="); MyToastView.getInstance().Toast(context, "您拒绝了" + permission + "权限,请手动打开"); } @Override public void onGuarantee(String permission, int position) { Log.e("main", "====onGuarantee===="); } }); } /*** * 拍照返回 */ public void takeCameraPhoto() { try { FileUtils.creatFileNotExciet(); File file = new File(AppConstant.cameralSavePath); if (file.exists()) { file.delete(); } file.createNewFile(); if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N) { //7.0执行该方法 Uri imageUri = FileProvider.getUriForFile(context, AppConstant.authorities, file); Intent intent = new Intent(); //添加这一句表示对目标应用临时授权该Uri所代表的文件 intent.addFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION); intent.setAction(MediaStore.ACTION_IMAGE_CAPTURE);//设置Action为拍照 intent.putExtra(MediaStore.EXTRA_OUTPUT, imageUri);//将拍取的照片保存到指定URI context.startActivityForResult(intent, AppConstant.CAMERA_IMAGE_BACK); } else { //7.0以下手机系统执行这个方法 Intent getPhoto = new Intent(MediaStore.ACTION_IMAGE_CAPTURE); Uri uri = Uri.fromFile(file); getPhoto.putExtra(MediaStore.EXTRA_OUTPUT, uri);//根据uri保存照片 getPhoto.putExtra(MediaStore.EXTRA_VIDEO_QUALITY, 1);//保存照片的质量 context.startActivityForResult(getPhoto, AppConstant.CAMERA_IMAGE_BACK);//启动相机拍照 } } catch (Exception e) { MyToastView.getInstance().Toast(context, e.toString()); } } }
界面拍照 ,获取图库代码
@Override public void clickFirst() { //拍照 imageCutUtil.checkCameraPermission(); } @Override public void clickSecond() { //本地取图片 imageCutUtil.checkSdImagePermiss(); }
String updatePath = ""; @Override protected void onActivityResult(int requestCode, int resultCode, Intent data) { super.onActivityResult(requestCode, resultCode, data); if (requestCode == AppConstant.CAMERA_IMAGE_BACK) { //拍照返回的数据 imageCutUtil.cutImage(AppConstant.cameralSavePath, AppConstant.CACHE_IMAGE); } else if (requestCode == AppConstant.LOCAL_FILE_BACK) { //本地图片选择 imageCutUtil.cutImageLocal(data); // String filePath = data.getStringExtra(AppConstant.TAG_LOCALFILE_BACK); // imageCutUtil.cutImage(filePath, AppConstant.CACHE_IMAGE); } else if (requestCode == AppConstant.IMAGE_CUT_BACK) { //切割之后返回的数据 Bitmap bitmap = BitmapFactory.decodeFile(AppConstant.CACHE_IMAGE); iv_show_image.setImageBitmap(bitmap); updatePath = AppConstant.CACHE_IMAGE; } }