Seleziona più immagini dalla galleria Android


114

Quindi, in pratica, quello che sto cercando di ottenere è aprire il Galleryin Android e lasciare che l'utente selezioni multiple images. Ora questa domanda è stata posta frequentemente ma non sono soddisfatto delle risposte. Principalmente perché ho trovato qualcosa di interessante in de docs nel mio IDE (ci tornerò più tardi) e quindi non voglio usare un adattatore personalizzato ma solo quello vaniglia.

Ora il mio codice per selezionare un'immagine è:

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

Ora le persone su SO e altri siti Web ti diranno che hai 2 opzioni:

1) Non usare ACTION_GET_CONTENTma ACTION_SEND_MULTIPLEinvece.
Questo non funziona. Questo è secondo i documenti per i sendingfile e non retrievinged è esattamente quello che fa. Quando si utilizza ACTION_SEND_MULTIPLE, sul mio dispositivo si apre una finestra in cui devo selezionare un'applicazione a cui inviare i miei dati. Non è quello che voglio, quindi mi chiedo come le persone abbiano ottenuto questo risultato con questa soluzione .. Mi manca qualcosa?

2) Implementare un file custom Gallery. Questa è la mia ultima opzione che prenderò in considerazione perché imho non è quello che sto cercando perché devo modellarlo da solo E perché diamine non puoi selezionare più immagini nella galleria vanilla?

Ci deve essere un'opzione per questo .. Ora la cosa interessante che ho trovato è questa: l'
ho trovata nella descrizione della documentazione di ACTION_GET_CONTENT.

Se il chiamante può gestire più elementi restituiti (l'utente che esegue la selezione multipla), può specificare EXTRA_ALLOW_MULTIPLE per indicarlo.

Questo è piuttosto interessante. Qui lo fanno riferimento al caso d'uso in cui un utente può selezionare più elementi?

Più tardi si dice nei documenti:

Puoi utilizzare EXTRA_ALLOW_MULTIPLE per consentire all'utente di selezionare più elementi.

Quindi questo è abbastanza ovvio, vero? Questo è ciò di cui ho bisogno. Ma la mia domanda seguente è: dove posso metterlo EXTRA_ALLOW_MULTIPLE? La cosa triste è che non riesco a trovarlo da nessuna parte nella guida developers.android e inoltre non è definito come una costante nella classe INTENT.

Qualcuno può aiutarmi con questo EXTRA_ALLOW_MULTIPLE?




1
La soluzione @KyleShank ha funzionato per me. L'impostazione EXTRA_ALLOW_MULTIPLEconsente di selezionare più elementi. Ottieni gli URI richiamando getClipData()l'intento restituito in onActivityResult. L'unico problema è che il widget della galleria non consente la selezione multipla. In tal caso, facendo clic su qualsiasi immagine, il selezionatore terminerà e potrai ottenere l'URI (del singolo elemento) chiamando getDatal'intento restituito
Tanweer Alam

Risposte:


122

L'opzione EXTRA_ALLOW_MULTIPLE è impostata sull'intento tramite il metodo Intent.putExtra ():

intent.putExtra(Intent.EXTRA_ALLOW_MULTIPLE, true);

Il tuo codice sopra dovrebbe assomigliare a questo:

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

Nota: l' EXTRA_ALLOW_MULTIPLEopzione è disponibile solo in Android API 18 e versioni successive.


Lo so ma come ho detto nella mia risposta: "La cosa triste è che non riesco a trovarlo da nessuna parte nella guida developers.android e inoltre non è definito come una costante nella classe INTENT." Il mio IDE non riconosce Intent.EXTRA_ALLOW_MULTIPLE. Ho installato il livello API 18. Il mio IDE dice: "EXTRA_ALLOW_MULTIPLE non può essere risolto o non è un campo"
Dion Segijn

intent.putExtra (Intent.EXTRA_ALLOW_MULTIPLE, true); usa l'emulatore, non supporta la selezione multipla.
qinmiao

11
Sta selezionando l'immagine multipla. ma come ottenere l'URL dell'immagine dal risultato dell'attività ????
John

4
Questo avvia il selettore di immagini e mi consente di selezionare più immagini, ma non so come ottenere gli URL in onActivityResult.
Tom Kincaid

5
Puoi ottenere gli URL nel risultato Intent.getClipData. Ha l'array di ClipData Item.
Tam Huynh

71

Definisci queste variabili nella classe:

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

Supponiamo che facendo clic su un pulsante dovrebbe aprire la galleria per selezionare le immagini

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

Quindi dovresti sovrascrivere il metodo 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);
}

NOTA CHE: la galleria non ti dà la possibilità di selezionare multi-immagini, quindi qui apriamo tutto lo studio di immagini che puoi selezionare multi-immagini da loro. e non dimenticare di aggiungere le autorizzazioni al tuo manifest

MOLTO IMPORTANTE: getData (); per ottenere una singola immagine e l'ho memorizzata qui in imageEncoded String se l'utente seleziona più immagini allora dovrebbero essere memorizzate nell'elenco

Quindi devi controllare quale è nullo per usare l'altro

Ti auguro una buona prova e agli altri


Ho saltato "intent.setType (" image / * ");" e invia gli utenti direttamente a Foto invece di dare all'utente la possibilità di andare alla Galleria che non consente la selezione di più immagini. Non sono sicuro che sia per questo motivo, il mio getData () non restituisce mai null, quindi ho finito per utilizzare getClipData esclusivamente per la selezione di immagini singole e multiple.
Johnny Wu

1
basta usare la parte data.getClipData () è sufficiente, non c'è bisogno di controllare data.getData ()
truongnm

&& null! = dati ??
Odaym

8
Uri uri = content: //com.android.providers.media.documents/document/image%3A772 uri ha dati ma cursor.getString mi restituisce null imageEncoded = cursor.getString (columnIndex);
Muhammad Zubair Ashraf

2
E 'stato utile, ma ho dovuto integrare con queste funzioni per la getPath: stackoverflow.com/a/20559175/6141959
Geynen

31

Molte di queste risposte hanno somiglianze ma mancano tutte la parte più importante che si trova onActivityResult, controlla se data.getClipDataè nulla prima di controllaredata.getData

Il codice per chiamare il selettore di file:

Intent intent = new Intent(Intent.ACTION_GET_CONTENT);
intent.setType("image/*"); //allows any image file type. Change * to specific extension to limit it
//**The 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

Il codice per ottenere tutte le immagini selezionate:

@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)
            }
        }
    }
}

Nota che il selettore di Android ha Foto e Galleria disponibili su alcuni dispositivi. Foto consente di selezionare più immagini. La galleria consente solo uno alla volta.


cos'è getClipData ()? data.getData non è sufficiente?
adi

1
In alcuni dispositivi Samsung, i risultati saranno diversi rispetto ai dispositivi non Samsung. Se l'utente seleziona più file, getData()a volte NON sarà nullo ma avrà solo un Uri. Se vuoi gestire quando un utente seleziona più file, controlla getClipData()prima getData(): se i dati del clip non sono nulli, l'utente potrebbe aver selezionato più immagini. Gestire getClipData prima di getData ma gestire entrambi i casi è importante per supportare dispositivi diversi pur consentendo più Uris.
Mira_Cole

@Mira_Code Come posso impostare le immagini selezionate su diverse visualizzazioni dell'immagine.
Hasnain Ghias

20

Spero che questa risposta non sia in ritardo. Perché il widget della galleria non supporta la selezione multipla per impostazione predefinita, ma puoi personalizzare la visualizzazione griglia che ha accettato il tuo intento di selezione multipla. L'altra opzione è estendere la visualizzazione della galleria e aggiungere il proprio codice per consentire la selezione multipla.
Questa è la semplice libreria che può farlo: https://github.com/luminousman/MultipleImagePick

Aggiornamento :
dal commento di @ ilsy, CustomGalleryActivity in questa libreria usa manageQuery, che è deprecato, quindi dovrebbe essere cambiato in getContentResolver().query()e cursor.close()come questa risposta


@ R4j Sì e ho scritto su questo: la libreria non è pronta per l'uso nei progetti. Sono necessari molti aggiornamenti per iniziare a usarlo. E sul tuo aggiornamento: non usare getContentResolver().query()nel thread dell'interfaccia utente. Informazioni sui caricatori e sulla libreria di supporto.
mbelsky

.cacheOnDisc()anche deprecato, quindi modificalo in .cacheOnDisc(true)con parametro booleano
Pratik Butani

5

Inizializza istanza:

private String imagePath;
private List<String> imagePathList;

In onActivityResult devi scrivere questo blocco If-else 2. Uno per un'immagine singola e un altro per un'immagine multipla.

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

La parte più importante, Ottieni percorso immagine da 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();
    }
}

Spero che questo possa aiutarti.


1

Ho ottenuto null dal Cursor. Quindi ho trovato una soluzione per convertire Uriin Bitmapche funziona perfettamente.

Ecco la soluzione che funziona per me:

@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

Ciao sotto il codice funziona bene.

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

Vuoi maggiori chiarimenti. http://mylearnandroid.blogspot.in/2014/02/multiple-choose-custom-gallery.html


1
se funziona va bene. È utile sottolineare il codice deprecato, ma finché lo si utilizza senza problemi va bene da usare. È importante sapere perché è deprecato, se si tratta di problemi di sicurezza, il codice più recente è più efficiente, ecc. Ma poiché le app Android sono compatibili con il futuro, il codice deprecato continuerà a funzionare in futuro.
JStephen

0

Ho anche avuto lo stesso problema. Volevo anche che gli utenti potessero scattare foto facilmente mentre selezionavano le foto dalla galleria. Non riuscivo a trovare un modo nativo per farlo, quindi ho deciso di creare un progetto opensource. È molto simile a MultipleImagePick ma è solo un modo migliore per implementarlo.

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

Prova questo IntentChooser . Aggiungi solo alcune righe di codice, io ho fatto il resto per te.

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: come menzionato nelle risposte sopra, EXTRA_ALLOW_MULTIPLE è disponibile solo per API> = 18. E alcune app della galleria non rendono disponibile questa funzione (Google Foto e Documenti ( com.android.documentsui) funzionano.


Non permettermi di scegliere più immagini anche se aggiunteintent.putExtra(Intent.EXTRA_ALLOW_MULTIPLE, true);
Scorpion
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.