MediaExtractor.setDataSource会抛出IOException异常,错误信息为“无法实例化解析器”。

6
我正在使用Android 4.2,调用MediaExtractor.setDataSource时,有时会抛出“无法实例化提取器”的IOException。我已经找到了这个问题从C++实现中抛出的位置,但没有帮助。

其他遇到同样问题的人要么没有答案,要么得到的答案对我没有帮助:

android.media.MediaExtractor。有人让这个东西工作了吗?“无法实例化提取器”异常

媒体提取器显示“无法实例化提取器”

在使用setDataSource()时无法实例化mediaextractor

为了拼命尝试解决这个问题,我编写了一个最小的演示应用程序:

public class MainActivity extends Activity {
  @Override
  protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.activity_main);
  }
  @Override
  public boolean onCreateOptionsMenu(Menu menu) {
    // Inflate the menu; this adds items to the action bar if it is present.
    getMenuInflater().inflate(R.menu.main, menu);
    return true;
  }
  public boolean doStuff(View view) {
    File f = getExternalFilesDir(null);
    File[] files = f.listFiles();
    for (File file : files) {
      if (file.isFile()) {
        Log.e("Andy", "trying file [" + file.getName() + "]");
        startExtractor(file);
      }
    }
    return true;
  }
  private void startExtractor(File f) {
    MediaExtractor extractor = new MediaExtractor();
    try {
      extractor.setDataSource(f.getAbsolutePath());
    } catch (IOException e) {
      Log.e("Andy", "splat " + e.getMessage());
    }
    extractor.release();
  }
}

这个应用程序的活动有一个单独的按钮,调用 "doStuff"。输出如下:

05-12 15:27:42.639: E/Andy(18757): trying file [aaitn.mp4]
05-12 15:27:42.689: E/Andy(18757): splat Failed to instantiate extractor.
05-12 15:27:42.689: E/Andy(18757): trying file [unusual aspect.mp4]
05-12 15:27:42.709: E/Andy(18757): trying file [test.mp4]
05-12 15:27:55.039: E/Andy(18757): trying file [aaitn.mp4]
05-12 15:27:55.119: E/Andy(18757): trying file [unusual aspect.mp4]
05-12 15:27:55.149: E/Andy(18757): trying file [test.mp4]
05-12 15:28:03.209: E/Andy(18757): trying file [aaitn.mp4]
05-12 15:28:03.259: E/Andy(18757): splat Failed to instantiate extractor.
05-12 15:28:03.259: E/Andy(18757): trying file [unusual aspect.mp4]
05-12 15:28:03.279: E/Andy(18757): trying file [test.mp4]
05-12 15:28:12.289: E/Andy(18757): trying file [aaitn.mp4]
05-12 15:28:12.379: E/Andy(18757): trying file [unusual aspect.mp4]
05-12 15:28:12.419: E/Andy(18757): trying file [test.mp4]
05-12 15:28:17.879: E/Andy(18757): trying file [aaitn.mp4]
05-12 15:28:17.929: E/Andy(18757): trying file [unusual aspect.mp4]
05-12 15:28:17.949: E/Andy(18757): splat Failed to instantiate extractor.
05-12 15:28:17.949: E/Andy(18757): trying file [test.mp4]

这让人感到困惑的几点是:

  • 有时候它有效,有时候则无法运行
  • 它在第一次尝试时就失败了。

现在,我相当确定其他人正在使用此界面并且它对他们有效,这意味着我使用的设备(MK808s)可能有损坏的固件,或者我错过了使其变得可靠的技巧。 有人有什么想法吗?

当GC启动时,logcat非常清晰,但GC时间与问题不相关。

编辑

我更改了按钮,以便启动一个线程,该线程循环1000次所有三个文件。 它一路畅通无阻。 很多人都感到困惑。 我发现如果我摆动鼠标而该线程正在运行,则它会开始失败,但是只要我松开鼠标,它就又开始工作了。 运行另一个仅进行一段时间的数学操作的线程则没有导致它。 在来自真实世界的应用程序中,删除鼠标并不能使问题消失,但这是一个大型应用程序,还会做很多其他事情。


日志输出中是否有来自系统媒体代码的任何信息? - fadden
不,这很清晰,除非垃圾回收启动,而且垃圾回收的时间与问题无关。 - Andy Newman
1
嗯,我猜我知道为什么我的应用在Android 4.2上评分最低了。废柴的东西真是太棒了。 - Steve M
5个回答

9

对我来说,已接受的答案不起作用。我必须指定开始偏移量和长度:

// Assuming a raw resource located at "res/raw/test_audio.mp3"
MediaExtractor extractor = new MediaExtractor();
AssetFileDescriptor afd = getResources().openRawResourceFd(R.raw.test_audio);
try {
    extractor.setDataSource(afd.getFileDescriptor(), afd.getStartOffset(), afd.getLength());
} catch (IOException e) {
    e.printStackTrace();
}

7

正如安迪在这篇文章中所写的,下面是示例代码:

MediaExtractor extractor = new MediaExtractor();
File file = new File(pathToFile);
FileInputStream fis = null;
try {
    fis = new FileInputStream(file);
    FileDescriptor fd = fis.getFD();
    extractor.setDataSource(fd);
} catch (Exception e) {
    e.printStackTrace();
} finally {
    //Release stuff
    extractor.release();
    try {
        if(fis != null) {
            fis.close();
        }
    } catch (Exception e){
        e.printStackTrace();
    }
}

6
似乎,如果我自己打开文件,获取输入流,从输入流获取FileDescriptor,然后要求从文件描述符中提取,每次都能正常工作。即使我晃动鼠标!我会认为这是Android的一个bug,并用此方式回答其他人的问题。不确定在这种情况下是否正确?

7
你能否贴出实现这个策略的代码呢? - JellicleCat

3
我也遇到了同样的问题,原因是我在manifest文件中忘记声明权限。 你可以检查一下这个。

5
如果缺少某个权限只会偶尔导致文件读取失败,那么我们的问题就更大了:p - Andy Newman

0

我曾经遇到过同样的问题。在我的资产文件夹中直接移动文件,而不是将其放在子文件夹中,这对我起了作用。


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