HardBirch

Android提高第二十篇之MediaPlayer播放网络音频

时间:11-05-09 栏目:安卓入门与提高 作者:张飞不张,文采横飞 评论:66 点击: 20,607 次


     以前曾经地介绍过《MediaPlayer的基本用法》,这里就深入地讲解MediaPlayer的在线播放功能。本文主要实现MediaPlayer在线播放音频的功能,由于在线视频播放比在线音频播放复杂,因此先介绍在线音频播放的实现,这样可以帮助大家逐步深入了解MediaPlayer的在线播放功能。先来看看本文程序运行的结果:

main.xml的源码如下:



























Player.java是本文的核心,Player.java实现了“进度条更新”、“数据缓冲”等功能,虽然不是很复杂的功能,但却是非常有用的功能。Player.java源码如下:

import java.io.IOException;
import java.util.Timer;
import java.util.TimerTask;
import android.media.AudioManager;
import android.media.MediaPlayer;
import android.media.MediaPlayer.OnBufferingUpdateListener;
import android.media.MediaPlayer.OnCompletionListener;
import android.os.Handler;
import android.os.Message;
import android.util.Log;
import android.widget.SeekBar;

public class Player implements OnBufferingUpdateListener,
OnCompletionListener, MediaPlayer.OnPreparedListener{
public MediaPlayer mediaPlayer;
private SeekBar skbProgress;
private Timer mTimer=new Timer();
public Player(SeekBar skbProgress)
{
this.skbProgress=skbProgress;

try {
mediaPlayer = new MediaPlayer();
mediaPlayer.setAudioStreamType(AudioManager.STREAM_MUSIC);
mediaPlayer.setOnBufferingUpdateListener(this);
mediaPlayer.setOnPreparedListener(this);
} catch (Exception e) {
Log.e("mediaPlayer", "error", e);
}

mTimer.schedule(mTimerTask, 0, 1000);
}

/*******************************************************
* 通过定时器和Handler来更新进度条
******************************************************/
TimerTask mTimerTask = new TimerTask() {
@Override
public void run() {
if(mediaPlayer==null)
return;
if (mediaPlayer.isPlaying() && skbProgress.isPressed() == false) {
handleProgress.sendEmptyMessage(0);
}
}
};

Handler handleProgress = new Handler() {
public void handleMessage(Message msg) {

int position = mediaPlayer.getCurrentPosition();
int duration = mediaPlayer.getDuration();

if (duration > 0) {
long pos = skbProgress.getMax() * position / duration;
skbProgress.setProgress((int) pos);
}
};
};
//*****************************************************

public void play()
{
mediaPlayer.start();
}

public void playUrl(String videoUrl)
{
try {
mediaPlayer.reset();
mediaPlayer.setDataSource(videoUrl);
mediaPlayer.prepare();//prepare之后自动播放
//mediaPlayer.start();
} catch (IllegalArgumentException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (IllegalStateException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}

public void pause()
{
mediaPlayer.pause();
}

public void stop()
{
if (mediaPlayer != null) {
mediaPlayer.stop();
mediaPlayer.release();
mediaPlayer = null;
}
}

@Override
/**
* 通过onPrepared播放
*/
public void onPrepared(MediaPlayer arg0) {
arg0.start();
Log.e("mediaPlayer", "onPrepared");
}

@Override
public void onCompletion(MediaPlayer arg0) {
Log.e("mediaPlayer", "onCompletion");
}

@Override
public void onBufferingUpdate(MediaPlayer arg0, int bufferingProgress) {
skbProgress.setSecondaryProgress(bufferingProgress);
int currentProgress=skbProgress.getMax()*mediaPlayer.getCurrentPosition()/mediaPlayer.getDuration();
Log.e(currentProgress+"% play", bufferingProgress + "% buffer");
}

}

test_musicplayer.java是主程序,负责调用Player类,其中关键部分是SeekBarChangeEvent这个SeekBar拖动的事件:SeekBar的Progress是0~SeekBar.getMax()之内的数,而MediaPlayer.seekTo()的参数是0~MediaPlayer.getDuration()之内数,所以MediaPlayer.seekTo()的参数是(progress/seekBar.getMax())*player.mediaPlayer.getDuration()。

test_musicplayer.java源码如下:

import android.app.Activity;
import android.os.Bundle;
import android.view.View;
import android.view.View.OnClickListener;
import android.widget.Button;
import android.widget.SeekBar;

public class test_musicplayer extends Activity {
private Button btnPause, btnPlayUrl, btnStop;
private SeekBar skbProgress;
private Player player;

/** Called when the activity is first created. */
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.main);

this.setTitle("在线音乐播放---hellogv编写");

btnPlayUrl = (Button) this.findViewById(R.id.btnPlayUrl);
btnPlayUrl.setOnClickListener(new ClickEvent());

btnPause = (Button) this.findViewById(R.id.btnPause);
btnPause.setOnClickListener(new ClickEvent());

btnStop = (Button) this.findViewById(R.id.btnStop);
btnStop.setOnClickListener(new ClickEvent());

skbProgress = (SeekBar) this.findViewById(R.id.skbProgress);
skbProgress.setOnSeekBarChangeListener(new SeekBarChangeEvent());
player = new Player(skbProgress);

}

class ClickEvent implements OnClickListener {

@Override
public void onClick(View arg0) {
if (arg0 == btnPause) {
player.pause();
} else if (arg0 == btnPlayUrl) {
//在百度MP3里随便搜索到的,大家可以试试别的链接
String url="http://219.138.125.22/myweb/mp3/CMP3/JH19.MP3";
player.playUrl(url);
} else if (arg0 == btnStop) {
player.stop();
}
}
}

class SeekBarChangeEvent implements SeekBar.OnSeekBarChangeListener {
int progress;

@Override
public void onProgressChanged(SeekBar seekBar, int progress,
boolean fromUser) {
// 原本是(progress/seekBar.getMax())*player.mediaPlayer.getDuration()
this.progress = progress * player.mediaPlayer.getDuration()
/ seekBar.getMax();
}

@Override
public void onStartTrackingTouch(SeekBar seekBar) {

}

@Override
public void onStopTrackingTouch(SeekBar seekBar) {
// seekTo()的参数是相对与影片时间的数字,而不是与seekBar.getMax()相对的数字
player.mediaPlayer.seekTo(progress);
}
}

}

声明: 本文由( 张飞不张,文采横飞 )原创编译,转载请保留链接: Android提高第二十篇之MediaPlayer播放网络音频

Android提高第二十篇之MediaPlayer播放网络音频:目前有66 条留言

  1. 0楼
    kf156:

    第一时间顶起

    2011-05-09 15:47 [回复]
  2. 顶你

    2011-05-09 15:51 [回复]
  3. 0楼
    scyclone:

    顶GV

    2011-05-09 15:51 [回复]
  4. 0楼
    sinberuser:

    [e03]

    2011-05-09 15:51 [回复]
  5. 0楼
    Tomaslee:

    [e01]

    2011-05-09 15:51 [回复]
  6. 0楼
    hmc1985:

    [e01]这个功能很实用

    2011-05-09 15:52 [回复]
  7. 顶起

    2011-05-09 15:53 [回复]
  8. 0楼
    xuyan87101:

    呃,一会的功夫那么多[e01]

    2011-05-09 15:54 [回复]
  9. 0楼
    toni001:

    牛人,留名

    2011-05-10 12:17 [回复]
  10. [e01]

    2011-05-10 17:01 [回复]
  11. 0楼
    mf24272:

    [e03]学习了 希望楼主早日出 在线视频播放功能!

    2011-05-10 17:36 [回复]
  12. 0楼
    jeanthbian:

    [e01]

    2011-05-11 09:16 [回复]
  13. 0楼
    p08170082:

    呵呵 弱弱问一句 这个编代码的软件是什么?

    2011-05-11 18:57 [回复]
  14. 0楼
    lwwit:

    [e01][e01]好耶

    2011-05-12 09:14 [回复]
  15. 0楼
    wjb_yd:

    回复 p08170082:eclipse

    2011-05-12 10:11 [回复]
  16. 0楼
    amaomao510:

    决定把你的每一篇文章都读一遍,先谢谢咯,[e04]

    2011-05-12 11:43 [回复]
  17. 0楼
    junfu2009:

    有意转Android,持续关注!

    2011-05-12 13:23 [回复]
  18. [e01]支持啊

    2011-05-12 20:28 [回复]
  19. 0楼
    lagymama:

    先顶!!几个问题:1)暂停后怎么继续播放而不是从头再来
    2)播放时按了返回键,虽然还在继续播放,但是怎么才能回到播放界面
    3)。。。

    2011-05-12 21:05 [回复]
  20. 0楼
    hellogv:

    回复 lagymama:
    你看看里面的代码就知道了
    1.播放是读取文件并播放
    2.没有在activity的onKeyDown()里面做返回键处理,本文的重点是讲解播放网络音频,这些细节不会写太多。

    2011-05-12 21:09 [回复]
  21. 0楼
    lyshsd:

    请教:可以支持外持字幕,如LRC,SRT之类吗?

    2011-05-12 21:21 [回复]
  22. 好像很复杂哦

    2011-05-12 22:42 [回复]
  23. 0楼
    hellogv:

    回复 lyshsd:
    字幕要自己程序加入

    2011-05-12 23:35 [回复]
  24. 0楼
    Lsxily:

    [e01]

    2011-05-13 12:39 [回复]
  25. 0楼
    Lisowski:

    不错 不错[e01]

    2011-05-13 19:39 [回复]
  26. 0楼
    woanon:

    好文慢慢看[e01]

    2011-05-13 22:11 [回复]
  27. 0楼
    delphiwd:

    [e01]学习学习

    2011-05-14 18:34 [回复]
  28. [e01]

    2011-05-14 19:00 [回复]
  29. 顶下[e01]

    2011-05-15 08:34 [回复]
  30. 留个名。。。

    2011-05-15 09:42 [回复]
  31. 0楼
    showming34:

    大牛,顶起![e03]

    2011-05-15 11:25 [回复]
  32. 0楼
    chen123yan:

    好 [e01]

    2011-05-15 21:04 [回复]
  33. 0楼
    ZHUB329:

    [e01]

    2011-05-16 13:18 [回复]
  34. 0楼
    hfbi121324:

    [e03]

    2011-05-16 13:50 [回复]
  35. 0楼
    wenwei0902:

    请问,这个方法可以播RTSP流吗?模拟器中一直遇到“Command PLAYER_INIT completed with an error or info PVMFFailure”这个错误。

    2011-05-17 08:13 [回复]
  36. [e01][e01][e01][e03][e03]

    2011-05-17 13:19 [回复]
  37. 0楼
    luke3510:

    想问下,seekbar的max值是用百分比好,还是准确毫秒好,好处在那?更新的时候,seekbar的移动更连贯?

    2011-05-19 16:30 [回复]
  38. 0楼
    p08170082:

    回复 wjb_yd:谢谢了

    2011-05-19 22:24 [回复]
  39. 0楼
    hellogv:

    回复 luke3510:
    效果都差不多。。。。我个人比较喜欢百分比

    2011-05-19 22:31 [回复]
  40. 0楼
    luke3510:

    回复 hellogv:谢谢了,那我就不改我的代码了。。。。。

    2011-05-20 10:22 [回复]
  41. [e10]

    2011-05-25 15:07 [回复]
  42. 0楼
    hellogv:

    回复 luke3510:
    看你实际需要吧,以后也许还要改回来的

    2011-05-25 17:27 [回复]
  43. [e10]

    2011-05-31 16:02 [回复]
  44. 0楼
    luchen210:

    seekBar拖动的时候,加载好的第二个进度条也会跟着拖动条走,重新从网络上获取流,而不像我们平常用的音乐播放器那样可以预加载,是因为那个过程也是要自己实现的吗。。。

    2011-06-11 15:02 [回复]
  45. 0楼
    vincent4j:

    你好,能不能留个联系方式,请教你一些 MediaPlayer处理mms流媒体的知识。

    2011-06-12 09:53 [回复]
  46. 0楼
    peper001:

    好的很啊

    2011-07-26 09:42 [回复]
  47. 顶起

    2011-08-09 11:43 [回复]
  48. 缓冲的时候,容易造成响应超时页面阻塞怎么解决呢?

    2011-08-15 17:42 [回复]
  49. 0楼
    hellogv:

    [reply]android_janet[/reply]
    多线程

    2011-08-16 12:19 [回复]
  50. 0楼
    y567843241:

    [reply]luchen210[/reply]
    这个,同问,有什么办法能解决呢?

    2011-08-26 16:32 [回复]
  51. 0楼
    lhl2828242:

    不用双线程,还可以播放,用了双线程,在mediaplayer的setdatasource时,与网络连接不成功,返回-1002,不知道怎么回事,求解答

    2011-08-28 16:27 [回复]
  52. 0楼
    hellogv:

    [reply]lhl2828242[/reply]
    多线程跟网络连接没关系,只与UI有冲突而已

    2011-08-28 18:14 [回复]
  53. 0楼
    macd2666:

    Thanks…

    2011-09-02 17:54 [回复]
  54. 0楼
    liro:

    谢谢,prepare改成prepareAnsyc不就可以异步了么?
    下面是在android帮助文档查到的:
    Prepares the player for playback, asynchronously. After setting the datasource and the display surface, you need to either call prepare() or prepareAsync(). For streams, you should call prepareAsync(), which returns immediately, rather than blocking until enough data has been buffered.

    2011-10-13 17:50 [回复]
  55. 0楼
    liro:

    [quote=liro]谢谢,prepare改成prepareAnsyc不就可以异步了么?
    下面是在android帮助文档查…[/quote]

    更正一下,应该是prepareAsync。

    2011-10-13 17:53 [回复]
  56. 请楼主找时间试一下,使用三星或摩托罗拉的手机,在用http方式播放mp3时,如果mp3里面设置了专题图片,就播放不了。
    而htc就可以。。。

    2011-11-02 12:59 [回复]
  57. 楼主你好 你的是不是不能播放m4a格式的歌曲

    2012-03-22 17:30 [回复]
  58. 0楼
    hellogv:

    [reply]yangxiaoliang123[/reply]
    能不能播放m4a是手机的mediaplayer说了算,我只是调用mediaplayer的api而已

    2012-03-22 22:21 [回复]
  59. [reply]hellogv[/reply]
    今天看了下,这个播放器是支持m4a格式的

    2012-03-23 18:58 [回复]
  60. 我疑惑的一点是···这在CMWAP CMNET下 测试 是无法正常的播放的···········

    2012-04-08 15:44 [回复]
  61. 0楼
    hellogv:

    [reply]zhongdaxia456456[/reply]
    先试试wifi行不行,wifi也不行,估计链接无效了

    2012-05-27 09:58 [回复]
  62. 0楼
    kondoh:

    楼主,Android上有没有播放MMS协议流的完美解决方案,敬请告知。

    2012-05-30 10:57 [回复]
  63. 0楼
    TQW4321:

    感谢楼主!感谢楼主!再三感谢!!

    2012-08-28 19:35 [回复]
  64. 0楼
    TQW4321:

    我用它编译成功了。注意要加上访问网络的权限
    <uses-permission android:name="android.permission.INTERNET"/>

    2012-08-28 19:36 [回复]
  65. 0楼
    oozeoops:

    大神,音乐名字叫啥?

    2012-09-01 16:55 [回复]
  66. 0楼
    kondoh:

    在android4.0中 onBufferingUpdate这个方法不被自动调用是怎么回事?

    2012-09-05 17:58 [回复]

发表评论


QQ群互动

Linux系统与内核学习群:194051772

WP建站技术学习交流群:194062106

魔豆之路QR

魔豆的Linux内核之路

魔豆的Linux内核之路

优秀工程师当看优秀书籍

优秀程序员,要看优秀书!

赞助商广告

友荐云推荐