上一篇写了个简单的MP3播放器 ,这次写一个可以播放网络音频资源的播放器
本实例可以实现音乐播放器除了来电的时候会暂停播放,通话结束后恢复播放外,打开其他的Activity都可以继续播放音乐,享受一边听音乐一边做其他的事情。该播放器可以实现进度条的显示,拖动进度条,可以调节播放进度。
Step 1 :新建一个Android工程,命名为AudioNetPlayer
Step 2: 设计UI布局,在main.xml里放入4个ImageButton,代码如下:
<?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"> <TextView android:layout_width="wrap_content" android:layout_height="40dp" android:text="@string/file_name" android:id="@+id/tips" /> <EditText android:layout_width="fill_parent" android:layout_height="wrap_content" android:id="@+id/file_name" android:text="http://192.168.153.50:8080/Hello/Complicated.mp3" /> <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="80dip" android:layout_height="wrap_content" android:id="@+id/btnPlayUrl" android:text="@string/button_play"></Button> <Button android:layout_height="wrap_content" android:id="@+id/btnPause" android:text="@string/button_pause" android:layout_width="80dip"></Button> <Button android:layout_height="wrap_content" android:layout_width="80dip" android:text="@string/button_stop" android:id="@+id/btnStop"></Button> <Button android:layout_height="wrap_content" android:layout_width="80dip" android:text="@string/button_replay" android:id="@+id/btnReplay"></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>
Step 3 :主控制程序MainActivity.java的实现,代码如下:
package cn.roco.netaudio.player;import android.app.Activity;import android.content.Context;import android.os.Bundle;import android.telephony.PhoneStateListener;import android.telephony.TelephonyManager;import android.view.View;import android.view.View.OnClickListener;import android.widget.Button;import android.widget.EditText;import android.widget.SeekBar;import android.widget.TextView;public class MainActivity extends Activity { private Button btnPause, btnPlayUrl, btnStop,btnReplay; private SeekBar skbProgress; private Player player; private EditText file_name_text; private TextView tipsView; /** Called when the activity is first created. */ @Override public void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.main); this.setTitle("在线音乐播放---ouyangpeng编写"); 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()); btnReplay = (Button) this.findViewById(R.id.btnReplay); btnReplay.setOnClickListener(new ClickEvent()); file_name_text=(EditText) this.findViewById(R.id.file_name); tipsView=(TextView) this.findViewById(R.id.tips); skbProgress = (SeekBar) this.findViewById(R.id.skbProgress); skbProgress.setOnSeekBarChangeListener(new SeekBarChangeEvent()); String url=file_name_text.getText().toString(); player = new Player(url,skbProgress); TelephonyManager telephonyManager=(TelephonyManager) getSystemService(Context.TELEPHONY_SERVICE); telephonyManager.listen(new MyPhoneListener(), PhoneStateListener.LISTEN_CALL_STATE); } /** * 只有电话来了之后才暂停音乐的播放 */ private final class MyPhoneListener extends android.telephony.PhoneStateListener{ @Override public void onCallStateChanged(int state, String incomingNumber) { switch (state) { case TelephonyManager.CALL_STATE_RINGING://电话来了 player.callIsComing(); break; case TelephonyManager.CALL_STATE_IDLE: //通话结束 player.callIsDown(); break; } } } class ClickEvent implements OnClickListener { @Override public void onClick(View arg0) { if (arg0 == btnPause) { boolean pause=player.pause(); if (pause) { btnPause.setText("继续"); tipsView.setText("音乐暂停播放..."); }else{ btnPause.setText("暂停"); tipsView.setText("音乐继续播放..."); } } else if (arg0 == btnPlayUrl) { player.play(); tipsView.setText("音乐开始播放..."); } else if (arg0 == btnStop) { player.stop(); tipsView.setText("音乐停止播放..."); } else if (arg0==btnReplay) { player.replay(); tipsView.setText("音乐重新播放..."); } } } 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); } } }播放器实现功能如下:
package cn.roco.netaudio.player;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(); private String videoUrl; private boolean pause; private int playPosition; public Player(String videoUrl, SeekBar skbProgress) { this.skbProgress = skbProgress; this.videoUrl = videoUrl; 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 callIsComing() { if (mediaPlayer.isPlaying()) { playPosition = mediaPlayer.getCurrentPosition();// 获得当前播放位置 mediaPlayer.stop(); } } /** * 通话结束 */ public void callIsDown() { if (playPosition > 0) { playNet(playPosition); playPosition = 0; } } /** * 播放 */ public void play() { playNet(0); } /** * 重播 */ public void replay() { if (mediaPlayer.isPlaying()) { mediaPlayer.seekTo(0);// 从开始位置开始播放音乐 } else { playNet(0); } } /** * 暂停 */ public boolean pause() { if (mediaPlayer.isPlaying()) {// 如果正在播放 mediaPlayer.pause();// 暂停 pause = true; } else { if (pause) {// 如果处于暂停状态 mediaPlayer.start();// 继续播放 pause = false; } } return pause; } /** * 停止 */ public void stop() { if (mediaPlayer != null && mediaPlayer.isPlaying()) { mediaPlayer.stop(); } } @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"); } /** * 播放音乐 * * @param playPosition */ private void playNet(int playPosition) { try { mediaPlayer.reset();// 把各项参数恢复到初始状态 /** * 通过MediaPlayer.setDataSource() * 的方法,将URL或文件路径以字符串的方式传入.使用setDataSource ()方法时,要注意以下三点: * 1.构建完成的MediaPlayer 必须实现Null 对像的检查. * 2.必须实现接收IllegalArgumentException 与IOException * 等异常,在很多情况下,你所用的文件当下并不存在. 3.若使用URL 来播放在线媒体文件,该文件应该要能支持pragressive * 下载. */ mediaPlayer.setDataSource(videoUrl); mediaPlayer.prepare();// 进行缓冲 mediaPlayer.setOnPreparedListener(new MyPreparedListener( playPosition)); } catch (Exception e) { e.printStackTrace(); } } private final class MyPreparedListener implements android.media.MediaPlayer.OnPreparedListener { private int playPosition; public MyPreparedListener(int playPosition) { this.playPosition = playPosition; } @Override public void onPrepared(MediaPlayer mp) { mediaPlayer.start();// 开始播放 if (playPosition > 0) { mediaPlayer.seekTo(playPosition); } } }}Step 4:由于加入了监听电话的功能,所以要在AndroidManifest.xml中配置权限
<?xml version="1.0" encoding="utf-8"?><manifest xmlns:android="http://schemas.android.com/apk/res/android" package="cn.roco.netaudio.player" android:versionCode="1" android:versionName="1.0"> <uses-sdk android:minSdkVersion="8" /> <uses-permission android:name="android.permission.INTERNET" /> <!-- 注意:这里要加入一个监听电话的权限 --> <uses-permission android:name="android.permission.READ_PHONE_STATE"/> <application android:icon="@drawable/icon" android:label="@string/app_name"> <activity android:name="MainActivity" android:label="@string/app_name"> <intent-filter> <action android:name="android.intent.action.MAIN" /> <category android:name="android.intent.category.LAUNCHER" /> </intent-filter> </activity> </application></manifest>Step 5: 运行效果如下,一首动听的Avril Lavigne - Complicated.mp3在播放...