Виберіть кілька зображень з андроїд галереї


114

Тому в основному те, що я намагаюся досягти, - це відкрити Galleryв Android і дати користувачеві вибір multiple images. Зараз це питання задають часто, але я не задоволений відповідями. Головним чином, тому, що я знайшов щось цікаве в de docs у своєму IDE (я повернусь до цього пізніше), і тому я не хочу використовувати спеціальний адаптер, а лише ванільний.

Тепер мій код вибору одного зображення:

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

Тепер люди на SO та інших веб-сайтах скажуть вам, що у вас є два варіанти:

1) Не використовуйте, ACTION_GET_CONTENTа ACTION_SEND_MULTIPLEнатомість.
Цей не працює. Цей відповідає документам для sendingфайлів, а не, retrievingі саме це робить. Під час використання ACTION_SEND_MULTIPLE у мене на пристрої відкрилося вікно, де мені потрібно вибрати програму, на яку потрібно надсилати свої дані. Це не те, чого я хочу, тому мені цікаво, як люди домоглися цього рішення? .. Чи щось я сумую?

2) Впровадити custom Gallery. Тепер це мій останній варіант, який я буду розглядати, тому що імхо це не те, що я шукаю, тому що я мушу сам його стилювати І чому чорт ви просто не можете вибрати кілька зображень у ванільній галереї?

Має бути варіант для цього. Тепер цікаве, що я знайшов, це таке:
я знайшов це в описі документів ACTION_GET_CONTENT.

Якщо абонент може обробляти декілька повернених елементів (користувач, що здійснює багаторазовий вибір), він може вказати EXTRA_ALLOW_MULTIPLE для позначення цього.

Це досить цікаво. Тут вони посилаються на випадок використання, коли користувач може вибрати кілька елементів?

Пізніше в документах кажуть:

Ви можете використовувати EXTRA_ALLOW_MULTIPLE, щоб дозволити користувачеві вибирати кілька елементів.

Так це досить очевидно, правда? Це те, що мені потрібно. Але моє наступне питання: Де я можу це поставити EXTRA_ALLOW_MULTIPLE? Сумно в тому, що я не можу знайти це не там, де в керівництві developers.android, а також це не визначено як константа в класі INTENT.

Хтось може мені допомогти у цьому EXTRA_ALLOW_MULTIPLE?




1
@KyleShank рішення працювало на мене. Налаштування EXTRA_ALLOW_MULTIPLEдозволяє вибрати декілька елементів. Отримайте URI, зателефонувавши getClipData()на повернутий намір у onActivityResult. Єдина проблема полягає в тому, що віджет галереї не дозволить отримати багаторазовий вибір. У такому випадку натискання будь-якого зображення завершить вибір, і ви зможете отримати URI (одного елемента), зателефонувавши getDataпри поверненому намірі
Tanweer Alam

Відповіді:


122

Параметр EXTRA_ALLOW_MULTIPLE встановлюється за допомогою методу Intent.putExtra ():

intent.putExtra(Intent.EXTRA_ALLOW_MULTIPLE, true);

Ваш код вище повинен виглядати так:

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

Примітка. EXTRA_ALLOW_MULTIPLEЦя опція доступна лише в Android API 18 і новіших версій.


Я це знаю, але, як я згадую у своїй відповіді: "Сумно в тому, що я не можу знайти це не там, де в керівництві developers.android, а також це не визначено як константа в класі INTENT". Мій IDE не розпізнає наміри.EXTRA_ALLOW_MULTIPLE. У мене встановлений API рівня 18. Мій IDE говорить: "EXTRA_ALLOW_MULTIPLE неможливо вирішити або це не поле"
Dion Segijn

intent.putExtra (Intent.EXTRA_ALLOW_MULTIPLE, правда); використовувати емулятор, не підтримуйте багаторазовий вибір.
qinmiao

11
Її вибір декількох зображень. але як отримати URL-адресу зображення за результатами діяльності ????
Джон

4
Це запускає програму вибору зображень і дозволяє мені вибирати кілька зображень, але я не знаю, як отримати URL-адреси в onActivityResult.
Том Кінкейд

5
Ви можете отримати URL-адреси в результаті Intent.getClipData. Він має масив елемента ClipData.
Там Хуйнх

71

Визначте ці змінні у класі:

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

Припустимо, що onClick на кнопці має відкрити галерею для вибору зображень

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

Тоді вам слід перекрити метод 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);
}

Зверніть увагу, що галерея не дає вам можливості вибирати багато зображень, тому ми тут відкриваємо всі студії зображень, щоб ви могли вибрати з них багато зображень. і не забудьте додати дозволи до свого маніфесту

ДУЖЕ ВАЖЛИВО: getData (); щоб отримати одне єдине зображення, і я зберігав його тут у imageEncoded String, якщо користувач вибирає кілька зображень, то вони повинні зберігатися у списку

Отже, ви повинні перевірити, що є нульовим для використання іншого

Бажаю вам приємно постаратися і іншим


Я пропустив "intent.setType (" image / * ");" і він надсилає користувачів безпосередньо до Photo, а не надає користувачеві можливість перейти до Галереї, яка не дозволяє вибирати кілька зображень. Не впевнений, що через це, мій getData () ніколи не повертається до нуля, тому я в кінцевому підсумку використовую getClipData виключно для вибору одного та декількох зображень.
Джонні Ву

1
просто використовувати частину data.getClipData () достатньо, не потрібно перевіряти data.getData ()
truongnm

&& null! = дані ??
Одайм

8
Uri uri = content: //com.android.providers.media.documents/document/image%3A772 uri має дані, але cursor.getString повертає мені null imageEncoded = cursor.getString (columnIndex);
Мухаммад Зубайр Ашраф

2
Це було корисно, але я повинен був доповнити з цими функціями для GetPath: stackoverflow.com/a/20559175/6141959
Geynen

30

Багато з цих відповідей мають схожість, але у всіх пропущена найважливіша частина, яка є в ній onActivityResult, перед перевіркою перевірте, чи data.getClipDataнемаєdata.getData

Код для вибору вибору файлу:

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

Код для отримання всіх обраних зображень:

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

Зауважте, що на деяких пристроях у вибору Android є фотографії та галерея. Фотографії дозволяє вибирати кілька зображень. Галерея дозволяє лише по одному.


що таке getClipData ()? Чи недостатньо даних.getData?
adi

1
У деяких пристроях Samsung результати будуть іншими, ніж у пристроїв, що не належать Samsung. Якщо користувач вибирає кілька файлів, getData()іноді НЕ буде нульовим, але матиме лише один Uri. Якщо ви хочете обробити , коли користувач вибирає кілька файлів, перевірте , getClipData()перш ніж getData()- якщо кліп даних не дорівнює нулю, то користувач може бути вибрано декілька зображень. Поводження з getClipData перед getData, але обробка обох випадків важлива для підтримки різних пристроїв, одночасно дозволяючи мати кілька Uris.
Mira_Cole

@Mira_Code Як можна встановити вибрані зображення для різних переглядів зображень.
Hasnain Ghias

20

Я сподіваюся, що ця відповідь не пізно. Оскільки віджет галереї не підтримує багаторазовий вибір за замовчуванням, але ви можете налаштувати перегляд сітки, який прийняв ваш багатоцільовий намір. Інший варіант - розширити подання галереї та додати власний код, щоб дозволити багаторазовий вибір.
Це проста бібліотека може це зробити: https://github.com/luminousman/MultipleImagePick

Оновлення :
з коментаря @ ilsy, CustomGalleryActivity у цій бібліотеці використовується manageQuery, яка застаріла, тому її слід змінити на цю відповідьgetContentResolver().query() і cursor.close()сподобатися їй


@ R4j Так, і я писав про це: бібліотека не готова до використання в проектах. Потрібно багато оновлень, щоб почати його використовувати. А щодо оновлення: не використовуйте getContentResolver().query()в потоці інтерфейсу користувача. Читайте про Бібліотеку навантажувачів та підтримки.
mbelsky

.cacheOnDisc()також застаріло, тож змініть його на .cacheOnDisc(true)булевий парам
Пратік Бутані

5

Ініціалізувати примірник:

private String imagePath;
private List<String> imagePathList;

У програмі onActivityResult потрібно записати цей блок If-else 2. Один для одного зображення та інший для декількох зображень.

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

Найважливіша частина - Отримати Зображення Шлях від урі :

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

Сподіваюся, що це може вам допомогти.


1

Я отримав нуль від Cursor. Тоді знайшли рішення для перетворення Uriв, Bitmapщо працює ідеально.

Ось рішення, яке працює для мене:

@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

Привіт нижче код працює нормально.

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

Ви хочете отримати більше роз'яснень. http://mylearnandroid.blogspot.in/2014/02/multiple-choose-custom-gallery.html


1
якщо це працює, це добре. Добре вказати на застарілий код, але поки ви без проблем користуєтесь ним штрафом у використанні. Важливо знати, чому його застарілий, чи це проблеми із безпекою, новіший код є більш ефективним і т. Д. Але оскільки програми Android переносять сумісний застарілий код, він все ще працюватиме в майбутньому.
JStephen

0

У мене теж було таке ж питання. Мені також хотілося, щоб користувачі могли легко фотографувати, вибираючи фотографії з галереї. Не вдалося знайти рідний спосіб зробити це, тому я вирішив зробити проект із відкритим кодом. Це дуже схоже на MultipleImagePick, але просто кращий спосіб його реалізації.

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

Спробуйте цей IntentChooser . Просто додайте кілька рядків коду, решту я зробив за вас.

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: як зазначено у відповідях вище, EXTRA_ALLOW_MULTIPLE доступний лише для API> = 18. А деякі додатки галереї не надають цієї функції (Google Photos and Documents ( com.android.documentsui) працюють.


Не дозволяючи мені вибирати кілька зображень, хоча вони доданіintent.putExtra(Intent.EXTRA_ALLOW_MULTIPLE, true);
Скорпіон
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.