java – 如何使用自定义android.media.MediaDataSource和android.media.MediaPlayer?

我知道 Android的MediaPlayer是一件好事.它允许我们播放本地文件和媒体流.它很容易使用(例如):
MediaPlayer mediaPlayer = new MediaPlayer();
mediaPlayer.setDataSource("http://streaming.shoutcast.com/80sPlanet"); // this steam broadcasts audio/mpeg
mediaPlayer.prepareAsync();
mediaPlayer.start();

可以通过使用不同的参数集调用重载的setDataSource()来设置不同类型的DataSource.
这个函数一个有趣的原型:

void setDataSource(MediaDataSource dataSource)

看起来可以使用您自己的实现完全覆盖DataSource.它确实有效:

import android.media.MediaDataSource;
import java.io.BufferedInputStream;
import java.io.IOException;
import java.net.URL;
import java.net.HttpURLConnection;

public class UrlMediaDataSource extends MediaDataSource {
    URL url;
    HttpURLConnection connection;
    BufferedInputStream stream;

    public UrlMediaDataSource(URL url) throws IOException {
        this.url = url;
        connection = (HttpURLConnection) url.openConnection();
    }

    @Override
    public long getSize() {
        return 0;
    }

    @Override
    public int readAt(long position,byte[] buffer,int offset,int size) throws IOException {
        if (stream == null)
            stream = new BufferedInputStream(connection.getInputStream());
        return stream.read(buffer,offset,size);
    }

    @Override
    public void close() throws IOException {
        stream.close();
        stream = null;
        connection.disconnect();
        connection = null;
    }
}

并在主要代码中:

UrlMediaDataSource dataSource = new UrlMediaDataSource(new URL("http://streaming.shoutcast.com/80sPlanet"));
mediaPlayer.setDataSource(dataSource);

是的,这很好用.但是,如果我尝试音频/ aacp广播流(例如:“http://111.223.51.8:8005” – 它是“COOLfahrenheit 93”收音机),则播放器不播放. Logcat跟踪:

06-07 23:26:01.680 1352-1147/? E/GenericSource: Failed to init from data source!
06-07 23:26:01.681 1352-1093/? D/NuPlayerDriver: notifyListener_l(0xf3e051e0),(100,1,-2147483648)
06-07 23:26:01.735 1352-2013/? D/NuPlayerDriver: reset(0xf3e051e0)
06-07 23:26:01.735 1352-2013/? D/NuPlayerDriver: notifyListener_l(0xf3e051e0),(8,0)
06-07 23:26:01.736 1352-1093/? D/NuPlayerDriver: notifyResetComplete(0xf3e051e0)

但是,当没有使用自定义MediaDataSource时,URL工作正常(音乐播放):

mediaPlayer.setDataSource("http://111.223.51.8:8005");

有人知道管理这个的正确方法吗?
只是不建议我直接使用URL – 我需要一个自定义的MediaDataSource来访问流的原始数据.

解决方法

The main point is that the MediaPlayer does playback audio/mpeg (both ways – through URL and through custom MediaDataSource),but audio/aacp streams Could be played back only via URL as DataSource.

所以,让我们了解一下发生了什么.

当您将URL作为数据源传递时,正在执行this检查:


if ("file".equals(scheme)) {
        path = uri.getPath();
    } else if (scheme != null) {
        // handle non-file sources
        nativeSetDataSource(
            MediaHTTPService.createHttpServiceBinderIfNecessary(path),path,keys,values);
        return;
    }

MediaPlayer uses MediaHTTPService类,which is responsible用于提供来自http,https和widevine协议的数据. MediaHTTPService在内部使用MediaHTTPConnection,它可以解决所有繁重的工作问题.不幸的是,这些API尚未公开(但),但您可以看到如何在MediaHTTPConnection源(特别是seekTo method)中建立连接.因此,您提供给MediaPlayer的自定义数据源应该描述MediaHTTPConnection类实现的大致逻辑.

相关文章

Android性能优化——之控件的优化 前面讲了图像的优化,接下...
前言 上一篇已经讲了如何实现textView中粗字体效果,里面主要...
最近项目重构,涉及到了数据库和文件下载,发现GreenDao这个...
WebView加载页面的两种方式 一、加载网络页面 加载网络页面,...
给APP全局设置字体主要分为两个方面来介绍 一、给原生界面设...
前言 最近UI大牛出了一版新的效果图,按照IOS的效果做的,页...