问题描述:
遇到过这样一个问题,向服务器发送一个请求,然后服务器给一个返回,这个返回当中包含有json数据和音频数据,我需要做的就是解析出这段音频数据然后播放出来。
目前Android播放音频有两种方式,一种是MediaPlayer,支持播放本地文件、网络文件等;另一种是AudioTrack,可以用来播放音频流,但是只支持播放原生的音频数据。
因此如果想要实现播放的功能,就有两种解决方案:
1.将拿到的音频数据解码成原生的音频数据,再以流的方式传输给AudioTrack进行播放,但是这种方案需要自己去找解码器,而且每一种不同的音频格式对应的解码器不同,工作量比较大;
2.第二种方案,在Android本地搭建HTTP服务器,然后其设置为MediaPlayer的播放源,让其进行播放,这种方式的好处就是,不需要管解码,MediaPlayer所支持的格式都能够以这种方式来播放。
实现过程:
搭建HTTP服务器
采用开源框架AndServer可以很方便的在Android上搭建起自己的服务器,
网址为 https://github.com/yanzhenjie/AndServer
1.设置请求响应
public class MusicHandler implements RequestHandler {
@Override
public void handle(HttpRequest httpRequest, HttpResponse httpResponse, HttpContext httpContext) throws HttpException, IOException {
Log.i("MusicHandler","收到请求了");
try {
Attachment attachment = AttachmentQueue.get();
InputStreamEntity inputStreamEntity = new InputStreamEntity(attachment.getInputStream(), attachment.getLength());
httpResponse.setEntity(inputStreamEntity);
Log.i("MusicHandler", "发送成功");
}catch(Exception e){
e.printStackTrace();
Log.i("MusicHandler", "发送异常"+e);
}
}
}
MusicHandler继承自RequestHandler,相当于java里面的serverlet,当收到musci请求的时候便会执行这一段代码。Attachment里面包含有一段音频流和音频流的长度,当收到请求时,便会把音频流返回。
2.服务器
public class HttpServer extends Service{
private AndServer andServer;
private Server mServer;
private AssetManager mAssetManager;
@Override
public void onCreate() {
mAssetManager = getAssets();
andServer = new AndServer.Build()
.port(8080)
.website(new AssetsWebsite(mAssetManager, ""))
.timeout(10*1000)
.registerHandler("music",new MusicHandler())
.build();
mServer = andServer.createServer();
mServer.start();
Log.i("httpserver","服务已经启动");
}
@Nullable
@Override
public IBinder onBind(Intent intent) {
return null;
}
public void startServer(){
mServer.start();
}
public void stopServer(){
mServer.stop();
}
public boolean isRunning(){
return mServer.isRunning();
}
}
HttpServer继承自server,当开启服务时,会在8080端口启动http服务,并且关联了MusicHandler,因此当访问路径为时 Http://localhost:8080/music ,就会执行MusicHandler代码。
3.开启服务
Intent intent = new Intent(this, HttpServer.class);
startService(intent);
这样服务便开启了。
别忘了在AndroidManifest.xml文件里面注册服务。
播放音频
AttachmentQueue.add(attachmentContent,length);
try {
MediaPlayer mediaPlayer = new MediaPlayer();
mediaPlayer.setDataSource(context, Uri.parse("http://localhost:8080/music"));
mediaPlayer.prepare();
mediaPlayer.start();
}catch(Exception e){
Log.i("mediaplayer","播放异常"+e);
e.printStackTrace();
}
当收到音频时,把音频数据添加到队列里面,然后再向本地服务器发出请求,服务器从队列里面取出音频然后传输给MediaPlayer进行播放。
总结
个人感觉这是一个比较笨的方法,但是可以绕过解码的环节,让MediaPlayer去承担解码的工作,如果有更好的方法,请指教。