Taking pictures from camera or gallery is an essential feature for many applications those includes media in their apps. A simple notes app may need a profile picture show to make the notes more personal. Getting a thumbnail image from camera is easy, merely sometimes you lot want the total resolution image without storing it in gallery, crop it and avoid the possible memory exceptions.

In this tutorial we are going to learn building a elementary social profile UI, choose the profile motion picture from camera or gallery with ingather and image transformation features.

android-image-pick-and-crop-tutorial (1)

1. uCrop – cropping library

For cropping functionality, nosotros are going to employ uCrop library. This library is used many pop apps and tested on various devices / OS versions. Even though the library provides all-time cropping experience, it won't provide an selection to cull the input paradigm from camera or gallery. All it takes is a bitmap and gives back the cropped bitmap.

In this article we use the same cropping library but on superlative of it, nosotros'll build a feature to pick the image from camera or gallery.

For information about uCrop, visit the official documentation.

2. Starting New Project / Profile Screen

Our goal is to build a elementary social contour UI (like Instagram) and utilize the image cropping functionality to employ the contour image. You can take picture using camera or choose from gallery, ingather and fix information technology every bit profile prototype. So let'south kickoff by creating a new project in Android Studio.

1. Create a new project in Android Studio from File ⇒ New Project and select Bones Activity from templates. I have given my bundle proper name as info.androidhive.imagepicker

2. Open app/build.gradle and add Dexter, ButterKnife, Glide, CircularImageView and uCrop dependencies.

dependencies {     // ...      //Butterknife     implementation 'com.jakewharton:butterknife:viii.eight.1'     annotationProcessor 'com.jakewharton:butterknife-compiler:8.8.ane'      //dexter permissions     implementation "com.karumi:dexter:v.0.0"      // round imageview     implementation 'com.mikhaellopez:circularimageview:3.2.0'      //Glide     implementation 'com.github.bumptech.glide:glide:4.7.1'     implementation 'com.github.bumptech.glide:annotations:4.seven.one'     implementation('com.github.bumptech.glide:okhttp3-integration:iv.0.0') {         exclude group: 'glide-parent'     }     annotationProcessor 'com.github.bumptech.glide:compiler:4.vii.1'      implementation 'com.github.yalantis:ucrop:2.two.2' }        

iii. Add the beneath resources to respective strings.xml, dimen.xml and colors.xml files.

<resource>     <string name="app_name">Image Pick &amp; Crop</string>     <string proper name="action_settings">Settings</string>     <cord name="profile_desc">Rowan Sebastian Atkinson CBE is an English actor,  comedian and screenwriter</string>     <string name="profile_title">Mr Bean</string>     <cord name="posts">posts</string>     <cord name="followers">followers</string>     <cord proper name="post-obit">post-obit</string>     <string name="msg_error_unable_select_profile_pic">Unable to fix profile image. Please attempt again!</cord>     <string name="lbl_set_profile_photo">Set profile prototype</cord>     <string name="lbl_take_camera_picture">Have a picture</cord>     <string name="lbl_choose_from_gallery">Choose from gallery</string>     <string name="toast_image_intent_null">Image picker option is missing!</string>      <!-- font families -->     <string proper noun="font_family_light">sans-serif-low-cal</string>     <string proper name="font_family_medium">sans-serif-medium</cord>     <cord name="font_family_regular">sans-serif</string>     <string name="font_family_condensed">sans-serif-condensed</string>     <string name="font_family_black">sans-serif-black</cord>     <string proper noun="font_family_thin">sans-serif-thin</string>     <cord name="dialog_permission_title">Grant Permissions</string>     <string name="dialog_permission_message">This app needs permission to apply this feature. You can grant them in app settings.</string>     <string name="go_to_settings">GOTO SETTINGS</string> </resources>        
<resources>     <dimen name="fab_margin">16dp</dimen>     <dimen name="toolbar_profile_width">90dp</dimen>     <dimen name="dimen_20dp">20dp</dimen>     <dimen proper noun="activity_padding">16dp</dimen>     <dimen proper noun="profile_title">23dp</dimen>     <dimen name="profile_desc">13dp</dimen>     <dimen proper noun="meta_count">20dp</dimen>     <dimen name="meta_label">12dp</dimen>     <dimen name="dimen_40dp">40dp</dimen>     <dimen name="ic_plus_width">28dp</dimen> </resources>        
<?xml version="i.0" encoding="utf-eight"?> <resources>     <color name="colorPrimary">#5770f3</colour>     <colour name="colorPrimaryDark">#5770f3</color>     <color name="colorAccent">#D81B60</colour>     <color proper noun="gradient_start">#5770f3</color>     <colour name="gradient_end">#8e5aeb</colour>     <color proper name="profile_desc">#D1D1FF</color>     <color name="bg_meta_container">#000000</color>     <colour name="profile_default_tint">#e0e0e0</colour> </resource>        

four. Download this res folder and add the contents to your projection'due south res folder. This folder contains necessary icons needed to build the profile screen.

5. Open the layout file your main activeness (activity_main.xml) and add together the below code to achieve the profile layout.

<?xml version="1.0" encoding="utf-eight"?> <android.support.design.widget.CoordinatorLayout xmlns:android="http://schemas.android.com/apk/res/android"     xmlns:app="http://schemas.android.com/apk/res-motorcar"     xmlns:tools="http://schemas.android.com/tools"     android:layout_width="match_parent"     android:layout_height="match_parent"     tools:context=".MainActivity">      <android.back up.design.widget.AppBarLayout         android:layout_width="match_parent"         android:layout_height="wrap_content"         android:theme="@style/AppTheme.AppBarOverlay">          <android.back up.v7.widget.Toolbar             android:id="@+id/toolbar"             android:layout_width="match_parent"             android:layout_height="?attr/actionBarSize"             android:background="?attr/colorPrimary"             app:popupTheme="@style/AppTheme.PopupOverlay" />          <include layout="@layout/layout_toolbar_profile" />      </android.support.design.widget.AppBarLayout>      <include layout="@layout/content_main" />  </android.support.design.widget.CoordinatorLayout>        

Create a new xml layout layout_toolbar_profile.xml and add together the below code.

<?xml version="1.0" encoding="utf-eight"?> <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"     xmlns:app="http://schemas.android.com/apk/res-auto"     android:layout_width="match_parent"     android:layout_height="wrap_content"     android:gravity="center_horizontal"     android:orientation="vertical">      <RelativeLayout         android:layout_width="@dimen/toolbar_profile_width"         android:layout_height="wrap_content">          <com.mikhaellopez.circularimageview.CircularImageView             android:id="@+id/img_profile"             android:layout_width="@dimen/toolbar_profile_width"             android:layout_height="@dimen/toolbar_profile_width"             android:layout_marginTop="@dimen/activity_padding"             android:layout_marginBottom="@dimen/activity_padding"             android:scaleType="centerInside"             android:src="@drawable/baseline_account_circle_black_48"             app:civ_border_color="@android:colour/white"             app:civ_border_width="2dp" />          <com.mikhaellopez.circularimageview.CircularImageView             android:id="@+id/img_plus"             android:layout_width="@dimen/ic_plus_width"             android:layout_height="@dimen/ic_plus_width"             android:layout_alignBottom="@id/img_profile"             android:layout_alignParentRight="truthful"             android:src="@drawable/ic_plus"             app:civ_shadow="true"             app:civ_shadow_radius="ane" />     </RelativeLayout>      <TextView         android:layout_width="wrap_content"         android:layout_height="wrap_content"         android:fontFamily="@string/font_family_medium"         android:text="@string/profile_title"         android:textColor="@android:color/white"         android:textSize="@dimen/profile_title" />      <TextView         android:id="@+id/profile_desc"         android:layout_width="wrap_content"         android:layout_height="wrap_content"         android:layout_marginBottom="@dimen/dimen_40dp"         android:gravity="center_horizontal"         android:paddingLeft="@dimen/dimen_20dp"         android:paddingRight="@dimen/dimen_20dp"         android:text="@string/profile_desc"         android:textColor="@colour/profile_desc"         android:textSize="@dimen/profile_desc" />      <LinearLayout         android:layout_width="match_parent"         android:layout_height="wrap_content"         android:groundwork="@color/bg_meta_container"         android:orientation="horizontal"         android:paddingTop="@dimen/activity_padding"         android:paddingBottom="@dimen/activity_padding"         android:weightSum="3">          <LinearLayout             android:layout_width="0dp"             android:layout_height="wrap_content"             android:layout_weight="1"             android:gravity="center"             android:orientation="vertical">              <TextView                 android:layout_width="wrap_content"                 android:layout_height="wrap_content"                 android:text="1320"                 android:textColor="@android:color/white"                 android:textSize="@dimen/meta_count"                 android:textStyle="bold" />              <TextView                 android:layout_width="wrap_content"                 android:layout_height="wrap_content"                 android:fontFamily="@string/font_family_condensed"                 android:text="@string/posts"                 android:textColor="@android:color/white"                 android:textSize="@dimen/meta_label" />         </LinearLayout>          <LinearLayout             android:layout_width="0dp"             android:layout_height="wrap_content"             android:layout_weight="1"             android:gravity="center"             android:orientation="vertical">              <TextView                 android:layout_width="wrap_content"                 android:layout_height="wrap_content"                 android:text="four.3m"                 android:textColor="@android:color/white"                 android:textSize="@dimen/meta_count"                 android:textStyle="bold" />              <TextView                 android:layout_width="wrap_content"                 android:layout_height="wrap_content"                 android:fontFamily="@string/font_family_condensed"                 android:text="@cord/followers"                 android:textColor="@android:color/white"                 android:textSize="@dimen/meta_label" />         </LinearLayout>          <LinearLayout             android:layout_width="0dp"             android:layout_height="wrap_content"             android:layout_weight="1"             android:gravity="center"             android:orientation="vertical">              <TextView                 android:layout_width="wrap_content"                 android:layout_height="wrap_content"                 android:text="123"                 android:textColor="@android:colour/white"                 android:textSize="@dimen/meta_count"                 android:textStyle="bold" />              <TextView                 android:layout_width="wrap_content"                 android:layout_height="wrap_content"                 android:fontFamily="@cord/font_family_condensed"                 android:text="@string/following"                 android:textColor="@android:color/white"                 android:textSize="@dimen/meta_label" />         </LinearLayout>     </LinearLayout>  </LinearLayout>        

Now if you run your project, yous should able to see the screen equally below.

android-social-profile-like-instagram-min

iii. Adding Image Pick and Ingather functionality

Now as the UI role is done, let's meet how to add together the prototype picking functionality on tapping the profile image or plus icon.

6. Create an xml file named file_paths.xml under res ⇒ xml folder. If you don't see xml folder under res, create a new binder with the same name. Here we are defining a FileProvider path to store the photographic camera images in a buried location instead of storing them in gallery.

<?xml version="one.0" encoding="utf-viii"?> <paths>     <external-enshroud-path         name="cache"         path="camera" /> </paths>        

7. Open up AndroidManifest.xml and practice the below changes.

> Add Cyberspace, CAMERA and STORAGE permissions.

> Add UCropActivity intent to launch the crop activity.

> Add FileProvider information using the xml we have defined in the in a higher place pace.

<?xml version="1.0" encoding="utf-eight"?> <manifest xmlns:android="http://schemas.android.com/apk/res/android"     xmlns:tools="http://schemas.android.com/tools"     package="info.androidhive.imagepicker">      <uses-permission android:proper noun="android.permission.INTERNET" />     <uses-permission android:proper noun="android.permission.Photographic camera" />     <uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE" />     <uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />      <application         android:allowBackup="true"         android:icon="@mipmap/ic_launcher"         android:label="@string/app_name"         android:roundIcon="@mipmap/ic_launcher_round"         android:supportsRtl="true"         android:theme="@style/AppTheme"         tools:ignore="GoogleAppIndexingWarning">         <action android:proper noun=".ImagePickerActivity" />         <activity             android:name=".MainActivity"             android:label="@string/app_name"             android:screenOrientation="portrait"             android:theme="@style/AppTheme.NoActionBar">             <intent-filter>                 <action android:name="android.intent.activity.MAIN" />                  <category android:name="android.intent.category.LAUNCHER" />             </intent-filter>         </activity>          <!-- uCrop cropping activity -->         <activity             android:name="com.yalantis.ucrop.UCropActivity"             android:screenOrientation="portrait"             android:theme="@style/AppTheme.NoActionBar" />          <!-- enshroud directory file provider paths -->         <provider             android:name="android.back up.v4.content.FileProvider"             android:authorities="${applicationId}.provider"             android:exported="false"             android:grantUriPermissions="true">             <meta-data                 android:name="android.support.FILE_PROVIDER_PATHS"                 android:resource="@xml/file_paths" />         </provider>     </application>  </manifest>        

eight. Equally we are using Glide to display the image, create a class named MyGlideModule and annotate the class with @GlideModule.

package info.androidhive.imagepicker;  import com.bumptech.glide.annotation.GlideModule; import com.bumptech.glide.module.AppGlideModule;  @GlideModule public course MyGlideModule extends AppGlideModule { }        

9. To reduce the complication, I accept written an action that takes care of choosing the prototype and cropping. All you lot have to do is, add this activeness to your project and telephone call couple of lines to launch the activity. That's all.

Create a bare activity ImagePickerActivity.java and add the beneath code.

package info.androidhive.imagepicker;  import android.Manifest; import android.app.Action; import android.content.ContentResolver; import android.content.Context; import android.content.Intent; import android.database.Cursor; import android.net.Uri; import android.os.Packet; import android.provider.MediaStore; import android.provider.OpenableColumns; import android.back up.v4.content.ContextCompat; import android.back up.v7.app.AlertDialog; import android.back up.v7.app.AppCompatActivity; import android.util.Log; import android.widget.Toast;  import com.karumi.dexter.Dexter; import com.karumi.dexter.MultiplePermissionsReport; import com.karumi.dexter.PermissionToken; import com.karumi.dexter.listener.PermissionRequest; import com.karumi.dexter.listener.multi.MultiplePermissionsListener; import com.yalantis.ucrop.UCrop;  import java.io.File; import coffee.util.List;  import static android.support.v4.content.FileProvider.getUriForFile;  public form ImagePickerActivity extends AppCompatActivity {     private static final String TAG = ImagePickerActivity.class.getSimpleName();     public static final String INTENT_IMAGE_PICKER_OPTION = "image_picker_option";     public static last String INTENT_ASPECT_RATIO_X = "aspect_ratio_x";     public static final Cord INTENT_ASPECT_RATIO_Y = "aspect_ratio_Y";     public static final String INTENT_LOCK_ASPECT_RATIO = "lock_aspect_ratio";     public static final String INTENT_IMAGE_COMPRESSION_QUALITY = "compression_quality";     public static final String INTENT_SET_BITMAP_MAX_WIDTH_HEIGHT = "set_bitmap_max_width_height";     public static final String INTENT_BITMAP_MAX_WIDTH = "max_width";     public static final String INTENT_BITMAP_MAX_HEIGHT = "max_height";       public static final int REQUEST_IMAGE_CAPTURE = 0;     public static final int REQUEST_GALLERY_IMAGE = ane;      private boolean lockAspectRatio = simulated, setBitmapMaxWidthHeight = false;     private int ASPECT_RATIO_X = xvi, ASPECT_RATIO_Y = 9, bitmapMaxWidth = 1000, bitmapMaxHeight = 1000;     individual int IMAGE_COMPRESSION = eighty;     public static String fileName;      public interface PickerOptionListener {         void onTakeCameraSelected();          void onChooseGallerySelected();     }      @Override     protected void onCreate(Packet savedInstanceState) {         super.onCreate(savedInstanceState);         setContentView(R.layout.activity_image_picker);          Intent intent = getIntent();         if (intent == naught) {             Toast.makeText(getApplicationContext(), getString(R.string.toast_image_intent_null), Toast.LENGTH_LONG).show();             render;         }          ASPECT_RATIO_X = intent.getIntExtra(INTENT_ASPECT_RATIO_X, ASPECT_RATIO_X);         ASPECT_RATIO_Y = intent.getIntExtra(INTENT_ASPECT_RATIO_Y, ASPECT_RATIO_Y);         IMAGE_COMPRESSION = intent.getIntExtra(INTENT_IMAGE_COMPRESSION_QUALITY, IMAGE_COMPRESSION);         lockAspectRatio = intent.getBooleanExtra(INTENT_LOCK_ASPECT_RATIO, false);         setBitmapMaxWidthHeight = intent.getBooleanExtra(INTENT_SET_BITMAP_MAX_WIDTH_HEIGHT, false);         bitmapMaxWidth = intent.getIntExtra(INTENT_BITMAP_MAX_WIDTH, bitmapMaxWidth);         bitmapMaxHeight = intent.getIntExtra(INTENT_BITMAP_MAX_HEIGHT, bitmapMaxHeight);          int requestCode = intent.getIntExtra(INTENT_IMAGE_PICKER_OPTION, -1);         if (requestCode == REQUEST_IMAGE_CAPTURE) {             takeCameraImage();         } else {             chooseImageFromGallery();         }     }      public static void showImagePickerOptions(Context context, PickerOptionListener listener) {         // setup the alert builder         AlertDialog.Builder builder = new AlertDialog.Builder(context);         builder.setTitle(context.getString(R.cord.lbl_set_profile_photo));          // add a list         Cord[] animals = {context.getString(R.string.lbl_take_camera_picture), context.getString(R.string.lbl_choose_from_gallery)};         builder.setItems(animals, (dialog, which) -> {             switch (which) {                 example 0:                     listener.onTakeCameraSelected();                     break;                 case 1:                     listener.onChooseGallerySelected();                     suspension;             }         });          // create and show the alert dialog         AlertDialog dialog = builder.create();         dialog.show();     }      private void takeCameraImage() {         Dexter.withActivity(this)                 .withPermissions(Manifest.permission.CAMERA, Manifest.permission.WRITE_EXTERNAL_STORAGE)                 .withListener(new MultiplePermissionsListener() {                     @Override                     public void onPermissionsChecked(MultiplePermissionsReport report) {                         if (report.areAllPermissionsGranted()) {                             fileName = Organisation.currentTimeMillis() + ".jpg";                             Intent takePictureIntent = new Intent(MediaStore.ACTION_IMAGE_CAPTURE);                             takePictureIntent.putExtra(MediaStore.EXTRA_OUTPUT, getCacheImagePath(fileName));                             if (takePictureIntent.resolveActivity(getPackageManager()) != null) {                                 startActivityForResult(takePictureIntent, REQUEST_IMAGE_CAPTURE);                             }                         }                     }                      @Override                     public void onPermissionRationaleShouldBeShown(List<PermissionRequest> permissions, PermissionToken token) {                         token.continuePermissionRequest();                     }                 }).bank check();     }      private void chooseImageFromGallery() {         Dexter.withActivity(this)                 .withPermissions(Manifest.permission.CAMERA, Manifest.permission.WRITE_EXTERNAL_STORAGE)                 .withListener(new MultiplePermissionsListener() {                     @Override                     public void onPermissionsChecked(MultiplePermissionsReport written report) {                         if (written report.areAllPermissionsGranted()) {                             Intent pickPhoto = new Intent(Intent.ACTION_PICK,                                     android.provider.MediaStore.Images.Media.EXTERNAL_CONTENT_URI);                             startActivityForResult(pickPhoto, REQUEST_GALLERY_IMAGE);                         }                     }                      @Override                     public void onPermissionRationaleShouldBeShown(Listing<PermissionRequest> permissions, PermissionToken token) {                         token.continuePermissionRequest();                     }                 }).check();      }      protected void onActivityResult(int requestCode, int resultCode, Intent data) {         switch (requestCode) {             case REQUEST_IMAGE_CAPTURE:                 if (resultCode == RESULT_OK) {                     cropImage(getCacheImagePath(fileName));                 } else {                     setResultCancelled();                 }                 pause;             instance REQUEST_GALLERY_IMAGE:                 if (resultCode == RESULT_OK) {                     Uri imageUri = information.getData();                     cropImage(imageUri);                 } else {                     setResultCancelled();                 }                 pause;             case UCrop.REQUEST_CROP:                 if (resultCode == RESULT_OK) {                     handleUCropResult(information);                 } else {                     setResultCancelled();                 }                 break;             case UCrop.RESULT_ERROR:                 concluding Throwable cropError = UCrop.getError(information);                 Log.e(TAG, "Crop error: " + cropError);                 setResultCancelled();                 break;             default:                 setResultCancelled();         }     }      private void cropImage(Uri sourceUri) {         Uri destinationUri = Uri.fromFile(new File(getCacheDir(), queryName(getContentResolver(), sourceUri)));         UCrop.Options options = new UCrop.Options();         options.setCompressionQuality(IMAGE_COMPRESSION);         options.setToolbarColor(ContextCompat.getColor(this, R.color.colorPrimary));         options.setStatusBarColor(ContextCompat.getColor(this, R.color.colorPrimary));         options.setActiveWidgetColor(ContextCompat.getColor(this, R.color.colorPrimary));          if (lockAspectRatio)             options.withAspectRatio(ASPECT_RATIO_X, ASPECT_RATIO_Y);          if (setBitmapMaxWidthHeight)             options.withMaxResultSize(bitmapMaxWidth, bitmapMaxHeight);          UCrop.of(sourceUri, destinationUri)                 .withOptions(options)                 .start(this);     }      private void handleUCropResult(Intent information) {         if (data == naught) {             setResultCancelled();             return;         }         final Uri resultUri = UCrop.getOutput(data);         setResultOk(resultUri);     }      private void setResultOk(Uri imagePath) {         Intent intent = new Intent();         intent.putExtra("path", imagePath);         setResult(Activeness.RESULT_OK, intent);         finish();     }      individual void setResultCancelled() {         Intent intent = new Intent();         setResult(Activeness.RESULT_CANCELED, intent);         finish();     }      private Uri getCacheImagePath(String fileName) {         File path = new File(getExternalCacheDir(), "photographic camera");         if (!path.exists()) path.mkdirs();         File epitome = new File(path, fileName);         return getUriForFile(ImagePickerActivity.this, getPackageName() + ".provider", image);     }      individual static String queryName(ContentResolver resolver, Uri uri) {         Cursor returnCursor =                 resolver.query(uri, zero, zero, null, null);         assert returnCursor != null;         int nameIndex = returnCursor.getColumnIndex(OpenableColumns.DISPLAY_NAME);         returnCursor.moveToFirst();         String name = returnCursor.getString(nameIndex);         returnCursor.shut();         render name;     }      /**      * Calling this will delete the images from enshroud directory      * useful to clear some memory      */     public static void clearCache(Context context) {         File path = new File(context.getExternalCacheDir(), "camera");         if (path.exists() && path.isDirectory()) {             for (File child : path.listFiles()) {                 child.delete();             }         }     } }        

3.ane Launching copping activity

To evidence the paradigm picking choices, call ImagePickerActivity.showImagePickerOptions() method.

ImagePickerActivity.showImagePickerOptions(this, new ImagePickerActivity.PickerOptionListener() {             @Override             public void onTakeCameraSelected() {                 // launchCameraIntent();             }              @Override             public void onChooseGallerySelected() {                 // launchGalleryIntent();             }         });        

In one case, an option is selected, you can pass Intent data depending on the choice. For example, to pick the epitome from gallery with i×i attribute ratio, the below intent tin be used.

Intent intent = new Intent(MainActivity.this, ImagePickerActivity.class); intent.putExtra(ImagePickerActivity.INTENT_IMAGE_PICKER_OPTION, ImagePickerActivity.REQUEST_IMAGE_CAPTURE);  // setting aspect ratio intent.putExtra(ImagePickerActivity.INTENT_LOCK_ASPECT_RATIO, true); intent.putExtra(ImagePickerActivity.INTENT_ASPECT_RATIO_X, one); // 16x9, 1x1, 3:4, 3:2 intent.putExtra(ImagePickerActivity.INTENT_ASPECT_RATIO_Y, 1);  startActivityForResult(intent, REQUEST_IMAGE);        

10. At present nosotros'll run across how this can exist applied to our profile activity. Open MainActivity.java and call image picker activity on tapping the profile image or plus icon.

bundle info.androidhive.imagepicker;  import android.Manifest; import android.app.Activity; import android.content.Intent; import android.graphics.Bitmap; import android.internet.Uri; import android.bone.Bundle; import android.provider.MediaStore; import android.provider.Settings; import android.support.annotation.Nullable; import android.back up.v4.content.ContextCompat; import android.back up.v7.app.AlertDialog; import android.support.v7.app.AppCompatActivity; import android.support.v7.widget.Toolbar; import android.util.Log; import android.widget.ImageView;  import com.karumi.dexter.Dexter; import com.karumi.dexter.MultiplePermissionsReport; import com.karumi.dexter.PermissionToken; import com.karumi.dexter.listener.PermissionRequest; import com.karumi.dexter.listener.multi.MultiplePermissionsListener;  import java.io.IOException; import java.util.List;  import butterknife.BindView; import butterknife.ButterKnife; import butterknife.OnClick;  public course MainActivity extends AppCompatActivity {     private static final String TAG = MainActivity.grade.getSimpleName();     public static final int REQUEST_IMAGE = 100;      @BindView(R.id.img_profile)     ImageView imgProfile;      @Override     protected void onCreate(Bundle savedInstanceState) {         super.onCreate(savedInstanceState);         setContentView(R.layout.activity_main);         ButterKnife.demark(this);         Toolbar toolbar = findViewById(R.id.toolbar);         setSupportActionBar(toolbar);         getSupportActionBar().setDisplayHomeAsUpEnabled(true);         getSupportActionBar().setTitle(nil);          loadProfileDefault();          // Clearing older images from cache directory         // don't phone call this line if you desire to cull multiple images in the same activeness         // call this once the bitmap(southward) usage is over         ImagePickerActivity.clearCache(this);     }      private void loadProfile(String url) {         Log.d(TAG, "Prototype cache path: " + url);          GlideApp.with(this).load(url)                 .into(imgProfile);         imgProfile.setColorFilter(ContextCompat.getColor(this, android.R.color.transparent));     }      individual void loadProfileDefault() {         GlideApp.with(this).load(R.drawable.baseline_account_circle_black_48)                 .into(imgProfile);         imgProfile.setColorFilter(ContextCompat.getColor(this, R.colour.profile_default_tint));     }      @OnClick({R.id.img_plus, R.id.img_profile})     void onProfileImageClick() {         Dexter.withActivity(this)                 .withPermissions(Manifest.permission.Photographic camera, Manifest.permission.WRITE_EXTERNAL_STORAGE)                 .withListener(new MultiplePermissionsListener() {                     @Override                     public void onPermissionsChecked(MultiplePermissionsReport report) {                         if (report.areAllPermissionsGranted()) {                             showImagePickerOptions();                         }                          if (report.isAnyPermissionPermanentlyDenied()) {                             showSettingsDialog();                         }                     }                      @Override                     public void onPermissionRationaleShouldBeShown(List<PermissionRequest> permissions, PermissionToken token) {                         token.continuePermissionRequest();                     }                 }).check();     }      individual void showImagePickerOptions() {         ImagePickerActivity.showImagePickerOptions(this, new ImagePickerActivity.PickerOptionListener() {             @Override             public void onTakeCameraSelected() {                 launchCameraIntent();             }              @Override             public void onChooseGallerySelected() {                 launchGalleryIntent();             }         });     }      private void launchCameraIntent() {         Intent intent = new Intent(MainActivity.this, ImagePickerActivity.class);         intent.putExtra(ImagePickerActivity.INTENT_IMAGE_PICKER_OPTION, ImagePickerActivity.REQUEST_IMAGE_CAPTURE);          // setting aspect ratio         intent.putExtra(ImagePickerActivity.INTENT_LOCK_ASPECT_RATIO, truthful);         intent.putExtra(ImagePickerActivity.INTENT_ASPECT_RATIO_X, 1); // 16x9, 1x1, 3:four, 3:two         intent.putExtra(ImagePickerActivity.INTENT_ASPECT_RATIO_Y, 1);          // setting maximum bitmap width and height         intent.putExtra(ImagePickerActivity.INTENT_SET_BITMAP_MAX_WIDTH_HEIGHT, true);         intent.putExtra(ImagePickerActivity.INTENT_BITMAP_MAX_WIDTH, chiliad);         intent.putExtra(ImagePickerActivity.INTENT_BITMAP_MAX_HEIGHT, m);          startActivityForResult(intent, REQUEST_IMAGE);     }      private void launchGalleryIntent() {         Intent intent = new Intent(MainActivity.this, ImagePickerActivity.class);         intent.putExtra(ImagePickerActivity.INTENT_IMAGE_PICKER_OPTION, ImagePickerActivity.REQUEST_GALLERY_IMAGE);          // setting aspect ratio         intent.putExtra(ImagePickerActivity.INTENT_LOCK_ASPECT_RATIO, true);         intent.putExtra(ImagePickerActivity.INTENT_ASPECT_RATIO_X, 1); // 16x9, 1x1, 3:four, 3:2         intent.putExtra(ImagePickerActivity.INTENT_ASPECT_RATIO_Y, i);         startActivityForResult(intent, REQUEST_IMAGE);     }      @Override     protected void onActivityResult(int requestCode, int resultCode, @Nullable Intent data) {         if (requestCode == REQUEST_IMAGE) {             if (resultCode == Action.RESULT_OK) {                 Uri uri = data.getParcelableExtra("path");                 try {                     // You tin can update this bitmap to your server                     Bitmap bitmap = MediaStore.Images.Media.getBitmap(this.getContentResolver(), uri);                      // loading profile paradigm from local cache                     loadProfile(uri.toString());                 } catch (IOException e) {                     e.printStackTrace();                 }             }         }     }      /**      * Showing Alert Dialog with Settings selection      * Navigates user to app settings      * Annotation: Keep proper title and message depending on your app      */     private void showSettingsDialog() {         AlertDialog.Builder builder = new AlertDialog.Architect(MainActivity.this);         builder.setTitle(getString(R.cord.dialog_permission_title));         builder.setMessage(getString(R.string.dialog_permission_message));         builder.setPositiveButton(getString(R.string.go_to_settings), (dialog, which) -> {             dialog.cancel();             openSettings();         });         builder.setNegativeButton(getString(android.R.string.abolish), (dialog, which) -> dialog.cancel());         builder.bear witness();      }      // navigating user to app settings     private void openSettings() {         Intent intent = new Intent(Settings.ACTION_APPLICATION_DETAILS_SETTINGS);         Uri uri = Uri.fromParts("bundle", getPackageName(), zero);         intent.setData(uri);         startActivityForResult(intent, 101);     } }        

Now run and test the app. Y'all should be able to set the profile prototype from camera or gallery.

android-image-from-gallery-or-camera-with-crop-min

If you have whatever queries or suggestions, delight do post in the annotate section beneath.

Happy Coding 🙂