Androidギャラリーから複数の画像を選択する


114

したがって、基本的に私が達成しようとしているのはGallery、Androidでを開いて、ユーザーに選択させることmultiple imagesです。今、この質問は頻繁に尋ねられていますが、私は答えに満足していません。主に私は私のIDEのde docsで何か面白いものを見つけたので(後でこれに戻ります)、それによってカスタムアダプターを使用したくはなく、通常のアダプターだけを使用します。

1つの画像を選択するためのコードは次のとおりです。

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

People on SOや他のWebサイトでは、2つのオプションがあることがわかります。

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。唯一の問題は、ギャラリーウィジェットが複数選択を許可しないことです。その場合、任意の画像をクリックするとチューザーが終了し、getData返されたインテントを呼び出すことで(単一のアイテムの)URIを取得できます
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がIntent.EXTRA_ALLOW_MULTIPLEを認識しません。APIレベル18がインストールされています。私のIDEは言う:「EXTRA_ALLOW_MULTIPLEは解決できないか、フィールドではありません」
Dion Segijn

intent.putExtra(Intent.EXTRA_ALLOW_MULTIPLE、true); エミュレータを使用し、複数選択をサポートしないでください。
qinmiao 2014年

11
その複数の画像を選択します。しかし、アクティビティの結果から画像のURLを取得する方法????
ジョン

4
これにより画像ピッカーが起動し、複数の画像を選択できますが、onActivityResultでURLを取得する方法がわかりません。
トムキンケイド2015

5
結果のURLを取得できますIntent.getClipData。ClipDataアイテムの配列があります。
タムHuynh '15

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(); 1つの単一の画像を取得し、ここでimageEncoded Stringに保存しました。ユーザーが複数の画像を選択した場合は、それらをリストに保存する必要があります。

したがって、他を使用するにはどちらがnullかを確認する必要があります

あなたが良い試みをして他の人に願っています


「intent.setType( "image / *");」をスキップしました また、複数の写真を選択できないギャラリーにアクセスする機会をユーザーに与える代わりに、ユーザーを写真に直接送信します。それが原因かどうかわからないので、私のgetData()がnullを返すことはありません。そのため、単一および複数の画像選択の両方で排他的にgetClipDataを使用することになりました。
Johnny Wu

1
data.getClipData()の部分を使用するだけで十分です。data.getData()を確認する必要はありません
truongnm

&& null!=データ??
Odaym、2016年

8
Uri uri = content://com.android.providers.media.documents/document/image%3A772 uriにはデータがありますが、cursor.getStringはnullを返しますimageEncoded = cursor.getString(columnIndex);
Muhammad Zubair Ashraf 2016

2
それは便利でしたが、getPathのこれらの関数を補完する必要がありました:stackoverflow.com/a/20559175/6141959
Geynen

30

これらの回答の多くは類似点がありますが、にある最も重要な部分がすべてありません。前に null 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のセレクターには、一部のデバイスで利用できる写真とギャラリーがあります。写真では、複数の画像を選択できます。ギャラリーでは、一度に1つしか許可されません。


getClipData()とは data.getDataは十分ではありませんか?
アナログ・デバイセズ

1
一部のSamsungデバイスでは、結果がSamsung以外のデバイスとは異なります。ユーザーが複数のファイルを選択した場合、getData()nullにならない場合がありますが、URI は1つしかありません。ユーザーが複数のファイルを選択したときに処理する場合は、getClipData()前にチェックしgetData()ます。クリップデータがnullでない場合は、ユーザーが複数の画像を選択した可能性があります。getClipDataをgetDataの前に処理しますが、両方のケースを処理することは、複数のUrisを許可しながら異なるデバイスをサポートするために重要です。
Mira_Cole

@Mira_Code選択した画像を別の画像ビューに設定するにはどうすればよいですか。
Hasnain Ghias

20

この回答が遅れないことを願っています。ギャラリーウィジェットはデフォルトでは複数選択をサポートしていませんが、複数選択インテントを受け入れたグリッドビューをカスタマイズできます。もう1つのオプションは、ギャラリービューを拡張して独自のコードを追加し、複数選択を可能にすることです。
これはそれを行うことができる単純なライブラリです:https : //github.com/luminousman/MultipleImagePick

更新
@ilsyのコメントから、このライブラリのCustomGalleryActivitymanageQueryは非推奨になっているので、この回答に変更してgetContentResolver().query()この回答のcursor.close()ようにする必要があります


@ R4jはい、私はそれについて書きました:ライブラリはプロジェクトで使用する準備ができていません。使い始めるには多くのアップデートが必要です。更新について:getContentResolver().query()UIスレッドでは使用しないでください。ローダーとサポートライブラリについてお読みください。
mbelsky、2015年

.cacheOnDisc()また、非推奨になったので.cacheOnDisc(true)、ブールparamに変更します
Pratik Butani

5

インスタンスを初期化:

private String imagePath;
private List<String> imagePathList;

onActivityResultあなたは場合は、他の2ブロック、これを記述する必要があります。1つは単一の画像用で、もう1つは複数の画像用です。

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

からnullを取得しました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

これを1つの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は18以上のAPIでのみ使用できます。また、一部のギャラリーアプリではこの機能を利用できません(Googleフォトとドキュメント(com.android.documentsui)は機能します)。


追加されても複数の画像を選択できないintent.putExtra(Intent.EXTRA_ALLOW_MULTIPLE, true);
スコーピオン
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.