前面讲到Vitamio可以支持一些流媒体,在这里就用Vitamio来播放网络上的一些流媒体,如:mms、rtsp、http,参考前辈的一些文章来写一个网络收音机程序,对于界面的要求不高,要求实现一些实用的功能
程序目录结构
初期界面,左边是用开源项目SlidingMenu,不清楚的可以参考:Android开源项目SlidingMenu的学习笔记
电台信息是通过XML来保存channel.xml,这里只添加一部分,更详细的可以参考文章最后的链接,自行添加
<?xml version="1.0" encoding="utf-8"?>
<Channel>
<ChannelType
name="推荐电台"
ID="1"
Icon="fm_icon"
Level="1" >
<RadioChannel
name="国际电台怀旧金曲"
ID="001"
Icon="default_channel_icon"
Level="2"
URL="mms://live.cri.cn/oldies/" />
<RadioChannel
name="国际电台都市流行"
ID="002"
Icon="default_channel_icon"
Level="2"
URL="mms://live.cri.cn/pop/" />
<RadioChannel
name="广东电台音乐之声"
ID="003"
Icon="default_channel_icon"
Level="2"
URL="mms://live.rgd.com.cn/993" />
<RadioChannel
name="广东珠江经济电台"
ID="004"
Icon="default_channel_icon"
Level="2"
URL="mms://live.rgd.com.cn/974" />
<RadioChannel
name="深圳电台飞扬音乐"
ID="005"
Icon="default_channel_icon"
Level="2"
URL="mms://vod.szr.com.cn/szr_2" />
<RadioChannel
name="佛山电台飞跃924"
ID="006"
Icon="default_channel_icon"
Level="2"
URL="mms://59.38.110.90/924" />
<RadioChannel
name="猫扑网络电台"
ID="007"
Icon="default_channel_icon"
Level="2"
URL="mms://ting.mop.com/mopradio" />
<RadioChannel
name="厦门音乐广播"
ID="008"
Icon="default_channel_icon"
Level="2"
URL="mms://mediasrv2.iptv.xmg.com.cn/yinyue" />
<RadioChannel
name="北京电台怀旧金曲"
ID="009"
Icon="default_channel_icon"
Level="2"
URL="mms://alive.bjradio.com.cn/cfm1075" />
<RadioChannel
name="湖南电台音乐之声"
ID="010"
Icon="default_channel_icon"
Level="2"
URL="mms://202.103.67.185/音乐" />
<RadioChannel
name="银河相声小品"
ID="011"
Icon="default_channel_icon"
Level="2"
URL="mms://media.radio.cn/radio2" />
<RadioChannel
name="上海故事广播"
ID="012"
Icon="default_channel_icon"
Level="2"
URL="mms://diantai.smgbb.cn/sgwy" />
</ChannelType>
<ChannelType
name="网络电台"
ID="2"
Icon="fm_icon"
Level="1" >
<RadioChannel
name="猫扑电台"
ID="001"
Icon="default_channel_icon"
Level="2"
URL="mms://ting.mop.com/mopradio" />
<RadioChannel
name="香港AirPOWER"
ID="002"
Icon="default_channel_icon"
Level="2"
URL="rtsp://live.onairpower.com:444/" />
<RadioChannel
name="华语之声综合"
ID="003"
Icon="default_channel_icon"
Level="2"
URL="rtsp://60.191.21.139/hy960/rtx" />
<RadioChannel
name="华语流行畅销"
ID="004"
Icon="default_channel_icon"
Level="2"
URL="mms://media.justaiwan.com/22" />
<RadioChannel
name="中国古典乐"
ID="005"
Icon="default_channel_icon"
Level="2"
URL="mms://media.justaiwan.com/24" />
<RadioChannel
name="舒适环境音乐"
ID="006"
Icon="default_channel_icon"
Level="2"
URL="mms://media.justaiwan.com/19" />
<RadioChannel
name="i RADIO网路音乐台"
ID="007"
Icon="default_channel_icon"
Level="2"
URL="http://www.iradio.com.tw/radio.asx" />
<RadioChannel
name="银河电台中国民乐"
ID="008"
Icon="default_channel_icon"
Level="2"
URL="mms://media.radio.cn/radio1" />
<RadioChannel
name="CVC中文电台"
ID="009"
Icon="default_channel_icon"
Level="2"
URL="http://www2.cvc.tv/stream/CVC_Chinese_24kbps.m3u" />
<RadioChannel
name="QQ综艺之声"
ID="010"
Icon="default_channel_icon"
Level="2"
URL="http://qr.fm.qq.com/qqradio?qqradio" />
<RadioChannel
name="QQ-都市流行"
ID="011"
Icon="default_channel_icon"
Level="2"
URL="rtsp://live.cri.cn/pop" />
<RadioChannel
name="青少年音乐台"
ID="012"
Icon="default_channel_icon"
Level="2"
URL="rtsp://58.63.245.9/live/stream=3" />
</ChannelType>
<ChannelType
name="广东电台"
ID="3"
Icon="fm_icon"
Level="1" >
<RadioChannel
name="广东电台音乐之声"
ID="001"
Icon="default_channel_icon"
Level="2"
URL="mms://live.fm993.com.cn/musicfm" />
<RadioChannel
name="广东珠江经济台"
ID="002"
Icon="default_channel_icon"
Level="2"
URL="mms://live.rgd.com.cn/974" />
<RadioChannel
name="广东南方生活广播"
ID="003"
Icon="default_channel_icon"
Level="2"
URL="mms://live.rgd.com.cn/936" />
<RadioChannel
name="广东羊城交通台"
ID="004"
Icon="default_channel_icon"
Level="2"
URL="mms://live.rgd.com.cn/1052" />
<RadioChannel
name="深圳电台飞扬音乐"
ID="005"
Icon="default_channel_icon"
Level="2"
URL="mms://vod.szr.com.cn/szr_2" />
<RadioChannel
name="佛山电台飞跃924"
ID="006"
Icon="default_channel_icon"
Level="2"
URL="mms://59.38.110.90/924" />
<RadioChannel
name="佛山电台千色985"
ID="007"
Icon="default_channel_icon"
Level="2"
URL="mms://59.38.110.90/985" />
<RadioChannel
name="珠海电台新闻资讯"
ID="008"
Icon="default_channel_icon"
Level="2"
URL="mms://www.zhtv.com/fm951" />
<RadioChannel
name="东莞电台新闻综合"
ID="009"
Icon="default_channel_icon"
Level="2"
URL="mms://radio.sun0769.com/fm1008" />
<RadioChannel
name="江门电台新闻综合"
ID="010"
Icon="default_channel_icon"
Level="2"
URL="mms://116.254.197.80/fm1002" />
<RadioChannel
name="汕头电台音乐之声"
ID="011"
Icon="default_channel_icon"
Level="2"
URL="mms://media.strtv.cn/strch3" />
<RadioChannel
name="潮州电台综合频道"
ID="012"
Icon="default_channel_icon"
Level="2"
URL="http://219.131.159.151/czdt939" />
</ChannelType>
<ChannelType
name="中央电台"
ID="4"
Icon="fm_icon"
Level="1" >
<RadioChannel
name="中央电台中国之声"
ID="001"
Icon="default_channel_icon"
Level="2"
URL="mms://mms.cnr.cn//cnr1?MTUjMCM" />
<RadioChannel
name="中央电台音乐之声"
ID="002"
Icon="default_channel_icon"
Level="2"
URL="mms://mms.cnr.cn//cnr3?MTUjMCM" />
<RadioChannel
name="国际电台乡村民谣"
ID="003"
Icon="default_channel_icon"
Level="2"
URL="mms://live.cri.cn/country" />
</ChannelType>
</Channel>读取XML数据放在NetRadioApp.java,使用两个全局的变量来保存,方便其它类的使用
package com.dzt.netradio;
import java.io.InputStream;
import java.util.ArrayList;
import com.dzt.netradio.constant.GlobalConstants;
import com.dzt.netradio.domain.RadioChannelData;
import com.dzt.netradio.utils.XmlPullParserUtils;
import android.app.Application;
public class NetRadioApp extends Application {
public static ArrayList<RadioChannelData> ChannelTypeList = new ArrayList<RadioChannelData>();
public static ArrayList<ArrayList<RadioChannelData>> finalChanneldata = new ArrayList<ArrayList<RadioChannelData>>();
@Override
public void onCreate() {
// TODO Auto-generated method stub
super.onCreate();
InputStream is = null;
try {
is = getResources().getAssets().open("channel.xml");
XmlPullParserUtils.getRadioListData(is, ChannelTypeList,
finalChanneldata);
} catch (Exception e) {
// TODO Auto-generated catch block
GlobalConstants.print_i("NetRadioApp",
"onCreate Exception = " + e.toString());
e.printStackTrace();
}
}
@Override
public void onLowMemory() {
// TODO Auto-generated method stub
super.onLowMemory();
System.gc();
}
}
在左侧菜单中使用观察者模式监听点击事件
public void setOnMenuListOnItemClickListener(
OnMenuListOnItemClickListener listener) {
mListener = listener;
}
public interface OnMenuListOnItemClickListener {
public void onSelectItem(int groupPosition, int childPosition);
}
@Override
public boolean onChildClick(ExpandableListView parent, View v,
int groupPosition, int childPosition, long id) {
// TODO Auto-generated method stub
if (mListener != null) {
mListener.onSelectItem(groupPosition, childPosition);
}
return false;
}在MainActivity.java类中设置监听器,和设置Handler与Service通信
/**
* 选择对应的Item
*/
@Override
public void onSelectItem(int groupPosition, int childPosition) {
// TODO Auto-generated method stub
RadioChannelData channelData = NetRadioApp.finalChanneldata.get(
groupPosition).get(childPosition);
mName.setText(channelData.getChannelName());
for (int i = 0; i < mUpdateHandler.size(); i++) {
Handler h = mUpdateHandler.get(i);
Message msg = h.obtainMessage();
msg.what = GlobalConstants.SELECT_ITEM;
Bundle data = new Bundle();
data.putInt("groupPosition", groupPosition);
data.putInt("childPosition", childPosition);
msg.setData(data);
h.sendMessage(msg);
}
}
public static void addUpdateHandler(Handler handler) {
mUpdateHandler.add(handler);
}
public static void removeUpdateHandler(Handler handler) {
mUpdateHandler.remove(handler);
}在Service中处理播放PlayService.java
package com.dzt.netradio.player;
import java.io.IOException;
import io.vov.vitamio.MediaPlayer;
import io.vov.vitamio.MediaPlayer.OnBufferingUpdateListener;
import io.vov.vitamio.MediaPlayer.OnCompletionListener;
import io.vov.vitamio.MediaPlayer.OnPreparedListener;
import android.app.Service;
import android.content.Intent;
import android.os.Binder;
import android.os.Bundle;
import android.os.Handler;
import android.os.IBinder;
import android.os.Message;
import com.dzt.netradio.MainActivity;
import com.dzt.netradio.NetRadioApp;
import com.dzt.netradio.WeakHandler;
import com.dzt.netradio.constant.GlobalConstants;
import com.dzt.netradio.domain.RadioChannelData;
public class PlayService extends Service implements OnBufferingUpdateListener,
OnCompletionListener, OnPreparedListener {
private MediaPlayer mPlayer;
public void MyMethod() {
GlobalConstants.print_i("PlayService", "MyMethod called");
}
public PlayService() {
}
@Override
public IBinder onBind(Intent intent) {
// TODO Auto-generated method stub
return myBinder;
}
public class MyBinder extends Binder {
public PlayService getService() {
return PlayService.this;
}
}
private MyBinder myBinder = new MyBinder();
@Override
public void onCreate() {
// TODO Auto-generated method stub
super.onCreate();
MainActivity.addUpdateHandler(selectItemHandler);
GlobalConstants.print_i("PlayService", "onCreate called");
}
@Override
public void onDestroy() {
// TODO Auto-generated method stub
MainActivity.removeUpdateHandler(selectItemHandler);
if (mPlayer != null) {
mPlayer.release();
mPlayer = null;
}
super.onDestroy();
}
@Override
public void onPrepared(MediaPlayer mp) {
// TODO Auto-generated method stub
GlobalConstants.print_i("PlayService", "onPrepared called");
if (mPlayer != null)
mPlayer.start();// 开始播放
}
@Override
public void onCompletion(MediaPlayer mp) {
// TODO Auto-generated method stub
GlobalConstants.print_i("PlayService", "onCompletion called");
}
@Override
public void onBufferingUpdate(MediaPlayer mp, int percent) {
// TODO Auto-generated method stub
// GlobalConstants.print_i("PlayService", "onBufferingUpdate called");
}
private void playSelectItem(String url) {
if (mPlayer == null) {
try {
mPlayer = new MediaPlayer(this);// 播放流媒体的对象
mPlayer.setDataSource(url);// 设置流媒体的数据源
mPlayer.prepare();
mPlayer.setOnBufferingUpdateListener(this);
mPlayer.setOnCompletionListener(this);
mPlayer.setOnPreparedListener(this);
} catch (Exception e) {
GlobalConstants.print_i("PlayService", "onCreate Exception = "
+ e.toString());
e.printStackTrace();
}
} else {
try {
mPlayer.setDataSource(url);// 设置流媒体的数据源
} catch (Exception e) {
GlobalConstants.print_i("PlayService", "onCreate Exception = "
+ e.toString());
e.printStackTrace();
}
}
GlobalConstants.print_i("PlayService", "playSelectItem url = " + url);
}
private Handler selectItemHandler = new SelectItemHandler(this);
private static class SelectItemHandler extends WeakHandler<PlayService> {
public SelectItemHandler(PlayService owner) {
super(owner);
// TODO Auto-generated constructor stub
}
@Override
public void handleMessage(Message msg) {
// TODO Auto-generated method stub
PlayService owner = getOwner();
if (owner == null)
return;
switch (msg.what) {
case GlobalConstants.SELECT_ITEM:
Bundle data = msg.getData();
int groupPosition = data.getInt("groupPosition");
int childPosition = data.getInt("childPosition");
RadioChannelData channelData = NetRadioApp.finalChanneldata
.get(groupPosition).get(childPosition);
owner.playSelectItem(channelData.getChannelURL());
break;
default:
break;
}
}
}
}
但只能播放一次,再点击Item就不能播放或自动退出,还没找到是什么原因,在后续再解决这个问题Vitamio中的MediaPlayer与系统中的MediaPlayer非常相似,用起来也方便,比VLC要方便相关代码:http://download.csdn.net/detail/deng0zhaotai/7905367
参考文档:
3、http://www.cnblogs.com/mythou/p/3231184.html
原文:http://blog.csdn.net/deng0zhaotai/article/details/39234305