我的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

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


相关文章
|
3月前
|
弹性计算 监控 数据库
制造企业ERP系统迁移至阿里云ECS的实例,详细介绍了从需求分析、数据迁移、应用部署、网络配置到性能优化的全过程
本文通过一个制造企业ERP系统迁移至阿里云ECS的实例,详细介绍了从需求分析、数据迁移、应用部署、网络配置到性能优化的全过程,展示了企业级应用上云的实践方法与显著优势,包括弹性计算资源、高可靠性、数据安全及降低维护成本等,为企业数字化转型提供参考。
90 5
|
3月前
|
网络协议 Go
Go语言网络编程的实例
【10月更文挑战第27天】Go语言网络编程的实例
45 7
|
4月前
|
网络协议 Shell 网络安全
解决两个 Android 模拟器之间无法网络通信的问题
让同一个 PC 上运行的两个 Android 模拟器之间能相互通信,出(qiong)差(ren)的智慧。
50 3
|
6月前
|
安全 网络安全 Android开发
安卓与iOS开发:选择的艺术网络安全与信息安全:漏洞、加密与意识的交织
【8月更文挑战第20天】在数字时代,安卓和iOS两大平台如同两座巍峨的山峰,分别占据着移动互联网的半壁江山。它们各自拥有独特的魅力和优势,吸引着无数开发者投身其中。本文将探讨这两个平台的特点、优势以及它们在移动应用开发中的地位,帮助读者更好地理解这两个平台的差异,并为那些正在面临选择的开发者提供一些启示。
143 56
|
6月前
|
Android开发
Android 利用MediaPlayer实现音乐播放
本文提供了一个简单的Android MediaPlayer音乐播放示例,包括创建PlayerActivity、配置AndroidManifest.xml和activity_player.xml布局,以及实现播放和暂停功能的代码。
61 0
Android 利用MediaPlayer实现音乐播放
|
6月前
|
安全 网络安全 Android开发
探索安卓开发之旅:从新手到专家网络安全与信息安全:防范网络威胁,保护数据安全
【8月更文挑战第29天】在这篇技术性文章中,我们将踏上一段激动人心的旅程,探索安卓开发的世界。无论你是刚开始接触编程的新手,还是希望提升技能的资深开发者,这篇文章都将为你提供宝贵的知识和指导。我们将从基础概念入手,逐步深入到安卓开发的高级主题,包括UI设计、数据存储、网络通信等方面。通过阅读本文,你将获得一个全面的安卓开发知识体系,并学会如何将这些知识应用到实际项目中。让我们一起开启这段探索之旅吧!
|
6月前
|
存储 Linux 网络安全
【Azure 应用服务】App Service For Linux 如何在 Web 应用实例上住抓取网络日志
【Azure 应用服务】App Service For Linux 如何在 Web 应用实例上住抓取网络日志
|
6月前
|
Java Android开发 Kotlin
Android项目架构设计问题之要在Glide库中加载网络图片到ImageView如何解决
Android项目架构设计问题之要在Glide库中加载网络图片到ImageView如何解决
60 0
|
6月前
|
Java Android开发 开发者
Android项目架构设计问题之使用Retrofit2作为网络库如何解决
Android项目架构设计问题之使用Retrofit2作为网络库如何解决
114 0
|
8月前
|
监控 网络协议 安全
Socket网络编程中的常见应用场景与实例分析
Socket网络编程中的常见应用场景与实例分析

热门文章

最新文章

  • 1
    如何修复 Android 和 Windows 不支持视频编解码器的问题?
  • 2
    Android历史版本与APK文件结构
  • 3
    【08】flutter完成屏幕适配-重建Android,增加GetX路由,屏幕适配,基础导航栏-多版本SDK以及gradle造成的关于fvm的使用(flutter version manage)-卓伊凡换人优雅草Alex-开发完整的社交APP-前端客户端开发+数据联调|以优雅草商业项目为例做开发-flutter开发-全流程-商业应用级实战开发-优雅草Alex
  • 4
    【04】flutter补打包流程的签名过程-APP安卓调试配置-结构化项目目录-完善注册相关页面-开发完整的社交APP-前端客户端开发+数据联调|以优雅草商业项目为例做开发-flutter开发-全流程
  • 5
    当flutter react native 等混开框架-并且用vscode-idea等编译器无法打包apk,打包安卓不成功怎么办-直接用android studio如何打包安卓apk -重要-优雅草卓伊凡
  • 6
    APP-国内主流安卓商店-应用市场-鸿蒙商店上架之必备前提·全国公安安全信息评估报告如何申请-需要安全评估报告的资料是哪些-优雅草卓伊凡全程操作
  • 7
    【09】flutter首页进行了完善-采用android studio 进行真机调试开发-增加了直播间列表和短视频人物列表-增加了用户中心-卓伊凡换人优雅草Alex-开发完整的社交APP-前端客户端开发+数据联调|以优雅草商业项目为例做开发-flutter开发-全流程-商业应用级实战开发-优雅草Alex
  • 8
    【03】仿站技术之python技术,看完学会再也不用去购买收费工具了-修改整体页面做好安卓下载发给客户-并且开始提交网站公安备案-作为APP下载落地页文娱产品一定要备案-包括安卓android下载(简单)-ios苹果plist下载(稍微麻烦一丢丢)-优雅草卓伊凡
  • 9
    Android经典面试题之Kotlin中Lambda表达式和匿名函数的区别
  • 10
    【02】仿站技术之python技术,看完学会再也不用去购买收费工具了-本次找了小影-感觉页面很好看-本次是爬取vue需要用到Puppeteer库用node.js扒一个app下载落地页-包括安卓android下载(简单)-ios苹果plist下载(稍微麻烦一丢丢)-优雅草卓伊凡