Android 갤러리에서 여러 이미지 선택


114

그래서 기본적으로 내가 달성하려는 Gallery것은 Android에서을 열고 사용자가 multiple images. 이제이 질문이 자주 제기 되었지만 답변이 만족스럽지 않습니다. 주로 IDE의 de 문서에서 흥미로운 것을 발견했기 때문에 (나중에 다시 설명합니다) 사용자 지정 어댑터를 사용하지 않고 바닐라 어댑터 만 사용하고 싶습니다.

이제 하나의 이미지를 선택하는 코드는 다음과 같습니다.

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통해 여러 항목을 선택할 수 있습니다. getClipData()에서 반환 된 인 텐트를 호출하여 URI를 가져옵니다 onActivityResult. 유일한 문제는 갤러리 위젯이 다중 선택을 허용하지 않는다는 것입니다. 이 경우의 클릭으로 모든 이미지는 choser을 완료하고 당신은 호출하여 (단일 항목) URI를 얻을 수 getData반환 의도에
Tanweer 알람

답변:


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가 Intent.EXTRA_ALLOW_MULTIPLE을 인식하지 못합니다. API 레벨 18이 설치되어 있습니다. 내 IDE는 "EXTRA_ALLOW_MULTIPLE을 확인할 수 없거나 필드가 아닙니다."라고 말합니다.
Dion Segijn 2013

intent.putExtra (Intent.EXTRA_ALLOW_MULTIPLE, true); 에뮬레이터를 사용하고 다중 선택을 지원하지 마십시오.
qinmiao

11
여러 이미지를 선택합니다. 하지만 활동 결과에서 이미지 URL을 얻는 방법 ????
John

4
이렇게하면 이미지 선택기가 시작되고 여러 이미지를 선택할 수 있지만 onActivityResult에서 URL을 가져 오는 방법을 모르겠습니다.
Tom Kincaid

5
결과에서 URL을 얻을 수 있습니다 Intent.getClipData. ClipData 항목의 배열이 있습니다.
Tam Huynh

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에 저장 한 다음 목록에 저장해야합니다.

따라서 다른 것을 사용하려면 어떤 것이 null인지 확인해야합니다.

당신이 좋은 시도를하고 다른 사람들에게 기원합니다


"intent.setType ("image / * ");"을 건너 뛰었습니다. 다중 사진을 선택할 수없는 갤러리로 이동할 수있는 기회를 제공하는 대신 사용자를 직접 사진으로 보냅니다. 그 때문인지 확실하지 않은 경우 내 getData ()는 null을 반환하지 않으므로 단일 및 다중 이미지 선택 모두에 대해 독점적으로 getClipData를 사용하게되었습니다.
Johnny Wu

1
data.getClipData () 부분 만 사용하면 충분하며 data.getData ()를 확인할 필요가 없습니다.
truongnm

&& null! = 데이터 ??
Odaym

8
URI uri = content : //com.android.providers.media.documents/document/image%3A772 uri에 데이터가 있지만 cursor.getString은 나에게 null을 반환합니다. imageEncoded = cursor.getString (columnIndex);
Muhammad Zubair Ashraf

2
유용했지만 getPath에 대해 다음 함수를 보완해야했습니다. stackoverflow.com/a/20559175/6141959
Geynen

30

이 답변의 대부분은 유사점이 있지만 모두에있는 가장 중요한 부분이 누락되어 있습니다 onActivityResult. 확인 하기 전에data.getClipData null 인지 확인하십시오.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 ()는 무엇입니까? data.getData가 충분하지 않습니까?
adi

1
일부 삼성 기기에서는 결과가 삼성 이외의 기기와 다를 수 있습니다. 사용자 선택 여러 파일 경우, getData()종종 null이되지 않습니다 만 것이다 열린 우리당을. 이 때 사용자 선택 처리하려면 여러 개의 파일을 확인 getClipData()하기 전에 getData()클립 데이터가 null가 아닌 경우, 사용자가 여러 개의 이미지를 선택했을 수 있습니다 -. getData 이전에 getClipData를 처리하지만 경우 모두 처리 하는 것은 여러 Uris를 허용하면서 다른 장치를 지원하는 데 중요합니다.
Mira_Cole

@Mira_Code 선택한 이미지를 다른 이미지보기로 설정하려면 어떻게해야합니까?
Hasnain Ghias

20

이 답변이 늦지 않았기를 바랍니다. 갤러리 위젯은 기본적으로 다중 선택을 지원하지 않기 때문에 다중 선택 의도를 허용하는 gridview를 사용자 정의 할 수 있습니다. 다른 옵션은 갤러리보기를 확장하고 여러 항목을 선택할 수 있도록 고유 한 코드를 추가하는 것입니다.
이것이 할 수있는 간단한 라이브러리입니다 : https://github.com/luminousman/MultipleImagePick

업데이트 :
@ ilsy의 주석에서 CustomGalleryActivity 이 라이브러리 사용 manageQuery이 변경되어야하므로, 사용되지 않습니다, getContentResolver().query()그리고 cursor.close()같은 이 답변


@ R4j 예 그리고 저는 그것에 대해 썼습니다 : 라이브러리는 프로젝트에서 사용할 준비가되지 않았습니다. 사용을 시작하려면 많은 업데이트가 필요합니다. 그리고 업데이트에 대해 : getContentResolver().query()UI 스레드에서 사용하지 마십시오 . 로더 및 지원 라이브러리에 대해 읽어보십시오.
mbelsky

.cacheOnDisc()또한 너무로 변경 deprecated 된 .cacheOnDisc(true)부울 PARAM로
Pratik Butani

5

인스턴스 초기화 :

private String imagePath;
private List<String> imagePathList;

에서 onActivityResult를 당신은 IF-다른 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);
    }
}

가장 중요한 부분 은 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();
    }
}

이것이 당신을 도울 수 있기를 바랍니다.


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 2015 년

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

추신 : 위 답변에서 언급했듯이 EXTRA_ALLOW_MULTIPLE은 API> = 18에서만 사용할 수 있습니다. 일부 갤러리 앱에서는이 기능을 사용할 수 없습니다 (Google 포토 및 문서 ( com.android.documentsui) 작동).


내가 여러 이미지에도 불구하고 추가 선택하게되지 않음intent.putExtra(Intent.EXTRA_ALLOW_MULTIPLE, true);
전갈
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.