348

This question was originally asked for Android 1.6.

I am working on photos options in my app.

I have a button and an ImageView in my Activity. When I click the button it would redirect to the gallery and I would be able to select an image. The selected image would appear in my ImageView.

W4R10CK
  • 5,502
  • 2
  • 19
  • 30
Praveen
  • 90,477
  • 74
  • 177
  • 219
  • 1
    look at this answer, i posted an improved code there to handle picks from file managers also http://stackoverflow.com/questions/2169649/open-an-image-in-androids-built-in-gallery-app-programmatically/4470069#4470069 – mad Dec 20 '10 at 09:34

10 Answers10

419

Updated answer, nearly 5 years later:

The code in the original answer no longer works reliably, as images from various sources sometimes return with a different content URI, i.e. content:// rather than file://. A better solution is to simply use context.getContentResolver().openInputStream(intent.getData()), as that will return an InputStream that you can handle as you choose.

For example, BitmapFactory.decodeStream() works perfectly in this situation, as you can also then use the Options and inSampleSize field to downsample large images and avoid memory problems.

However, things like Google Drive return URIs to images which have not actually been downloaded yet. Therefore you need to perform the getContentResolver() code on a background thread.


Original answer:

The other answers explained how to send the intent, but they didn't explain well how to handle the response. Here's some sample code on how to do that:

protected void onActivityResult(int requestCode, int resultCode, 
       Intent imageReturnedIntent) {
    super.onActivityResult(requestCode, resultCode, imageReturnedIntent); 

    switch(requestCode) { 
    case REQ_CODE_PICK_IMAGE:
        if(resultCode == RESULT_OK){  
            Uri selectedImage = imageReturnedIntent.getData();
            String[] filePathColumn = {MediaStore.Images.Media.DATA};

            Cursor cursor = getContentResolver().query(
                               selectedImage, filePathColumn, null, null, null);
            cursor.moveToFirst();

            int columnIndex = cursor.getColumnIndex(filePathColumn[0]);
            String filePath = cursor.getString(columnIndex);
            cursor.close();


            Bitmap yourSelectedImage = BitmapFactory.decodeFile(filePath);
        }
    }
}

After this, you've got the selected image stored in "yourSelectedImage" to do whatever you want with. This code works by getting the location of the image in the ContentResolver database, but that on its own isn't enough. Each image has about 18 columns of information, ranging from its filepath to 'date last modified' to the GPS coordinates of where the photo was taken, though many of the fields aren't actually used.

To save time as you don't actually need the other fields, cursor search is done with a filter. The filter works by specifying the name of the column you want, MediaStore.Images.Media.DATA, which is the path, and then giving that string[] to the cursor query. The cursor query returns with the path, but you don't know which column it's in until you use the columnIndex code. That simply gets the number of the column based on its name, the same one used in the filtering process. Once you've got that, you're finally able to decode the image into a bitmap with the last line of code I gave.

Steve Haley
  • 55,374
  • 17
  • 77
  • 85
  • 4
    cursor.moveToFirst() should be checked for existence: if (cursor.moveToFirst()) {do something with cursor data} – mishkin Feb 01 '11 at 18:34
  • columnIndex is always 0 because your query asks for only one column, which of course has index 0. Or am I missing something and this isn't always the case? – Catalin Morosan Sep 15 '11 at 15:50
  • 1
    It's not something I've particularly experimented with, so I couldn't say for sure. It would make sense that if you only ever ask for one column, you can assume that it's always going to be at index 0. However, I think for the sake of added safety in case you changed something, that one line is worth it. – Steve Haley Sep 19 '11 at 14:21
  • 14
    Instead of the cursor you should get the image in this way : Bitmap b = MediaStore.Images.Media.getBitmap(this.getContentResolver(), selectedImage); – Luigi Agosti Mar 27 '12 at 08:57
  • http://stackoverflow.com/questions/9564644/null-pointer-exception-while-loading-images-from-gallery – Luigi Agosti Mar 27 '12 at 08:58
  • 4
    Luigi, if the Bitmap is large MediaStore.Images.Media.getBitmap() can cause OutOfMemory exceptions. Steve's method allows for scaling the image down before loading it into memory. – Frank Harper Jul 21 '12 at 17:12
  • @SteveHaley, need your guide, regarding same functionality, but I want to capture multiple images from camera and show them on my Activity, I am a lit bit newbee – Abdul Wahab Jul 24 '12 at 05:33
  • 9
    this is not working for me, I get a null from cursor.getString(columnIndex); – Alexis Pautrot Sep 14 '13 at 15:18
  • 9
    Careful with this method: the filename will be 'null' when the user selects a photo from a picasa album or from the Google+ Photos app. – Divisible by Zero Mar 12 '14 at 11:54
  • @CiskeBoekelo: Yup, calling uri.getPath() returns an `http` url :S – Martin Konecny May 26 '14 at 18:07
  • Here is a fix for KitKat: stackoverflow.com/a/26690628/860488 – Morten Holmgaard Nov 01 '14 at 15:36
  • 1
    This doesn't work if the user chooses an image from google drive, see: https://github.com/jdamcd/android-crop/pull/70 – waterlooalex Jan 29 '15 at 00:05
  • This doesn't work any longer, use solution provided by @siamii. – Warpzit Apr 23 '15 at 08:52
  • if you have problem with picassa try adding this permision – Gjoko Bozhinov Aug 31 '15 at 19:06
  • Will it handle also images from cloud storages like dropbox, onedrive, etc, google drive??? – mkorszun Nov 10 '15 at 12:06
317
private static final int SELECT_PHOTO = 100;

Start intent

Intent photoPickerIntent = new Intent(Intent.ACTION_PICK);
photoPickerIntent.setType("image/*");
startActivityForResult(photoPickerIntent, SELECT_PHOTO);    

Process result

@Override
protected void onActivityResult(int requestCode, int resultCode, Intent imageReturnedIntent) { 
    super.onActivityResult(requestCode, resultCode, imageReturnedIntent); 

    switch(requestCode) { 
    case SELECT_PHOTO:
        if(resultCode == RESULT_OK){  
            Uri selectedImage = imageReturnedIntent.getData();
            InputStream imageStream = getContentResolver().openInputStream(selectedImage);
            Bitmap yourSelectedImage = BitmapFactory.decodeStream(imageStream);
        }
    }
}

Alternatively, you can also downsample your image to avoid OutOfMemory errors.

private Bitmap decodeUri(Uri selectedImage) throws FileNotFoundException {

        // Decode image size
        BitmapFactory.Options o = new BitmapFactory.Options();
        o.inJustDecodeBounds = true;
        BitmapFactory.decodeStream(getContentResolver().openInputStream(selectedImage), null, o);

        // The new size we want to scale to
        final int REQUIRED_SIZE = 140;

        // Find the correct scale value. It should be the power of 2.
        int width_tmp = o.outWidth, height_tmp = o.outHeight;
        int scale = 1;
        while (true) {
            if (width_tmp / 2 < REQUIRED_SIZE
               || height_tmp / 2 < REQUIRED_SIZE) {
                break;
            }
            width_tmp /= 2;
            height_tmp /= 2;
            scale *= 2;
        }

        // Decode with inSampleSize
        BitmapFactory.Options o2 = new BitmapFactory.Options();
        o2.inSampleSize = scale;
        return BitmapFactory.decodeStream(getContentResolver().openInputStream(selectedImage), null, o2);

    }
siamii
  • 23,374
  • 28
  • 93
  • 143
  • 8
    putting a 1.5MB jpeg into my small 100px by 100px imageview resulted in VM out of memory error. Downsampling fixed that problem :-) – Someone Somewhere May 31 '11 at 04:44
  • 1
    Hi. Shouldn't both streams be closed? – Denys Kniazhev-Support Ukraine Dec 16 '14 at 16:51
  • Hello @siamii..I followed your code..but it is partially working for me.. :( when image is selected from gallery under captured images section,then it is giving json error,but when image is selected from gallery under bluetooth section image is accessed and sent to server..could you please check this link and suggest me any solution please... http://stackoverflow.com/questions/29234409/image-is-not-uploaded – Prabs Mar 25 '15 at 10:55
  • The section about finding the scale could be written as: `int scale = 1; for ( ; bfOptions.outWidth / scale > TARGET_SIZE && bfOptions.outWidth > TARGET_SIZE; scale*=2);` – The_Rafi Mar 22 '16 at 18:02
  • @siamii Where and how to call this method -------- decodeUri – Akshay Kumar Mar 26 '17 at 18:51
87

You have to start the gallery intent for a result.

Intent i = new Intent(Intent.ACTION_PICK,
               android.provider.MediaStore.Images.Media.EXTERNAL_CONTENT_URI);
startActivityForResult(i, ACTIVITY_SELECT_IMAGE); 

Then in onActivityForResult, call intent.getData() to get the Uri of the Image. Then you need to get the Image from the ContentProvider.

Robby Pond
  • 73,164
  • 16
  • 126
  • 119
  • How does ACTION_PICK differ from ACTION_GET_CONTENT used in two other answers? – penguin359 May 05 '11 at 02:27
  • 4
    With ACTION_PICK you specify a specific URI and with ACTION_GET_CONTENT you specify a mime_type. I used ACTION_PICK because the question was specifically images from the SDCARD and not all images. – Robby Pond May 05 '11 at 13:00
  • 2
    Cool. This is exactly what i needed and worked like a charm :) Wonder from where you guys find this stuff :) – Jayshil Dave Dec 13 '11 at 14:43
  • @WilliamKinaan ACTIVITY_SELECT_IMAGE is any int value that you specify in order to identify which result your expecting to receive. It is then sent back in onActivityResult(int requestCode, int resultCode, Intent data) as the 'requestCode'. – Fydo May 28 '13 at 18:10
  • @Fydo I realized that later, Thanks – William Kinaan May 28 '13 at 18:37
23

Here is a tested code for image and video.It will work for all APIs less than 19 and greater than 19 as well.

Image:

if (Build.VERSION.SDK_INT <= 19) {
                        Intent i = new Intent();
                        i.setType("image/*");
                        i.setAction(Intent.ACTION_GET_CONTENT);
                        i.addCategory(Intent.CATEGORY_OPENABLE);
                        startActivityForResult(i, 10);
                    } else if (Build.VERSION.SDK_INT > 19) {
                        Intent intent = new Intent(Intent.ACTION_PICK, android.provider.MediaStore.Images.Media.EXTERNAL_CONTENT_URI);
                        startActivityForResult(intent, 10);
                    }

Video:

if (Build.VERSION.SDK_INT <= 19) {
                        Intent i = new Intent();
                        i.setType("video/*");
                        i.setAction(Intent.ACTION_GET_CONTENT);
                        i.addCategory(Intent.CATEGORY_OPENABLE);
                        startActivityForResult(i, 20);
                    } else if (Build.VERSION.SDK_INT > 19) {
                        Intent intent = new Intent(Intent.ACTION_PICK, android.provider.MediaStore.Video.Media.EXTERNAL_CONTENT_URI);
                        startActivityForResult(intent, 20);
                    }    

.

     @Override
    public void onActivityResult(int requestCode, int resultCode, Intent data) {
        super.onActivityResult(requestCode, resultCode, data);
        if (resultCode == Activity.RESULT_OK) {               
            if (requestCode == 10) {
                Uri selectedImageUri = data.getData();
                String selectedImagePath = getRealPathFromURI(selectedImageUri);
            } else if (requestCode == 20) {
                Uri selectedVideoUri = data.getData();
                String selectedVideoPath = getRealPathFromURI(selectedVideoUri);
            }
        }
     }

     public String getRealPathFromURI(Uri uri) {
            if (uri == null) {
                return null;
            }
            String[] projection = {MediaStore.Images.Media.DATA};
            Cursor cursor = getActivity().getContentResolver().query(uri, projection, null, null, null);
            if (cursor != null) {
                int column_index = cursor
                        .getColumnIndexOrThrow(MediaStore.Images.Media.DATA);
                cursor.moveToFirst();
                return cursor.getString(column_index);
            }
            return uri.getPath();
        }
Muhammad Umair Shafique
  • 2,475
  • 1
  • 30
  • 39
14

Do this to launch the gallery and allow the user to pick an image:

Intent intent = new Intent(Intent.ACTION_GET_CONTENT);
intent.setType("image/*");
startActivityForResult(intent, IMAGE_PICK);

Then in your onActivityResult() use the URI of the image that is returned to set the image on your ImageView.

Mark B
  • 183,023
  • 24
  • 297
  • 295
11
public class EMView extends Activity {
ImageView img,img1;
int column_index;
  Intent intent=null;
// Declare our Views, so we can access them later
String logo,imagePath,Logo;
Cursor cursor;
//YOU CAN EDIT THIS TO WHATEVER YOU WANT
private static final int SELECT_PICTURE = 1;

 String selectedImagePath;
//ADDED
 String filemanagerstring;

@Override
public void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.main);
    img= (ImageView)findViewById(R.id.gimg1);



    ((Button) findViewById(R.id.Button01))
    .setOnClickListener(new OnClickListener() {

        public void onClick(View arg0) {

            // in onCreate or any event where your want the user to
            // select a file
            Intent intent = new Intent();
            intent.setType("image/*");
            intent.setAction(Intent.ACTION_GET_CONTENT);
            startActivityForResult(Intent.createChooser(intent,
                    "Select Picture"), SELECT_PICTURE);


        }
    });
}

//UPDATED
@Override
public void onActivityResult(int requestCode, int resultCode, Intent data) {
    if (resultCode == Activity.RESULT_OK) {
        if (requestCode == SELECT_PICTURE) {
            Uri selectedImageUri = data.getData();

            //OI FILE Manager
            filemanagerstring = selectedImageUri.getPath();

            //MEDIA GALLERY
            selectedImagePath = getPath(selectedImageUri);


            img.setImageURI(selectedImageUri);

           imagePath.getBytes();
           TextView txt = (TextView)findViewById(R.id.title);
           txt.setText(imagePath.toString());


           Bitmap bm = BitmapFactory.decodeFile(imagePath);

          // img1.setImageBitmap(bm);



        }

    }

}

//UPDATED!
public String getPath(Uri uri) {
String[] projection = { MediaColumns.DATA };
Cursor cursor = managedQuery(uri, projection, null, null, null);
column_index = cursor
        .getColumnIndexOrThrow(MediaColumns.DATA);
cursor.moveToFirst();
 imagePath = cursor.getString(column_index);

return cursor.getString(column_index);
}

}
Sheetal More
  • 157
  • 1
  • 2
  • 5
8
public class BrowsePictureActivity extends Activity {
private static final int SELECT_PICTURE = 1;

private String selectedImagePath;

public void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.main);

    ((Button) findViewById(R.id.Button01))
            .setOnClickListener(new OnClickListener() {

                public void onClick(View arg0) {

                    Intent intent = new Intent();
                    intent.setType("image/*");
                    intent.setAction(Intent.ACTION_GET_CONTENT);
                    startActivityForResult(Intent.createChooser(intent,
                            "Select Picture"), SELECT_PICTURE);
                }
            });
}

public void onActivityResult(int requestCode, int resultCode, Intent data) {
    if (resultCode == RESULT_OK) {
        if (requestCode == SELECT_PICTURE) {
            Uri selectedImageUri = data.getData();
            selectedImagePath = getPath(selectedImageUri);
        }
    }
}

public String getPath(Uri uri) {

        if( uri == null ) {
            return null;
        }

        // this will only work for images selected from gallery
        String[] projection = { MediaStore.Images.Media.DATA };
        Cursor cursor = managedQuery(uri, projection, null, null, null);
        if( cursor != null ){
            int column_index = cursor
            .getColumnIndexOrThrow(MediaStore.Images.Media.DATA);
            cursor.moveToFirst();
            return cursor.getString(column_index);
        }

        return uri.getPath();
}

}
Muhammad Usman Ghani
  • 1,279
  • 13
  • 19
4

For some reasons, all of the answers in this thread, in onActivityResult() try to post-process the received Uri, like getting the real path of the image and then use BitmapFactory.decodeFile(path) to get the Bitmap.

This step is unnecessary. The ImageView class has a method called setImageURI(uri). Pass your uri to it and you should be done.

Uri imageUri = data.getData();
imageView.setImageURI(imageUri);

For a complete working example you could take a look here: http://androidbitmaps.blogspot.com/2015/04/loading-images-in-android-part-iii-pick.html

PS:
Getting the Bitmap in a separate variable would make sense in cases where the image to be loaded is too large to fit in memory, and a scale down operation is necessary to prevent OurOfMemoryError, like shown in the @siamii answer.

Andy Res
  • 15,963
  • 5
  • 60
  • 96
3

call chooseImage method like-

public void chooseImage(ImageView v)
{
    Intent intent = new Intent(Intent.ACTION_PICK);
    intent.setType("image/*");
    startActivityForResult(intent, SELECT_PHOTO);
}

@Override
protected void onActivityResult(int requestCode, int resultCode, Intent imageReturnedIntent) {
    // TODO Auto-generated method stub
    super.onActivityResult(requestCode, resultCode, imageReturnedIntent);

    if(imageReturnedIntent != null)
    {
        Uri selectedImage = imageReturnedIntent.getData();
    switch(requestCode) { 
    case SELECT_PHOTO:
        if(resultCode == RESULT_OK)
        {
            Bitmap datifoto = null;
            temp.setImageBitmap(null);
            Uri picUri = null;
            picUri = imageReturnedIntent.getData();//<- get Uri here from data intent
             if(picUri !=null){
               try {
                   datifoto = android.provider.MediaStore.Images.Media.getBitmap(this.getContentResolver(),                                 picUri);
                   temp.setImageBitmap(datifoto);
               } catch (FileNotFoundException e) {
                  throw new RuntimeException(e);
               } catch (IOException e) {
                  throw new RuntimeException(e);
               } catch (OutOfMemoryError e) {
                Toast.makeText(getBaseContext(), "Image is too large. choose other", Toast.LENGTH_LONG).show();
            }

        }
        }
        break;

}
    }
    else
    {
        //Toast.makeText(getBaseContext(), "data null", Toast.LENGTH_SHORT).show();
    }
}
Akshay Paliwal
  • 3,718
  • 2
  • 39
  • 43
1
#initialize in main activity 
    path = Environment.getExternalStorageDirectory()
            + "/images/make_machine_example.jpg"; #
     ImageView image=(ImageView)findViewById(R.id.image);
 //--------------------------------------------------||

 public void FromCamera(View) {

    Log.i("camera", "startCameraActivity()");
    File file = new File(path);
    Uri outputFileUri = Uri.fromFile(file);
    Intent intent = new Intent(
            android.provider.MediaStore.ACTION_IMAGE_CAPTURE);
    intent.putExtra(MediaStore.EXTRA_OUTPUT, outputFileUri);
    startActivityForResult(intent, 1);

}

public void FromCard() {
    Intent i = new Intent(Intent.ACTION_PICK,
            android.provider.MediaStore.Images.Media.EXTERNAL_CONTENT_URI);
    startActivityForResult(i, 2);
}

 protected void onActivityResult(int requestCode, int resultCode, Intent data) {

    super.onActivityResult(requestCode, resultCode, data);

    if (requestCode == 2 && resultCode == RESULT_OK
            && null != data) {

        Uri selectedImage = data.getData();
        String[] filePathColumn = { MediaStore.Images.Media.DATA };

        Cursor cursor = getContentResolver().query(selectedImage,
                filePathColumn, null, null, null);
        cursor.moveToFirst();

        int columnIndex = cursor.getColumnIndex(filePathColumn[0]);
        String picturePath = cursor.getString(columnIndex);
        cursor.close();

        bitmap = BitmapFactory.decodeFile(picturePath);
        image.setImageBitmap(bitmap);

        if (bitmap != null) {
            ImageView rotate = (ImageView) findViewById(R.id.rotate);

        }

    } else {

        Log.i("SonaSys", "resultCode: " + resultCode);
        switch (resultCode) {
        case 0:
            Log.i("SonaSys", "User cancelled");
            break;
        case -1:
            onPhotoTaken();
            break;

        }

    }

}

protected void onPhotoTaken() {
    // Log message
    Log.i("SonaSys", "onPhotoTaken");
    taken = true;
    imgCapFlag = true;
    BitmapFactory.Options options = new BitmapFactory.Options();
    options.inSampleSize = 4;
    bitmap = BitmapFactory.decodeFile(path, options);
    image.setImageBitmap(bitmap);


}