MediaPlayer setDataSource,更好地使用路径还是FileDescriptor?

时间:2012-03-08 21:59:33

标签: android

假设我有一个文件的完整路径。将该文件加载到MediaPlayer中的哪种方法更好?

String filePath = "somepath/somefile.mp3";
mediaPlayer.setDataSource(filePath);

String filePath = "somepath/somefile.mp3";
File file = new File(filePath);
FileInputStream inputStream = new FileInputStream(file);
mediaPlayer.setDataSource(inputStream.getFD());
inputStream.close();

重要吗?简单地使用路径似乎更容易,但是有理由做额外的工作来使用FileDescriptor吗?

2 个答案:

答案 0 :(得分:32)

实际上,事实证明在某些情况下存在差异。

如果您尝试从mediaPlayer.setDataSource(String path)加载文件,则在致电mediaPlayer.prepare()

getApplicationContext().getFilesDir()将失败,具体取决于文件的保存方式。例如,如果我使用new RandomAccessFile(filePath, "rw")编写文件,如果您使用mediaPlayer.setDataSource(String path),则媒体播放器实际上无法读取该文件。 prepare()会立即从媒体播放器触发error(1, -2147483648);本质上是文件权限错误。 SDK 9引入了file.setReadable (boolean readable, boolean ownerOnly),这可能会让您通过将ownerOnly设置为false来解决此问题...但如果您需要支持较旧的SDK,这对您没有帮助。

但是,mediaPlayer.setDataSource(FileDescriptor fd)没有此问题,媒体播放器将成功准备相同的文件而没有权限问题。

答案 1 :(得分:2)

MediaPlayer.java具有接受字符串(路径)和FD的setDataSource()签名。 他们最终都进入了本机C代码。虽然其中一个可能会更加有效,但除非您设置的数据源频率超过每秒一次,否则它可以忽略不计。

/**
 * Sets the data source (file-path or http/rtsp URL) to use. Call this after 
 * reset(), or before any other method (including setDataSource()) that might
 * throw IllegalStateException in this class.
 * 
 * @param path the path of the file, or the http/rtsp URL of the stream you want to play
 * @throws IllegalStateException if it is called
 * in an order other than the one specified above
 */
public native void setDataSource(String path) throws IOException, IllegalArgumentException, IllegalStateException;

/**
 * Sets the data source (FileDescriptor) to use. It is the caller's responsibility
 * to close the file descriptor. It is safe to do so as soon as this call returns.
 * Call this after reset(), or before any other method (including setDataSource()) 
 * that might throw IllegalStateException in this class.
 * 
 * @param fd the FileDescriptor for the file you want to play
 * @throws IllegalStateException if it is called
 * in an order other than the one specified above
 */
public void setDataSource(FileDescriptor fd) 
        throws IOException, IllegalArgumentException, IllegalStateException {
    // intentionally less than LONG_MAX
    setDataSource(fd, 0, 0x7ffffffffffffffL);
}

/**
 * Sets the data source (FileDescriptor) to use.  It is the caller's responsibility
 * to close the file descriptor. It is safe to do so as soon as this call returns.
 * Call this after reset(), or before any other method (including setDataSource()) 
 * that might throw IllegalStateException in this class.
 * 
 * @param fd the FileDescriptor for the file you want to play
 * @param offset the offset into the file where the data to be played starts, in bytes
 * @param length the length in bytes of the data to be played
 * @throws IllegalStateException if it is called
 * in an order other than the one specified above
 */
public native void setDataSource(FileDescriptor fd, long offset, long length) 
        throws IOException, IllegalArgumentException, IllegalStateException;