前面有文章曾经地介绍过mediaplayer的基本用法,这里就更加深入地讲解mediaplayer的在线播放功能。本文主要实现mediaplayer在线播放音频的功能,由于在线视频播放比在线音频播放复杂,因此先介绍在线音频播放的实现,这样可以帮助大家逐步深入了解mediaplayer的在线播放功能。
先来看看本文程序运行的结果如下图所示:
main.xml的源码如下:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
|
<?xml version= "1.0" encoding= "utf-8" ?> <framelayout xmlns:android= "http://schemas.android.com/apk/res/android" android:layout_height= "fill_parent" android:layout_width= "fill_parent" > <linearlayout android:layout_height= "wrap_content" android:layout_width= "fill_parent" android:orientation= "vertical" android:layout_gravity= "top" > <linearlayout android:orientation= "horizontal" android:layout_gravity= "center_horizontal" android:layout_margintop= "4.0dip" android:layout_height= "wrap_content" android:layout_width= "wrap_content" > <button android:layout_width= "wrap_content" android:layout_height= "wrap_content" android:id= "@+id/btnplayurl" android:text= "播放网络音频" ></button> <button android:layout_height= "wrap_content" android:id= "@+id/btnpause" android:text= "暂停" android:layout_width= "80dip" ></button> <button android:layout_height= "wrap_content" android:layout_width= "80dip" android:text= "停止" android:id= "@+id/btnstop" ></button> </linearlayout> <linearlayout android:orientation= "horizontal" android:layout_width= "fill_parent" android:layout_height= "wrap_content" android:layout_marginbottom= "20dip" > <seekbar android:paddingright= "10dip" android:layout_gravity= "center_vertical" android:paddingleft= "10dip" android:layout_weight= "1.0" android:layout_height= "wrap_content" android:layout_width= "wrap_content" android:id= "@+id/skbprogress" android:max= "100" ></seekbar> </linearlayout> </linearlayout> </framelayout> |
player.java是本文的核心,player.java实现了“进度条更新”、“数据缓冲”等功能,虽然不是很复杂的功能,但却是非常有用的功能。
player.java源码如下:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
|
package com.musicplayer; 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源码如下:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
|
package com.musicplayer; 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程序设计起到一定的促进作用。