MediaMetadataRetriever的setDataSource方法抛出了IllegalArgumentException异常。

22
我正在使用这个类尝试获取远程视频的大小,但如果视频是远程的,则会出现IllegalArgumentException异常。
该视频是存储在一个服务器上的mp4文件...
如果我使用mediaplayer播放它,视频可以正常播放,但是如果我尝试执行以下操作,则会出错。
try {
    MediaMetadataRetriever retriever = new  MediaMetadataRetriever();
    Bitmap bmp = null;      
    retriever.setDataSource(context, uri);
    bmp = retriever.getFrameAtTime();           
    videoHeight = (int) (bmp.getHeight()*((float)getIntWidth()/bmp.getWidth()));
} catch (Exception e) {
    e.printStackTrace();
}   

错误发生在这一行:

retriever.setDataSource(context, uri);

代码有什么问题?

and uri contains Uri.parse("http://www.myweb.com/myvideo.mp4");

12-19 13:38:08.610: W/System.err(13333): java.lang.IllegalArgumentException
12-19 13:38:08.611: W/System.err(13333):    at android.media.MediaMetadataRetriever.setDataSource(MediaMetadataRetriever.java:175)

你解决了这个问题吗? - ClassA
6个回答

27

也许你遇到了这个bug。如果是这样,请尝试:

try {
    MediaMetadataRetriever retriever = new  MediaMetadataRetriever();
    Bitmap bmp = null;      
    retriever.setDataSource("http://www.myweb.com/myvideo.mp4", new HashMap<String, String>());
    bmp = retriever.getFrameAtTime();           
    videoHeight = (int) (bmp.getHeight()*((float)getIntWidth()/bmp.getWidth()));
} catch (Exception e) {
    e.printStackTrace();
}

如果那不奏效,你可以尝试使用FFmpegMediaMetadataRetriever

FFmpegMediaMetadataRetriever retriever = new  FFmpegMediaMetadataRetriever();

try {
    Bitmap bmp = null;      
    retriever.setDataSource("http://www.myweb.com/myvideo.mp4"));
    bmp = retriever.getFrameAtTime();           
    videoHeight = (int) (bmp.getHeight()*((float)getIntWidth()/bmp.getWidth()));
} catch (Exception e) {
    e.printStackTrace();
}

retriever.release();

MediaMetadataRetriever 类中的 setDataSource(String) 方法不适用于参数 (String, HashMap<String,String>)。 - NullPointerException
方法签名在此处:http://developer.android.com/reference/android/media/MediaMetadataRetriever.html#setDataSource%28java.lang.String,%20java.util.Map%3Cjava.lang.String,%20java.lang.String%3E%29 - William Seemann
FFmpegMediaMetadataRetriever 只需要 5 MB 的空间。在使用 NDK 时,您应该为每个架构制作单独的 APK。 - William Seemann
我认为你可以添加Maven仓库并使用FFmpegMediaMetadataRetriever,或者是我误解了概念?为可能的答案点赞。 - user1767754
这是现在的首选方法,因为Android Studio已经取代了Eclipse。 - William Seemann
我查看了@WilliamSeemann指出的错误,并发现:发现了一种新方法:setDataSource(link, headers); 我用下面的代码解决了这个问题:if (Build.VERSION.SDK_INT >= 14) mmr.setDataSource(link, new HashMap<String, String>()); else mmr.setDataSource(link);对我很有用。 - DeltaCap019

10

我也遇到了同样的错误,我使用的是Android 10。

我只需在application标签内的清单文件中添加 android:requestLegacyExternalStorage="true"即可解决问题。

请查看此处链接。

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

<application
    android:requestLegacyExternalStorage="true"
    android:allowBackup="true"
    android:icon="@mipmap/ic_launcher"
    android:label="@string/app_name"
    android:roundIcon="@mipmap/ic_launcher_round"
    android:supportsRtl="true"
    android:theme="@style/AppTheme">
    <activity android:name=".MainActivity">
        <intent-filter>
            <action android:name="android.intent.action.MAIN" />

            <category android:name="android.intent.category.LAUNCHER" />
        </intent-filter>
    </activity>
</application>

->


我已经设置了 "android:requestLegacyExternalStorage="true",但仍然遇到相同的错误。 - Tarun Kumar

3

就我的情况而言,我正在创建一个简单的元数据提取测试应用程序,因此我使用adb将一个文件复制到了我的手机上,如下所示:

adb push 350950598.mp4 /sdcard/Movies

但是我忘记在应用程序清单中添加读取外部存储目录权限。具体来说:
<manifest xmlns:android="http://schemas.android.com/apk/res/android" package="my.cool.package.name">
    <uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
    <uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE" />
    ...
</manifest>

对我来说,添加这些权限解决了问题,即使是简单的文件字符串调用:

    MediaMetadataRetriever mediaMetadataRetriever = new MediaMetadataRetriever();
    mediaMetadataRetriever.setDataSource(movie.getPath());

当然,如果您的目标是API 23+ marshmallow,则还必须动态请求这些权限。


3
try {
    MediaMetadataRetriever retriever = new  MediaMetadataRetriever();
    Bitmap bmp = null;      
    retriever.setDataSource(uri.toString(), new HashMap<String, String>());
    bmp = retriever.getFrameAtTime();           
    videoHeight = (int) (bmp.getHeight()*((float)getIntWidth()/bmp.getWidth()));
} catch (Exception e) {
    e.printStackTrace();
}   

2

如果您使用的是Android 10或以上版本,则需要将requestLegacyExternalStorage设置为true。

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

<application
    android:label="@string/app_name"
    android:roundIcon="@mipmap/ic_launcher_round"
    android:requestLegacyExternalStorage="true"
    android:supportsRtl="true"
    android:theme="@style/AppTheme">

注意:如果这样做仍然遇到相同的问题,则需要重新安装应用程序。 :)

1
如果您使用的是Android Marshmallow或更高版本,则需要授予运行时权限。
Android清单文件:
<manifest xmlns:android="http://schemas.android.com/apk/res/android" package="my.cool.package.name">
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
<uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE" />
...

然后在您的活动中添加运行时权限代码。之后,运行您的应用程序,它应该可以正常工作。


2
为什么需要WRITE_EXTERNAL_STORAGE权限? - android developer

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