从Android图库中选择多个图像


114

所以基本上我想要实现的是Gallery在Android中打开,然后让用户选择multiple images。现在,这个问题已被频繁问到,但我对答案不满意。主要是因为我在IDE的de docs中发现了一些有趣的东西(我稍后会再介绍),因此我不想使用自定义适配器,而只想使用普通适配器。

现在,我选择一张图片的代码是:

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。现在,这是我要考虑的最后一个选择,因为恕我直言,这不是我要搜索的内容,因为我必须自己设置样式,为什么您根本无法在香草廊中选择多个图像?

现在必须有一个选择。现在,我发现有趣的事情是:
我在的docs描述中找到了它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。唯一的问题是图库窗口小部件不允许多项选择。在这种情况下,单击任何图像将完成选择者,您可以通过调用getData返回的意图来获取(单个项目的)URI
Tanweer Alam

Answers:


122

通过Intent.putExtra()方法在意图上设置EXTRA_ALLOW_MULTIPLE选项:

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

intent.putExtra(Intent.EXTRA_ALLOW_MULTIPLE,true); 使用模拟器,不支持多项选择。
qinmiao 2014年

11
其选择多重图像。但是如何从Activity结果中获取图片网址?
约翰

4
这将启动图像选择器,并允许我选择多个图像,但是我不知道如何在onActivityResult中获取网址。
汤姆·金凯德

5
您可以在结果中获得网址Intent.getClipData。它具有ClipData Item的数组。
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中,然后将它们存储在列表中

因此,您必须检查哪个为空才能使用其他

希望你能尝试和他人


我跳过了“ intent.setType(” image / *“);” 它将用户直接发送到照片,而不是给用户机会去不允许多图片选择的画廊。不知道是否是因为这个原因,我的getData()永远不会返回null,所以我最终将getClipData专门用于单个和多个图像选择。
约翰尼·吴

1
只需使用零件data.getClipData()就足够了,无需检查data.getData()
truongnm

&& null!=数据??
Odaym '15

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为nulldata.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,而只有一个 Uri。如果你想处理当用户选择多个文件,检查getClipData()之前getData()-如果剪辑数据不为空,则用户可以选择多个图像。在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()也已弃用,因此将其更改为.cacheOnDisc(true)boolean param
Pratik Butani 2015年

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

最重要的部分,从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。然后找到了将转换UriBitmap完美。

这是适合我的解决方案:

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

PS:如上面的答案所述,EXTRA_ALLOW_MULTIPLE仅适用于API> =18。并且某些图库应用程序无法使用此功能(Google照片和文档(com.android.documentsui)起作用。


即使添加也不让我选择多个图像intent.putExtra(Intent.EXTRA_ALLOW_MULTIPLE, true);
Scorpion
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.