Android:让用户从图库中选择图片或视频

问题描述 投票:0回答:11

是否可以以这样的方式启动图库,以便同时显示图片和视频?

谢谢

android android-intent mime-types
11个回答
66
投票

从图库中选择音频文件:

//Use MediaStore.Audio.Media.EXTERNAL_CONTENT_URI
Intent intent = new Intent(Intent.ACTION_PICK, MediaStore.Audio.Media.EXTERNAL_CONTENT_URI);

从图库中选择视频文件:

//Use MediaStore.Audio.Media.EXTERNAL_CONTENT_URI
Intent intent = new Intent(Intent.ACTION_PICK, MediaStore.Video.Media.EXTERNAL_CONTENT_URI);

从图库中选择图片:

//Use  MediaStore.Images.Media.EXTERNAL_CONTENT_URI
Intent intent = new Intent(Intent.ACTION_PICK, MediaStore.Images.Media.EXTERNAL_CONTENT_URI);

选择媒体文件或图像:

 Intent intent = new Intent(Intent.ACTION_PICK, MediaStore.Images.Media.EXTERNAL_CONTENT_URI);
intent.setType("image/* video/*");

54
投票

你这样开始画廊:

Intent pickIntent = new Intent(Intent.ACTION_PICK, android.provider.MediaStore.Images.Media.EXTERNAL_CONTENT_URI);
pickIntent.setType("image/* video/*");
startActivityForResult(pickIntent, IMAGE_PICKER_SELECT);

然后在您的

onActivityResult
中,您可以检查是否选择了视频或图像:

public void onActivityResult(int requestCode, int resultCode, Intent data) {

if (resultCode == RESULT_OK) {
    Uri selectedMediaUri = data.getData();
    if (selectedMediaUri.toString().contains("image")) {
        //handle image
    } else  if (selectedMediaUri.toString().contains("video")) {
        //handle video
    }
}

27
投票

(编辑:我不再使用它了,我们回到了“选择图像”和“选择视频”这两个选项。问题出在一些索尼手机上。所以,下面不是 100% 的解决方案,小心! )

这是我用的:

if (Build.VERSION.SDK_INT < 19) {
    Intent intent = new Intent(Intent.ACTION_GET_CONTENT);
    intent.setType("image/* video/*");
    startActivityForResult(Intent.createChooser(intent, getResources().getString(R.string.select_picture)), SELECT_GALLERY);
} else {
    Intent intent = new Intent(Intent.ACTION_OPEN_DOCUMENT);
    intent.addCategory(Intent.CATEGORY_OPENABLE);
    intent.setType("image/*");
    intent.putExtra(Intent.EXTRA_MIME_TYPES, new String[] {"image/*", "video/*"});
    startActivityForResult(intent, SELECT_GALLERY_KITKAT);
}

这里的关键是

intent.putExtra(Intent.EXTRA_MIME_TYPES, new String[] {"image/*", "video/*"});


11
投票
intent.setType("*/*");

这为用户提供了对话框,但至少适用于 ICS。还没有在其他平台上测试过。


7
投票

当需要判断返回的是什么内容时,可以使用内容解析器获取返回内容的MIME类型:

if( data != null) {
    Uri selectedUri = data.getData();   
    String[] columns = { MediaStore.Images.Media.DATA,
                         MediaStore.Images.Media.MIME_TYPE };

    Cursor cursor = getContentResolver().query(selectedUri, columns, null, null, null);
    cursor.moveToFirst();

    int pathColumnIndex     = cursor.getColumnIndex( columns[0] );
    int mimeTypeColumnIndex = cursor.getColumnIndex( columns[1] );

    String contentPath = cursor.getString(pathColumnIndex);
    String mimeType    = cursor.getString(mimeTypeColumnIndex);
    cursor.close();

    if(mimeType.startsWith("image")) {
          //It's an image
    }
    else if(mimeType.startsWith("video")) {
         //It's a video
    }       
}
else {
    // show error or do nothing
}

2
投票

我的 galaxy tab 自带的 CoolIris 可以做到。但是我的 acer betouch 上的 cooliris 不会 :S 在我的里程碑上,您无法通过视频 url 上的选择意图启动图库,但是当您在图像 url 上启动它时,您可以选择一个视频,它也会返回一个视频 url。


2
投票

UPDATE 2021

最终适用于 Android 9 的解决方案。

这段代码只打开图片应用,图片和视频都可以选择。我尝试了一堆不同的组合,这个确切的代码将使它工作。

    libraryIntent.setType("video/*, image/*");
    String[] mimetypes = {"image/*", "video/*"};
    libraryIntent.putExtra(Intent.EXTRA_MIME_TYPES, mimetypes);

2
投票

仍在努力2022年1月

如果这对你有用,那就试试吧,

Intent intent = new Intent(Intent.ACTION_PICK, android.provider
                          .MediaStore.Images.Media.EXTERNAL_CONTENT_URI);
    intent.setType("image/* video/*");
    startActivityForResult(intent,PICK_FILE);

else 对于旧的 SDK 和某些设备尝试下面的,

 Intent intent = new Intent(Intent.ACTION_OPEN_DOCUMENT);
    intent.addCategory(Intent.CATEGORY_OPENABLE);
    intent.setType("image/*");
    intent.putExtra(Intent.EXTRA_MIME_TYPES, new String[] {"image/*", "video/*"});
     startActivityForResult(intent,PICK_FILE);

其中,PICK_FILE是一个变量,

private static final int PICK_FILE = 1;

1
投票

这对我适用于 Android 12 (SDK 32)
从图库中选择多张图片和视频
还有最新的registerForActivityResult

val resultLauncher =
        registerForActivityResult(ActivityResultContracts.StartActivityForResult()) { result ->
            onActivityResult(result)
        }

fun pickMediaFiles() {
        val intent = Intent(Intent.ACTION_GET_CONTENT)
        intent.addCategory(Intent.CATEGORY_OPENABLE)
        intent.type = "image/* video/*"
        intent.putExtra(Intent.EXTRA_ALLOW_MULTIPLE, true);
        intent.putExtra(Intent.EXTRA_MIME_TYPES, arrayOf("image/*", "video/*"))
        resultLauncher.launch(intent)
    }

fun onActivityResult(result: ActivityResult) {
        if (result.resultCode == RESULT_OK && result.data != null) {
            //If selected multiple medias
            if (result.data?.clipData != null) {
                val count: Int =
                    result.data!!.clipData!!.itemCount 
                for (i in 0 until count) {
                    val selectedUri: Uri? = result.data!!.clipData?.getItemAt(i)?.uri
                }
            }
            //If selected single media
            else if (result.data?.data != null) {
                val selectedUri: Uri? = result.data?.data
            }
        }
    }

0
投票

您需要使用以下作为选择 Intent

Intent photoLibraryIntent = new Intent(Intent.ACTION_PICK, android.provider.MediaStore.Images.Media.EXTERNAL_CONTENT_URI);
photoLibraryIntent.setType("image/* video/*");

0
投票

在尝试了上述答案和其他问题的不同组合之后。 这就是终于对我有用的API 级别我在 v23 到 v34 上测试过它。 但它也应该适用于以下和更高版本。

/**
 * Open gallery intent
 */
private void dispatchGalleryIntent() {
    final Intent openGalleryIntent = getOpenGalleryIntent();
    startActivityForResult(openGalleryIntent, REQ_CHOOSE_GALLERY);
}

/**
 * Returns gallery intent
 */
@NonNull
private Intent getOpenGalleryIntent() {
    final Intent openGalleryIntent = new Intent(Intent.ACTION_PICK);
    openGalleryIntent.setDataAndType(MediaStore.Images.Media.INTERNAL_CONTENT_URI, "*/*");
    openGalleryIntent.putExtra(Intent.EXTRA_MIME_TYPES, new String[] {"image/*", "video/*"});
    openGalleryIntent.putExtra(Intent.EXTRA_ALLOW_MULTIPLE, true);
    return openGalleryIntent;
}

Key Factors 上面代码中的

  1. 先定义 输入
    "*/*"
    {代表所有数据类型},然后传递您的过滤器 MimeType。 就像我的情况一样,我想要视频和图像,所以我将 mimeType 数组作为
    {"image/*", "video/*"}"
  2. INTERNAL_CONTENT_URI
    代替
    EXTERNAL_CONTENT_URI

配置要求

需要清单权限 对于 API 级别 32 及更低级别

<uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE" />

对于 API 级别 33 及更高级别

<uses-permission android:name="android.permission.READ_MEDIA_IMAGES" />
<uses-permission android:name="android.permission.READ_MEDIA_VIDEO" />

以下是完整的代码,包括检查权限和从 GALLERY 中选择文件。

选择文件后的回调可以在

onActivityResult

中处理

如何请求权限? 我正在使用 EasyPermissions 来检查和请求权限。但是你可以使用任何方法或者简单地使用 Android 默认权限方法。

private String[] attachmentsPathArr = new String[]{};
private final int REQ_GALLERY_PERMISSION = 300;
private final int REQ_CHOOSE_GALLERY = 600;

@RequiresApi(api = 33)
public static final String[] PERMISSIONS_STORAGE_AVI_V33_ARR = {        //AVI - Audio, Video, Image
            Manifest.permission.READ_MEDIA_VIDEO,
            Manifest.permission.READ_MEDIA_IMAGES
    };
public static final String PERMISSION_STORAGE = Manifest.permission.READ_EXTERNAL_STORAGE;

 /**
 * Open Gallery task with permission
 */
@AfterPermissionGranted(REQ_GALLERY_PERMISSION)
private void galleryTask() {
    if (hasStoragePermission()) {
        // Have permission, call the gallery intent!
        dispatchGalleryIntent();
    } else {
        // Request one permission
        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.TIRAMISU) {
            EasyPermissions.requestPermissions(this, getString(R.string.gallery_permission_message),
                    REQ_GALLERY_PERMISSION, PERMISSIONS_STORAGE_AVI_V33_ARR);
        } else {
            EasyPermissions.requestPermissions(this, getString(R.string.gallery_permission_message),
                    REQ_GALLERY_PERMISSION, PERMISSION_STORAGE);
        }
    }
}

权限检查

 /**
 * Storage specific permission check
 */
private boolean hasStoragePermission() {
    if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.TIRAMISU) {
        return EasyPermissions.hasPermissions(getActivity(), PERMISSIONS_STORAGE_AVI_V33_ARR);
    } else {
        return EasyPermissions.hasPermissions(getActivity(), PERMISSION_STORAGE);
    }
}

处理/保存从画廊返回的选定文件路径。

@Override
    public void onActivityResult(int requestCode, int resultCode, Intent data) {
if (resultCode == RESULT_OK) {
            if (requestCode == REQ_CHOOSE_GALLERY) {
                showLog(TAG, "onActivityResult REQ_CHOOSE_GALLERY- " + REQ_CHOOSE_GALLERY);
                if (data != null) {
                    Uri selectedImageUri = data.getData();
                    if (data.getClipData() != null) {
                        int count = data.getClipData().getItemCount();
                        attachmentsPathArr = new String[count];  //Initializing the array based on number of files path received
                        for (int index = 0; index < count; index++) {
                            attachmentsPathArr[index] = FileUtils.getPath(getActivity(), data.getClipData().getItemAt(index).getUri());
                            showLog(TAG, "onActivityResult \n -attachmentsPathArr[" + index + "].getUri()- " + data.getClipData().getItemAt(index).getUri());
                        }

                        setSelectedFiles(); //Do your next operation here like displaying the files or saving it.
                    } else {
                        showLog(TAG, "onActivityResult selectedImageUri == null selectedImageUri- " + selectedImageUri);
                    }
                }
            }
        } 
}

希望对您有所帮助并节省您的时间! 谢谢

© www.soinside.com 2019 - 2024. All rights reserved.