Sometimes in your Android application you’ll want the user to choose an image from the gallery that’ll be displayed by the application (and even uploaded to your servers) after the selection is made. In this article we’ll see how to invoke a single interface from which the user is able to select images across all his apps (like Gallery, Photos, ES File Explorer, etc.) and folders (Google Drive, Recent, Downloads, etc.) using Intents.
Launch the Gallery Image Chooser
Triggering the following Intent from your Activity/Fragment, you can allow the user to select an image.
What's the one thing every developer wants? More screens! Enhance your coding experience with an external monitor to increase screen real estate.
Intent intent = new Intent(); // Show only images, no videos or anything else intent.setType("image/*"); intent.setAction(Intent.ACTION_GET_CONTENT); // Always show the chooser (if there are multiple options available) startActivityForResult(Intent.createChooser(intent, "Select Picture"), PICK_IMAGE_REQUEST);
PICK_IMAGE_REQUEST
is the request code defined as an instance variable.
private int PICK_IMAGE_REQUEST = 1;
More on Android Intents here (if you don’t know much). If you’re wondering why I used ACTION_GET_CONTENT
and not ACTION_PICK
, then the answer lies here.
Show Up the Selected Image in the Activity/Fragment
Now once the selection has been made, we’ll show up the image in the Activity/Fragment user interface, using an ImageView
. For this, we’ll have to override onActivityResult()
:
@Override protected void onActivityResult(int requestCode, int resultCode, Intent data) { super.onActivityResult(requestCode, resultCode, data); if (requestCode == PICK_IMAGE_REQUEST && resultCode == RESULT_OK && data != null && data.getData() != null) { Uri uri = data.getData(); try { Bitmap bitmap = MediaStore.Images.Media.getBitmap(getContentResolver(), uri); // Log.d(TAG, String.valueOf(bitmap)); ImageView imageView = (ImageView) findViewById(R.id.imageView); imageView.setImageBitmap(bitmap); } catch (IOException e) { e.printStackTrace(); } } }
Your layout will need to have an ImageView
like this:
<ImageView android:layout_width="wrap_content" android:layout_height="wrap_content" android:id="@+id/imageView" />
Voila! you’re ready to test the code and see how the selected photo shows up in your UI when you pick from your gallery.
Getting the Absolute File Path from Content URI
The Content URI returned can be different depending upon where the selection has been made from. Especially since Kitkat (API level 19) which introduces the Storage Access Framework (SAF) you get to see all your document storage providers while selecting a photo. The content URIs can different basis each provider and then if you try to use that to get the file path with a piece of code like this (used to generally work pre-Kitkat):
Uri uri = data.getData(); String[] projection = { MediaStore.Images.Media.DATA }; Cursor cursor = getContentResolver().query(uri, projection, null, null, null); cursor.moveToFirst(); Log.d(TAG, DatabaseUtils.dumpCursorToString(cursor)); int columnIndex = cursor.getColumnIndex(projection[0]); String picturePath = cursor.getString(columnIndex); // returns null cursor.close();
Then you’ll notice that the value of MediaStore.Images.Media.DATA
returned in the cursor is null
.
This issue (and fixes for it) has been addressed in the following StackOverflow threads:
- http://stackoverflow.com/questions/19834842/android-gallery-on-kitkat-returns-different-uri-for-intent-action-get-content
- http://stackoverflow.com/questions/20260416/retrieve-absolute-path-when-select-image-from-gallery-kitkat-android
Let’s see the different types of Content URIs returned when making a selection of images from various sections (in the navigation drawer) in the app that is invoked by the Intent. This is what you’d get from a selection in the Gallery (app) section:
content://media/external/images/media/3753
From Recents (or generally I guess), you get this:
content://com.android.providers.media.documents/document/image:2505
and when selecting something from Google Drive, this is the URI:
content://com.google.android.apps.docs.storage/document/acc=1;doc=22
Also from Photos (app) section, you get this (url encoded):
content://com.google.android.apps.photos.content/0/https%3A%2F%2Flh5.googleusercontent.com%2F-H7yZgZCQmFF1zec-_uU0aiyCfol1TH-b9QBWnFZ7rU%3Ds0-d
Hope that’s useful!