web-dev-qa-db-fra.com

Sélectionnez plusieurs images dans la galerie Android

Donc, en gros, ce que je cherche à faire, c’est d’ouvrir la Gallery dans Android et de laisser l’utilisateur sélectionner multiple images. Maintenant cette question a été posée fréquemment mais je ne suis pas satisfait des réponses. Principalement parce que j'ai trouvé quelque chose d'intéressant dans de docs dans mon IDE (j'y reviens plus tard) et que, par conséquent, je ne veux pas utiliser d'adaptateur personnalisé, mais simplement celui de Vanilla.

Maintenant, mon code pour sélectionner une image est:

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

À présent, les utilisateurs de SO et d'autres sites Web vous diront que vous avez 2 options:

1) N'utilisez pas ACTION_GET_CONTENT mais ACTION_SEND_MULTIPLE à la place.
Celui-ci ne fonctionne pas. Celui-ci est conforme à la documentation pour les fichiers sending et non retrieving et c'est exactement ce qu'il fait. Lors de l’utilisation de ACTION_SEND_MULTIPLE, une fenêtre s’est ouverte sur mon appareil, où je dois sélectionner une application à laquelle envoyer mes données. Ce n'est pas ce que je veux, alors je me demande comment les gens ont pu y arriver avec cette solution. Est-ce que quelque chose me manque?

2) Implémentez un custom Gallery. Maintenant, ceci est ma dernière option que je vais considérer car à mon humble avis ce n’est pas ce que je cherche parce que je dois le styler moi-même ET pourquoi diable vous ne pouvez pas sélectionner plusieurs images dans la galerie Vanilla?

Il doit y avoir une option pour cela .. Maintenant, la chose intéressante que j'ai trouvée est la suivante:
J'ai trouvé cela dans la description de la documentation de ACTION_GET_CONTENT.

Si l'appelant peut gérer plusieurs éléments renvoyés (l'utilisateur effectuant une sélection multiple), il peut alors spécifier EXTRA_ALLOW_MULTIPLE pour l'indiquer.

C'est assez intéressant. Ici, ils se réfèrent au cas d'utilisation où un utilisateur peut sélectionner plusieurs éléments?

Plus tard, ils disent dans la documentation:

Vous pouvez utiliser EXTRA_ALLOW_MULTIPLE pour permettre à l'utilisateur de sélectionner plusieurs éléments.

Donc c'est assez évident non? C'est de quoi j'ai besoin. Mais ma question suivante est: Où puis-je mettre ce EXTRA_ALLOW_MULTIPLE? Ce qui est triste, c'est que je ne trouve pas ce dans la liste guide des développeurs.Android et que cela n'est pas non plus défini comme une constante dans la classe INTENT.

Tout le monde peut m'aider avec ce EXTRA_ALLOW_MULTIPLE?

97
Dion Segijn

L'option EXTRA_ALLOW_MULTIPLE est définie sur l'intention via la méthode Intent.putExtra ():

intent.putExtra(Intent.EXTRA_ALLOW_MULTIPLE, true);

Votre code ci-dessus devrait ressembler à ceci:

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

Remarque: l'option EXTRA_ALLOW_MULTIPLE est uniquement disponible dans Android API 18 et versions supérieures.

97
Kyle Shank

Définissez ces variables dans la classe:

int PICK_IMAGE_MULTIPLE = 1; 
String imageEncoded;    
List<String> imagesEncodedList;

Supposons qu’onClick sur un bouton ouvre la galerie pour sélectionner des images

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

Ensuite, vous devez remplacer la méthode onActivityResult

@Override
protected void onActivityResult(int requestCode, int resultCode, Intent data) {
    try {
        // When an Image is picked
        if (requestCode == PICK_IMAGE_MULTIPLE && resultCode == RESULT_OK
                    && null != data) {
            // Get the Image from data

            String[] filePathColumn = { MediaStore.Images.Media.DATA };
            imagesEncodedList = new ArrayList<String>();
            if(data.getData()!=null){

                Uri mImageUri=data.getData();

                // Get the cursor
                Cursor cursor = getContentResolver().query(mImageUri,
                            filePathColumn, null, null, null);
                // Move to first row
                cursor.moveToFirst();

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

            } else {
                if (data.getClipData() != null) {
                    ClipData mClipData = data.getClipData();
                    ArrayList<Uri> mArrayUri = new ArrayList<Uri>();
                    for (int i = 0; i < mClipData.getItemCount(); i++) {

                        ClipData.Item item = mClipData.getItemAt(i);
                        Uri uri = item.getUri();
                        mArrayUri.add(uri);
                        // Get the cursor
                        Cursor cursor = getContentResolver().query(uri, filePathColumn, null, null, null);
                        // Move to first row
                        cursor.moveToFirst();

                        int columnIndex = cursor.getColumnIndex(filePathColumn[0]);
                        imageEncoded  = cursor.getString(columnIndex);
                        imagesEncodedList.add(imageEncoded);
                        cursor.close();

                    }
                    Log.v("LOG_TAG", "Selected Images" + mArrayUri.size());
                }
            }
        } else {
            Toast.makeText(this, "You haven't picked Image",
                        Toast.LENGTH_LONG).show();
        }
    } catch (Exception e) {
        Toast.makeText(this, "Something went wrong", Toast.LENGTH_LONG)
                    .show();
    }

    super.onActivityResult(requestCode, resultCode, data);
}

NOTE QUE: la galerie ne vous donne pas la possibilité de sélectionner plusieurs images, nous ouvrons ici tous les studios d'images pour lesquels vous pouvez sélectionner plusieurs images. et n'oubliez pas d'ajouter les autorisations à votre manifeste

TRÈS IMPORTANT: getData (); pour obtenir une seule image et je l'ai stockée ici dans imageEncoded String si l'utilisateur sélectionne plusieurs images, elles doivent être stockées dans la liste.

Donc, vous devez vérifier lequel est nul pour utiliser l'autre

Je vous souhaite un bon essai et à d'autres

62
Laith Mihyar

J'espère que cette réponse n'est pas en retard. Parce que le widget de galerie ne prend pas en charge la sélection multiple par défaut, vous pouvez personnaliser la vue grille qui a accepté votre intention de sélection multiple. L'autre option consiste à étendre la vue de la galerie et à ajouter votre propre code pour permettre une sélection multiple.
C’est la bibliothèque simple qui peut le faire: https://github.com/luminousman/MultipleImagePick

Mise à jour :
D'après le commentaire de @ ilsy, ​​ CustomGalleryActivity dans cette bibliothèque, utilisez manageQuery, qui est obsolète. Vous devez donc le remplacer par getContentResolver().query() et cursor.close() comme cette réponse

20
R4j

Beaucoup de ces réponses ont des similitudes, mais il manque à la partie la plus importante qui est dans onActivityResult, vérifiez si data.getClipData est null avant vérifiant data.getData

Le code pour appeler le sélecteur de fichier:

Intent intent = new Intent(Intent.ACTION_GET_CONTENT);
intent.setType("image/*"); //allows any image file type. Change * to specific extension to limit it
//**These following line is the important one!
intent.putExtra(Intent.EXTRA_ALLOW_MULTIPLE, true);
startActivityForResult(Intent.createChooser(intent, "Select Picture"), SELECT_PICTURES); //SELECT_PICTURES is simply a global int used to check the calling intent in onActivityResult

Le code à obtenir toutes des images sélectionnées:

@Override
public void onActivityResult(int requestCode, int resultCode, Intent data) {
    super.onActivityResult(requestCode, resultCode, data);
    if(requestCode == SELECT_PICTURES) {
        if(resultCode == Activity.RESULT_OK) {
            if(data.getClipData() != null) {
                int count = data.getClipData().getItemCount(); //evaluate the count before the for loop --- otherwise, the count is evaluated every loop.
                for(int i = 0; i < count; i++)  
                    Uri imageUri = data.getClipData().getItemAt(i).getUri();
                    //do something with the image (save it to some directory or whatever you need to do with it here) 
                }
            } else if(data.getData() != null) {
                String imagePath = data.getData().getPath();
                //do something with the image (save it to some directory or whatever you need to do with it here)
            }
        }
    }
}

Notez que le sélecteur d'Android a Photos et Galerie disponibles sur certains appareils. Photos permet de sélectionner plusieurs images. Galerie permet seulement un à la fois.

15
Mira_Cole

Initialiser l'instance:

private String imagePath;
private List<String> imagePathList;

Dans onActivityResult Vous devez écrire ceci, If-else 2 block. Un pour une seule image et un autre pour plusieurs images.

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

    imagePathList = new ArrayList<>();

    if(data.getClipData() != null){

        int count = data.getClipData().getItemCount();
        for (int i=0; i<count; i++){

            Uri imageUri = data.getClipData().getItemAt(i).getUri();
            getImageFilePath(imageUri);
        }
    }
    else if(data.getData() != null){

        Uri imgUri = data.getData();
        getImageFilePath(imgUri);
    }
}

Partie la plus importante, Get Image Path from uri:

public void getImageFilePath(Uri uri) {

    File file = new File(uri.getPath());
    String[] filePath = file.getPath().split(":");
    String image_id = filePath[filePath.length - 1];

    Cursor cursor = getContentResolver().query(Android.provider.MediaStore.Images.Media.EXTERNAL_CONTENT_URI, null, MediaStore.Images.Media._ID + " = ? ", new String[]{image_id}, null);
    if (cursor!=null) {
        cursor.moveToFirst();
        imagePath = cursor.getString(cursor.getColumnIndex(MediaStore.Images.Media.DATA));
        imagePathList.add(imagePath);
        cursor.close();
    }
}

J'espère que cela peut vous aider.

2
Hasib Akter

J'ai aussi eu le même problème. Je souhaitais également que les utilisateurs puissent prendre des photos facilement tout en choisissant des photos dans la galerie. N'ayant pas trouvé de moyen de le faire, j'ai donc décidé de faire un projet opensource. Cela ressemble beaucoup à MultipleImagePick mais constitue un meilleur moyen de le mettre en œuvre.

https://github.com/giljulio/Android-multiple-image-picker

private static final RESULT_CODE_PICKER_IMAGES = 9000;


Intent intent = new Intent(this, SmartImagePicker.class);
startActivityForResult(intent, RESULT_CODE_PICKER_IMAGES);


@Override
public void onActivityResult(int requestCode, int resultCode, Intent data) {
    switch (requestCode){
        case RESULT_CODE_PICKER_IMAGES:
            if(resultCode == Activity.RESULT_OK){
                Parcelable[] parcelableUris = data.getParcelableArrayExtra(ImagePickerActivity.TAG_IMAGE_URI);

                //Java doesn't allow array casting, this is a little hack
                Uri[] uris = new Uri[parcelableUris.length];
                System.arraycopy(parcelableUris, 0, uris, 0, parcelableUris.length);

                //Do something with the uris array
            }
            break;

        default:
            super.onActivityResult(requestCode, resultCode, data);
            break;
    }
}
0
Gil Julio

Je suis null de la Cursor. Nous avons ensuite trouvé une solution pour convertir la Uri en Bitmap qui fonctionne parfaitement.

Voici la solution qui fonctionne pour moi:

@Override
public void onActivityResult(int requestCode, int resultCode, @Nullable Intent data) {
{

    if (resultCode == Activity.RESULT_OK) {

        if (requestCode == YOUR_REQUEST_CODE) {

            if (data != null) {

                if (data.getData() != null) {

                    Uri contentURI = data.getData();
                    ex_one.setImageURI(contentURI);

                    Log.d(TAG, "onActivityResult: " + contentURI.toString());
                    try {

                        Bitmap bitmap = MediaStore.Images.Media.getBitmap(context.getContentResolver(), contentURI);

                    } catch (IOException e) {
                        e.printStackTrace();
                    }

                } else {

                    if (data.getClipData() != null) {
                        ClipData mClipData = data.getClipData();
                        ArrayList<Uri> mArrayUri = new ArrayList<Uri>();
                        for (int i = 0; i < mClipData.getItemCount(); i++) {

                            ClipData.Item item = mClipData.getItemAt(i);
                            Uri uri = item.getUri();
                            try {
                                Bitmap bitmap = MediaStore.Images.Media.getBitmap(context.getContentResolver(), uri);
                            } catch (IOException e) {
                                e.printStackTrace();
                            }

                        }
                    }

                }

            }

        }

    }

}
0
Sudarshan

Salut ci-dessous le code fonctionne bien.

 Cursor imagecursor1 = managedQuery(
    MediaStore.Images.Media.EXTERNAL_CONTENT_URI, columns, null,
    null, orderBy + " DESC");

   this.imageUrls = new ArrayList<String>();
  imageUrls.size();

   for (int i = 0; i < imagecursor1.getCount(); i++) {
   imagecursor1.moveToPosition(i);
   int dataColumnIndex = imagecursor1
     .getColumnIndex(MediaStore.Images.Media.DATA);
   imageUrls.add(imagecursor1.getString(dataColumnIndex));
  }

   options = new DisplayImageOptions.Builder()
  .showStubImage(R.drawable.stub_image)
  .showImageForEmptyUri(R.drawable.image_for_empty_url)
  .cacheInMemory().cacheOnDisc().build();

   imageAdapter = new ImageAdapter(this, imageUrls);

   gridView = (GridView) findViewById(R.id.PhoneImageGrid);
  gridView.setAdapter(imageAdapter);

Vous voulez plus de clarifications. http://mylearnandroid.blogspot.in/2014/02/multiple-choose-custom-gallery.html

0

Essayez celui-ci IntentChooser . Ajoutez juste quelques lignes de code, j'ai fait le reste pour vous.

private void startImageChooserActivity() {
    Intent intent = ImageChooserMaker.newChooser(MainActivity.this)
            .add(new ImageChooser(true))
            .create("Select Image");
    startActivityForResult(intent, REQUEST_IMAGE_CHOOSER);
}

@Override
protected void onActivityResult(int requestCode, int resultCode, Intent data) {
    super.onActivityResult(requestCode, resultCode, data);
    if (requestCode == REQUEST_IMAGE_CHOOSER && resultCode == RESULT_OK) {
        List<Uri> imageUris = ImageChooserMaker.getPickMultipleImageResultUris(this, data);
    }
}

PS: comme mentionné dans les réponses ci-dessus, EXTRA_ALLOW_MULTIPLE est uniquement disponible pour les API> = 18. Et certaines applications de galerie ne rendent pas cette fonctionnalité disponible (Google Photos et Documents (com.Android.documentsui)).

0
Tuan Chau