MediaPlayer setDataSource, лучше использовать путь или FileDescriptor?
Скажем, у меня есть полный путь к файлу. Каков наилучший подход к загрузке этого файла в 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?
Ответы
Ответ 1
На самом деле, оказывается, что в определенных ситуациях есть разница.
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.
HOWEVER, mediaPlayer.setDataSource(FileDescriptor fd)
НЕ имеет этой проблемы, и mediaplayer успешно подготовит тот же самый точный файл без разрешения.
Ответ 2
MediaPlayer.java имеет подписи setDataSource(), которые принимают как String (путь), так и FD.
Оба они в конце концов переходят в собственный код 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 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 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;