【问题标题】:Select multiple images from android gallery从 android 图库中选择多张图片
【发布时间】:2013-11-04 08:01:04
【问题描述】:

所以基本上我想要实现的是在 Android 中打开 Gallery 并让用户选择 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 和其他网站上的人们会告诉您,您有 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吗?

【问题讨论】:

  • @KyleShank 解决方案对我有用。设置EXTRA_ALLOW_MULTIPLE 让您可以选择多个项目。通过在 onActivityResult 中返回的意图调用 getClipData() 来获取 URI。唯一的问题是图库小部件不允许多选。在这种情况下,单击任何图像将完成选择器,您可以通过在返回的意图上调用 getData 来获取(单个项目的)URI

标签: android image-gallery


【解决方案1】:

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

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 及更高版本。

【讨论】:

  • 我知道这一点,但正如我在回答中提到的那样:“可悲的是,我在 developer.android 指南中找不到这个,而且在意图课。”我的 IDE 无法识别 Intent.EXTRA_ALLOW_MULTIPLE。我安装了 API 级别 18。我的 IDE 说:“EXTRA_ALLOW_MULTIPLE 无法解析或不是字段”
  • intent.putExtra(Intent.EXTRA_ALLOW_MULTIPLE, true);使用模拟器,不支持多选。
  • 它选择了多个图像。但是如何从 Activity 结果中获取图像 url????
  • 这会启动图像选择器并允许我选择多个图像,但我不知道如何获取 onActivityResult 中的 url。
  • 你可以在结果Intent.getClipData中得到url。它有 ClipData Item 的数组。
【解决方案2】:

在类中定义这些变量:

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

请注意: 图库没有让您选择多张图像的能力,因此我们在这里打开所有图像工作室,您可以从中选择多张图像。 并且不要忘记将权限添加到您的清单中

非常重要: 获取数据();获取一张图片,我将其存储在 imageEncoded String 中 如果用户选择多张图片,那么 它们应该存储在列表中

所以你必须检查哪个为空才能使用另一个

希望你有一个很好的尝试和其他人

【讨论】:

  • 我跳过了"intent.setType("image/*");"它直接将用户发送到照片,而不是让用户有机会去不允许多图片选择的画廊。不知道是不是因为这个,我的 getData() 永远不会返回 null,所以我最终将 getClipData 专门用于单张和多张图像选择。
  • 只用部分data.getClipData()就够了,不用检查data.getData()
  • && null != data ??
  • Uri uri = content://com.android.providers.media.documents/document/image%3A772 uri 有数据但 cursor.getString 向我返回 null imageEncoded = cursor.getString(columnIndex);
  • 这很有用,但我必须为 getPath 补充这些功能:stackoverflow.com/a/20559175/6141959
【解决方案3】:

很多这些答案有相似之处,但都缺少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() ? data.getData 还不够吗?
  • 在某些三星设备中,结果会与非三星设备不同。如果用户选择多个文件,getData() 有时不会为空,但只有 一个 Uri。如果要处理用户选择多个文件时,请在getData()之前检查getClipData()——如果剪辑数据不为空,则用户可能选择了多个图像。在 getData 之前处理 getClipData 但同时处理 both 情况对于支持不同设备同时仍允许多个 Uris 很重要。
  • @Mira_Code 如何将所选图像设置为不同的图像视图。
【解决方案4】:

我希望这个答案不会迟到。因为画廊小部件默认不支持多选,但您可以自定义接受多选意图的网格视图。另一种选择是扩展图库视图并添加您自己的代码以允许多项选择。
这是可以做到的简单库:https://github.com/luminousman/MultipleImagePick

更新
从@ilsy 的评论来看,这个库中的CustomGalleryActivity 使用manageQuery,它已被弃用,因此应将其更改为getContentResolver().query()cursor.close(),如this answer

【讨论】:

  • @R4j 是的,我写过:该库尚未准备好在项目中使用。需要许多更新才能开始使用它。关于您的更新:不要在 UI 线程中使用 getContentResolver().query()。阅读有关加载程序和支持库的信息。
  • .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);
    }
}

最重要的部分,从 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();
    }
}

希望对你有帮助。

【讨论】:

    【解决方案6】:

    这适用于多个图像选择。还在 Google 照片的 API 29,30 中进行了测试。

    private static final int PICK_IMAGE = 2;
    
    Intent intent = new Intent(Intent.ACTION_PICK, 
        android.provider.MediaStore.Images.Media.EXTERNAL_CONTENT_URI);
                    intent.putExtra(Intent.EXTRA_ALLOW_MULTIPLE, true);
                    startActivityForResult(Intent.createChooser(intent, "Select 
        images"),PICK_IMAGE);
    
    public void onActivityResult(int requestCode, int resultCode, Intent data) {
        super.onActivityResult(requestCode, resultCode, data);
    if (requestCode == PICK_IMAGE && resultCode == RESULT_OK) {
            if(data.getClipData() != null) {
                int count = data.getClipData().getItemCount();
                for(int i = 0; i < count; i++) {
                Uri imageUri = data.getClipData().getItemAt(i).getUri();
                //do what do you want to do
                }
            }
            else if(data.getData() != null) {
                Uri selectedImageUri = data.getData();
                //do what do you want to do
            }
    }
    

    【讨论】:

      【解决方案7】:

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

      【讨论】:

        【解决方案8】:

        您好,下面的代码工作正常。

         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

        【讨论】:

        • 如果它可以正常工作。指出不推荐使用的代码很好,但只要您使用它没有任何问题,它就可以使用。重要的是要知道它被弃用的原因,是否是安全问题,新代码更高效等等。但由于 Android 应用程序是向前兼容的,弃用的代码在未来仍然可以工作。
        【解决方案9】:

        我也有同样的问题。我还希望用户可以在从图库中挑选照片时轻松拍照。找不到这样做的本机方式,因此我决定制作一个开源项目。它很像 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;
            }
        }
        

        【讨论】:

          【解决方案10】:

          试试这个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);也不允许我选择多个图像
          【解决方案11】:
               // for choosing multiple images declare variables
               int PICK_IMAGE_MULTIPLE = 2;
               String realImagePath;
          
               // After requesting FILE READ PERMISSION may be on button click
               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 Images"), PICK_IMAGE_MULTIPLE);
          
          
              public void onActivityResult(int requestCode, int resultCode, Intent data) {
                  super.onActivityResult(requestCode, resultCode, data);// FOR CHOOSING MULTIPLE IMAGES
                  try {
                      // When an Image is picked
                      if (requestCode == PICK_IMAGE_MULTIPLE && resultCode == RESULT_OK
                              && null != data) {
                          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();
                                  realImagePath = getPath(this, imageUri);
                                  //do something with the image (save it to some directory or whatever you need to do with it here)
                                  Log.e("ImagePath", "onActivityResult: " + realImagePath);
                              }
                          } else if (data.getData() != null) {
                              Uri imageUri = data.getData();
                              realImagePath = getPath(this, imageUri);
                              //do something with the image (save it to some directory or whatever you need to do with it here)
                              Log.e("ImagePath", "onActivityResult: " + realImagePath);
                          }
                      }
                  } catch (Exception e) {
                      Toast.makeText(this, "Something went wrong", Toast.LENGTH_LONG)
                              .show();
                  }
              }
               
          
              public static String getPath(final Context context, final Uri uri) {
                  // DocumentProvider
                  if (DocumentsContract.isDocumentUri(context, uri)) {
                      // ExternalStorageProvider
                      if (isExternalStorageDocument(uri)) {
                          final String docId = DocumentsContract.getDocumentId(uri);
                          final String[] split = docId.split(":");
                          final String type = split[0];
              
                          if ("primary".equalsIgnoreCase(type)) {
                              return Environment.getExternalStorageDirectory() + "/" + split[1];
                          }
              
                          // TODO handle non-primary volumes
                      }
                      // DownloadsProvider
                      else if (isDownloadsDocument(uri)) {
              
                          final String id = DocumentsContract.getDocumentId(uri);
                          final Uri contentUri = ContentUris.withAppendedId(
                                  Uri.parse("content://downloads/public_downloads"), Long.parseLong(id));
              
                          return getDataColumn(context, contentUri, null, null);
                      }
                      // MediaProvider
                      else if (isMediaDocument(uri)) {
                          final String docId = DocumentsContract.getDocumentId(uri);
                          final String[] split = docId.split(":");
                          final String type = split[0];
              
                          Uri contentUri = null;
                          if ("image".equals(type)) {
                              contentUri = MediaStore.Images.Media.EXTERNAL_CONTENT_URI;
                          } else if ("video".equals(type)) {
                              contentUri = MediaStore.Video.Media.EXTERNAL_CONTENT_URI;
                          } else if ("audio".equals(type)) {
                              contentUri = MediaStore.Audio.Media.EXTERNAL_CONTENT_URI;
                          }
              
                          final String selection = "_id=?";
                          final String[] selectionArgs = new String[]{
                                  split[1]
                          };
              
                          return getDataColumn(context, contentUri, selection, selectionArgs);
                      }
                  }
                  // MediaStore (and general)
                  else if ("content".equalsIgnoreCase(uri.getScheme())) {
                      return getDataColumn(context, uri, null, null);
                  }
                  // File
                  else if ("file".equalsIgnoreCase(uri.getScheme())) {
                      return uri.getPath();
                  }
              
                  return null;
              }
              
              /**
               * Get the value of the data column for this Uri. This is useful for
               * MediaStore Uris, and other file-based ContentProviders.
               *
               * @param context       The context.
               * @param uri           The Uri to query.
               * @param selection     (Optional) Filter used in the query.
               * @param selectionArgs (Optional) Selection arguments used in the query.
               * @return The value of the _data column, which is typically a file path.
               */
              public static String getDataColumn(Context context, Uri uri, String selection,
                                                 String[] selectionArgs) {
              
                  Cursor cursor = null;
                  final String column = "_data";
                  final String[] projection = {
                          column
                  };
              
                  try {
                      cursor = context.getContentResolver().query(uri, projection, selection, selectionArgs,
                              null);
                      if (cursor != null && cursor.moveToFirst()) {
                          final int column_index = cursor.getColumnIndexOrThrow(column);
                          return cursor.getString(column_index);
                      }
                  } finally {
                      if (cursor != null)
                          cursor.close();
                  }
                  return null;
              }
              
              
              /**
               * @param uri The Uri to check.
               * @return Whether the Uri authority is ExternalStorageProvider.
               */
              public static boolean isExternalStorageDocument(Uri uri) {
                  return "com.android.externalstorage.documents".equals(uri.getAuthority());
              }
              
              /**
               * @param uri The Uri to check.
               * @return Whether the Uri authority is DownloadsProvider.
               */
              public static boolean isDownloadsDocument(Uri uri) {
                  return "com.android.providers.downloads.documents".equals(uri.getAuthority());
              }
              
              /**
               * @param uri The Uri to check.
               * @return Whether the Uri authority is MediaProvider.
               */
              public static boolean isMediaDocument(Uri uri) {
                  return "com.android.providers.media.documents".equals(uri.getAuthority());
              }
          

          这对我来说非常适合学分:Get real path from URI, Android KitKat new storage access framework

          【讨论】:

            【解决方案12】:

            用于从图库中选择多张图片

            i.putExtra(Intent.EXTRA_ALLOW_MULTIPLE,true);
            

            使用相机选项上传多张图片的终极解决方案,也适用于 Android Lollipop 到 Android 10、SDK 30。

            private static final int FILECHOOSER_RESULTCODE   = 1;
            private ValueCallback<Uri> mUploadMessage;
            private ValueCallback<Uri[]> mUploadMessages;
            private Uri mCapturedImageURI = null;
            

            将此添加到 MainActivity 的 OnCreate

            mWebView.setWebChromeClient(new WebChromeClient() {
            
                        // openFileChooser for Android 3.0+
            
                        public void openFileChooser(ValueCallback<Uri> uploadMsg, String acceptType){
                            mUploadMessage = uploadMsg;
                            openImageChooser();
                        }
            
                        // For Lollipop 5.0+ Devices
            
                        public boolean onShowFileChooser(WebView mWebView, ValueCallback<Uri[]> filePathCallback, WebChromeClient.FileChooserParams fileChooserParams) {
                            mUploadMessages = filePathCallback;
                            openImageChooser();
                            return true;
                        }
            
                        // openFileChooser for Android < 3.0
            
                        public void openFileChooser(ValueCallback<Uri> uploadMsg){
                            openFileChooser(uploadMsg, "");
                        }
            
                        //openFileChooser for other Android versions
            
                        public void openFileChooser(ValueCallback<Uri> uploadMsg, String acceptType, String capture) {
                            openFileChooser(uploadMsg, acceptType);
                        }
            
            private void openImageChooser() {
                try {
                    File imageStorageDir = new File(Environment.getExternalStoragePublicDirectory(Environment.DIRECTORY_PICTURES), "FolderName");
                    if (!imageStorageDir.exists()) {
                        imageStorageDir.mkdirs();
                    }
                    File file = new File(imageStorageDir + File.separator + "IMG_" + String.valueOf(System.currentTimeMillis()) + ".jpg");
                    mCapturedImageURI = Uri.fromFile(file);
            
                    final Intent captureIntent = new Intent(MediaStore.ACTION_IMAGE_CAPTURE);
                    captureIntent.putExtra(MediaStore.EXTRA_OUTPUT, mCapturedImageURI);
            
                    Intent i = new Intent(Intent.ACTION_GET_CONTENT);
                    i.addCategory(Intent.CATEGORY_OPENABLE);
                    i.setType("image/*");
                    i.putExtra(Intent.EXTRA_ALLOW_MULTIPLE,true);
                    Intent chooserIntent = Intent.createChooser(i, "Image Chooser");
                    chooserIntent.putExtra(Intent.EXTRA_INITIAL_INTENTS, new Parcelable[]{captureIntent});
            
                    startActivityForResult(chooserIntent, FILECHOOSER_RESULTCODE);
                } catch (Exception e) {
                    e.printStackTrace();
                }
            }
            
                    });
            

            onActivityResult

            public void onActivityResult(final int requestCode, final int resultCode, final Intent data) {
            
            
                    super.onActivityResult(requestCode, resultCode, data);
                    if (requestCode == FILECHOOSER_RESULTCODE) {
            
                        if (null == mUploadMessage && null == mUploadMessages) {
                            return;
                        }
            
                        if (null != mUploadMessage) {
                            handleUploadMessage(requestCode, resultCode, data);
            
                        } else if (mUploadMessages != null) {
                            handleUploadMessages(requestCode, resultCode, data);
                        }
                    }
            
            
            
            
            
                }
            
                private void handleUploadMessage(final int requestCode, final int resultCode, final Intent data) {
                    Uri result = null;
                    try {
                        if (resultCode != RESULT_OK) {
                            result = null;
                        } else {
                            // retrieve from the private variable if the intent is null
            
                            result = data == null ? mCapturedImageURI : data.getData();
                        }
                    } catch (Exception e) {
                        e.printStackTrace();
                    }
                    mUploadMessage.onReceiveValue(result);
                    mUploadMessage = null;
            
                    // code for all versions except of Lollipop
                    if (Build.VERSION.SDK_INT < Build.VERSION_CODES.LOLLIPOP) {
            
                            result = null;
            
                            try {
                                if (resultCode != RESULT_OK) {
                                    result = null;
                                } else {
                                    // retrieve from the private variable if the intent is null
                                    result = data == null ? mCapturedImageURI : data.getData();
                                }
                            } catch (Exception e) {
                                Toast.makeText(getApplicationContext(), "activity :" + e, Toast.LENGTH_LONG).show();
                            }
            
                            mUploadMessage.onReceiveValue(result);
                            mUploadMessage = null;
                        }
            
                    } // end of code for all versions except of Lollipop
            
            
            
            
            
            
                private void handleUploadMessages(final int requestCode, final int resultCode, final Intent data) {
                    Uri[] results = null;
                    try {
                        if (resultCode != RESULT_OK) {
                            results = null;
                        } else {
                            if (data != null) {
                                String dataString = data.getDataString();
                                ClipData clipData = data.getClipData();
                                if (clipData != null) {
                                    results = new Uri[clipData.getItemCount()];
                                    for (int i = 0; i < clipData.getItemCount(); i++) {
                                        ClipData.Item item = clipData.getItemAt(i);
                                        results[i] = item.getUri();
                                    }
                                }
                                if (dataString != null) {
                                    results = new Uri[]{Uri.parse(dataString)};
                                }
                            } else {
                                results = new Uri[]{mCapturedImageURI};
                            }
                        }
                    } catch (Exception e) {
                        e.printStackTrace();
                    }
                    mUploadMessages.onReceiveValue(results);
                    mUploadMessages = null;
                }
            

            【讨论】:

              【解决方案13】:

              对于多张图片选择和选择限制限制功能,请使用 chintan369/MultiImagePicker 库,它是 2021 年最新的并且也支持 Android 11。它有据可查,并且在youtube 上解释了演示以供使用。在项目中添加非常简单,调用库进行图片选择和获取所选图片的结果为Uri list,您也可以请求结果列表为绝对文件路径列表

              【讨论】:

                【解决方案14】:

                如下定义getContent;

                val getContent = 
                registerForActivityResult(ActivityResultContracts.GetMultipleContents()) 
                { uriList ->
                    // todo
                }
                

                在您授予相关权限后运行以下代码

                getContent.launch("images/*")
                

                【讨论】:

                  【解决方案15】:

                  2022 - Android Jetpack Compose 方式

                  用于使用 Android Jetpack Compose 在图库中选择多个图像。

                  val launcherMultipleImages = rememberLauncherForActivityResult(
                      contract = ActivityResultContracts.GetMultipleContents(),
                  ) { uriList: List<Uri> ->
                      // TODO
                  }
                  

                  然后使用launcherMultipleImages.launch("image/*") 开始图像选择。

                  例如:

                  Button(onClick = { launcherMultipleImages.launch("image/*") }) {
                      Text(text = "Select images")
                  }
                  

                  【讨论】:

                    猜你喜欢
                    • 1970-01-01
                    • 1970-01-01
                    • 2012-03-11
                    • 1970-01-01
                    • 2018-10-27
                    • 1970-01-01
                    相关资源
                    最近更新 更多