2012-03-08 18 views
18

Giả sử tôi có đường dẫn đầy đủ đến tệp. Cách tiếp cận nào tốt hơn để tải tệp đó vào MediaPlayer?MediaPlayer setDataSource, tốt hơn để sử dụng đường dẫn hoặc FileDescriptor?

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

HOẶC

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

Có vấn đề gì? Đơn giản chỉ cần sử dụng đường dẫn có vẻ dễ dàng hơn nhưng có một lý do để làm công việc phụ để sử dụng một FileDescriptor?

+0

'FileDescriptor' có thể sử dụng được khi phát từ nội dung từ thư mục' ContentProvider' hoặc tài sản chẳng hạn. – Jens

Trả lời

29

Thực ra, nó chỉ ra rằng có sự khác biệt trong một số trường hợp nhất định.

mediaPlayer.setDataSource(String path) sẽ không thành công khi bạn gọi mediaPlayer.prepare(), nếu bạn đang cố gắng tải tệp từ getApplicationContext().getFilesDir(), tùy thuộc vào cách tệp được lưu. Ví dụ: nếu tôi viết tệp bằng cách sử dụng new RandomAccessFile(filePath, "rw"), tệp phương tiện không thực sự có thể đọc được bởi trình phát đa phương tiện nếu bạn sử dụng mediaPlayer.setDataSource(String path). prepare() sẽ kích hoạt ngay error(1, -2147483648) từ trình phát đa phương tiện; về cơ bản là lỗi cho phép tệp. SDK 9 đã giới thiệu file.setReadable (boolean readable, boolean ownerOnly) có thể cho phép bạn giải quyết vấn đề này bằng cách đặt ownerOnly thành false ... nhưng điều đó không giúp bạn nếu bạn cần hỗ trợ các SDK cũ hơn.

BAO GIỜ, mediaPlayer.setDataSource(FileDescriptor fd) KHÔNG có sự cố này và trình phát đa phương tiện sẽ chuẩn bị thành công cùng một tệp chính xác mà không có sự cố về quyền.

+1

-2147483648 không phải là lỗi cho phép tệp. – braden

+1

http://www.weston-fl.com/blog/?p=2988 Bất kể lý do gì, chỉ trình phát phương tiện tại một tệp trong Tệp Dir của ứng dụng bằng cách sử dụng Chuỗi không thành công nhưng sử dụng Trình mô tả tệp hoạt động. –

+0

Trên ghi chú liên quan; khi phát video từ tệp mở rộng APK được mã hóa (.OBB), bạn cần sử dụng FileDescriptor để video của bạn phát trong MediaPlayer. MediaPlayer cố gắng truy cập các tệp từ bên ngoài ngữ cảnh của ứng dụng của bạn, nơi mà nó không có quyền chính xác để đọc tệp OBB của bạn. Sử dụng 'FileDescriptor' khắc phục vấn đề này. – Reinier

2

Chữ ký MediaPlayer.java đã đặtDataSource() chấp nhận cả chuỗi (đường dẫn) và FD. Cả hai cuối cùng đều đi vào mã C gốc. Mặc dù một trong số này có thể hiệu quả hơn nhưng nó sẽ không đáng kể trừ khi bạn thiết lập nguồn dữ liệu của mình thường xuyên hơn một lần trong một giây.

/** 
* 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; 
+0

Cảm ơn! Tôi nghĩ có lẽ FileDescriptor có thể mang lại một số lợi ích không rõ ràng; buffering lợi thế hoặc một số điều như vậy. –

Các vấn đề liên quan