142 votes

Sélectionnez plusieurs images dans la galerie Android

En gros, ce que j'essaie de faire, c'est d'ouvrir la Galerie sur Android et de permettre à l'utilisateur de sélectionner plusieurs images. 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 la documentation de mon IDE (je reviendrai là-dessus plus tard) et donc je ne veux pas utiliser un adaptateur personnalisé mais juste celui par défaut.

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

Intent intent = new Intent();
intent.setType("image/*");
intent.setAction(Intent.ACTION_GET_CONTENT);
startActivityForResult(Intent.createChooser(intent,"Sélectionnez une image"), 1);

Maintenant, les gens sur SO et d'autres sites vous diront que vous avez 2 options :

1) Ne pas utiliser ACTION_GET_CONTENT mais plutôt ACTION_SEND_MULTIPLE à la place.
Cela ne fonctionne pas. Cela est selon la documentation pour envoyer des fichiers et non récupérer et c'est exactement ce qu'il fait. Lorsque j'utilise ACTION_SEND_MULTIPLE, une fenêtre s'ouvre sur mon appareil où je dois sélectionner une application pour envoyer mes données. Ce n'est pas ce que je veux, donc je me demande comment les gens ont réussi à le faire avec cette solution... Est-ce que je manque quelque chose ?

2) Implémenter une Galerie personnalisée. C'est ma dernière option que je considérerai car à mon avis, ce n'est pas ce que je recherche car je dois styliser moi-même ET pourquoi diable vous ne pouvez pas simplement sélectionner plusieurs images dans la galerie par défaut ?

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 ACTION_GET_CONTENT._

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

C'est assez intéressant. Ils y font référence au cas d'utilisation où un utilisateur peut sélectionner plusieurs éléments, non ?

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, n'est-ce pas ? C'est ce dont j'ai besoin. Mais ma question suivante est : Où puis-je mettre ce EXTRA_ALLOW_MULTIPLE ? La triste chose est que je ne le trouve nulle part dans le guide des développeurs Android et ce n'est pas non plus défini comme une constante dans la classe INTENT.

Est-ce que quelqu'un peut m'aider avec ce EXTRA_ALLOW_MULTIPLE ?

0voto

Gil Julio Points 782

J'ai également rencontré le même problème. Je voulais aussi que les utilisateurs puissent prendre des photos facilement tout en choisissant des photos dans la galerie. Je n'ai pas trouvé de moyen natif de le faire, alors j'ai décidé de créer un projet open source. C'est un peu comme MultipleImagePick mais une meilleure façon 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 ne permet pas le casting de tableau, c'est un petit hack
                Uri[] uris = new Uri[parcelableUris.length];
                System.arraycopy(parcelableUris, 0, uris, 0, parcelableUris.length);

                //Faites quelque chose avec le tableau d'URI
            }
            break;

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

0voto

Tuan Chau Points 488

Essayez celui-ci IntentChooser. Ajoutez simplement 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("Sélectionner une 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 imageUris = ImageChooserMaker.getPickMultipleImageResultUris(this, data);
    }
}

PS : comme mentionné dans les réponses ci-dessus, EXTRA_ALLOW_MULTIPLE n'est disponible que pour API >= 18. Et certaines applications galerie ne proposent pas cette fonctionnalité (Google Photos et Documents (com.android.documentsui) travaillent.

0voto

Mahmood Hussain Points 83
     // pour choisir plusieurs images, déclarez des variables
     int PICK_IMAGE_MULTIPLE = 2;
     String realImagePath;

     // Après avoir demandé l'autorisation de LECTURE DE FICHIER, peut-être lors d'un clic sur un bouton
     Intent intent = new Intent();
     intent.setType("image/*");
     intent.putExtra(Intent.EXTRA_ALLOW_MULTIPLE, true);
     intent.setAction(Intent.ACTION_GET_CONTENT);
     startActivityForResult(Intent.createChooser(intent,"Sélectionner des images"), PICK_IMAGE_MULTIPLE);

    public void onActivityResult(int requestCode, int resultCode, Intent data) {
        super.onActivityResult(requestCode, resultCode, data);// POUR CHOISIR PLUSIEURS IMAGES
        try {
            // Lorsqu'une image est sélectionnée
            if (requestCode == PICK_IMAGE_MULTIPLE && resultCode == RESULT_OK
                    && null != data) {
                if (data.getClipData() != null) {
                    int count = data.getClipData().getItemCount(); // évaluer le nombre avant la boucle for --- sinon, le nombre est évalué à chaque boucle.
                    for (int i = 0; i < count; i++) {
                        Uri imageUri = data.getClipData().getItemAt(i).getUri();
                        realImagePath = getPath(this, imageUri);
                        // faire quelque chose avec l'image (la sauvegarder dans un répertoire ou tout ce que vous devez faire avec ici)
                        Log.e("CheminDeLimage", "onActivityResult: " + realImagePath);
                    }
                } else if (data.getData() != null) {
                    Uri imageUri = data.getData();
                    realImagePath = getPath(this, imageUri);
                    // faire quelque chose avec l'image (la sauvegarder dans un répertoire ou tout ce que vous devez faire avec ici)
                    Log.e("CheminDeLimage", "onActivityResult: " + realImagePath);
                }
            }
        } catch (Exception e) {
            Toast.makeText(this, "Quelque chose s'est mal passé", Toast.LENGTH_LONG)
                    .show();
        }
    }

    public static String getPath(final Context context, final Uri uri) {
        // DocumentProvider
        if (DocumentsContract.isDocumentUri(context, uri)) {
            // ExternalStorageProvider
            if (isExternalStorageDocument(uri)) {
                final String docId = DocumentsContract.getDocumentId(uri);
                final String[] split = docId.split(":");
                final String type = split[0];

                if ("primary".equalsIgnoreCase(type)) {
                    return Environment.getExternalStorageDirectory() + "/" + split[1];
                }

                // TODO traiter les volumes non primaires
            }
            // DownloadsProvider
            else if (isDownloadsDocument(uri)) {

                final String id = DocumentsContract.getDocumentId(uri);
                final Uri contentUri = ContentUris.withAppendedId(
                        Uri.parse("content://downloads/public_downloads"), Long.parseLong(id));

                return getDataColumn(context, contentUri, null, null);
            }
            // MediaProvider
            else if (isMediaDocument(uri)) {
                final String docId = DocumentsContract.getDocumentId(uri);
                final String[] split = docId.split(":");
                final String type = split[0];

                Uri contentUri = null;
                if ("image".equals(type)) {
                    contentUri = MediaStore.Images.Media.EXTERNAL_CONTENT_URI;
                } else if ("video".equals(type)) {
                    contentUri = MediaStore.Video.Media.EXTERNAL_CONTENT_URI;
                } else if ("audio".equals(type)) {
                    contentUri = MediaStore.Audio.Media.EXTERNAL_CONTENT_URI;
                }

                final String selection = "_id=?";
                final String[] selectionArgs = new String[]{
                        split[1]
                };

                return getDataColumn(context, contentUri, selection, selectionArgs);
            }
        }
        // MediaStore (et général)
        else if ("content".equalsIgnoreCase(uri.getScheme())) {
            return getDataColumn(context, uri, null, null);
        }
        // Fichier
        else if ("file".equalsIgnoreCase(uri.getScheme())) {
            return uri.getPath();
        }

        return null;
    }

    /**
     * Obtenez la valeur de la colonne de données pour cette Uri. C'est utile pour
     * les Uri MediaStore et d'autres ContentProviders basés sur des fichiers.
     *
     * @param context       Le contexte.
     * @param uri           L'Uri à interroger.
     * @param selection     (Facultatif) Filtre utilisé dans la requête.
     * @param selectionArgs Arguments de sélection (Facultatif) utilisés dans la requête.
     * @return La valeur de la colonne _data, qui est généralement un chemin de fichier.
     */
    public static String getDataColumn(Context context, Uri uri, String selection,
                                       String[] selectionArgs) {

        Cursor cursor = null;
        final String column = "_data";
        final String[] projection = {
                column
        };

        try {
            cursor = context.getContentResolver().query(uri, projection, selection, selectionArgs,
                    null);
            if (cursor != null && cursor.moveToFirst()) {
                final int column_index = cursor.getColumnIndexOrThrow(column);
                return cursor.getString(column_index);
            }
        } finally {
            if (cursor != null)
                cursor.close();
        }
        return null;
    }

    /**
     * @param uri L'Uri à vérifier.
     * @return Si l'autorité de l'Uri est ExternalStorageProvider.
     */
    public static boolean isExternalStorageDocument(Uri uri) {
        return "com.android.externalstorage.documents".equals(uri.getAuthority());
    }

    /**
     * @param uri L'Uri à vérifier.
     * @return Si l'autorité de l'Uri est DownloadsProvider.
     */
    public static boolean isDownloadsDocument(Uri uri) {
        return "com.android.providers.downloads.documents".equals(uri.getAuthority());
    }

    /**
     * @param uri L'Uri à vérifier.
     * @return Si l'autorité de l'Uri est MediaProvider.
     */
    public static boolean isMediaDocument(Uri uri) {
        return "com.android.providers.media.documents".equals(uri.getAuthority());
    }

cela a parfaitement fonctionné pour moi crédits : Obtenir le chemin réel à partir de l'URI, Android KitKat nouveau cadre d'accès au stockage

0voto

Pour sélectionner plusieurs images dans la galerie

i.putExtra(Intent.EXTRA_ALLOW_MULTIPLE,true);

Une solution ultime pour le téléchargement de plusieurs images avec une option appareil photo également pour Android Lollipop à Android 10, SDK 30.

private static final int FILECHOOSER_RESULTCODE   = 1;
private ValueCallback mUploadMessage;
private ValueCallback mUploadMessages;
private Uri mCapturedImageURI = null;

Ajoutez ceci à OnCreate de MainActivity

mWebView.setWebChromeClient(new WebChromeClient() {

            // openFileChooser pour Android 3.0+

            public void openFileChooser(ValueCallback uploadMsg, String acceptType){
                mUploadMessage = uploadMsg;
                openImageChooser();
            }

            // Pour les appareils Lollipop 5.0+

            public boolean onShowFileChooser(WebView mWebView, ValueCallback filePathCallback, WebChromeClient.FileChooserParams fileChooserParams) {
                mUploadMessages = filePathCallback;
                openImageChooser();
                return true;
            }

            // openFileChooser pour Android < 3.0

            public void openFileChooser(ValueCallback uploadMsg){
                openFileChooser(uploadMsg, "");
            }

            // openFileChooser pour d'autres versions Android

            public void openFileChooser(ValueCallback uploadMsg, String acceptType, String capture) {
                openFileChooser(uploadMsg, acceptType);
            }

private void openImageChooser() {
    try {
        File imageStorageDir = new File(Environment.getExternalStoragePublicDirectory(Environment.DIRECTORY_PICTURES), "FolderName");
        if (!imageStorageDir.exists()) {
            imageStorageDir.mkdirs();
        }
        File file = new File(imageStorageDir + File.separator + "IMG_" + String.valueOf(System.currentTimeMillis()) + ".jpg");
        mCapturedImageURI = Uri.fromFile(file);

        final Intent captureIntent = new Intent(MediaStore.ACTION_IMAGE_CAPTURE);
        captureIntent.putExtra(MediaStore.EXTRA_OUTPUT, mCapturedImageURI);

        Intent i = new Intent(Intent.ACTION_GET_CONTENT);
        i.addCategory(Intent.CATEGORY_OPENABLE);
        i.setType("image/*");
        i.putExtra(Intent.EXTRA_ALLOW_MULTIPLE,true);
        Intent chooserIntent = Intent.createChooser(i, "Sélecteur d'images");
        chooserIntent.putExtra(Intent.EXTRA_INITIAL_INTENTS, new Parcelable[]{captureIntent});

        startActivityForResult(chooserIntent, FILECHOOSER_RESULTCODE);
    } catch (Exception e) {
        e.printStackTrace();
    }
}

        });

onActivityResult

public void onActivityResult(final int requestCode, final int resultCode, final Intent data) {

        super.onActivityResult(requestCode, resultCode, data);
        if (requestCode == FILECHOOSER_RESULTCODE) {

            if (null == mUploadMessage && null == mUploadMessages) {
                return;
            }

            if (null != mUploadMessage) {
                handleUploadMessage(requestCode, resultCode, data);

            } else if (mUploadMessages != null) {
                handleUploadMessages(requestCode, resultCode, data);
            }
        }

    }

    private void handleUploadMessage(final int requestCode, final int resultCode, final Intent data) {
        Uri result = null;
        try {
            if (resultCode != RESULT_OK) {
                result = null;
            } else {
                // récupérer de la variable privée si l'intent est nul

                result = data == null ? mCapturedImageURI : data.getData();
            }
        } catch (Exception e) {
            e.printStackTrace();
        }
        mUploadMessage.onReceiveValue(result);
        mUploadMessage = null;

        // code pour toutes les versions sauf Lollipop
        if (Build.VERSION.SDK_INT < Build.VERSION_CODES.LOLLIPOP) {

                result = null;

                try {
                    if (resultCode != RESULT_OK) {
                        result = null;
                    } else {
                        // récupérer de la variable privée si l'intent est nul
                        result = data == null ? mCapturedImageURI : data.getData();
                    }
                } catch (Exception e) {
                    Toast.makeText(getApplicationContext(), "activité :" + e, Toast.LENGTH_LONG).show();
                }

                mUploadMessage.onReceiveValue(result);
                mUploadMessage = null;
            }

        } // fin du code pour toutes les versions sauf Lollipop

    private void handleUploadMessages(final int requestCode, final int resultCode, final Intent data) {
        Uri[] results = null;
        try {
            if (resultCode != RESULT_OK) {
                results = null;
            } else {
                if (data != null) {
                    String dataString = data.getDataString();
                    ClipData clipData = data.getClipData();
                    if (clipData != null) {
                        results = new Uri[clipData.getItemCount()];
                        for (int i = 0; i < clipData.getItemCount(); i++) {
                            ClipData.Item item = clipData.getItemAt(i);
                            results[i] = item.getUri();
                        }
                    }
                    if (dataString != null) {
                        results = new Uri[]{Uri.parse(dataString)};
                    }
                } else {
                    results = new Uri[]{mCapturedImageURI};
                }
            }
        } catch (Exception e) {
            e.printStackTrace();
        }
        mUploadMessages.onReceiveValue(results);
        mUploadMessages = null;
    }

0voto

Chintak Patel Points 446

Pour la sélection multiple d'images et la fonction de restriction de limite de sélection, utilisez la bibliothèque chintan369/MultiImagePicker qui est la dernière de 2021 et prend également en charge Android 11. Elle est bien documentée et une démo est également expliquée sur youtube pour utilisation. Il est très facile à ajouter dans le projet, facile à utiliser pour appeler la bibliothèque pour la sélection d'images et obtenir les résultats des images sélectionnées en tant que liste d'Uri et vous pouvez également demander la liste des résultats en tant que liste de chemins de fichiers absolus.

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X