245

I want to create a picture chooser from gallery. I use code

 intent = new Intent(Intent.ACTION_PICK, android.provider.MediaStore.Images.Media.EXTERNAL_CONTENT_URI);
 startActivityForResult(intent, TFRequestCodes.GALLERY);

My problem is that in this activity and video files are displayed. Is there a way to filter displayed files so that no video files will be displayed in this activity?

Glenn Sallis
  • 415
  • 3
  • 11
Buda Gavril
  • 21,409
  • 40
  • 127
  • 196
  • 4
    This article nicely describes how to pick images from gallery: http://androidbitmaps.blogspot.com/2015/04/loading-images-in-android-part-iii-pick.html – Andy Res Apr 17 '15 at 05:13
  • There's one similar question like you. http://stackoverflow.com/a/31382240/1835650 – TeeTracker Jul 13 '15 at 11:39

21 Answers21

409

Absolutely. Try this:

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

Don't forget also to create the constant PICK_IMAGE, so you can recognize when the user comes back from the image gallery Activity:

public static final int PICK_IMAGE = 1;

@Override
public void onActivityResult(int requestCode, int resultCode, Intent data)
{
    if (requestCode == PICK_IMAGE) {
        //TODO: action
    }
}

That's how I call the image gallery. Put it in and see if it works for you.

EDIT:

This brings up the Documents app. To allow the user to also use any gallery apps they might have installed:

    Intent getIntent = new Intent(Intent.ACTION_GET_CONTENT);
    getIntent.setType("image/*");

    Intent pickIntent = new Intent(Intent.ACTION_PICK, android.provider.MediaStore.Images.Media.EXTERNAL_CONTENT_URI);
    pickIntent.setType("image/*");

    Intent chooserIntent = Intent.createChooser(getIntent, "Select Image");
    chooserIntent.putExtra(Intent.EXTRA_INITIAL_INTENTS, new Intent[] {pickIntent});

    startActivityForResult(chooserIntent, PICK_IMAGE);
Gabcvit
  • 1,468
  • 1
  • 15
  • 32
JMRboosties
  • 15,500
  • 20
  • 76
  • 116
  • 7
    I get 2 options on this "Android System", "Documents". If i select Android System, then it presents me with Gallery and Photos. How do I get rid of this intermediate option list? – Udayaditya Barua Dec 11 '15 at 07:54
  • 4
    @Uday it's simply because you haven't set the default. Just leave it :) – Tristan Jan 08 '16 at 22:31
  • 15
    What does the PICK_IMAGE constant have to be set to? It says "Cannot resolve symbol "PICK_IMAGE" – Michael Aug 20 '16 at 18:15
  • 5
    @Michael the **PICK_IMAGE** constant holds any **static int** value determined by you on this very class, this is further used on the `@Override` function `onActivityResult(int requestCode, resultCode, Intent data)`, where it's recommended that you use this constant to check the `requestCode` parameter before doing any action :) – Gabcvit Sep 14 '17 at 14:06
  • 3
    You can retrieve the Bitmap from the onActivityResult(...) method with the following code (assuming RESULT_OK): Bitmap bitmap = data.getExtras().getParcelable("data"); – Shane Sepac Mar 01 '18 at 21:58
  • when doing this i ALWAYS GET A RANDOM number on requestCode at onActivityResult – Rafael Lima Apr 27 '20 at 21:34
  • @Michael the PICK_IMAGE constant can be a container of an arbitrary integer value, the most important this is not to use that integer value for another `requestCode` constant because each `requestCode` is a unique identifier for their intent operations. – Favour Felix Chinemerem May 24 '20 at 03:12
  • You can also use this code, to open specific gallery apps from your phone. `Intent gallery = new Intent(Intent.ACTION_PICK, MediaStore.Images.Media.INTERNAL_CONTENT_URI); startActivityForResult(gallery, PICK_IMAGE); ` For example Gallery, Google Photos app – Ransike Randeni Oct 12 '20 at 14:43
  • On Samsung devices to show proper options do this `Intent chooserIntent = Intent.createChooser(pickIntent, "Select Image"); chooserIntent.putExtra(Intent.EXTRA_INITIAL_INTENTS, new Intent[] {getIntent});` – Shyam Sunder Oct 07 '21 at 02:53
216

Sometimes, you can't get a file from the picture you choose. It's because the choosen one came from Google+, Drive, Dropbox or any other provider.

The best solution is to ask the system to pick a content via Intent.ACTION_GET_CONTENT and get the result with a content provider.

You can follow the code bellow or look at my updated gist.

public void pickImage() {
  Intent intent = new Intent(Intent.ACTION_GET_CONTENT);
  intent.setType("image/*");
  startActivityForResult(intent, PICK_PHOTO_FOR_AVATAR);
}

@Override
public void onActivityResult(int requestCode, int resultCode, Intent data) {
    super.onActivityResult(requestCode, resultCode, data);
    if (requestCode == PICK_PHOTO_FOR_AVATAR && resultCode == Activity.RESULT_OK) {
        if (data == null) {
            //Display an error
            return;
        }
        InputStream inputStream = context.getContentResolver().openInputStream(data.getData());
        //Now you can do whatever you want with your inpustream, save it as file, upload to a server, decode a bitmap...
    }
}
Benjamin
  • 2,777
  • 2
  • 16
  • 14
  • 15
    `if(resultCode == Activity.RESULT_OK) {...}` can be used to detect success/cancel – Thamme Gowda Feb 04 '14 at 13:57
  • 1
    How can you get path ? –  Oct 09 '15 at 10:27
  • @delive, I think you could try `new File(data.getData()).getAbsolutePath()` Just a guess, I haven't tried it – Someone Somewhere Dec 17 '15 at 15:14
  • Or you can pass path static variable is bad but works ;) from pick –  Dec 17 '15 at 15:41
  • 1
    FileNotFound exception warning by Android Studio in fragment in `getActivity().getContentResolver().openInputStream(data.getData());`. – Iqbal Jan 27 '16 at 11:02
  • 1
    This works on certain devices in which the path of the file is not returned. However, I see no way to determine - once I have the InputStream - how to figure out the orientation of the image. – Casey Perkins Feb 09 '17 at 19:08
  • @Benjamin It crashes with exception SecurityException: Permission Denial: opening provider android.support.v4.content.FileProvider from ProcessRecord{d1846aa 2979:com.android.documentsui/u0a13} (pid=2979, uid=10013) that is not exported from UID 10285 on android Oreo 8.1 Do you have any idea ? – Smeet Sep 23 '18 at 16:17
  • Nice. How to know the length of bytes to be read from the inputStream though? inputStream.read(bytes, 0 , ???). I usually use file.length() here but in this case it is not given. – Khaled Ahmed Sobhy Nov 14 '20 at 13:37
37
public void FromCamera() {

    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);


}
28

You can use this method to pick image from gallery. Only images will be displayed.

public void pickImage() {
    Intent intent = new Intent(Intent.ACTION_PICK,
            MediaStore.Images.Media.INTERNAL_CONTENT_URI);
    intent.setType("image/*");
    intent.putExtra("crop", "true");
    intent.putExtra("scale", true);
    intent.putExtra("outputX", 256);
    intent.putExtra("outputY", 256);
    intent.putExtra("aspectX", 1);
    intent.putExtra("aspectY", 1);
    intent.putExtra("return-data", true);
    startActivityForResult(intent, 1);
}

and override onActivityResult as

    @Override
    protected void onActivityResult(int requestCode, int resultCode, Intent data) {
        if (resultCode != RESULT_OK) {
            return;
        }
        if (requestCode == 1) {
            final Bundle extras = data.getExtras();
            if (extras != null) {
                //Get image
                Bitmap newProfilePic = extras.getParcelable("data");
            }
        }
    }
Abhishek
  • 2,295
  • 24
  • 28
  • 2
    @Abhishek...where did you find the list of extras allowed for ACTION_PICK intent? Thanks! – Johnny Wu May 27 '16 at 02:09
  • 2
    Please don't forget to add runtime permissions for READ_EXTERNAL_STORAGE and WRITE_EXTERNAL_STORAGE for api level 23 and higher. Otherwise you may not get bitmap from gallery as not null. See https://stackoverflow.com/a/35285667/3341089 – oguzhan Feb 06 '18 at 21:35
  • 1
    Calling setType after setting URI will clear the data. – Taslim Oseni Feb 28 '20 at 11:36
  • I just can't get this to work. The `getParcelable("data")` is always `null` even when I set `return-data=true` and add the `READ_EXTERNAL_STORAGE` permission. – xjcl Apr 14 '21 at 19:49
21

Here is a full example for request permission (if need), pick image from gallery, then convert image to bitmap or file

AndroidManifesh.xml

<uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE"/>

Activity

class MainActivity : AppCompatActivity() {

    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setContentView(R.layout.activity_main)

        button_pick_image.setOnClickListener {
            pickImage()
        }
    }

    private fun pickImage() {
        if (ActivityCompat.checkSelfPermission(this, READ_EXTERNAL_STORAGE) == PackageManager.PERMISSION_GRANTED) {
            val intent = Intent(
                Intent.ACTION_PICK,
                MediaStore.Images.Media.INTERNAL_CONTENT_URI
            )
            intent.type = "image/*"
            intent.putExtra("crop", "true")
            intent.putExtra("scale", true)
            intent.putExtra("aspectX", 16)
            intent.putExtra("aspectY", 9)
            startActivityForResult(intent, PICK_IMAGE_REQUEST_CODE)
        } else {
            ActivityCompat.requestPermissions(
                this,
                arrayOf(Manifest.permission.READ_EXTERNAL_STORAGE),
                READ_EXTERNAL_STORAGE_REQUEST_CODE
            )
        }
    }

    override fun onActivityResult(requestCode: Int, resultCode: Int, data: Intent?) {
        super.onActivityResult(requestCode, resultCode, data)
        if (requestCode == PICK_IMAGE_REQUEST_CODE) {
            if (resultCode != Activity.RESULT_OK) {
                return
            }
            val uri = data?.data
            if (uri != null) {
                val imageFile = uriToImageFile(uri)
                // todo do something with file
            }
            if (uri != null) {
                val imageBitmap = uriToBitmap(uri)
                // todo do something with bitmap
            }
        }
    }

    override fun onRequestPermissionsResult(requestCode: Int, permissions: Array<out String>, grantResults: IntArray) {
        super.onRequestPermissionsResult(requestCode, permissions, grantResults)
        when (requestCode) {
            READ_EXTERNAL_STORAGE_REQUEST_CODE -> {
                if (grantResults[0] == PackageManager.PERMISSION_GRANTED) {
                    // pick image after request permission success
                    pickImage()
                }
            }
        }
    }

    private fun uriToImageFile(uri: Uri): File? {
        val filePathColumn = arrayOf(MediaStore.Images.Media.DATA)
        val cursor = contentResolver.query(uri, filePathColumn, null, null, null)
        if (cursor != null) {
            if (cursor.moveToFirst()) {
                val columnIndex = cursor.getColumnIndex(filePathColumn[0])
                val filePath = cursor.getString(columnIndex)
                cursor.close()
                return File(filePath)
            }
            cursor.close()
        }
        return null
    }

    private fun uriToBitmap(uri: Uri): Bitmap {
        return MediaStore.Images.Media.getBitmap(this.contentResolver, uri)
    }

    companion object {
        const val PICK_IMAGE_REQUEST_CODE = 1000
        const val READ_EXTERNAL_STORAGE_REQUEST_CODE = 1001
    }
}

Demo
https://github.com/PhanVanLinh/AndroidPickImage

Linh
  • 57,942
  • 23
  • 262
  • 279
  • 1
    This is nothing less than a library, especially with that crop and aspect ratio feature. I never knew such a thing existed. Thank you very much, sir. – Lalit Fauzdar May 09 '20 at 14:43
  • 1
    Back here, it's not so good as I hoped seeing the first impressions. It doesn't pick the image when edited with snapseed, no crash but no image, huawei's default gallery app doesn't do anything when I click on next after editing, it doesn't edit image when picked from google photos, bring it back without it directly. It works good only if I choose huawei's default gallery and google photos to edit it. – Lalit Fauzdar May 09 '20 at 16:14
  • Thanks. Very good answer and works very well at very first time. – sagar.android May 25 '21 at 13:05
13

2021 Kotlin solution with new version of Fragment:

dependencies {
  implementation "androidx.fragment:fragment:1.3.3"
}
class YourFragment : Fragment() {

    private val fileChooserContract = registerForActivityResult(ActivityResultContracts.GetContent()) { imageUri ->
        if (imageUri != null) {
            // imageUri now contains URI to selected image
        }
    }

    // ...

    fun openFileChooser() {
        fileChooserContract.launch("image/*")
    }
}
frankelot
  • 13,666
  • 16
  • 54
  • 89
mklkj
  • 300
  • 4
  • 8
10

I have same problem .I use this codes

addIntent

 Intent intent = new Intent();
        intent.setType("image/*");
        intent.setAction(Intent.ACTION_GET_CONTENT);
        startActivityForResult(Intent.createChooser(intent, "Tack Image"), PICK_PHOTO);

add onActivityResult

 @Override
  public void onActivityResult(int requestCode, int resultCode, Intent data) {
    super.onActivityResult(requestCode, resultCode, data);
    if (requestCode == PICK_PHOTO && resultCode == Activity.RESULT_OK) {
      if (data == null) {
      //error
        return;
      }
      try {
        Uri uri = data.getData();
        File file = FileUtil.from(currentActivity, uri);
      } catch (IOException e) {
        e.printStackTrace();
      }
    }
  }

FileUtil class

import android.content.Context;
import android.database.Cursor;
import android.net.Uri;
import android.provider.OpenableColumns;
import android.util.Log;

import java.io.File;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;

public class FileUtil {
  private static final int EOF = -1;
  private static final int DEFAULT_BUFFER_SIZE = 1024 * 4;

  private FileUtil() {

  }

  public static File from(Context context, Uri uri) throws IOException {
    InputStream inputStream = context.getContentResolver().openInputStream(uri);
    String fileName = getFileName(context, uri);
    String[] splitName = splitFileName(fileName);
    File tempFile = File.createTempFile(splitName[0], splitName[1]);
    tempFile = rename(tempFile, fileName);
    tempFile.deleteOnExit();
    FileOutputStream out = null;
    try {
      out = new FileOutputStream(tempFile);
    } catch (FileNotFoundException e) {
      e.printStackTrace();
    }
    if (inputStream != null) {
      copy(inputStream, out);
      inputStream.close();
    }

    if (out != null) {
      out.close();
    }
    return tempFile;
  }

  private static String[] splitFileName(String fileName) {
    String name = fileName;
    String extension = "";
    int i = fileName.lastIndexOf(".");
    if (i != -1) {
      name = fileName.substring(0, i);
      extension = fileName.substring(i);
    }

    return new String[]{name, extension};
  }

  private static String getFileName(Context context, Uri uri) {
    String result = null;
    if (uri.getScheme().equals("content")) {
      Cursor cursor = context.getContentResolver().query(uri, null, null, null, null);
      try {
        if (cursor != null && cursor.moveToFirst()) {
          result = cursor.getString(cursor.getColumnIndex(OpenableColumns.DISPLAY_NAME));
        }
      } catch (Exception e) {
        e.printStackTrace();
      } finally {
        if (cursor != null) {
          cursor.close();
        }
      }
    }
    if (result == null) {
      result = uri.getPath();
      int cut = result.lastIndexOf(File.separator);
      if (cut != -1) {
        result = result.substring(cut + 1);
      }
    }
    return result;
  }

  private static File rename(File file, String newName) {
    File newFile = new File(file.getParent(), newName);
    if (!newFile.equals(file)) {
      if (newFile.exists() && newFile.delete()) {
        Log.d("FileUtil", "Delete old " + newName + " file");
      }
      if (file.renameTo(newFile)) {
        Log.d("FileUtil", "Rename file to " + newName);
      }
    }
    return newFile;
  }

  private static long copy(InputStream input, OutputStream output) throws IOException {
    long count = 0;
    int n;
    byte[] buffer = new byte[DEFAULT_BUFFER_SIZE];
    while (EOF != (n = input.read(buffer))) {
      output.write(buffer, 0, n);
      count += n;
    }
    return count;
  }
}

and you must add provider_paths.xml to xml folder like image enter image description here

provider_paths.xml

<?xml version="1.0" encoding="utf-8"?>
<paths>
    <external-path name="external_files" path="."/>
</paths>

and finaly add below in AndroidManifest.xml

<application
...>

...
      <provider
          android:name="androidx.core.content.FileProvider"
          android:authorities="${applicationId}.provider"
          android:exported="false"
          android:grantUriPermissions="true">
          <meta-data
            android:name="android.support.FILE_PROVIDER_PATHS"
            android:resource="@xml/provider_paths" />
        </provider>
...
</application>

I hope I helped

abolfazl bazghandi
  • 935
  • 15
  • 29
10

Goodbye startActivityForResult()

Proper way nowadays with AndroidX Activity, is Activity Result APIs and that is strongly recommended way by google

private val selectImageFromGalleryResult = registerForActivityResult(ActivityResultContracts.GetContent()) { uri: Uri? ->
    uri?.let { previewImage.setImageURI(uri) }
}

Simply call selectImageFromGallery() when needed

private fun selectImageFromGallery() = selectImageFromGalleryResult.launch("image/*")
Zoran
  • 1,502
  • 19
  • 22
8

Since startActivityForResult() is depracated we can choose only image from gallery in the following way using ActivityResultLauncher:

At first we need to define an ActivityResultLauncher<String[]> and initialize it in onCreate() (for Activities) or onViewCreated() (for fragments)

ActivityResultLauncher<String[]> galleryActivityLauncher = registerForActivityResult(new ActivityResultContracts.OpenDocument(), new ActivityResultCallback<Uri>() {
    @Override
    public void onActivityResult(Uri result) {
        if (result != null) {
            // perform desired operations using the result Uri
        } else {
            Log.d(TAG, "onActivityResult: the result is null for some reason");
        }
    }
});

Let's say we need to open the gallery when submitButton is clicked.

So inside the onClickListener we need to call

galleryActivityLauncher.launch(new String[]{"image/*"});

The trick here is the argument for launch(). By adding "image/*" to the argument array, we are specifying that the file explorer should load images only.

ganjaam
  • 1,030
  • 3
  • 17
  • 29
5

Just to offer an update to the answer for people with API min 19, per the docs:

On Android 4.4 (API level 19) and higher, you have the additional option of using the ACTION_OPEN_DOCUMENT intent, which displays a system-controlled picker UI controlled that allows the user to browse all files that other apps have made available. From this single UI, the user can pick a file from any of the supported apps.

On Android 5.0 (API level 21) and higher, you can also use the ACTION_OPEN_DOCUMENT_TREE intent, which allows the user to choose a directory for a client app to access.

Open files using storage access framework - Android Docs

     val intent = Intent(Intent.ACTION_OPEN_DOCUMENT)
     intent.type = "image/*"
     startActivityForResult(intent, PICK_IMAGE_REQUEST_CODE)
P Fuster
  • 2,224
  • 1
  • 20
  • 30
5

OnActivityResult method is deprecated

val singleImageResultLauncher =
            registerForActivityResult(ActivityResultContracts.StartActivityForResult()) { result ->
                if (result.resultCode == Activity.RESULT_OK) {
                    // There are no request codes
                    val data: Intent? = result.data
                    val selectedImageUri: Uri? = data?.data
                    if (null != selectedImageUri) {
                        // Get the path from the Uri
                        val path = getPathFromURI(selectedImageUri)
                        findViewById<TextView>(R.id.textView).text = path
                        findViewById<ImageView>(R.id.imageView2).setImageURI(selectedImageUri)
                    }
                }
            }
findViewById<Button>(R.id.oneImageSelectBtn).setOnClickListener {
            val intent = Intent()
            intent.type = "image/*"
            intent.action = Intent.ACTION_GET_CONTENT
            intent.putExtra(Intent.EXTRA_ALLOW_MULTIPLE, false)
            singleImageResultLauncher.launch(Intent.createChooser(intent, "Select Picture"))

        }
private fun getPathFromURI(uri: Uri?): String {
        var path = ""
        if (contentResolver != null) {
            val cursor = contentResolver.query(uri!!, null, null, null, null)
            if (cursor != null) {
                cursor.moveToFirst()
                val idx = cursor.getColumnIndex(MediaStore.Images.ImageColumns.DISPLAY_NAME)
                path = cursor.getString(idx)
                cursor.close()
            }
        }
        return path
}
Meet Bhavsar
  • 442
  • 6
  • 12
2

If you are only looking for images and multiple selection.

Look @ once https://stackoverflow.com/a/15029515/1136023

It's helpful for future.I personally feel great by using MultipleImagePick.

Community
  • 1
  • 1
Bhavesh Hirpara
  • 22,255
  • 15
  • 63
  • 104
  • what's the quickest way to use MultipleImagePick as a library? It comes as a standalone project/application.. – ticofab Sep 06 '14 at 11:44
2

thanks to mklkj.

this is a activity version.

fileChooserContract can select a image. filesChooserContract can select multi images.

class MainActivity : AppCompatActivity() {

    companion object {
        private const val TAG = "MainActivity"
    }

    lateinit var viewBinding: ActivityMainBinding

    private val fileChooserContract = registerForActivityResult(ActivityResultContracts.GetContent()) { uri ->
        Log.d(TAG, "onActivityResult: uri $uri")
    }

    private val filesChooserContract = registerForActivityResult(ActivityResultContracts.GetMultipleContents()) { uriList ->
        for (uri in uriList) {
            Log.d(TAG, "onActivityResult: uri $uri")
        }
    }

    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        viewBinding = ActivityMainBinding.inflate(layoutInflater)
        setContentView(viewBinding.root)

        viewBinding.btnPick.setOnClickListener {
            fileChooserContract.launch("image/*")
        }

        viewBinding.btnPickMulti.setOnClickListener {
            filesChooserContract.launch("image/*")
        }
    }
}
aotian16
  • 767
  • 1
  • 10
  • 21
1

OPTION-1

The below code allows user to select an image from any file explorer application

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

But in some devices, the above solution will not fetch the image with EXIF information such as orientation. So in those devices, EXIF processing such as changing image orientation could not be performed as expected.

OPTION-2

The below code allows user to select an image from any gallery application

Intent intent = new Intent(Intent.ACTION_PICK, MediaStore.Images.Media.EXTERNAL_CONTENT_URI);
intent.setType("image/*");
startActivityForResult ( intent, PICK_IMAGE_CODE );

But in some devices, while setting the intent type, the above solution will clear the intent data (MediaStore.Images.Media.EXTERNAL_CONTENT_URI) which could hinder the gallery opening process.

OPTION-3

Finally, I suggest the below code which allows user to select an image from any gallery application which does not cause any problem and does not show up any warning

Intent intent = new Intent ();
intent.setAction ( Intent.ACTION_PICK );
intent.setDataAndType ( MediaStore.Images.Media.EXTERNAL_CONTENT_URI, "image/*" );
startActivityForResult ( intent, PICK_IMAGE_CODE );
niranj1997
  • 719
  • 8
  • 16
1

Here is working code a util method in kotlin:

fun launchGalleryWithFragment() {
        val intent = Intent(Intent.ACTION_PICK, MediaStore.Images.Media.EXTERNAL_CONTENT_URI)
        intent.type = "image/*"
        startActivityForResult(Intent.createChooser(intent, "Select Picture"), 1001)
    }

Now override onActivityResult method:

override fun onActivityResult(requestCode: Int, resultCode: Int, data: Intent?) {
    super.onActivityResult(requestCode, resultCode, data)
var path: Uri? = null
        if (requestCode == PICK_IMAGE_REQUEST && resultCode == Activity.RESULT_OK) {
            if(dataIntent == null || dataIntent.data == null){
                return null
            }
            path = dataIntent.data
        }

}

Ali Nawaz
  • 2,016
  • 20
  • 30
0

For only pick from local add this :

        i.putExtra(Intent.EXTRA_LOCAL_ONLY,true)

And this working nice :

    val i = Intent(Intent.ACTION_GET_CONTENT,MediaStore.Images.Media.EXTERNAL_CONTENT_URI)
    i.type = "image/*"
    i.putExtra(Intent.EXTRA_LOCAL_ONLY,true)
    startActivityForResult(Intent.createChooser(i,"Select Photo"),pickImageRequestCode)
Burak Dizlek
  • 4,805
  • 2
  • 23
  • 19
0

Kotlin: Open the ACTION_GET_CONTENT event when you want to prompt the user:

val intent = Intent(Intent.ACTION_GET_CONTENT).apply { type = "image/*" }
startActivityForResult(intent, 9998)

After the user picked an image, handle that event in the onActivityResult function of your Activity. As an example I am displaying it in an ImageView and storing it in the app cache:

override fun onActivityResult(requestCode: Int, resultCode: Int, data: Intent?) {
    super.onActivityResult(requestCode, resultCode, data)
    if (requestCode == 9998) {
        val uri: Uri = data?.data ?: return
        val bytes = contentResolver.openInputStream(uri)?.readBytes() ?: return
        imageView.setImageBitmap(BitmapFactory.decodeByteArray(bytes, 0, bytes.size))
        File("$cacheDir/imgPicked").writeBytes(bytes)  // if needed: store to cache
    }
}

Ideally, replace 9998 with some internal request code enum your app uses. This is just so you can differentiate callbacks from your own requests.

Unlike getParcelable("data") this does not require any permissions.

Note that this doesn't handle the Exif rotation bit on images that set it, so a few images will end up with incorrect orientation (Kotlin solution).

xjcl
  • 12,848
  • 6
  • 67
  • 89
0

For Kotlin using new ActivityResultContracts since startActivityForResult is depricated:

private val mSelectedPicDataResult = registerForActivityResult(
    ActivityResultContracts.StartActivityForResult()
) { result ->
    if (result.resultCode == Activity.RESULT_OK) {
        val selectedPicUri = result.data?.data
        //use your selected pic
    }
}

private fun startSelectPic() {
    val intent = Intent(Intent.ACTION_OPEN_DOCUMENT)
    intent.addCategory(Intent.CATEGORY_OPENABLE)
    intent.type = "image/*"
    mSelectedPicDataResult.launch(intent)
}
Choletski
  • 7,074
  • 6
  • 43
  • 64
0

Pick Media 2023


Implement a block field and register a single media selection.

private var pickMediaBlock: (Uri?) -> Unit = { }
private val pickMedia = registerForActivityResult(ActivityResultContracts.PickVisualMedia()) { uri -> pickMediaBlock(uri) }

override fun onCreate(savedInstanceState: Bundle?) { 
...

Mandatory before calling the onCreate method or somehow take into account the life cycle.


Implement the launch method:

fun launchPickMedia(type: ActivityResultContracts.PickVisualMedia.VisualMediaType, block: (Uri?) -> Unit) {
    pickMediaBlock = block
    pickMedia.launch(PickVisualMediaRequest(type))
}

Usage:

screenBox2d.game.activity.launchPickMedia(ActivityResultContracts.PickVisualMedia.ImageOnly) {
    log("uri: $it")
}

PS. Vel_daN: Love what You DO .

0

in Compose we can choose an image like this:

@Composable
fun ChangeProfilePictureScreen(viewModel: ChangeProfilePictureViewModel = viewModel()) {

  val pickMedia = rememberLauncherForActivityResult(ActivityResultContracts.PickVisualMedia()) { uri: Uri? ->
        if (uri != null) {
            Log.d("PhotoPicker", "Selected URI: $uri")
        } else {
            Log.d("PhotoPicker", "No media selected")
        }
    }

  Button(
    text = "Select image",
    onClick = {
        pickMedia.launch(PickVisualMediaRequest(ActivityResultContracts.PickVisualMedia.SingleMimeType(mimeType = "image/*")))
    }
  )
 ...
Dan Alboteanu
  • 9,404
  • 1
  • 52
  • 40
-6

U can do it easier than this answers :

Uri Selected_Image_Uri = data.getData();
ImageView imageView = (ImageView) findViewById(R.id.loadedimg);
imageView.setImageURI(Selected_Image_Uri);
Marat
  • 15,215
  • 2
  • 39
  • 48
Reza Taghizadeh
  • 347
  • 5
  • 11
  • i do it , and it worked. if u need use to file for example to sending to server u have to use other ways but just for loading an image to imageview u can do this easy solution. – Reza Taghizadeh Oct 29 '15 at 20:52
  • 5
    Welcome to SO! Instead of commenting on your own post, you can also edit your post. If your comment is supposed to explain the answer, then why not put it in the answer itself? Personally, I do not see how your (late) answer to this old question is related to the question. May I suggest to focus on answering questions first, which do not yet have an accepted answer? – cfi Oct 29 '15 at 21:23
  • 1
    i cant find android questions. how i can see just android questions? – Reza Taghizadeh Oct 31 '15 at 01:53
  • 3
    Please read the help pages. Also, comments are not for discussions about how the site works, you can use chat rooms for live discussions with other users, and you can ask specific questions on Meta (help->Meta) – cfi Oct 31 '15 at 07:38