preface
Almost every APP needs image selection and clipping function. Because it involves camera and storage, this function still needs to consider a lot of compatibility. This is why there are a lot of picture selection frameworks on github, but you will find that the picture selection framework found on github is not just picture selection. It also includes a lot of functions such as video selection, video recording, picture compression and so on. In fact, you only need one avatar selection function. You can't use many functions of those frameworks, and the code has at least dozens of classes. It's troublesome to change problems in the later stage. So I encapsulated a code and its concise picture selection framework, without any redundant functions. There are only three main function classes involved, and the use is very simple.
Original address: https://www.jianshu.com/p/6ac6b681c413
The renderings are as follows:
design sketch. jpg
Functional features
- Support obtaining pictures by taking photos
- Support to get pictures through photo album
- Support image clipping
- Support the effect of imitating the action sheet of the pop-up selection menu at the bottom of IOS
- Support 6.0 dynamic authorization
- Solve the problem of black edge in the picture
- Solve the problem of calling the camera message FileUriExposedException in 7.0
- Solve the crash problem of Xiaomi miui system calling the system clipping picture function
use
Step 1. Add JitPack warehouse
In the project build Add JitPack warehouse to gradle
allprojects { repositories { ... maven { url "https://jitpack.io" } } }
Step 2. Add dependency
Add dependencies in the module s to be used (see for the latest version) PictureSelector)
dependencies { compile 'com.github.wildma:PictureSelector:1.1.1' }
Or reference the local lib
compile project(':pictureselector')
Step 3. Take a picture or choose a picture from an album
/** * create()The first parameter of the method is the context, which is passed in the activity This, pass the fragment in the fragment this. Parameter 2 is the request code, which is used to determine the result callback in onActivityResult * selectPicture()The method parameters are whether to crop, the width of the cropped picture (unit px), the height, width ratio and height ratio of the cropped picture. If it is not transmitted, the default is clipping, with a width of 200, a height of 200, and a width height ratio of 1:1. */ PictureSelector .create(MainActivity.this, PictureSelector.SELECT_REQUEST_CODE) .selectPicture(true, 200, 200, 1, 1);
Step 4. Get the cropped picture address
@Override protected void onActivityResult(int requestCode, int resultCode, Intent data) { super.onActivityResult(requestCode, resultCode, data); /*Result callback*/ if (requestCode == PictureSelector.SELECT_REQUEST_CODE) { if (data != null) { String picturePath = data.getStringExtra(PictureSelector.PICTURE_PATH); } } }
code
I have written the notes of each class very clearly, so only the main picture tool classes are posted here. For others, you can check the source code on my Github (see the end of the article).
Select Picture tool class
package com.wildma.pictureselector; import android.app.Activity; import android.content.Context; import android.content.Intent; import android.graphics.Bitmap; import android.graphics.BitmapFactory; import android.net.Uri; import android.os.Build; import android.provider.MediaStore; import android.support.v4.content.FileProvider; import android.widget.Toast; import java.io.File; import java.io.FileNotFoundException; /** * Author wildma * Github https://github.com/wildma * CreateDate 2018/6/10 * Desc ${Select Picture tool class} * usage method: * 1. Call getByCamera() and getByAlbum() to get pictures by taking photos or albums * 2. The onActivityResult method of this tool class is invoked in onActivityResult to process pictures obtained through photo albums or photographs. */ public class PictureSelectUtils { public static final int GET_BY_ALBUM = 0x11;//Album tag public static final int GET_BY_CAMERA = 0x12;//Photo mark public static final int CROP = 0x13;//Trim marks private static Uri takePictureUri;//Photo uri public static Uri cropPictureTempUri;//Crop picture uri /** * Get pictures from album * @param activity */ public static void getByAlbum(Activity activity) { Intent intent = new Intent(Intent.ACTION_PICK, MediaStore.Images.Media.EXTERNAL_CONTENT_URI); intent.setType("image/*"); activity.startActivityForResult(intent, GET_BY_ALBUM); } /** * Get pictures by taking pictures * @param activity */ public static void getByCamera(Activity activity) { takePictureUri = createImagePathUri(activity); if (takePictureUri != null) { Intent i = new Intent(MediaStore.ACTION_IMAGE_CAPTURE); i.putExtra(MediaStore.EXTRA_OUTPUT, takePictureUri);//Output path (save path after taking photos) activity.startActivityForResult(i, GET_BY_CAMERA); } else { Toast.makeText(activity, "Unable to save to album", Toast.LENGTH_LONG).show(); } } /** * Create a picture address uri to save the photos after taking photos * * @param activity * @return uri of the picture */ public static Uri createImagePathUri(Activity activity) { try { FileUtils.createOrExistsDir(Constant.DIR_ROOT); StringBuffer buffer = new StringBuffer(); String pathName = buffer.append(Constant.DIR_ROOT).append(Constant.APP_NAME).append(".").append(System.currentTimeMillis()).append(".jpg").toString(); File file = new File(pathName); if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N) { //Solve the problem of FileUriExposedException in Android 7.0 photography String authority = activity.getPackageName() + ".fileProvider"; takePictureUri = FileProvider.getUriForFile(activity, authority, file); } else { takePictureUri = Uri.fromFile(file); } } catch (Exception e) { e.printStackTrace(); Toast.makeText(activity, "Unable to save to album", Toast.LENGTH_LONG).show(); } return takePictureUri; } /** * Photo album, 1:480 by default, or 1:480 by default * @param activity context * @param requestCode Request code * @param resultCode Result code * @param data Intent * @return */ public static Bitmap onActivityResult(Activity activity, int requestCode, int resultCode, Intent data) { return onActivityResult(activity, requestCode, resultCode, data, 0, 0, 0, 0); } /** * Process pictures taken from photos or albums * @param activity context * @param requestCode Request code * @param resultCode Result code * @param data Intent * @param w Output width * @param h Output high * @param aspectX Width ratio * @param aspectY High proportion * @return */ public static Bitmap onActivityResult(Activity activity, int requestCode, int resultCode, Intent data, int w, int h, int aspectX, int aspectY) { Bitmap bm = null; if (resultCode == Activity.RESULT_OK) { Uri uri = null; switch (requestCode) { case GET_BY_ALBUM: uri = data.getData(); activity.startActivityForResult(crop(uri, w, h, aspectX, aspectY), CROP); break; case GET_BY_CAMERA: uri = takePictureUri; activity.startActivityForResult(crop(uri, w, h, aspectX, aspectY), CROP); break; case CROP: bm = dealCrop(activity); break; } } return bm; } /** * Clipping, default clipping output 480 * 480, scale 1:1 * @param uri uri of the picture * @return */ public static Intent crop(Uri uri) { return crop(uri, 480, 480, 1, 1); } /** * Cropping, for example: output 100 * 100 size pictures, with a width height ratio of 1:1 * @param uri uri of the picture * @param w Output width * @param h Output high * @param aspectX Width ratio * @param aspectY High proportion * @return */ public static Intent crop(Uri uri, int w, int h, int aspectX, int aspectY) { if (w == 0 && h == 0) { w = h = 480; } if (aspectX == 0 && aspectY == 0) { aspectX = aspectY = 1; } Intent intent = new Intent("com.android.camera.action.CROP"); intent.setDataAndType(uri, "image/*"); intent.putExtra("crop", "true"); intent.putExtra("aspectX", aspectX); intent.putExtra("aspectY", aspectY); intent.putExtra("outputX", w); intent.putExtra("outputY", h); /*Solve the problem of black edge in the picture*/ intent.putExtra("scale", true); intent.putExtra("scaleUpIfNeeded", true); /*Solve the problem of "picture loading failed" when jumping to the clipping prompt*/ intent.addFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION); intent.addFlags(Intent.FLAG_GRANT_WRITE_URI_PERMISSION); /*Solve the problem that Xiaomi miui system calls the system clipping picture function camera action. Problems after app reopens or crashes*/ StringBuffer buffer = new StringBuffer(); String pathName = buffer.append("file:///").append(FileUtils.getRootPath()).append(File.separator).append(Constant.APP_NAME).append(".temp.jpg").toString(); cropPictureTempUri = Uri.parse(pathName); intent.putExtra(MediaStore.EXTRA_OUTPUT, cropPictureTempUri);//Output path (saved path after clipping) // Output format intent.putExtra("outputFormat", "JPEG"); // Do not enable face recognition intent.putExtra("noFaceDetection", true); //Whether to keep data in Bitmap and return intent.putExtra("return-data", false); return intent; } /** * Process clipping and obtain the clipped picture * @param context context * @return */ public static Bitmap dealCrop(Context context) { Bitmap bitmap = null; try { bitmap = BitmapFactory.decodeStream(context.getContentResolver().openInputStream(cropPictureTempUri)); } catch (FileNotFoundException e) { e.printStackTrace(); } return bitmap; } }
github address: PictureSelector
ps: if it's helpful to you, clicking like is my greatest recognition.