Wählen Sie mehrere Bilder aus der Android-Galerie

114

Im Grunde versuche ich, das Galleryin Android zu öffnen und den Benutzer auswählen zu lassen multiple images. Jetzt wurde diese Frage häufig gestellt, aber ich bin mit den Antworten nicht zufrieden. Hauptsächlich, weil ich in meiner IDE etwas Interessantes in de docs gefunden habe (darauf komme ich später zurück) und daher keinen benutzerdefinierten Adapter verwenden möchte, sondern nur den Vanille-Adapter.

Jetzt lautet mein Code für die Auswahl eines Bildes:

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

Jetzt werden Ihnen die Leute auf SO und anderen Websites sagen, dass Sie zwei Möglichkeiten haben:

1) Verwenden Sie nicht , ACTION_GET_CONTENTsondern ACTION_SEND_MULTIPLEstattdessen.
Dieser funktioniert nicht. Dieser ist gemäß den Dokumenten für sendingDateien und nicht retrievingund genau das ist es, was es tut. Bei Verwendung von ACTION_SEND_MULTIPLE wurde auf meinem Gerät ein Fenster geöffnet, in dem ich eine Anwendung auswählen muss, an die meine Daten gesendet werden sollen. Das ist nicht das, was ich will, also frage ich mich, wie die Leute dies mit dieser Lösung erreicht haben. Vermisse ich etwas?

2) Implementieren Sie eine custom Gallery. Dies ist meine letzte Option, die ich in Betracht ziehen werde, weil ich imho nicht das bin, wonach ich suche, weil ich sie selbst stylen muss UND warum zum Teufel können Sie einfach nicht mehrere Bilder in der Vanille-Galerie auswählen?

Es muss eine Option dafür geben. Nun ist das Interessante, was ich gefunden habe, Folgendes:
Ich habe dies in der Beschreibung der Dokumentation von gefunden ACTION_GET_CONTENT.

Wenn der Anrufer mehrere zurückgegebene Elemente verarbeiten kann (der Benutzer führt eine Mehrfachauswahl durch), kann er EXTRA_ALLOW_MULTIPLE angeben, um dies anzuzeigen.

Das ist ziemlich interessant. Hier beziehen sie sich auf den Anwendungsfall, in dem ein Benutzer mehrere Elemente auswählen kann?

Später heißt es in den Dokumenten:

Sie können EXTRA_ALLOW_MULTIPLE verwenden, damit der Benutzer mehrere Elemente auswählen kann.

Das ist also ziemlich offensichtlich, oder? Das ist das, was ich benötige. Aber meine folgende Frage ist: Wo kann ich das hinstellen EXTRA_ALLOW_MULTIPLE? Das Traurige ist, dass ich dieses Nein nirgendwo im Entwickler.android-Handbuch finden kann und dass dies auch nicht als Konstante in der INTENT-Klasse definiert ist.

Kann mir jemand dabei helfen EXTRA_ALLOW_MULTIPLE?

Dion Segijn
quelle
1
Die @ KyleShank-Lösung hat bei mir funktioniert. Mit dieser Einstellung können EXTRA_ALLOW_MULTIPLESie mehrere Elemente auswählen. Rufen Sie die URIs ab, indem Sie die getClipData()zurückgegebene Absicht in aufrufen onActivityResult. Das einzige Problem ist, dass das Galerie-Widget keine Mehrfachauswahl zulässt. In diesem Fall wird durch Klicken auf ein Bild die Auswahl beendet und Sie können die URI (des einzelnen Elements) abrufen, indem Sie die getDatazurückgegebene Absicht aufrufen
Tanweer Alam,

Antworten:

122

Die Option EXTRA_ALLOW_MULTIPLE wird für die Absicht über die Methode Intent.putExtra () festgelegt:

intent.putExtra(Intent.EXTRA_ALLOW_MULTIPLE, true);

Ihr Code oben sollte folgendermaßen aussehen:

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

Hinweis: Die EXTRA_ALLOW_MULTIPLEOption ist nur in Android API 18 und höher verfügbar.

Kyle Shank
quelle
Ich weiß das, aber wie ich in meiner Antwort erwähne: "Das Traurige ist, dass ich dieses Nein nirgendwo im Entwickler.android-Handbuch finden kann und dies auch nicht als Konstante in der INTENT-Klasse definiert ist." Meine IDE erkennt Intent.EXTRA_ALLOW_MULTIPLE nicht. Ich habe API Level 18 installiert. Meine IDE sagt: "EXTRA_ALLOW_MULTIPLE kann nicht aufgelöst werden oder ist kein Feld"
Dion Segijn
intent.putExtra (Intent.EXTRA_ALLOW_MULTIPLE, true); Emulator verwenden, Mehrfachauswahl nicht unterstützen.
Qinmiao
11
Es wählt das Mehrfachbild aus. aber wie bekomme ich die Bild-URL aus dem Aktivitätsergebnis ????
John
4
Dadurch wird die Bildauswahl gestartet und ich kann mehrere Bilder auswählen, aber ich weiß nicht, wie ich die URLs in onActivityResult abrufen kann.
Tom Kincaid
5
Sie können die URLs im Ergebnis erhalten Intent.getClipData. Es hat das Array von ClipData Item.
Tam Huynh
71

Definieren Sie diese Variablen in der Klasse:

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

Angenommen, onClick auf eine Schaltfläche sollte die Galerie öffnen, um Bilder auszuwählen

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

Dann sollten Sie die onActivityResult-Methode überschreiben

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

HINWEIS: Die Galerie bietet Ihnen nicht die Möglichkeit, mehrere Bilder auszuwählen. Daher öffnen wir hier alle Bilder, in denen Sie mehrere Bilder auswählen können. und vergessen Sie nicht, die Berechtigungen zu Ihrem Manifest hinzuzufügen

SEHR WICHTIG: getData (); Um ein einzelnes Bild zu erhalten, habe ich es hier in imageEncoded String gespeichert. Wenn der Benutzer mehrere Bilder auswählt, sollten diese in der Liste gespeichert werden

Sie müssen also überprüfen, welche Null ist, um die andere zu verwenden

Ich wünsche Ihnen einen schönen Versuch und an andere

Laith Mihyar
quelle
Ich habe den "intent.setType (" image / * ") übersprungen." und es sendet die Benutzer direkt zu Foto, anstatt dem Benutzer die Möglichkeit zu geben, zur Galerie zu gehen, die keine Auswahl mehrerer Bilder erlaubt. Ich bin mir nicht sicher, ob dies der Fall ist. Mein getData () gibt niemals null zurück. Daher habe ich getClipData ausschließlich für die Auswahl einzelner und mehrerer Bilder verwendet.
Johnny Wu
1
Verwenden Sie einfach das Teil data.getClipData () ist genug, keine Notwendigkeit, data.getData () zu überprüfen
truongnm
&& null! = Daten ??
Odaym
8
Uri uri = content: //com.android.providers.media.documents/document/image%3A772 uri hat Daten, aber cursor.getString gibt mir null zurück imageEncoded = cursor.getString (columnIndex);
Muhammad Zubair Ashraf
2
Es war nützlich, aber ich musste diese Funktionen für getPath ergänzen: stackoverflow.com/a/20559175/6141959
Geynen
30

Viele dieser Antworten haben Ähnlichkeiten, aber allen fehlt der wichtigste Teil, der darin enthalten ist onActivityResult. Überprüfen Sie vor dem Überprüfen , ob er data.getClipDatanull istdata.getData

Der Code zum Aufrufen der Dateiauswahl:

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

Der Code, mit dem alle Bilder ausgewählt werden:

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

Beachten Sie, dass in der Android-Auswahl auf einigen Geräten Fotos und Galerien verfügbar sind. Mit Fotos können mehrere Bilder ausgewählt werden. Galerie erlaubt jeweils nur einen.

Mira_Cole
quelle
Was ist getClipData ()? reicht data.getData nicht aus?
adi
1
Bei einigen Samsung-Geräten unterscheiden sich die Ergebnisse von denen bei Nicht-Samsung-Geräten. Wenn der Benutzer mehrere Dateien auswählt, getData()ist diese manchmal NICHT null, sondern hat nur eine Uri. Wenn Sie behandeln möchten, wenn ein Benutzer mehrere Dateien auswählt , überprüfen Sie dies getClipData()zuvor. getData()Wenn die Clipdaten nicht null sind, hat der Benutzer möglicherweise mehrere Bilder ausgewählt. Die Behandlung von getClipData vor getData, aber die Behandlung beider Fälle ist wichtig, um verschiedene Geräte zu unterstützen und gleichzeitig mehrere Uris zuzulassen.
Mira_Cole
@Mira_Code Wie kann ich die ausgewählten Bilder auf verschiedene Bildansichten einstellen?
Hasnain Ghias
20

Ich hoffe, diese Antwort ist nicht zu spät. Da das Galerie-Widget standardmäßig keine Mehrfachauswahl unterstützt, können Sie jedoch die Rasteransicht anpassen, die Ihre Mehrfachauswahlabsicht akzeptiert hat. Die andere Option besteht darin, die Galerieansicht zu erweitern und Ihren eigenen Code hinzuzufügen, um eine Mehrfachauswahl zu ermöglichen.
Dies ist die einfache Bibliothek, die dies tun kann: https://github.com/luminousman/MultipleImagePick

Update :
Aus dem Kommentar von @ ilsy geht hervor, dass CustomGalleryActivity in dieser Bibliothek manageQueryveraltet ist. Daher sollte es in diese Antwort geändert werden getContentResolver().query()und ihr cursor.close()gefallen

R4j
quelle
@ R4j Ja und ich habe darüber geschrieben: Die Bibliothek ist nicht bereit für die Verwendung in Projekten. Benötigen Sie viele Updates, um es zu verwenden. Und zu Ihrem Update: Nicht getContentResolver().query()im UI-Thread verwenden. Lesen Sie mehr über Loader und Support Library.
Mbelsky
.cacheOnDisc()auch veraltet, also ändern Sie es .cacheOnDisc(true)mit boolean param
Pratik Butani
5

Instanz initialisieren:

private String imagePath;
private List<String> imagePathList;

In onActivityResult müssen Sie diesen If-else 2-Block schreiben. Eine für ein einzelnes Bild und eine für mehrere Bilder.

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

Wichtigster Teil: Holen Sie sich den Bildpfad von 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();
    }
}

Hoffe das kann dir helfen.

Hasib Akter
quelle
1

Ich habe null von der Cursor. Dann fand eine Lösung, um das Uriin Bitmapdas umzuwandeln, das perfekt funktioniert.

Hier ist die Lösung, die für mich funktioniert:

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

                        }
                    }

                }

            }

        }

    }

}
Sudarshan
quelle
0

Hallo unten Code funktioniert gut.

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

Sie möchten mehr Klarstellungen. http://mylearnandroid.blogspot.in/2014/02/multiple-choose-custom-gallery.html

Ramesh Thangaraj
quelle
1
Wenn es funktioniert, ist es in Ordnung. Es ist gut, auf veralteten Code hinzuweisen, aber solange Sie ihn ohne Probleme verwenden, ist es in Ordnung, ihn zu verwenden. Es ist wichtig zu wissen, warum es veraltet ist, ob es sich um Sicherheitsprobleme handelt, neuerer Code effizienter ist usw. Da Android-Apps jedoch vorwärtskompatibler veralteter Code sind, wird er auch in Zukunft funktionieren.
JStephen
0

Ich hatte auch das gleiche Problem. Ich wollte auch, dass Benutzer problemlos Fotos aufnehmen können, während sie Fotos aus der Galerie auswählen. Ich konnte keinen nativen Weg finden, dies zu tun, deshalb habe ich beschlossen, ein OpenSource-Projekt zu erstellen. Es ähnelt MultipleImagePick, ist aber nur eine bessere Möglichkeit, es zu implementieren.

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;
    }
}
Gil Julio
quelle
0

Probieren Sie diesen IntentChooser aus . Fügen Sie einfach einige Codezeilen hinzu, den Rest habe ich für Sie erledigt.

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: Wie in den obigen Antworten erwähnt, ist EXTRA_ALLOW_MULTIPLE nur für API> = 18 verfügbar. Einige Galerie-Apps stellen diese Funktion nicht zur Verfügung (Google Fotos und Dokumente ( com.android.documentsui)).

Tuan Chau
quelle
Ich darf nicht mehrere Bilder auswählen, obwohl sie hinzugefügt wurdenintent.putExtra(Intent.EXTRA_ALLOW_MULTIPLE, true);
Scorpion