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

简介: 上一篇写了个简单的MP3播放器 ,这次写一个可以播放网络音频资源的播放器 本实例可以实现音乐播放器除了来电的时候会暂停播放,通话结束后恢复播放外,打开其他的Activity都可以继续播放音乐,享受一边听音乐一边做其他的事情。

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

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


相关文章
|
6月前
|
网络协议 Java Linux
【App Service】在Azure环境中如何查看App Service实例当前的网络连接情况呢?
在 Azure App Service(Windows 和 Linux)中部署应用时,分析网络连接状态是排查异常、验证端口监听及确认后端连接的关键。本文介绍如何在 Linux 环境中使用 `netstat` 命令查看特定端口(如 443、3306、6380)的连接情况,并解析输出结果。同时说明在 Windows App Service 中 `netstat` 被禁用的情况下,如何通过门户抓包等替代方法进行网络诊断。内容涵盖命令示例、操作步骤及附录说明,帮助开发者快速掌握云环境中的网络分析技巧。
171 11
|
12月前
|
API 数据处理 Android开发
Android网络请求演变:从Retrofit到Flow的转变过程。
通过这个比喻,我们解释了 Android 网络请求从 Retrofit 到 Flow 的转变过程。这不仅是技术升级的体现,更是反映出开发者在面对并发编程问题时,持续探索和迭求更好地解决方案的精神。未来,还会有更多新的技术和工具出现,我们期待一同 witness 这一切的发展。
378 36
|
10月前
|
Web App开发 缓存 JavaScript
Android网络小说阅读器的实现
小说阅读Demo,。此Demo使用Jsoup解析HTML,实现小说数据抓取(数据源自网络),并包含自定义View、六章小说缓存等功能,但未实现下载。项目还包括屏幕适配、字体设置等,借助第三方框架完成优化。以下是主页、详情页、阅读页等界面展示。
306 0
|
12月前
|
XML JavaScript Android开发
【Android】网络技术知识总结之WebView,HttpURLConnection,OKHttp,XML的pull解析方式
本文总结了Android中几种常用的网络技术,包括WebView、HttpURLConnection、OKHttp和XML的Pull解析方式。每种技术都有其独特的特点和适用场景。理解并熟练运用这些技术,可以帮助开发者构建高效、可靠的网络应用程序。通过示例代码和详细解释,本文为开发者提供了实用的参考和指导。
453 15
|
安全 网络安全 Android开发
安卓与iOS开发:选择的艺术网络安全与信息安全:漏洞、加密与意识的交织
【8月更文挑战第20天】在数字时代,安卓和iOS两大平台如同两座巍峨的山峰,分别占据着移动互联网的半壁江山。它们各自拥有独特的魅力和优势,吸引着无数开发者投身其中。本文将探讨这两个平台的特点、优势以及它们在移动应用开发中的地位,帮助读者更好地理解这两个平台的差异,并为那些正在面临选择的开发者提供一些启示。
235 56
|
XML 开发工具 Android开发
FFmpeg开发笔记(五十六)使用Media3的Exoplayer播放网络视频
ExoPlayer最初是为了解决Android早期MediaPlayer控件对网络视频兼容性差的问题而推出的。现在,Android官方已将其升级并纳入Jetpack的Media3库,使其成为音视频操作的统一引擎。新版ExoPlayer支持多种协议,解决了设备和系统碎片化问题,可在整个Android生态中一致运行。通过修改`build.gradle`文件、布局文件及Activity代码,并添加必要的权限,即可集成并使用ExoPlayer进行网络视频播放。具体步骤包括引入依赖库、配置播放界面、编写播放逻辑以及添加互联网访问权限。
1426 1
FFmpeg开发笔记(五十六)使用Media3的Exoplayer播放网络视频
|
弹性计算 监控 数据库
制造企业ERP系统迁移至阿里云ECS的实例,详细介绍了从需求分析、数据迁移、应用部署、网络配置到性能优化的全过程
本文通过一个制造企业ERP系统迁移至阿里云ECS的实例,详细介绍了从需求分析、数据迁移、应用部署、网络配置到性能优化的全过程,展示了企业级应用上云的实践方法与显著优势,包括弹性计算资源、高可靠性、数据安全及降低维护成本等,为企业数字化转型提供参考。
419 5
|
网络协议 Go
Go语言网络编程的实例
【10月更文挑战第27天】Go语言网络编程的实例
230 7
|
网络协议 Shell 网络安全
解决两个 Android 模拟器之间无法网络通信的问题
让同一个 PC 上运行的两个 Android 模拟器之间能相互通信,出(qiong)差(ren)的智慧。
354 3
|
网络协议 开发者 Python
网络编程小白秒变大咖!Python Socket基础与进阶教程,轻松上手无压力!
【7月更文挑战第25天】在网络技术快速发展的背景下, Python因其简洁的语法和强大的库支持成为学习网络编程的理想选择。
218 5

热门文章

最新文章