假设我有一个文件的完整路径。将该文件加载到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吗?
答案 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;