图片选择和拍照在开发过程中,会遇到不少坑:

1.版本4.4以后选择图片后不会返回绝对路径,但返回Uri,要再查询一次

2.去剪辑时,设置了true的话直接返回bitmap,可能会很占内存,有些机子会挂掉(OOM)或者不会返回

3.图片未更好的压缩,应该做到宽高比压缩后再质量压缩,下面例子可以把几MB的图片压缩到100kb左右

4.解决7.0版本文件访问问题

下面代码处理解决了上面的问题,是个小笔记,以后就不会再麻烦找“轮子”了。

1.在AndroidManifest添加FileProvider

        <providerandroid:name="android.support.v4.content.FileProvider"android:authorities="${applicationId}.fileprovider"android:exported="false"android:grantUriPermissions="true"><meta-dataandroid:name="android.support.FILE_PROVIDER_PATHS"android:resource="@xml/file_paths" /></provider>

2.在res文件夹下添加文件夹xml,再添加file_paths.xml

<?xml version="1.0" encoding="utf-8"?>
<paths><root-pathname="root"path="" /><!--<files-path--><!--name="files"--><!--path="" />--><!--<cache-path--><!--name="cache"--><!--path="" />--><!-- <external-path--><!--name="external"--><!--path="" />--><!--<external-path--><!--name="external"--><!--path="/apk" />--><external-pathname="external"path="" /><!--<external-files-path--><!--name="name"--><!--path="path" />--><!--<external-cache-path--><!--name="name"--><!--path="path" />-->
</paths><!--<root-path/> 代表设备的根目录new File("/");-->
<!--<files-path/> 代表context.getFilesDir()-->
<!--<cache-path/> 代表context.getCacheDir()-->
<!--<external-path/> 代表Environment.getExternalStorageDirectory()-->
<!--<external-files-path>代表context.getExternalFilesDirs()-->
<!--<external-cache-path>代表getExternalCacheDirs()-->

3.使用:

调用SelectPicUtil.getByAlbum(Activity.this); 选择相册

调用SelectPicUtil.getByCamera(Activity.this);进行拍照

然后在onActivityResult进行设置返回:

   @Overrideprotected void onActivityResult(int requestCode, int resultCode, Intent data) {super.onActivityResult(requestCode, resultCode, data);Uri uri = SelectPicUtil.onActivityResult(this, requestCode, resultCode, data);//下面是需求要裁剪的示例
//        Uri uri = SelectPicUtil.onActivityResult(this, requestCode, resultCode, data,1,1, 500,500, true);if (null != uri) { // 当不为空时获取到图片UridecodeUriBitmap(uri);}}private void decodeUriBitmap(final Uri uri) {new Thread(new Runnable() {@Overridepublic void run() {try {String picturePath = SelectPicUtil.getImageAbsolutePath(OtherMsgActivity.this, uri);if (!TextUtils.isEmpty(picturePath)) {Bitmap bitmapSrc = SelectPicUtil.getImageThumbnail(picturePath, 1000, 1000); // 比例压缩图片if (bitmapSrc != null) {ByteArrayOutputStream baos = new ByteArrayOutputStream();bitmapSrc.compress(Bitmap.CompressFormat.JPEG, 80, baos); // 图片质量压缩80%bitmapSrc.recycle();byte[] bytes = baos.toByteArray();try {if (null != baos) {baos.close();}} catch (IOException e) {}// 对字节数组Base64编码final String bitmap = Base64.encodeToString(bytes, Base64.DEFAULT);// 返回Base64编码过的字节数组字符串upLoadPic(bitmap);} else {upLoadPic("");}} else {upLoadPic("");}} catch (Exception e) {}}}).start();}

4.工具类:

import android.app.Activity;
import android.content.ContentResolver;
import android.content.Context;
import android.content.Intent;
import android.database.Cursor;
import android.net.Uri;
import android.os.Build;
import android.os.Environment;
import android.provider.MediaStore;
import android.support.v4.content.FileProvider;
import android.text.TextUtils;import com.yingyou.demo.BuildConfig;import java.io.File;public class SelectPicUtil {private static final String temp = Environment.getExternalStorageDirectory().getAbsolutePath() + "/temp.jpg";public static final int GET_BY_ALBUM = 801;// 打开相册public static final int GET_BY_CAMERA = 802;// 打开相机public static final int CROP = 803;// 裁剪图片public static void getByAlbum(Activity act) {if (android.os.Build.VERSION.SDK_INT >= android.os.Build.VERSION_CODES.KITKAT) {Intent intent = new Intent(Intent.ACTION_PICK,android.provider.MediaStore.Images.Media.EXTERNAL_CONTENT_URI);intent.setDataAndType(MediaStore.Images.Media.EXTERNAL_CONTENT_URI, "image/*");act.startActivityForResult(intent, GET_BY_ALBUM);} else {Intent intentFromGallery = new Intent();intentFromGallery.setType("image/*");intentFromGallery.setAction(Intent.ACTION_GET_CONTENT);act.startActivityForResult(intentFromGallery, GET_BY_ALBUM);}}public static void getByCamera(Activity act) {getByCamera(act, temp, GET_BY_CAMERA);}// 给其他地方用public static void getByCamera(Activity act, String path, int requestCode) {String state = Environment.getExternalStorageState();if (state.equals(Environment.MEDIA_MOUNTED)) {Intent takePictureIntent = new Intent(MediaStore.ACTION_IMAGE_CAPTURE);Uri uri = getUri(act, new File(path));takePictureIntent.putExtra(MediaStore.EXTRA_OUTPUT, uri);takePictureIntent.putExtra(MediaStore.EXTRA_VIDEO_QUALITY, 1);act.startActivityForResult(takePictureIntent, requestCode);} else {ToastUtils.showText("请安装sd卡");}}public static Uri onActivityResult(Activity act, int requestCode,int resultCode, Intent data) {return onActivityResult(act, requestCode, resultCode, data, 0, 0, 0, 0, false);}public static Uri onActivityResult(Activity act, int requestCode,int resultCode, Intent data, int w, int h, int aspectX, int aspectY) {return onActivityResult(act, requestCode, resultCode, data, w, h, aspectX, aspectY, true);}public static Uri onActivityResult(Activity act, int requestCode,int resultCode, Intent data, int outputX, int outputY, int aspectX, int aspectY, boolean isCut) {if (resultCode == Activity.RESULT_OK) {Uri uri = null;switch (requestCode) {case GET_BY_ALBUM:if (isCut) {if (null == data) return null;String path = getImageAbsolutePath(act, data.getData());if (TextUtils.isEmpty(path)) return null;uri = getUri(act, new File(path));} else {return data.getData();}break;case GET_BY_CAMERA:if (isCut) {uri = getUri(act, new File(temp));} else {return Uri.parse(temp);}break;case CROP:
//                    return getUri(act, new File(temp));return Uri.fromFile(new File(temp));}if (isCut && null != uri) {crop(act, uri, outputX, outputY, aspectX, aspectY);return null;}}return null;}public static void crop(Activity act, Uri uri, int outputX, int outputY, int aspectX, int aspectY) {if (outputX == 0 && outputY == 0) {outputX = outputY = 480;}if (aspectX == 0 && aspectY == 0) {aspectX = aspectY = 1;}Intent intent = new Intent("com.android.camera.action.CROP");if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N) {//对目标应用临时授权该Uri所代表的文件intent.addFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION);intent.addFlags(Intent.FLAG_GRANT_WRITE_URI_PERMISSION);}intent.setDataAndType(uri, "image/*");intent.putExtra("crop", "true");intent.putExtra("aspectX", aspectX);intent.putExtra("aspectY", aspectY);intent.putExtra("outputX", outputX);intent.putExtra("outputY", outputY);//        intent.putExtra(MediaStore.EXTRA_OUTPUT, getUri(act, new File(temp)));intent.putExtra(MediaStore.EXTRA_OUTPUT, Uri.fromFile(new File(temp)));intent.putExtra("outputFormat", "JPEG");intent.putExtra("noFaceDetection", true);intent.putExtra("return-data", false);act.startActivityForResult(intent, CROP);}public static String getImageAbsolutePath(Activity context, Uri uri) {if (null == uri)return null;final String scheme = uri.getScheme();String data = null;if (scheme == null)data = uri.getPath();else if (ContentResolver.SCHEME_FILE.equals(scheme)) {data = uri.getPath();} else if (ContentResolver.SCHEME_CONTENT.equals(scheme)) {Cursor cursor = context.getContentResolver().query(uri, new String[]{MediaStore.Images.ImageColumns.DATA}, null,null, null);if (null != cursor) {if (cursor.moveToFirst()) {int index = cursor.getColumnIndex(MediaStore.Images.ImageColumns.DATA);if (index > -1) {data = cursor.getString(index);}}cursor.close();}}return data;}public static Uri getUri(Context context, File file) {Uri fileUri;if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N) {// BuildConfig 是工程包路径下的:如:com.yingyou.demo.BuildConfigfileUri = FileProvider.getUriForFile(context, BuildConfig.APPLICATION_ID + ".fileprovider", file);} else {fileUri = Uri.fromFile(file);}return fileUri;}public static Bitmap getImageThumbnail(String imagePath, int width,int height) {Bitmap bitmap = null;BitmapFactory.Options options = new BitmapFactory.Options();// Options中有个属性inJustDecodeBounds。我们可以充分利用它,来避免大图片的溢出问题options.inJustDecodeBounds = true;// 设置为true可以不加载到内存,直接获取Bitmap宽高// 获取这个图片的宽和高,注意此处的bitmap为nullbitmap = BitmapFactory.decodeFile(imagePath, options);if (bitmap == null) {// 计算缩放比int h = options.outHeight;// 获取Bitmap的实际高度int w = options.outWidth;// 获取Bitmap的实际宽度int beWidth = w / width;int beHeight = h / height;int rate = 1;if (beWidth < beHeight) {rate = beWidth;} else {rate = beHeight;}if (rate <= 0) {// 图片实际大小小于缩略图,不缩放rate = 1;}options.inSampleSize = rate;// rate就是压缩的比例options.inJustDecodeBounds = false;// 重新读入图片,读取缩放后的bitmap,注意这次要把options.inJustDecodeBounds 设为 falsebitmap = BitmapFactory.decodeFile(imagePath, options);// 获取压缩后的图片}return bitmap;}public static Bitmap getBitmapFormUri(Activity ac, Uri uri) {InputStream input;try {input = ac.getContentResolver().openInputStream(uri);BitmapFactory.Options onlyBoundsOptions = new BitmapFactory.Options();onlyBoundsOptions.inJustDecodeBounds = true;onlyBoundsOptions.inDither = true;// optionalonlyBoundsOptions.inPreferredConfig = Bitmap.Config.ARGB_8888;// optionalBitmapFactory.decodeStream(input, null, onlyBoundsOptions);input.close();int originalWidth = onlyBoundsOptions.outWidth;int originalHeight = onlyBoundsOptions.outHeight;if ((originalWidth == -1) || (originalHeight == -1))return null;// 图片分辨率以480x800为标准float hh = 800f;// 这里设置高度为800ffloat ww = 480f;// 这里设置宽度为480f// 缩放比。由于是固定比例缩放,只用高或者宽其中一个数据进行计算即可int be = 1;// be=1表示不缩放if (originalWidth > originalHeight && originalWidth > ww) {// 如果宽度大的话根据宽度固定大小缩放be = (int) (originalWidth / ww);} else if (originalWidth < originalHeight && originalHeight > hh) {// 如果高度高的话根据宽度固定大小缩放be = (int) (originalHeight / hh);}if (be <= 0)be = 1;// 比例压缩BitmapFactory.Options bitmapOptions = new BitmapFactory.Options();bitmapOptions.inSampleSize = be;// 设置缩放比例bitmapOptions.inDither = true;// optionalbitmapOptions.inPreferredConfig = Bitmap.Config.ARGB_8888;// optionalinput = ac.getContentResolver().openInputStream(uri);Bitmap bitmap = BitmapFactory.decodeStream(input, null,bitmapOptions);input.close();return compressImage(bitmap);// 再进行质量压缩} catch (FileNotFoundException e) {e.printStackTrace();} catch (IOException e) {e.printStackTrace();}return null;}
}

Android 图片选择和拍照(剪辑)及压缩问题 工具类相关推荐

  1. Android系统(74)--- 从零实现灵活且可高度定制的Android图片选择架构

    从零实现灵活且可高度定制的Android图片选择架构 https://www.jianshu.com/u/df76f81fe3ff 前言 这是我花费了数月闲暇时间从零开始写的一个库,在这期间,我学习到 ...

  2. Android 图片选择对话框,通过本地相册或照相机获得图片,可单选或多选,单选可设置是否裁剪

    AndroidPickPhotoDialog 项目地址: wanliyang1990/AndroidPickPhotoDialog 简介:Android 图片选择对话框,通过本地相册或照相机获得图片, ...

  3. android 图片方法,分享实现Android图片选择的两种方式

    Android选择图片的两种方式: 第一种:单张选取 通过隐式启动activity,跳转到相册选择一张返回结果 关键代码如下: 发送请求: private static final int PICTU ...

  4. Android旋转视频工具类,Android开发实现的IntentUtil跳转多功能工具类【包含视频、音频、图片、摄像头等操作功能】...

    本文实例讲述了Android开发实现的IntentUtil跳转多功能工具类.分享给大家供大家参考,具体如下: 说明:此工具类是本人开发中总结下来的,还有其它的跳转亲给我留言,希望大家一起把这个工具类打 ...

  5. 【Android 插件化】Hook 插件化框架 ( 反射工具类 | 反射常用操作整理 )

    Android 插件化系列文章目录 [Android 插件化]插件化简介 ( 组件化与插件化 ) [Android 插件化]插件化原理 ( JVM 内存数据 | 类加载流程 ) [Android 插件 ...

  6. java.util.zip 用法,Java压缩文件工具类ZipUtil使用方法代码示例

    本文实例通过Java的Zip输入输出流实现压缩和解压文件,前一部分代码实现获取文件路径,压缩文件名的更改等,具体如下: package com.utility.zip; import java.io. ...

  7. Java原生Zip压缩/解压缩工具类

    转载原文: 写了一个系列,写的很好,强烈推荐去看! Java压缩技术(二) ZIP压缩--Java原生实现 Java压缩技术(三) ZIP解压缩--Java原生实现 Zip压缩/解压缩工具类 缺点: ...

  8. Zip压缩/解压缩工具类

    package com.customcode.util; import java.io.*;import java.util.ArrayList; import java.util.List; imp ...

  9. Android 图片选择框架ImageSelector适配Android10及以上

    参考地址: 1.引入依赖 在Project的build.gradle在添加以下代码 allprojects {repositories {...maven { url 'https://jitpack ...

最新文章

  1. mysql使用sha256密码,MySQL5.6启用sha256_password插件
  2. 测量左右磁极的原片磁铁
  3. 自拟计算机作文100字,玩电脑作文100字胡佳慧
  4. 使用Dockerfile创建一个tomcat镜像
  5. 前端技术分享:教你玩转vue-router命令视图
  6. 计算机操作基本知识公务员,公务员计算机类操作系统知识.pdf
  7. winform + INotifyPropertyChanged + IDataErrorInfo + ErrorProvider实现自动验证功能
  8. 【Java-Web】初始化加载Serlvet工程后-HttpServlet报错
  9. hread.interrupt()到底意味着什么
  10. 特别实用的几种SQL语句送给大家,让你的SQL高大上!
  11. Java练习题(String)
  12. 多元线性回归模型检验-续上篇
  13. Unity3d Network 局域网多人对战之游戏大厅
  14. 地震数据读写segyio的脑图(c语言接口)
  15. Python交通流仿真【含源码】
  16. 深度分析数据恢复原理——那些数据可以恢复那些不可以数据恢复软件
  17. AD936x+ZYNQ搭建OpenWIFI
  18. Linux内核内存管理(2):固定映射地址(fixmap)和输入输出重映射(ioremap)
  19. torch-geometric安装详细步骤
  20. PowerPC PPC460-S MMU(三 Access Control)

热门文章

  1. idea 资源文件各种花色的意义。是做啥子的
  2. 【Java课堂】接口详解
  3. IDE新建gradle liferay workspace项目没有项目目录问题解决方案
  4. 英语学习详细笔记(三)代名词
  5. Qt编写可视化大屏电子看板系统1-布局方案
  6. opencv for python (6) 改变一幅图的特定区域 (往一幅图片上加标志)
  7. 顺丰速运面试java,顺丰三面Java后端面经分享
  8. Windows系统上搭建私有云OwnCloud【保姆级别的教程】
  9. Armijo-Goldstein准则与Wolfe-Powell准则
  10. Google Earth Engine(GEE)最全632个数据集在哪里找?文章末含名称!