Android 图片选择和拍照(剪辑)及压缩问题 工具类
生活随笔
收集整理的這篇文章主要介紹了
Android 图片选择和拍照(剪辑)及压缩问题 工具类
小編覺得挺不錯(cuò)的,現(xiàn)在分享給大家,幫大家做個(gè)參考.
圖片選擇和拍照在開發(fā)過程中,會(huì)遇到不少坑:
1.版本4.4以后選擇圖片后不會(huì)返回絕對(duì)路徑,但返回Uri,要再查詢一次
2.去剪輯時(shí),設(shè)置了true的話直接返回bitmap,可能會(huì)很占內(nèi)存,有些機(jī)子會(huì)掛掉(OOM)或者不會(huì)返回
3.圖片未更好的壓縮,應(yīng)該做到寬高比壓縮后再質(zhì)量壓縮,下面例子可以把幾MB的圖片壓縮到100kb左右
4.解決7.0版本文件訪問問題
下面代碼處理解決了上面的問題,是個(gè)小筆記,以后就不會(huì)再麻煩找“輪子”了。
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/> 代表設(shè)備的根目錄new File("/");--> <!--<files-path/> 代表context.getFilesDir()--> <!--<cache-path/> 代表context.getCacheDir()--> <!--<external-path/> 代表Environment.getExternalStorageDirectory()--> <!--<external-files-path>代表context.getExternalFilesDirs()--> <!--<external-cache-path>代表getExternalCacheDirs()-->3.使用:
調(diào)用SelectPicUtil.getByAlbum(Activity.this);?選擇相冊(cè)
調(diào)用SelectPicUtil.getByCamera(Activity.this);進(jìn)行拍照
然后在onActivityResult進(jìn)行設(shè)置返回:
@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) { // 當(dāng)不為空時(shí)獲取到圖片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); // 圖片質(zhì)量壓縮80%bitmapSrc.recycle();byte[] bytes = baos.toByteArray();try {if (null != baos) {baos.close();}} catch (IOException e) {}// 對(duì)字節(jié)數(shù)組Base64編碼final String bitmap = Base64.encodeToString(bytes, Base64.DEFAULT);// 返回Base64編碼過的字節(jié)數(shù)組字符串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;// 打開相冊(cè)public static final int GET_BY_CAMERA = 802;// 打開相機(jī)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("請(qǐng)安裝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) {//對(duì)目標(biāo)應(yīng)用臨時(shí)授權(quá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中有個(gè)屬性inJustDecodeBounds。我們可以充分利用它,來避免大圖片的溢出問題options.inJustDecodeBounds = true;// 設(shè)置為true可以不加載到內(nèi)存,直接獲取Bitmap寬高// 獲取這個(gè)圖片的寬和高,注意此處的bitmap為nullbitmap = BitmapFactory.decodeFile(imagePath, options);if (bitmap == null) {// 計(jì)算縮放比int h = options.outHeight;// 獲取Bitmap的實(shí)際高度int w = options.outWidth;// 獲取Bitmap的實(shí)際寬度int beWidth = w / width;int beHeight = h / height;int rate = 1;if (beWidth < beHeight) {rate = beWidth;} else {rate = beHeight;}if (rate <= 0) {// 圖片實(shí)際大小小于縮略圖,不縮放rate = 1;}options.inSampleSize = rate;// rate就是壓縮的比例options.inJustDecodeBounds = false;// 重新讀入圖片,讀取縮放后的bitmap,注意這次要把options.inJustDecodeBounds 設(shè)為 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為標(biāo)準(zhǔn)float hh = 800f;// 這里設(shè)置高度為800ffloat ww = 480f;// 這里設(shè)置寬度為480f// 縮放比。由于是固定比例縮放,只用高或者寬其中一個(gè)數(shù)據(jù)進(jìn)行計(jì)算即可int be = 1;// be=1表示不縮放if (originalWidth > originalHeight && originalWidth > ww) {// 如果寬度大的話根據(jù)寬度固定大小縮放be = (int) (originalWidth / ww);} else if (originalWidth < originalHeight && originalHeight > hh) {// 如果高度高的話根據(jù)寬度固定大小縮放be = (int) (originalHeight / hh);}if (be <= 0)be = 1;// 比例壓縮BitmapFactory.Options bitmapOptions = new BitmapFactory.Options();bitmapOptions.inSampleSize = be;// 設(shè)置縮放比例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);// 再進(jìn)行質(zhì)量壓縮} catch (FileNotFoundException e) {e.printStackTrace();} catch (IOException e) {e.printStackTrace();}return null;} }?
總結(jié)
以上是生活随笔為你收集整理的Android 图片选择和拍照(剪辑)及压缩问题 工具类的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: ios13全选手势_iOS13操作新手势
- 下一篇: 这不是广告!千万不要相信淘宝上卖的CSD