前面讲到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
参考文档:
1、网络电台地址(一)
2、网络电台地址(二)
3、http://www.cnblogs.com/mythou/p/3231184.html