SoFunction
Updated on 2025-04-11

Android picture or photo selection function example code

Preface

Generally, companies have the function of changing user avatars, and they need to select pictures or take photos from the gallery, and they will basically crop the pictures. Recently I took the time to make some simple packaging for easy use. It mainly uses the builder mode and chain calls, which is convenient and simple. The image path can be customized, with cropping and simple compression. Examples of use are as follows:

()
    .createBuilder(this)
    .setFileName("Picture Name")//There is a default one    .setFilePath("Picture Path")//There is a default one    .setIsCrop(false)//Crop    .setIsCompress(true)//compression    .setOnSelectListener(this)// Listen to the callback result    .setType(ChooseImageTask.TYPE_GALLERY)//type    .perform();

Photo album

/**
   * Select from the system gallery
   *
   * @param activity
   * @param builder
   */
 private void takeImageFromGallery(Activity activity, Builder builder) {
  OnSelectListener mOnSelectListener = ;
  Intent intent = new Intent(Intent.ACTION_PICK, .EXTERNAL_CONTENT_URI);
  ComponentName componentName = (());
  if (componentName != null) {
   (intent, );
  } else {
   if (mOnSelectListener != null) {
    ("takeImageFromGallery---> Activity is illegal");
   }
  }
 }

illustrate:ComponentName componentName = (())It is mainly used to verify the activity of the current jump, and the following jumps are also added.

Gallery Picture

/**
   * Select an image from the image type file
   *
   * @param activity
   */
 private void takeImageFromAlbum(Activity activity, Builder builder) {
  OnSelectListener mOnSelectListener = ;
  Intent intent = new Intent(Intent.ACTION_OPEN_DOCUMENT);//After api19// Intent intent = new Intent(Intent.ACTION_GET_CONTENT);//Before api19  ("image/*");
  ComponentName componentName = (());
  if (componentName != null) {
   (intent, );
  } else {
   if (mOnSelectListener != null) {
    ("takeImageFromAlbum---> Activity is illegal");
   }
  }
 }

Notice:ACTION has changed in different Android versions

Photograph

What is more special about taking pictures is that after Android 7.0, the URI reader method is adopted, so special processing is required. Create an xml folder under the res folder, and then create a storage path for taking pictures under the xml folder. The name can be started at will, but remember to be consistent when fetching.

 /**
   * Photograph
   *
   * @param activity
   */
 private void takePhoto(Activity activity,  builder) {
   mOnSelectListener = ;
  Intent takePictureIntent = new Intent(MediaStore.ACTION_IMAGE_CAPTURE);
  //Check whether the activity exists  if ((()) != null) {
   //Judge whether the path is customized and whether it is legal   Uri fileUri = (activity, new File(, ));
   (MediaStore.EXTRA_OUTPUT, fileUri);
   (takePictureIntent, );
  } else {
   if (mOnSelectListener != null) {
    ("takePhoto---> Activity is illegal");
   }
  }
 }
<?xml version="1.0" encoding="utf-8"?>
<paths xmlns:andro>
 <external-path
  name="external"
  path="." />
</paths>

Then you need to reference the current path in the manifest, as follows:

<provider
   android:name="."
   android:authorities="${applicationId}.fileprovider"
   android:exported="false"
   android:grantUriPermissions="true">
   <meta-data
    android:name=".FILE_PROVIDER_PATHS"
    android:resource="@xml/choose_image" />
  </provider>

Take a photo URI

 /**
   * Get URI based on file
   *
   * @param context
   * @param file
   * @return
   */
 public static Uri getUri(Context context, File file) {
  Uri uri;
  if (.SDK_INT &gt;= Build.VERSION_CODES.N) {
   uri = (context,
     FileProviderThe path , file);
  } else {
   uri = (file);
  }
  // Here we try to ensure that the URI is not empty, otherwise a null pointer exception will be reported.  return uri;
 }

Notice: android:authorities="${applicationId}.fileprovider"You must fill in the applicationId value inside. You cannot fill in the package name. If you don’t know about applicationId, you can check it yourself.

Crop pictures

/**
   * Cropping of image types
   *
   * @param activity
   * @param uri
   * @param outputUri
   */
 public void handleCropImage(Activity activity, Uri uri, Uri outputUri) {
  //Open the intent of the cropped pictures included with the system  Intent intent = new Intent("");
  if (.SDK_INT &gt;= Build.VERSION_CODES.N) {
   //Add this sentence to temporarily authorize the file represented by the Uri to the target application   (Intent.FLAG_GRANT_READ_URI_PERMISSION);
   (Intent.FLAG_GRANT_WRITE_URI_PERMISSION);
  }
  (uri, "image/*");
  ("scale", true);
  // Set the aspect ratio of the crop area  ("aspectX", 1);
  ("aspectY", 1);
  // Set the width and height of the crop area  ("outputX", 350);
  ("outputY", 350);
  // Face recognition  ("noFaceDetection", true);
  // Picture output format  ("outputFormat", ());
  // If false, it means no data is returned  ("return-data", false);
  //Output the picture to the specified location  (MediaStore.EXTRA_OUTPUT, outputUri);
  (intent, ChooseImageTask.TYPE_CROP);
 }

Notice: ("return-data", false);If the return value is true, it will directly return to bitmap. In order to return it through callback after unified compression, the return value is false and the output is outputUri.

Image rotation angle processing

Some mobile phones will have the rotation angle problem when taking pictures or selecting pictures, so new pictures should be regenerated according to the rotation angle to meet the requirements.

/**
   * The angle of rotation of the picture
   *
   * @param path The absolute path of the picture
   * @return The rotation angle of the picture
   */
 public static int getBitmapDegree(String path) {
  int degree = 0;
  try {
   // Read the picture from the specified path and obtain its EXIF ​​information   ExifInterface exifInterface = new ExifInterface(path);
   // Get the rotation information of the picture   int orientation = (ExifInterface.TAG_ORIENTATION,
     ExifInterface.ORIENTATION_NORMAL);
   switch (orientation) {
    case ExifInterface.ORIENTATION_ROTATE_90:
     degree = 90;
     break;
    case ExifInterface.ORIENTATION_ROTATE_180:
     degree = 180;
     break;
    case ExifInterface.ORIENTATION_ROTATE_270:
     degree = 270;
     break;
   }
  } catch (IOException e) {
   ();
  }
  return degree;
 }
/**
   * Rotate the picture so that the picture remains in the correct orientation.
   *
   * @param bitmap Original image
   * @param degrees The angle of the original image
   * @return Bitmap image after rotation
   */
 public static Bitmap rotateBitmap(Bitmap bitmap, int degrees) {
  if (degrees == 0 || null == bitmap) {
   return bitmap;
  }
  Matrix matrix = new Matrix();
  (degrees, () / 2, () / 2);
  Bitmap bmp = (bitmap, 0, 0, (), (), matrix, true);
  ();
  return bmp;
 }

Callback processing

By processing callbacks about image selection results in the onActivityResult of the activity, then processing different results according to the type

 /**
   * The return value process of proxy Activity then
   *
   * @param requestCode
   * @param resultCode
   * @param data
   */
 public void handleResult(int requestCode, int resultCode, @Nullable Intent data, Builder builder) {
  if (resultCode != Activity.RESULT_OK) {
   return;
  }

  switch (requestCode) {
   case TYPE_PHOTO:// Photograph    handlePhoto(builder);
    break;
   case TYPE_ALBUM://
    //Skip to crop page    handleGallery(data, builder);
    break;
   case TYPE_GALLERY:// Gallery selection picture    //Skip to crop page    handleGallery(data, builder);
    break;
   case TYPE_CROP:
    handleCropResult(builder);
    break;
  }
 }

Image compression

Compress the selected pictures by loop

/**
   * Quality compression method
   *
   * @param image
   * @return
   */
 public static Bitmap compressImage(Bitmap image) {

  ByteArrayOutputStream baos = new ByteArrayOutputStream();
  (, 100, baos);// Quality compression method, here 100 means no compression, store the compressed data in baos  int options = 100;
  while (().length / 1024 &gt; 100) { //Cyclically determine whether the image is greater than 100kb after compression, which is greater than continue compression.   ();//Reset baos means clear baos   //The first parameter: picture format, the second parameter: picture quality, 100 is the highest, 0 is the worst, and the third parameter: save the stream of compressed data   (, options, baos);//The compressed options% here, and the compressed data is stored in baos   options -= 10;//Reduce by 10 each time  }
  ByteArrayInputStream isBm = new ByteArrayInputStream(());//Storage the compressed data baos in ByteArrayInputStream  Bitmap bitmap = (isBm, null, null);//Create the ByteArrayInputStream data to generate pictures  return bitmap;
 }

Summarize

The general process is as shown above, but you must apply for dynamic permissions after Android 6.0. All functions have been written and GitHub has been uploaded. If you need it, please move to GitHub. If you encounter any problems, please comment and leave a message.Picture or take a photo to select pictures (Local download

OK, the above is the entire content of this article. I hope that the content of this article has certain reference value for everyone's study or work. Thank you for your support.