zl程序教程

您现在的位置是:首页 >  移动开发

当前栏目

我的Android进阶之旅------>Android MediaPlayer播放网络音频的实例--网络mp3播放器

Androidamp实例网络 -- 之旅 进阶 gt
2023-09-27 14:29:34 时间

上一篇写了个简单的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在播放...



==================================================================================================

  作者:欧阳鹏  欢迎转载,与人分享是进步的源泉!

  转载请保留原文地址:http://blog.csdn.net/ouyang_peng

==================================================================================================


Android音频架构 我们上面介绍的四个层面的音频API实现均在Framework层,其他各层音频相关有哪些功能?当我们调用某一API时最终是怎么驱动硬件工作的呢?下面我们先看看系统各层音频相关模块及功能。
Android音频API MediaRecorder与MediaPlayer并不能算完整意义的音频API,它们只是系统音频API的封装,除了采集/播放,他们集成了编码/解码、复用/解复用等能力。它们在最底层还是调用了AudioRecorder、AudioTrack。下面主要介绍它们的几个主要的配置项。
字节卷动 You will never know how excellent you are unless you impel yourself once.