Android Podcast Code Source
出自嵌入式大讲堂
Android Podcast player
工程目录:
UI设计:
UI设计部分只做了简单修改:
- 在TextView1下面由添加了一个TextView2
- imageView中删除了android:src="@raw/pic"
布局效果:
UI布局详细代码
工程代码
wikipodcast2.java
package com.emsym.wikipodcast2;
import java.io.IOException;
import java.io.InputStream;
import java.net.HttpURLConnection;
import java.net.MalformedURLException;
import java.net.URL;
import java.util.Iterator;
import java.util.LinkedList;
import java.util.List;
import javax.xml.parsers.DocumentBuilder;
import javax.xml.parsers.DocumentBuilderFactory;
import javax.xml.parsers.ParserConfigurationException;
import org.w3c.dom.Document;
import org.w3c.dom.Element;
import org.w3c.dom.Node;
import org.w3c.dom.NodeList;
import org.xml.sax.SAXException;
import android.app.Activity;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.media.MediaPlayer;
import android.media.MediaPlayer.OnCompletionListener;
import android.net.Uri;
import android.os.Bundle;
import android.view.View;
import android.view.View.OnClickListener;
import android.widget.Button;
import android.widget.ImageView;
import android.widget.ProgressBar;
import android.widget.SeekBar;
import android.widget.SeekBar.OnSeekBarChangeListener;
import android.widget.TextView;
类成员定义:(有点类似全局变量定义)
TextView mTextView;
TextView itemTextView;
Button startButton;
Button pauseButton;
Button nextButton;
ProgressBar mProgressBar;
SeekBar mSeekBar;
ImageView mImageView;
MediaPlayer mMediaPlayer;
int mVol = 50;
List<Item> itemList = new LinkedList<Item>();
Iterator it;
在OnCreat方法中:
setContentView():显示UI布局main.xml
widgetsConfigure():实例化使用的各种窗口部件并进行相应配置(主要是设置各种事件监听器)
XMLDOM():使用DOM对xml文件进行解析
@Override
public void onCreate(Bundle savedInstanceState) {
String uri = "http://www.voiceblog.jp/katsuhiro/rss2.0.xml";
super.onCreate(savedInstanceState);
setContentView(R.layout.main);
widgetsConfigure();
XMLDOM(uri);
}
widgetsConfigure()实例化了各种窗口部件并设置事件监听器,并声明了新建了mMediaPlayer。
public void widgetsConfigure(){
startButton = (Button) findViewById (R.id.startButton);
startButton.setOnClickListener(startButtonClicked);
pauseButton = (Button) findViewById (R.id.pauseorcontinueButton);
pauseButton.setOnClickListener(pauseButtonClicked);
nextButton = (Button) findViewById (R.id.nextButton);
nextButton.setOnClickListener(nextButtonClicked);
mSeekBar = (SeekBar) findViewById (R.id.VolumeSeekBar);
mSeekBar.setOnSeekBarChangeListener(mSeekBarChanged);
mTextView = (TextView) findViewById (R.id.TextView1);
mTextView.setText("Click start to play!");
itemTextView = (TextView) findViewById (R.id.TextView2);
mProgressBar = (ProgressBar) findViewById (R.id.MusicProgressBar);
mImageView = (ImageView) findViewById (R.id.musicImage);
mMediaPlayer = new MediaPlayer();
}
startButton点击事件监听器设置
public OnClickListener startButtonClicked = new OnClickListener(){
@Override
public void onClick(View v) {
// TODO Auto-generated method stub
it = itemList.iterator();
if(it.hasNext()){
Item ilist = (Item) it.next();
PlayMusic(ilist);
}
}
};
it = itemList.iterator();构建一个链表的迭代器;
调用函数PlayMusic()来播放音乐。
mMediaPlayer播放结束事件监听器设置
public OnCompletionListener completedPlay = new OnCompletionListener(){
public void onCompletion(MediaPlayer arg0){
PlayNext();
}
};
当播放结束事件被监听到时,则调用函数PlayNext()来播放下一首
函数PlayNext():播放下一首
public void PlayNext(){
if(it.hasNext()){
Item ilist = (Item)it.next();
PlayMusic(ilist);
}else{
it = itemList.iterator();
Item ilist = (Item)it.next();
PlayMusic(ilist);
}
}
播放下一首,首先判断itemList是否还有下一个Item,如果有,则去下一个Item播放;
如果没有,则重置迭代器(从头开始),选择第一个Item来播放
函数PlayMusic():开始播放音乐
public void PlayMusic(Item music){
itemTextView.setText("Title: "+music.title+"\n");
itemTextView.append("Authot: "+ music.author+"\n");
itemTextView.append("PubDate: "+ music.pubDate+"\n");
itemTextView.append("Duration: "+ music.duration+"\n");
Uri uri = Uri.parse(music.url);
mMediaPlayer.reset(); //**
try{
mMediaPlayer.setDataSource(this, uri);
mSeekBar.setProgress(mVol);
mMediaPlayer.setVolume((float)(0.01*mVol), (float)(0.01*mVol));
}catch(IllegalStateException e){
}catch(IOException e){
}catch(IllegalArgumentException e){
}catch(SecurityException e){
}
try{
mMediaPlayer.prepare();
}catch(IOException e){
}
mMediaPlayer.start();
mMediaPlayer.setOnCompletionListener(completedPlay);
changeProgressBar();
}
该函数的参数是Item,首先是取出Item中的各个变量,对一些变量进行显示;
然后设置播放的数据源,并调节播放音量和拖动条显示;
设置播放结束事件监听器;
调用函数changeProgressBar()来改变进度条显示;
函数changeProgressBar():新建线程负责改变进度条
public void changeProgressBar(){
mProgressBar.setMax(mMediaPlayer.getDuration());
new Thread(new Runnable(){
public void run(){
while(true){
mProgressBar.setProgress(mMediaPlayer.getCurrentPosition());
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
// TODO Auto-generated catch block
}
}
}
}).start();
}
新建一个线程,根据方法getCurrentPosition()得到的结果来设置进度条的进度
pauseButton点击事件监听器设置
public OnClickListener pauseButtonClicked = new OnClickListener(){
@Override
public void onClick(View v) {
// TODO Auto-generated method stub
if(mMediaPlayer.isPlaying()){
mMediaPlayer.pause();
pauseButton.setText("continue");
}else{
mMediaPlayer.start();
pauseButton.setText("pause");
}
}
};
nextButton点击事件监听器设置
public OnClickListener nextButtonClicked = new OnClickListener(){
@Override
public void onClick(View v) {
// TODO Auto-generated method stub
PlayNext();
}
};
这个的设置和播放一首结束时一样
mSeekBar改变事件监听器设置
public OnSeekBarChangeListener mSeekBarChanged = new OnSeekBarChangeListener(){
@Override
public void onProgressChanged(SeekBar seekBar, int progress,
boolean fromUser) {
// TODO Auto-generated method stub
mVol = progress;
mMediaPlayer.setVolume((float)(0.01*mVol), (float)(0.01*mVol));
}
@Override
public void onStartTrackingTouch(SeekBar seekBar) {
// TODO Auto-generated method stub
}
@Override
public void onStopTrackingTouch(SeekBar seekBar) {
// TODO Auto-generated method stub
}
};
函数XMLDOM():对xml文件的DOM解析
public void XMLDOM(String xmlUri){
DocumentBuilderFactory docBuilderFactory = null;
DocumentBuilder docBuilder = null;
Document doc = null;
String TITLE = "title";
String IMAGE = "itunes:image";
String ITEM = "item";
try{
docBuilderFactory = DocumentBuilderFactory.newInstance();
docBuilder = docBuilderFactory.newDocumentBuilder();
doc = docBuilder.parse(xmlUri);
Element root = doc.getDocumentElement();
//title
Node title = root.getElementsByTagName(TITLE).item(0);
mTextView.setText(title.getTextContent());
//image
Node image = root.getElementsByTagName(IMAGE).item(0);
Element elementImage = (Element) image;
String imageUrl =elementImage.getAttribute("href");
mImageView.setImageBitmap(GetNetBitmap(imageUrl));
//Items
NodeList items = root.getElementsByTagName(ITEM);
for(int i = 0;i<items.getLength();i++){
Node item = items.item(i);
Item music = new Item();
NodeList elements =item.getChildNodes();
for(int j=0;j<elements.getLength();j++){
Node tag = elements.item(j);
if(tag.getNodeName()!= "#text"){
if(tag.getNodeName().equals("title")) music.title = tag.getTextContent();
if(tag.getNodeName().equals("pubDate")) music.pubDate = tag.getTextContent();
if(tag.getNodeName().equals("itunes:duration")) music.duration = tag.getTextContent();
if(tag.getNodeName().equals("author")) music.author = tag.getTextContent();
if(tag.getNodeName().equals("enclosure")){
Element tagEnclosure = (Element) tag;
music.url = tagEnclosure.getAttribute("url");
}
}
}
itemList.add(music);
}
}catch(ParserConfigurationException e){
}catch(SAXException e){
}catch(IOException e){
}
}
对于XML的解析,需要明确几个概念:Element,Node,NodeList,了解它们用法。详细介绍请参见XML介绍
明确了以上几个概念,相信对上述代码的理解就很容易了。
函数GetNetBitmap():获取网络图片
public Bitmap GetNetBitmap(String url) {
URL myFileUrl = null;
Bitmap bitmap = null;
try {
myFileUrl = new URL(url);
}catch(MalformedURLException e) {
}
try {
HttpURLConnection conn = (HttpURLConnection) myFileUrl.openConnection();
conn.setDoInput(true);
conn.connect();
InputStream is = conn.getInputStream();
bitmap = BitmapFactory.decodeStream(is);
is.close();
}catch(IOException e) {
}
return bitmap;
}
AndroidManifest.xml
由于在程序中是用了网络,所以在AndroidManifest.xml中要添加使用网络的user-permission,使用方法:
<uses-permission android:name="android.permission.INTERNET" />