Подтвердить что ты не робот

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?

4b9b3361

Ответ 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;