Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

android pick images from gallery

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?

like image 867
Buda Gavril Avatar asked Mar 15 '11 08:03

Buda Gavril


15 Answers

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);
like image 183
JMRboosties Avatar answered Oct 04 '22 21:10

JMRboosties


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...
    }
}
like image 28
Benjamin Avatar answered Oct 04 '22 20:10

Benjamin


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


}
like image 42
ASHISH KUMAR Tiwary Avatar answered Oct 04 '22 19:10

ASHISH KUMAR Tiwary


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");
            }
        }
    }
like image 35
Abhishek Avatar answered Oct 04 '22 21:10

Abhishek


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

like image 24
Linh Avatar answered Oct 04 '22 21:10

Linh


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

like image 27
abolfazl bazghandi Avatar answered Oct 04 '22 20:10

abolfazl bazghandi


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/*")
    }
}
like image 34
mklkj Avatar answered Oct 04 '22 19:10

mklkj


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/*")
like image 21
Zoran Avatar answered Oct 04 '22 21:10

Zoran


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)
like image 24
P Fuster Avatar answered Oct 04 '22 19:10

P Fuster


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
}
like image 33
Meet Bhavsar Avatar answered Oct 04 '22 19:10

Meet Bhavsar


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.

like image 40
ganjaam Avatar answered Oct 04 '22 21:10

ganjaam


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.

like image 29
Bhavesh Hirpara Avatar answered Oct 04 '22 21:10

Bhavesh Hirpara


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/*")
        }
    }
}
like image 43
aotian16 Avatar answered Oct 04 '22 20:10

aotian16


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 );
like image 31
niranj1997 Avatar answered Oct 04 '22 20:10

niranj1997


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
        }

}

like image 36
Ali Nawaz Avatar answered Oct 04 '22 20:10

Ali Nawaz