做音乐播放器,有时候会用到系统自带的mediaplayer播放器,这个播放器底层是在linux上面,封装了一些api供使用者调用,由于网络HTTP请求歌曲流这一块的都已经被封装了,所以要想实现歌曲边下载同时还能缓存到我们的文件夹中,需要做的就是从请求过程中间再开辟一个中间代理,通过代理去处理之间的输入输出流,同时在代理中实现本文的功能,这样就能实现我们想要的边下边播了。
本文的采用的就是利用创建本地socket代理,通过代理mediaplayer发送的请求,之后由代理去发送真实的请求,获取真实地址返回数据,然后再由代理写回给mediaplayer,同时写给本地去缓存。
小坑:
1、只采用一个socket代理+ 一个http的模式,歌曲可以播放正常,但是mediaplayer的seekTo方法失效,原因:分析mediaplayer的请求抓包,少了一些请求数据,导致mediaPlayer的duration一直为0。
2、碰到服务端返回采用了ngnix的redirect 也就是302跳转,导致本地文件会写的特别小,因为mediaplayer会根据302跳转标识去解析redirect的地址然后重新发送绕过代理的新请求。
所以本文最后采用的是一个本地socket,专门负责代理mediaplayer的请求和回写,通过捕获mediaplayer请求,替换掉http中的请求地址,然后通过另一个socket代理去处理发送至真实请求地址,根据请求回来的返回流,分析是否是歌曲,是歌曲流返回给mediaplayer,不是歌曲流,解析出里面的真实地址,再次发送远程socket,继续迭代分析,最终获取歌曲流并解析。也就是说1个socket与mediaplayer打交道,一个与网络打交道。
逻辑上就是上面了,接下来就是实现之(准备了一份demo,因为和太多demo放一起了,此次暂不放出,之后会统一放入github上)
主要代码:
初始化本地代理:
public void init() {
isThreadRun = true;
try {
localSocket = new ServerSocket(LOCAL_PORT, 0, InetAddress.getByName(LOCAL_IP_ADDRESS));//监听本地端口和IP
localSocket.setSoTimeout(TIME_OUT);
} catch (Exception e) {
MLog.error(this, "Can`t create a local serverSocket to listener local port");
}
}
重点代理类在线程中运行: