相信大家对图片选择已经不陌生了,大家基本一直都在用。但是假如你在选择图片的时候遇到,反应比较慢。Android 7.0选择图片时闪退的问题。你不妨花几分钟往下看下。
随着相机像素越来越高,手机拍照获取到的照片越来越大,这就需要我们在选择照片时处理好内存溢出的问题。于是出现了选择照片时保存图片的本地路径,上传时在转换为需要的格式。但是,安卓7.0在选择图片时获取到的路径不是在file文件夹下,而是在content下。好多人都获取不好正确的路径。于是网上就有了使用previder这样的方法获取图片的文章。本篇文章是在结合以上两点的情况下,把选择图片的所有逻辑全部封装在一个dialog中。让大家在使用的时候尽可能的方便。
先给dialog
/** * 选择单张照片的dialog,是否裁剪可设置,裁剪尺寸目前没有做,可自己添加 */ public class ChoseSingleImgDialog extends Dialog implements View.OnClickListener { private String title = ""; private Activity activity; private int cameraRequestCode; private int cutRequestCode; private int selectRequestCode; private boolean cut; //动态获取权限监听 private static PermissionListener mListener; private TextView tv_chose_single_img_title; private TextView btn_chose_single_img_camera; private TextView btn_chose_single_img_chose; private Button btn_chose_single_img_cancel; private Fragment fragment; private String imageName; private File cacheFile;//裁剪后的地址 private File cameraFile;//相机文件 private Uri imageUri; private String cachPath; /** * @param activity * @param title 标题 * @param cameraRequestCode 相机图片请求码 * @param selectRequestCode 相册图片请求 * @param cutRequestCode 图片裁剪请求码 * @param imageName 图片名 * @param cut 是否剪切 */ public ChoseSingleImgDialog(Fragment fragment, Activity activity, String title, int cameraRequestCode, int selectRequestCode, int cutRequestCode, String imageName, boolean cut) { super(activity, R.style.Dialog_boc); this.activity = activity; this.title = title; this.cameraRequestCode = cameraRequestCode; this.selectRequestCode = selectRequestCode; this.cutRequestCode = cutRequestCode; this.imageName = imageName; this.fragment = fragment; this.cut = cut; } @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); //改变导航栏的颜色 if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT) { getWindow().addFlags(WindowManager.LayoutParams.FLAG_TRANSLUCENT_STATUS); // getWindow().addFlags(WindowManager.LayoutParams.FLAG_TRANSLUCENT_NAVIGATION); } setContentView(R.layout.dialog_chose_single_img); Window window = this.getWindow(); window.setGravity(Gravity.BOTTOM); // window.setWindowAnimations(R.style.dialogAnimation); initView(); } private void initView() { long time = Calendar.getInstance().getTime().getTime(); cachPath=getDiskCacheDir(activity)+ "/"+time+"crop_image.jpg"; cacheFile =getCacheFile(new File(getDiskCacheDir(activity)), time +"crop_image.jpg"); // TODO Auto-generated method stub tv_chose_single_img_title = (TextView) findViewById(R.id.tv_chose_single_img_title); btn_chose_single_img_camera = (TextView) findViewById(R.id.btn_chose_single_img_camera); btn_chose_single_img_chose = (TextView) findViewById(R.id.btn_chose_single_img_chose); btn_chose_single_img_cancel = (Button) findViewById(R.id.btn_chose_single_img_cancel); tv_chose_single_img_title.setText(title); btn_chose_single_img_camera.setOnClickListener(this); btn_chose_single_img_chose.setOnClickListener(this); btn_chose_single_img_cancel.setOnClickListener(this); } @Override public void onClick(View v) { // TODO Auto-generated method stub switch (v.getId()) { case R.id.btn_chose_single_img_camera://相机 getFromCamera(); break; case R.id.btn_chose_single_img_chose://相册选择 getFromSelect(); break; case R.id.btn_chose_single_img_cancel: dismiss(); break; default: break; } dismiss(); } /** * 动态监听权限 */ private void getFromSelect() { String[] permissions = {Manifest.permission.WRITE_EXTERNAL_STORAGE, Manifest.permission.READ_EXTERNAL_STORAGE}; requestRuntimePermission(permissions, new PermissionListener() { @Override public void onGranted() { openAlbum(); } @Override public void onDenied(ListdeniedPermission) { //没有获取到权限,什么也不执行,看你心情 OFBApplication.setToast("没有权限"); } }); } /** * 打开相册,选择照片 */ private void openAlbum() { Intent intent = new Intent("android.intent.action.GET_CONTENT"); intent.setType("image/*"); activity.startActivityForResult(intent, selectRequestCode); // 打开相册 } /** * 动态监听相机等权限 */ private void getFromCamera() { //openCamera(); String[] permissions = {Manifest.permission.CAMERA, Manifest.permission.READ_EXTERNAL_STORAGE, Manifest.permission.WRITE_EXTERNAL_STORAGE}; requestRuntimePermission(permissions, new PermissionListener() { @Override public void onGranted() { openCamera(); } @Override public void onDenied(List deniedPermission) { //有权限被拒绝,什么也不做好了,看你心情 OFBApplication.setToast("您已经拒绝拍照权限"); } }); } /** * 打开相机拍照 */ private void openCamera() { cameraFile = getCacheFile(new File(getDiskCacheDir(activity)), imageName); Intent intent = new Intent(MediaStore.ACTION_IMAGE_CAPTURE); if (Build.VERSION.SDK_INT < 24) {//7.0以下,直接获取到Uri imageUri = Uri.fromFile(cameraFile); } else {//7.0使用fileprovider获取Uri intent.addFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION); imageUri = FileProvider.getUriForFile(activity, "com.xlk.onefootball.fileprovider", cameraFile); } // 启动相机程序 intent.putExtra(MediaStore.EXTRA_OUTPUT, imageUri); activity.startActivityForResult(intent, cameraRequestCode); } /** * 创建File对象,用于存储拍照后的图片 * * @param parent * @param child * @return */ private File getCacheFile(File parent, String child) { // 创建File对象,用于存储拍照后的图片 File file = new File(parent, child); if (file.exists()) { file.delete(); } try { file.createNewFile(); } catch (IOException e) { e.printStackTrace(); } return file; } /** * 获取图片路径 * * @param context * @return */ public String getDiskCacheDir(Context context) { String cachePath = null; if (Environment.MEDIA_MOUNTED.equals(Environment.getExternalStorageState()) || !Environment.isExternalStorageRemovable()) { cachePath = context.getExternalCacheDir().getPath(); } else { cachePath = context.getCacheDir().getPath(); } return cachePath; } public String onActivityResult(int requestCode, int resultCode, Intent data, ImageView imageView) { String uri = null; // 从相册中去图片当resultcode == -1表示以选择0时没有选者 if (requestCode == selectRequestCode && resultCode == Activity.RESULT_OK) {//从相册选择 if (cut) { // 判断手机系统版本号 if (Build.VERSION.SDK_INT >= 19) { // 4.4及以上系统使用这个方法处理图片 OFBApplication.LogData("获取到4.4以上的图片",data.toString()); handleImageOnKitKat(data); } else { // 4.4以下系统使用这个方法处理图片 OFBApplication.LogData("获取到4.4以下的图片",data.toString()); handleImageBeforeKitKat(data); } } else { if (Build.VERSION.SDK_INT >= 19) { // 4.4及以上系统使用这个方法处理图片 Uri uri_temp = data.getData(); String imagePath = uriToPath(uri_temp); File file_temp = new File(imagePath); uri = Uri.fromFile(file_temp)+""; OFBApplication.LogData("不裁剪相册",uri); GlideUtils.setImage(activity,uri,imageView); } else { // 4.4以下系统使用这个方法处理图片 Uri uri_temp = data.getData(); String imagePath = getImagePath(uri_temp, null); File file_temp = new File(imagePath); uri = Uri.fromFile(file_temp)+""; OFBApplication.LogData("不裁剪相册",uri); GlideUtils.setImage(activity,uri,imageView); } } }else if (requestCode == cameraRequestCode && resultCode == Activity.RESULT_OK) {//拍照 if (cut) { try { // 将拍摄的照片显示出来 OFBApplication.LogData("获取到相机文件",cameraFile.getAbsolutePath()); startPhotoZoom(cameraFile, 350); } catch (Exception e) { e.printStackTrace(); } } else { //uri = uriToPath(Uri.fromFile(cameraFile)); uri = Uri.fromFile(cameraFile)+""; OFBApplication.LogData("不裁剪相机",uri); GlideUtils.setImage(activity,uri,imageView); } }else if (requestCode == cutRequestCode && resultCode == Activity.RESULT_OK) {//裁剪 try { uri = Uri.fromFile(new File(cachPath))+""; GlideUtils.setImage(activity,cachPath,imageView); } catch (Exception e) { e.printStackTrace(); } } return uri; } /** * 剪裁图片 */ private void startPhotoZoom(File file, int size) { OFBApplication.LogData("TAG",getImageContentUri(activity,file)+"裁剪照片的真实地址"); try { Intent intent = new Intent("com.android.camera.action.CROP"); intent.setDataAndType(getImageContentUri(activity,file), "image/*");//自己使用Content Uri替换File Uri intent.putExtra("crop", "true"); intent.putExtra("aspectX", 1); intent.putExtra("aspectY", 1); intent.putExtra("outputX", 180); intent.putExtra("outputY", 180); intent.putExtra("scale", true); intent.putExtra("return-data", false); intent.putExtra(MediaStore.EXTRA_OUTPUT,Uri.fromFile(cacheFile));//定义输出的File Uri intent.putExtra("outputFormat", Bitmap.CompressFormat.JPEG.toString()); intent.putExtra("noFaceDetection", true); if (fragment != null) { fragment.startActivityForResult(intent, cutRequestCode); } else { activity.startActivityForResult(intent, cutRequestCode); } } catch (ActivityNotFoundException e) { String errorMessage = "Your device doesn't support the crop action!"; Toast.makeText(activity, errorMessage, Toast.LENGTH_LONG).show(); } catch (Exception e) { e.printStackTrace(); } } /** * 4.4以上的图片 * @param data */ @TargetApi(19) private void handleImageOnKitKat(Intent data) { Uri uri = data.getData(); OFBApplication.LogData("TAG", "handleImageOnKitKat: uri is " + uri); String imagePath= uriToPath(uri); // displayImage(imagePath); // 根据图片路径显示图片 OFBApplication.LogData("TAG","file://"+imagePath+"选择图片的URI"+uri); startPhotoZoom(new File(imagePath),350); } /** * 4.4以下图片处理 * @param data */ private void handleImageBeforeKitKat(Intent data) { Uri uri = data.getData(); String imagePath = getImagePath(uri, null); // displayImage(imagePath); OFBApplication.LogData("TAG","file://"+imagePath+"选择图片的URI"+uri); startPhotoZoom(new File(imagePath),350); } /** * Uri转Path * @param uri * @return */ private String uriToPath(Uri uri) { String path=null; if (DocumentsContract.isDocumentUri(activity, uri)) { // 如果是document类型的Uri,则通过document id处理 String docId = DocumentsContract.getDocumentId(uri); if("com.android.providers.media.documents".equals(uri.getAuthority())) { String id = docId.split(":")[1]; // 解析出数字格式的id String selection = MediaStore.Images.Media._ID + "=" + id; path = getImagePath(MediaStore.Images.Media.EXTERNAL_CONTENT_URI, selection); } else if ("com.android.providers.downloads.documents".equals(uri.getAuthority())) { Uri contentUri = ContentUris.withAppendedId(Uri.parse("content://downloads/public_downloads"), Long.valueOf(docId)); path = getImagePath(contentUri, null); } } else if ("content".equalsIgnoreCase(uri.getScheme())) { // 如果是content类型的Uri,则使用普通方式处理 path = getImagePath(uri, null); } else if ("file".equalsIgnoreCase(uri.getScheme())) { // 如果是file类型的Uri,直接获取图片路径即可 path = uri.getPath(); } return path; } /** * 获取图片路径 * @param uri * @param selection * @return */ private String getImagePath(Uri uri, String selection) { String path = null; // 通过Uri和selection来获取真实的图片路径 Cursor cursor = activity.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; } /** * 获取ContentUri 7.0特有 * @param context * @param imageFile * @return */ public static Uri getImageContentUri(Context context, File imageFile) { String filePath = imageFile.getAbsolutePath(); Cursor cursor = context.getContentResolver().query( MediaStore.Images.Media.EXTERNAL_CONTENT_URI, new String[]{MediaStore.Images.Media._ID}, MediaStore.Images.Media.DATA + "=? ", new String[]{filePath}, null); if (cursor != null && cursor.moveToFirst()) { int id = cursor.getInt(cursor .getColumnIndex(MediaStore.MediaColumns._ID)); Uri baseUri = Uri.parse("content://media/external/images/media"); return Uri.withAppendedPath(baseUri, "" + id); } else { if (imageFile.exists()) { ContentValues values = new ContentValues(); values.put(MediaStore.Images.Media.DATA, filePath); return context.getContentResolver().insert( MediaStore.Images.Media.EXTERNAL_CONTENT_URI, values); } else { return null; } } } //andrpoid 6.0 需要写运行时权限 public void requestRuntimePermission(String[] permissions, PermissionListener listener) { mListener = listener; List permissionList = new ArrayList<>(); for (String permission : permissions) { if (ContextCompat.checkSelfPermission(activity, permission) != PackageManager.PERMISSION_GRANTED) { permissionList.add(permission); } } if (!permissionList.isEmpty()) { ActivityCompat.requestPermissions(activity, permissionList.toArray(new String[permissionList.size()]), 1); } else { mListener.onGranted(); } } public interface PermissionListener { /** * 成功获取权限 */ void onGranted(); /** * 为获取权限 * * @param deniedPermission */ void onDenied(List deniedPermission); } }
用法:
public class MainActivity extends Activity { ChoseSingleImgDialog choseSingleImgdialog; ImageView iv; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); iv = (ImageView) findViewById(R.id.iv_main); findViewById(R.id.btn_main_choseIMG).setOnClickListener(new View.OnClickListener() { @Override public void onClick(View view) { choseSingleImgdialog = new ChoseSingleImgDialog(null, MainActivity.this, "选择图片", 100, 101, 102, "head.jpg", true); choseSingleImgdialog.show(); } }); } @Override protected void onActivityResult(int requestCode, int resultCode, Intent data) { super.onActivityResult(requestCode, resultCode, data); if (choseSingleImgdialog != null) { //拿到图片路径,想干嘛随你 String url = choseSingleImgdialog.onActivityResult(requestCode, resultCode, data, iv); OFBApplication.setToast("图片路径是"+url); choseSingleImgdialog.dismiss(); }else{ OFBApplication.setToast("失败了"); } } }
具体使用中要用到glide,和一个previder。感兴趣的可以去看Android 7.0选择图片,获取路径的博客。或者直接下载源码。
源码链接:https://github.com/MoJieBlog/choseSingleIMG