检查文件是图像还是视频。

29

有没有办法在Android中检查我作为URI加载的文件是图像还是视频? 我正在尝试将图像和视频动态加载到片段以进行列表/详细视图,并需要区分它们。

6个回答

87

我会检查 mimeType,然后检查它是否对应图像或视频。

检查文件路径是否为图像的完整示例如下:

public static boolean isImageFile(String path) {
    String mimeType = URLConnection.guessContentTypeFromName(path);
    return mimeType != null && mimeType.startsWith("image");
}

视频相关:

public static boolean isVideoFile(String path) {
    String mimeType = URLConnection.guessContentTypeFromName(path);
    return mimeType != null && mimeType.startsWith("video");
}

好的回答。想要提一下,Java String对象有一个.startsWith方法,比indexOf == 0更易读。 - clocksmith
3
如果给定的路径不包含图像扩展名,则这将无法工作。例如,Android相机应用程序可能会返回类似于“content://com.android.providers.media.documents/document/image%3A130”的路径,此时isImageFile()将返回false。以下方法似乎是有效的:https://dev59.com/iGoy5IYBdhLWcg3wZdCr#31691791 - Johnson_145
1
糟糕的答案,因为该代码无法处理视频MIME类型。方法URLConnection.guessContentTypeFromName(...)的源代码在此处:https://github.com/AndroidSDKSources/android-sdk-sources-for-api-level-28/blob/master/java/net/URLConnection.java。正如您所看到的,仅支持最少的一组MIME类型,并且不包括任何视频MIME类型。源代码与Oracle Java 13和OpenJDK相同。 - Francesco Galgani

18

如果您从内容解析器中获取 Uri,则可以使用 getType(Uri) 获取 MIME 类型。

ContentResolver cR = context.getContentResolver();
String type = cR.getType(uri); 
应该得到类似于 "image/jpeg" 的东西,您可以将其与显示逻辑进行检查。

1
这段代码返回了null,URI是从一个包含代码的XML构建的。Uri uri = Uri.parse(packageLocation+DummyContent.INFO_MAP.get(getArguments().getString(ARG_ITEM_ID)).get(0));其中info_map是一个(String, ArrayList<String>)对的映射表,get(0)给出文件名,get(1)现在从xml中获取视频类型参数。我希望消除那里需要一个ArrayList来提高性能。如果文件名是vid.p4,get(0)将会给你类似于vid的东西。 - user2532233
如果无法确定给定URI的MIME类型,getType(Uri)函数将返回null。我猜你的文件MIME不是其中识别的类型之一。 - metalmonkeysoftware
1
但它们是JPG和MP4格式的,这很奇怪。 - user2532233

3

似乎最适合通过 ContentResolver 检查类型(如 jsrssoftware answer)。但是,在某些情况下,这可能返回 null

在这种情况下,我尝试将流解码为位图以确认它是否为图像(但仅解码边界,因此速度很快且不占用太多内存)。

我的图像测试助手函数如下:

public static boolean checkIsImage(Context context, Uri uri) {
    ContentResolver contentResolver = context.getContentResolver();
    String type = contentResolver.getType(uri);
    if (type != null) {
        return  type.startsWith("image/");
    } else {
        // try to decode as image (bounds only)
        InputStream inputStream = null;
        try {
            inputStream = contentResolver.openInputStream(uri);
            if (inputStream != null) {
                BitmapFactory.Options options = new BitmapFactory.Options();
                options.inJustDecodeBounds = true;
                BitmapFactory.decodeStream(inputStream, null, options);
                return options.outWidth > 0 && options.outHeight > 0;
            }
        } catch (IOException e) {
            // ignore
        } finally {
            FileUtils.closeQuietly(inputStream);
        }
    }
    // default outcome if image not confirmed
    return false;
}

对于视频,可以采用类似的方法。我没有需要,但我相信 MediaMetadataRetriever 可以用来验证流是否包含有效的视频,以防 type 检查失败。

3
enum class MediaType {
    MediaTypeImage,
    MediaTypeVideo,
    Unknown
}

fun getMediaType(context: Context, source: Uri): MediaType {
    val mediaTypeRaw = context.contentResolver.getType(source)
    if (mediaTypeRaw?.startsWith("image") == true)
        return MediaType.MediaTypeImage
    if (mediaTypeRaw?.startsWith("video") == true)
        return MediaType.MediaTypeVideo
    return MediaType.Unknown
}

0

检查的最佳方法是...

图片:

private fun isImage(path: String): Boolean {
        val mimeType: String = URLConnection.guessContentTypeFromName(path)
        return mimeType.startsWith("image")
}

视频:

private fun isVideo(path: String): Boolean {
        val mimeType: String = URLConnection.guessContentTypeFromName(path)
        return mimeType.startsWith("video")
}

.zip.rar

private fun isZip(name: String): Boolean {
        return name.contains(".zip") || name.contains(".rar")
}

-53

我想最简单的方法是检查扩展名

if ( file.toString().endsWith(".jpg") {
//photo
} else if (file.toString().endsWith(".3gp")) {
//video
}

43
我认为这不应该被接受作为答案。有很多扩展名可能是图片或视频,而且这个列表可能会随时间增长,所以手动维护很麻烦。我现在会写我的代码。 - alfongj
更不用说在 "toString()" 后面缺少的 toLowerCase() 了 ;-) - Rick77
这是一种非常糟糕的检测文件格式的方法。除了alfongj的评论之外,还有另一个问题,即扩展名不必匹配。 - Predrag Manojlovic
更新:请注意,@alfongj的答案是正确的,我的方法更像是一个hackish/quick fix的方式,可能在某些情况下适用。 - Marko Niciforovic
这不是正确的答案,因为文件扩展名可能与文件MIME类型不同! - Rez
仅仅因为你从URI中加载文件,并不意味着你会得到文件的路径或文件名。如果它是一个虚拟文件,你会得到DISPLAY_NAME,这可能是文件名,但并不保证。 - hippietrail

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接