Pilih beberapa gambar dari galeri android

114

Jadi pada dasarnya apa yang saya coba capai adalah membuka Gallerydi Android dan membiarkan pengguna memilih multiple images. Sekarang pertanyaan ini telah sering ditanyakan tetapi saya tidak puas dengan jawabannya. Terutama karena saya menemukan sesuatu yang menarik di de docs di IDE saya (saya kembali lagi nanti) dan oleh karena itu saya tidak ingin menggunakan adaptor khusus tetapi hanya yang vanilla.

Sekarang kode saya untuk memilih satu gambar adalah:

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

Sekarang Orang-orang di SO dan situs web lain akan memberi tahu Anda bahwa Anda memiliki 2 opsi:

1) Jangan gunakan ACTION_GET_CONTENTmelainkan ACTION_SEND_MULTIPLE.
Yang ini tidak berhasil. Yang ini sesuai dengan dokumen untuk sendingfile dan bukan retrievingdan itulah yang dilakukannya. Saat menggunakan ACTION_SEND_MULTIPLE saya mendapat jendela terbuka di perangkat saya di mana saya harus memilih aplikasi untuk mengirim data saya. Bukan itu yang saya inginkan, jadi saya bertanya-tanya bagaimana orang-orang mencapai ini dengan solusi ini .. Apakah saya melewatkan sesuatu?

2) Menerapkan custom Gallery. Sekarang ini adalah opsi terakhir saya yang akan saya pertimbangkan karena imho bukan itu yang saya cari karena saya harus menatanya sendiri DAN mengapa Anda tidak dapat memilih banyak gambar di galeri vanilla?

Harus ada opsi untuk ini .. Sekarang hal menarik yang saya temukan adalah ini:
Saya menemukan ini di deskripsi dokumen ACTION_GET_CONTENT.

Jika pemanggil dapat menangani beberapa item yang dikembalikan (pengguna melakukan beberapa pilihan), maka pemanggil dapat menentukan EXTRA_ALLOW_MULTIPLE untuk menunjukkan ini.

Ini cukup menarik. Di sini mereka merujuknya ke kasus penggunaan di mana pengguna dapat memilih beberapa item?

Kemudian mereka mengatakan di dokumen:

Anda dapat menggunakan EXTRA_ALLOW_MULTIPLE untuk memungkinkan pengguna memilih beberapa item.

Jadi ini cukup jelas bukan? Inilah yang saya butuhkan. Tetapi pertanyaan saya berikut ini adalah: Di mana saya bisa meletakkan ini EXTRA_ALLOW_MULTIPLE? Hal yang menyedihkan adalah bahwa saya tidak dapat menemukan ini tidak di mana dalam panduan developer.android dan juga ini tidak didefinisikan sebagai sebuah konstanta di kelas INTENT.

Ada yang bisa membantu saya dengan ini EXTRA_ALLOW_MULTIPLE?

Dion Segijn
sumber
1
Solusi @keluarga berhasil untuk saya. Pengaturan EXTRA_ALLOW_MULTIPLEmemungkinkan Anda memilih beberapa item. Dapatkan URI dengan memanggil getClipData()maksud yang dikembalikan dalam onActivityResult. Satu-satunya masalah adalah widget galeri tidak mengizinkan banyak pilihan. Dalam hal ini mengklik gambar apa pun akan menyelesaikan pemilihan dan Anda bisa mendapatkan URI (dari satu item) dengan memanggil getDatamaksud yang dikembalikan
Tanweer Alam

Jawaban:

122

Opsi EXTRA_ALLOW_MULTIPLE disetel pada maksud melalui metode Intent.putExtra ():

intent.putExtra(Intent.EXTRA_ALLOW_MULTIPLE, true);

Kode Anda di atas akan terlihat seperti ini:

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

Catatan: EXTRA_ALLOW_MULTIPLEopsi ini hanya tersedia di Android API 18 dan lebih tinggi.

Kyle Shank
sumber
Saya tahu ini tetapi seperti yang saya sebutkan dalam jawaban saya: "Hal yang menyedihkan adalah bahwa saya tidak dapat menemukan ini di mana pun di panduan developer.android dan juga apakah ini tidak didefinisikan sebagai sebuah konstanta di kelas INTENT." IDE saya tidak mengenali Intent.EXTRA_ALLOW_MULTIPLE. Saya telah memasang API level 18. IDE saya mengatakan: "EXTRA_ALLOW_MULTIPLE tidak dapat diselesaikan atau bukan merupakan bidang"
Dion Segijn
intent.putExtra (Intent.EXTRA_ALLOW_MULTIPLE, true); gunakan emulator, tidak mendukung banyak pilihan.
qinmiao
11
Ini memilih beberapa gambar. tapi bagaimana cara mendapatkan url gambar dari hasil Activity ????
Yohanes
4
Ini meluncurkan pemilih gambar dan memungkinkan saya memilih beberapa gambar, tetapi saya tidak tahu cara mendapatkan url di onActivityResult.
Tom Kincaid
5
Anda bisa mendapatkan url di hasilnya Intent.getClipData. Ini memiliki array Item ClipData.
Tam Huynh
71

Tentukan variabel-variabel ini di kelas:

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

Mari Asumsikan bahwa onClick pada tombol itu harus membuka galeri untuk memilih gambar

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

Kemudian Anda harus mengganti Metode 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);
}

CATATAN BAHWA: galeri tidak memberi Anda kemampuan untuk memilih multi-gambar jadi kami di sini membuka semua studio gambar yang Anda dapat memilih multi-gambar dari mereka. dan jangan lupa untuk menambahkan izin ke manifes Anda

SANGAT PENTING: getData (); untuk mendapatkan satu gambar tunggal dan saya telah menyimpannya di sini di imageEncoded String jika pengguna memilih multi-gambar maka mereka harus disimpan dalam daftar

Jadi, Anda harus memeriksa mana yang nol untuk menggunakan yang lain

Berharap Anda memiliki usaha yang bagus dan orang lain

Laith Mihyar
sumber
Saya melewatkan "intent.setType (" image / * ");" dan mengirim pengguna langsung ke Foto alih-alih memberi pengguna kesempatan untuk pergi ke Galeri yang tidak mengizinkan pemilihan multi-foto. Tidak yakin apakah karena itu, getData () saya tidak pernah mengembalikan nol, jadi saya akhirnya menggunakan getClipData secara eksklusif untuk pemilihan gambar tunggal dan ganda.
Johnny Wu
1
cukup gunakan bagian data.getClipData () sudah cukup, tidak perlu memeriksa data.getData ()
truongnm
&& null! = data ??
Odaym
8
Uri uri = content: //com.android.providers.media.documents/document/image%3A772 uri memiliki data tetapi cursor.getString mengembalikan null kepada saya imageEncoded = cursor.getString (columnIndex);
Muhammad Zubair Ashraf
2
Itu berguna, tetapi saya harus melengkapi dengan fungsi berikut untuk getPath: stackoverflow.com/a/20559175/6141959
Geynen
31

Banyak dari jawaban ini memiliki kesamaan tetapi semuanya kehilangan bagian terpenting yang ada onActivityResult, periksa apakah data.getClipDatanol sebelum memeriksadata.getData

Kode untuk memanggil pemilih 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

Kode untuk memilih semua gambar:

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

Perhatikan bahwa pemilih Android menyediakan Foto dan Galeri di beberapa perangkat. Foto memungkinkan beberapa gambar dipilih. Galeri mengizinkan hanya satu per satu.

Mira_Cole
sumber
apa itu getClipData ()? bukankah data.getData cukup?
adi
1
Di beberapa perangkat Samsung, hasilnya akan berbeda dengan perangkat non-Samsung. Jika pengguna memilih banyak file, getData()terkadang TIDAK null tetapi hanya memiliki satu Uri. Jika Anda ingin menangani saat pengguna memilih banyak file, periksa getClipData()sebelumnya getData()- jika data klip tidak null, pengguna mungkin telah memilih beberapa gambar. Menangani getClipData sebelum getData, tetapi menangani kedua kasus itu penting untuk mendukung perangkat yang berbeda sambil tetap mengizinkan beberapa Uris.
Mira_Cole
@Mira_Code Bagaimana cara mengatur gambar yang dipilih ke tampilan gambar yang berbeda.
Hasnain Ghias
20

Saya harap jawaban ini tidak terlambat. Karena widget galeri tidak mendukung beberapa pilihan secara default, tetapi Anda bisa menyesuaikan tampilan kisi yang menerima maksud multiselect Anda. Opsi lainnya adalah memperluas tampilan galeri dan menambahkan kode Anda sendiri untuk memungkinkan beberapa pilihan.
Ini adalah perpustakaan sederhana yang dapat melakukannya: https://github.com/luminousman/MultipleImagePick

Pembaruan :
Dari komentar @ ilsy, CustomGalleryActivity dalam penggunaan perpustakaan ini manageQuery, yang sudah usang, jadi harus diubah menjadi getContentResolver().query()dan cursor.close()menyukai jawaban ini

R4j
sumber
@ R4j Ya dan saya menulis tentang itu: perpustakaan tidak siap digunakan dalam proyek. Perlu banyak pembaruan untuk mulai menggunakannya. Dan tentang pembaruan Anda: jangan gunakan getContentResolver().query()di thread UI. Baca tentang Loader dan Support Library.
mbelsky
.cacheOnDisc()juga usang jadi gantilah .cacheOnDisc(true)dengan boolean param
Pratik Butani
5

Inisialisasi contoh:

private String imagePath;
private List<String> imagePathList;

Dalam onActivityResult Anda harus menulis ini, blok If-else 2. Satu untuk gambar tunggal dan satu lagi untuk banyak gambar.

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

Bagian terpenting, Dapatkan Jalur Gambar dari 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();
    }
}

Semoga ini bisa membantu Anda.

Hasib Akter
sumber
1

Saya mendapat null dari Cursor. Kemudian ditemukan solusi untuk mengubahnya Urimenjadi Bitmapyang berfungsi dengan sempurna.

Inilah solusi yang berhasil untuk saya:

@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
sumber
0

Hai, kode di bawah ini berfungsi dengan baik.

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

Anda ingin klarifikasi lebih lanjut. http://mylearnandroid.blogspot.in/2014/02/multiple-choose-custom-gallery.html

Ramesh Thangaraj
sumber
1
jika berhasil, tidak apa-apa. Ada baiknya untuk menunjukkan kode yang tidak digunakan lagi, tetapi selama Anda menggunakannya tanpa masalah, tidak masalah untuk menggunakannya. Penting untuk mengetahui mengapa ini tidak digunakan lagi, apakah itu masalah keamanan, kode yang lebih baru lebih efisien, dll. Tetapi karena aplikasi Android yang kompatibel ke depan, kode yang tidak digunakan lagi akan tetap berfungsi di masa mendatang.
JStephen
0

Saya juga memiliki masalah yang sama. Saya juga ingin agar pengguna dapat mengambil foto dengan mudah sambil mengambil foto dari galeri. Tidak dapat menemukan cara asli untuk melakukan ini, oleh karena itu saya memutuskan untuk membuat proyek sumber terbuka. Ini seperti MultipleImagePick tetapi hanya cara yang lebih baik untuk mengimplementasikannya.

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
sumber
0

Coba IntentChooser yang satu ini . Cukup tambahkan beberapa baris kode, saya melakukan sisanya untuk Anda.

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

NB: seperti yang disebutkan pada jawaban di atas, EXTRA_ALLOW_MULTIPLE hanya tersedia untuk API> = 18. Dan beberapa aplikasi galeri tidak membuat fitur ini tersedia (Foto dan Dokumen Google ( com.android.documentsui) berfungsi.

Tuan Chau
sumber
Tidak membiarkan saya memilih beberapa gambar meskipun ditambahkanintent.putExtra(Intent.EXTRA_ALLOW_MULTIPLE, true);
Scorpion