Android Development

Android Selecting Picture in Digicam / Gallery with Crop Perform

Taking photographs from a digicam or gallery is an important characteristic for a lot of functions, together with the media. A easy notice software could require a profile image to make the notes extra private. Getting a thumbnail picture from the digicam is straightforward, however typically you need a full decision picture with out storing it in a gallery, crop it and keep away from any reminiscence exceptions.

On this tutorial, we are going to discover ways to construct a easy social profile consumer interface, to decide on the profile image within the digicam or gallery with features of cropping and picture transformation.

DEMO

1. uCrop – Crop Library

For the cropping characteristic, we are going to use the uCrop library. This library is utilized by many fashionable functions and examined on completely different variations of units / working techniques. Regardless that the library gives the perfect cropping expertise, it doesn’t mean you can select the enter picture within the digicam or gallery. All it takes is a bitmap that renders the cropped bitmap.

On this article, we use the identical cropping library, however as well as, we are going to create a characteristic for select the picture of the digicam or gallery.

For extra info on uCrop, try the official documentation.

2. Begin a brand new challenge / profile

Our objective is to create a easy social profile consumer interface (like Instagram) and to make use of the picture cropping characteristic to use the profile picture. You may take photographs utilizing the digicam or select from gallery, crop and set as profile image. So let's begin by creating a brand new challenge in Android Studio.

1. Create a brand new challenge in Android Studio from File ⇒ New challenge and choose Primary exercise from fashions. I gave the title of my bundle as information.androidhive.imagepicker

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

dependencies

three. Add the assets beneath to the respective assets strings.xml, dimen.xml and couleurs.xml recordsdata.


Deciding on photographs and cropping
settings
Rowan Sebastian Atkinson CBE is an English actor, comic and screenwriter.
Mister Bean
posts
followers
following
Cannot set the profile image. Attempt Once more!
Set the profile image
To take an image
Select from the gallery
The choice of picture selector is lacking!


sans-serif-light
sans-serif-medium
sans serif
with out serif condensed
sans-serif, black
with out serif-thin
Grant permissions
This app wants an authorization to make use of this characteristic. You can provide them within the software settings.
GO TO PARAMETERS


16DP
90dp
20dp
16DP
23dp
13dp
20dp
12dp
40dp
28dp



# 5770f3 # 5770f3 # D81B60 # 5770f3 # 8e5aeb # D1D1FF # 000000 # e0e0e0

four. Obtain this folder and add the content material to your challenge. res folder. This folder incorporates the icons wanted to create the profile display screen.

5. Open the format file of your most important exercise (activity_main.xml) and add the code beneath to get the profile presentation.


Create a brand new XML format layout_toolbar_profile.xml and add the code beneath.







Now, in case you run your challenge, it is best to be capable of see the display screen beneath.

three. Including the choice and crop performance

Now that the UI portion is full, let's see the right way to add the picture choice characteristic by tapping the profile picture or the Plus icon.

6. Create an XML file named chemin_fichiers.xml beneath res ⇒ xml folder. If you don’t see the xml folder beneath res, create a brand new folder with the identical title. Right here we outline a FileProvider path to retailer digicam photographs in a cached location as an alternative of storing them within the gallery.

7. Open AndroidManifest.xml and make the adjustments beneath.

> Add L & # 39; INTERNET, CAMERA and STORAGE ROOM authorizations.

> Add UCropActivité intention to launch the exercise of tradition.

> Add FileProvider info utilizing the XML we outlined within the step above.













eight. As we use Glide to show the picture, create a named class MyGlideModule and annotate the category with @GlideModule.

bundle information.androidhive.imagepicker;

import com.bumptech.glide.annotation.GlideModule;
import com.bumptech.glide.module.AppGlideModule;

@GlideModule
Public class MyGlideModule extends AppGlideModule

9. To cut back the complexity, I wrote an exercise that helps the selection of picture and cropping. All you must do is add this exercise to your challenge and name a number of strains to start out the exercise. That's all.

Create an empty exercise ImagePickerActivity.java and add the code beneath.

bundle information.androidhive.imagepicker;

import android.Manifest;
import android.app.Exercise;
import android.content material.ContentResolver;
import android.content material.Context;
import android.content material.Intent;
import android.database.Cursor;
import android.internet.Uri;
import android.os.Bundle;
import android.supplier.MediaStore;
import android.supplier.OpenableColumns;
import android.help.v4.content material.ContextCompat;
import android.help.v7.app.AlertDialog;
import android.help.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 java.util.Listing;

import android.help.v4.content material.FileProvider.getUriForFile static;

Public class ImagePickerActivity lengthen AppCompatActivity {
non-public static ultimate String TAG = ImagePickerActivity.class.getSimpleName ();
public static ultimate String INTENT_IMAGE_PICKER_OPTION = "image_picker_option";
public static ultimate String INTENT_ASPECT_RATIO_X = "aspect_ratio_x";
public static ultimate String INTENT_ASPECT_RATIO_Y = "aspect_ratio_Y";
public static ultimate String INTENT_LOCK_ASPECT_RATIO = "lock_aspect_ratio";
public static ultimate String INTENT_IMAGE_COMPRESSION_QUALITY = "compression_quality";
public static ultimate String INTENT_SET_BITMAP_MAX_WIDTH_HEIGHT = "set_bitmap_max_width_height";
public static ultimate String INTENT_BITMAP_MAX_WIDTH = "max_width";
public static ultimate String INTENT_BITMAP_MAX_HEIGHT = "max_height";

public static ultimate int REQUEST_IMAGE_CAPTURE = zero;
public static ultimate int REQUEST_GALLERY_IMAGE = 1;

non-public boolean lockAspectRatio = false, setBitmapMaxWidthHeight = false;
non-public int ASPECT_RATIO_X = 16, ASPECT_RATIO_Y = 9, bitmapMaxWidth = 1000, bitmapMaxHeight = 1000;
non-public int IMAGE_COMPRESSION = 80;
public static String fileName;

public interface PickerOptionListener
void onTakeCameraSelected ();

empty onChooseGallerySelected ();

@Override
Protected void onCreate (Bundle savedInstanceState)

public static void showImagePickerOptions (context context, pickerOptionListener listener)

non-public non-public jack CameraImage () {
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 = System.currentTimeMillis () + ".jpg";
Intention takePictureIntent = new Intent (MediaStore.ACTION_IMAGE_CAPTURE);
takePictureIntent.putExtra (MediaStore.EXTRA_OUTPUT, getCacheImagePath (filename));
if (takePictureIntent.resolveActivity (getPackageManager ()) !! = null)

@Override
Public Void on ProxyRationaleShouldBeShown (Listing permissions, PermissionToken token)
).test();
}

non-public void choosesImageFromGallery ()

onActivityResult void protected (int requestCode, int resultCode, intent knowledge)
change (requestCode)

cropImage (Uri sourceUri) non-public void
Uri destinationUri = Uri.fromFile (new file (getCacheDir (), queryName (getContentResolver (), sourceUri))));
UCrop.Choices choices = new UCrop.Choices ();
choices.setCompressionQuality (IMAGE_COMPRESSION);
choices.setToolbarColor (ContextCompat.getColor (this, R.shade.colorPrimary));
choices.setStatusBarColor (ContextCompat.getColor (this, R.shade.colorPrimary));
choices.setActiveWidgetColor (ContextCompat.getColor (this, R.shade.colorPrimary));

if (lockAspectRatio)
choices.withAspectRatio (ASPECT_RATIO_X, ASPECT_RATIO_Y);

if (setBitmapMaxWidthHeight)
choices.withMaxResultSize (bitmapMaxWidth, bitmapMaxHeight);

UCrop.of (sourceUri, destinationUri)
.withOptions (choices)
.begin (this);

non-public void handleUCropResult (intent knowledge)
if (knowledge == null)
ultimate Uri resultUri = UCrop.getOutput (knowledge);
setResultOk (resultUri);

non-public void setResultOk (Uri imagePath)
Intent of intent = new intention ();
intent.putExtra ("path", imagePath);
setResult (Exercise.RESULT_OK, intent);
end ();

set empty privateResultantCancel ()
Intent of intent = new intention ();
setResult (Exercise.RESULT_CANCELED, intent);
end ();

Non-public URI getCacheImagePath (String filename)
File path = new file (getExternalCacheDir (), "digicam");
if (! path.exists ()) path.mkdirs ();
Picture file = new File (path, file title);
return getUriForFile (ImagePickerActivity.this, getPackageName () + ".supplier", picture);

non-public static String queryName (Resolver ContentResolver, Uri uri)

/ **
* Calling this may delete the photographs from the cache listing
* helpful for erasing reminiscence
* /
static public void clearCache (context context)
}

three.1 Launch exercise

To show the picture choice decisions, name ImagePickerActivity.showImagePickerOptions () methodology.

ImagePickerActivity.showImagePickerOptions (this, new ImagePickerActivity.PickerOptionListener () );

As soon as the choice is chosen, you possibly can transmit the intent knowledge in line with the selection. For instance, to decide on the picture the gallery with a 1 × 1 facet ratio, the intention beneath can be utilized.

Intent of intent = new intent (MainActivity.this, ImagePickerActivity.class);
intent.putExtra (ImagePickerActivity.INTENT_IMAGE_PICKER_OPTION, ImagePickerActivity.REQUEST_IMAGE_CAPTURE);

// format setting
intent.putExtra (ImagePickerActivity.INTENT_LOCK_ASPECT_RATIO, true);
intent.putExtra (ImagePickerActivity.INTENT_ASPECT_RATIO_X, 1); // 16×9, 1×1, three: four, three: 2
intent.putExtra (ImagePickerActivity.INTENT_ASPECT_RATIO_Y, 1);

startActivityForResult (intent, REQUEST_IMAGE);

ten. We are going to now see how this may be utilized to our profile exercise. Open MainActivity.java and name the picture choice exercise by tapping the profile picture or the Extra icon.

bundle information.androidhive.imagepicker;

import android.Manifest;
import android.app.Exercise;
import android.content material.Intent;
import android.graphics.Bitmap;
import android.internet.Uri;
import android.os.Bundle;
import android.supplier.MediaStore;
import android.supplier.Settings;
import android.help.annotation.Nullable;
import android.help.v4.content material.ContextCompat;
import android.help.v7.app.AlertDialog;
import android.help.v7.app.AppCompatActivity;
import android.help.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.Listing;

import butterknife.BindView;
import butterknife.ButterKnife;
import butterknife.OnClick;

Public class MainActivity extends AppCompatActivity {
non-public static ultimate String TAG = MainActivity.class.getSimpleName ();
public static ultimate int REQUEST_IMAGE = 100;

@BindView (R.id.img_profile)
ImageView imgProfile;

@Override
Protected void onCreate (Bundle savedInstanceState)
tremendous.onCreate (savedInstanceState);
setContentView (R.format.activity_main);
ButterKnife.bind (this);
Toolbar Toolbar = findViewById (R.id.toolbar);
setSupportActionBar (toolbar);
getSupportActionBar (). setDisplayHomeAsUpEnabled (true);
getSupportActionBar (). setTitle (null);

loadProfileDefault ();

// Clear outdated photographs from the cache listing
// don’t name this line if you wish to select a number of photographs in the identical exercise
// name this as soon as using the completed bitmap photographs
ImagePickerActivity.clearCache (this);

loadProfile (string url) non-public void

non-public void loadProfileDefault ()

@OnClick (R.id.img_plus, R.id.img_profile)
void onProfileImageClick ()
Dexter.withActivity (this)
.withPermissions (Manifest.permission.CAMERA, Manifest.permission.WRITE_EXTERNAL_STORAGE)
.withListener (new MultiplePermissionsListener ()
@Override
public void onPermissionsChecked (MultiplePermissionsReport report)

@Override
Public Void on ProxyRationaleShouldBeShown (Listing permissions, PermissionToken token)
).test();

showImagePickerOptions () ) non-public
ImagePickerActivity.showImagePickerOptions (this, new ImagePickerActivity.PickerOptionListener ()
@Override
public void onTakeCameraSelected ()
launchCameraIntent ();

@Override
public void onChooseGallerySelected ()
launchGalleryIntent ();

);

non-public void launchCameraIntent ()
Intent of intent = new intent (MainActivity.this, ImagePickerActivity.class);
intent.putExtra (ImagePickerActivity.INTENT_IMAGE_PICKER_OPTION, ImagePickerActivity.REQUEST_IMAGE_CAPTURE);

// format setting
intent.putExtra (ImagePickerActivity.INTENT_LOCK_ASPECT_RATIO, true);
intent.putExtra (ImagePickerActivity.INTENT_ASPECT_RATIO_X, 1); // 16×9, 1×1, three: four, three: 2
intent.putExtra (ImagePickerActivity.INTENT_ASPECT_RATIO_Y, 1);

// set the utmost width and peak of a bitmap
intent.putExtra (ImagePickerActivity.INTENT_SET_BITMAP_MAX_WIDTH_HEIGHT, true);
intent.putExtra (ImagePickerActivity.INTENT_BITMAP_MAX_WIDTH, 1000);
intent.putExtra (ImagePickerActivity.INTENT_BITMAP_MAX_HEIGHT, 1000);

startActivityForResult (intent, REQUEST_IMAGE);

non-public void launchGalleryIntent ()
Intent of intent = new intent (MainActivity.this, ImagePickerActivity.class);
intent.putExtra (ImagePickerActivity.INTENT_IMAGE_PICKER_OPTION, ImagePickerActivity.REQUEST_GALLERY_IMAGE);

// format setting
intent.putExtra (ImagePickerActivity.INTENT_LOCK_ASPECT_RATIO, true);
intent.putExtra (ImagePickerActivity.INTENT_ASPECT_RATIO_X, 1); // 16×9, 1×1, three: four, three: 2
intent.putExtra (ImagePickerActivity.INTENT_ASPECT_RATIO_Y, 1);
startActivityForResult (intent, REQUEST_IMAGE);

@Override
onActivityResult void protected (int requestCode, int resultCode, knowledge @Nullable Intent) {
if (requestCode == REQUEST_IMAGE)
if (resultCode == Exercise.RESULT_OK)

}

/ **
* Show of the alert dialog with the configuration possibility
* Navigate the consumer to the applying settings
* NOTE: Maintain the suitable title and message to your software.
* /
showSettingsDialog () non-public
AlertDialog.Builder generator = new AlertDialog.Builder (MainActivity.this);
builder.setTitle (getString (R.string.dialog_permission_title));
builder.setMessage (getString (R.string.dialog_permission_message));
builder.setPositiveButton (getString (R.string.go_to_settings), (dialog, who) ->
dialog.cancel ();
openSettings ();
);
builder.setNegativeButton (getString (android.R.string.cancel), (dialog, which) -> dialog.cancel ());
builder.present ();

// consumer navigation to the applying settings
non-public void openSettings ()

Now, launch and check the applying. You need to be capable of set the profile image from a digicam or gallery.

In case you have any questions or strategies, please put up them within the remark part beneath.

Good coding

Hello! I’m founding father of androidhive and passionate programming. My abilities embody Android, iOS, PHP, Ruby on Rails and way more. In case you have an concept that you desire to me to develop? Let's discuss ravi@androidhive.information