我的Android进阶之旅------>Android MediaPlayer播放mp3的实例--简易mp3播放器

简介: 大家好我们今天研究的是Android中很重要也最为复杂的媒体播放器---MediaPlayer. Android的MediaPlayer包含了Audio和video的播放功能,在Android的界面上,Music和Video两个应用程序都是调用MediaPlayer实现的。

大家好我们今天研究的是Android中很重要也最为复杂的媒体播放器---MediaPlayer.

Android的MediaPlayer包含了Audio和video的播放功能,在Android的界面上,Music和Video两个应用程序都是调用MediaPlayer实现的。

首先来看看MediaPlayer的生命周期:



从MediaPlayer的生命周期图或者说是状态转移图上来看:

  1. 当一个MediaPlayer对象别创建或者调用reset()方法之后,它处于空闲状态,在调用release()方法后,才会处于结束状态。
    • 一个新建的MediaPlayer对象在调用getCurrentPosition(), getDuration(), getVideoHeight(), getVideoWidth(), setAudioStreamType(int), setLooping(boolean), setVolume(float,float), pause(), start(), stop(), seekTo(int), prepare(), prepareAsync()方法时,不会触发OnErrorListener.onError()事件,但是MediaPlayer对象如果调用了reset()方法后,再使用这些方法则会触发OnErrorListener.onError()事件。
    • 当MediaPlayer对象不再被使用时,最好通过release()方法来释放,使其处于结束状态,以免造成不必要的错误。当MediaPlayer处于结束状态是,便不能再使用。
    • MediaPlayer对象被新建时处于空闲状态,如果通过creat()方法创建之后便处于准备状态。
  2. 一般情况下,一些常用的播放控制操作可能因为音频、视频的格式不被支持或者质量较差以及流超时,也有可能由于开发者的疏忽使得MediaPlayer对象处于无效状态而导致错误。这时可以通过注册setOnErrorListener()方法实现OnErrorListener.onError()方法来监控这些错误。如果发生了错误,MediaPlayer对象将处于错误状态,可以使用reset()方法来恢复错误。
  3. 任何MediaPlayer对象都必须先处于准备状态,然后才开始播放。
  4. 要开始播放MediaPlayer对象都必须成功调用start()方法。可以通过isPlaying()方法来检测当前是否正在播放。
  5. 当MediaPlayer对象在播放时,可以进行暂停和停止等操作,pause()方法暂停播放,stop()方法停止播放。处于暂停状态时可以通过start()方法来恢复播放,但是处于停止状态则必须先调用pause()方法处于准备状态,然后再通过start()方法来开始播放。
  6. 可以通过setLooping(boolean)方法来设置是否循环播放。

下边是MediaPlayer提供的常用方法:

方法 说明
MediaPlayer 构造方法
create 创建一个要播放的多媒体
getCurrentPosition 得到当前播放位置
getDuration 得到文件的时间
getVideoHeight 得到视频的高度
getVideoWidth 得到视频的宽度
isLooping 是否循环播放
isPlaying 是否正在播放
pause 暂停
prepare 准备(同步)
prepareAsync 准备(异步)
release 释放MediaPlayer对象
reset 重置MediaPlayer对象
seekTo 指定播放的位置(以毫秒为单位的时间)
setAudioStreamType 设置流媒体的类型
setDataSource 设置多媒体数据来源
setDisplay 设置用SurfaceHolder来显示多媒体
setLooping 设置是否循环播放
setOnButteringUpdateListener 网络流媒体的缓冲监听
setOnErrorListener 设置错误信息监听
setOnVideoSizeChangedListener 视频尺寸监听
setScreenOnWhilePlaying 设置是否使用SurfaceHolder来保持屏幕显示
setVolume 设置音量
start 开始播放
stop 停止播放

至此,可以得出Android中通过MediaPlayer来播放音乐的步骤:

 MediaPlayer mp = new MediaPlayer();//构建MediaPlayer对象
 mp.setDataSource("/sdcard/test.mp3");//设置文件路径
 mp.prepare();//准备
 mp.start();//开始播放


  MediaPlayer在底层是基于OpenCore(PacketVideo)的库实现的,为了构建一个MediaPlayer程序,上层还包含了进程间通讯等内容,这种进程间通讯的基础是Android基本库中的Binder机制。

而我们今天的例子只是利用MediaPlayer来播放res/raw文件夹中一首非常动听的英文哥Avril Lavigne - Complicated.mp3.程序有4个ImageButton按钮,播放,停止,重播和暂停!4个按钮的功能我就不用多说.下面我将Step By Step教你如何完成本Demo的实现.本实例可以实现音乐播放器除了来电的时候会暂停播放,通话结束后恢复播放外,打开其他的Activity都可以继续播放音乐,享受一边听音乐一边做其他的事情。

Step 1 :新建一个Android工程,命名为AudioPlayer



Step 2 :准备素材,将Avril Lavigne - Complicated.mp3导入到SDCard中


Step 3: 设计UI布局,在main.xml里放入4个ImageButton,代码如下:

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
	android:orientation="vertical" android:layout_width="fill_parent"
	android:layout_height="fill_parent">
	<TextView android:layout_width="wrap_content"
		android:layout_height="40dp" android:text="@string/file_name"
		android:id="@+id/textView" />
	<EditText android:layout_width="fill_parent"
		android:layout_height="wrap_content" android:id="@+id/file_name" 
		android:text="Avril Lavigne - Complicated.mp3"/>
	<LinearLayout android:orientation="horizontal"
		android:layout_width="fill_parent" android:layout_height="wrap_content">
		<Button android:layout_width="wrap_content"
			android:layout_height="wrap_content" android:text="@string/button_play"
			android:onClick="mediaPlay" android:id="@+id/button_play" />

		<Button android:layout_width="wrap_content"
			android:layout_height="wrap_content" android:text="@string/button_pause"
			android:onClick="mediaPlay" android:id="@+id/button_pause" />

		<Button android:layout_width="wrap_content"
			android:layout_height="wrap_content" android:text="@string/button_replay"
			android:onClick="mediaPlay" android:id="@+id/button_replay" />

		<Button android:layout_width="wrap_content"
			android:layout_height="wrap_content" android:text="@string/button_stop"
			android:onClick="mediaPlay" android:id="@+id/button_stop" />
	</LinearLayout>
</LinearLayout>

string.xml

<?xml version="1.0" encoding="utf-8"?>
<resources>
    <string name="hello">Hello World, MainActivity!</string>
    <string name="app_name">音乐播放器</string>
    <string name="file_name">请输入音乐文件名</string>
    <string name="file_noexist">音乐文件不存在</string>
    <string name="button_play">播放</string>
    <string name="button_pause">暂停</string>
    <string name="button_continue">继续</string>
    <string name="button_replay">重播</string>
    <string name="button_stop">停止</string>
</resources>


Step 4 :主控制程序MainActivity.java的实现,代码如下:

package cn.roco.mp3;

import java.io.File;

import android.app.Activity;
import android.content.Context;
import android.media.MediaPlayer;
import android.os.Bundle;
import android.os.Environment;
import android.telephony.PhoneStateListener;
import android.telephony.TelephonyManager;
import android.view.View;
import android.widget.Button;
import android.widget.EditText;
import android.widget.TextView;
import android.widget.Toast;

public class MainActivity extends Activity {
	private TextView textView;
	private EditText file_name_Text;
	private String filePath;
	private MediaPlayer mediaPlayer;
	private boolean pause;
	private int playPosition;

	/** Called when the activity is first created. */
	@Override
	public void onCreate(Bundle savedInstanceState) {
		super.onCreate(savedInstanceState);
		setContentView(R.layout.main);
		
		textView=(TextView) this.findViewById(R.id.textView);
		file_name_Text = (EditText) this.findViewById(R.id.file_name);
		mediaPlayer = new MediaPlayer();
		
		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://电话来了
				if (mediaPlayer.isPlaying()) {
					playPosition = mediaPlayer.getCurrentPosition();// 获得当前播放位置
					mediaPlayer.stop();
				}
				break;
			case TelephonyManager.CALL_STATE_IDLE: //通话结束
				if (playPosition > 0 && filePath != null) {
					play(playPosition);
					playPosition = 0;
				}
				break;
			}
			
		}
	}
	
	/*
	// 当该窗口处于不可见的时候触发
	@Override
	protected void onPause() {
		if (mediaPlayer.isPlaying()) {
			playPosition = mediaPlayer.getCurrentPosition();// 获得当前播放位置
			mediaPlayer.stop();
		}
		super.onPause();
	}

	// 当该窗口处于重新回到前台时候触发
	@Override
	protected void onResume() {
		if (playPosition > 0 && filePath != null) {
			play();
			mediaPlayer.seekTo(playPosition);
			playPosition = 0;
		}
		super.onResume();
	}
	*/
	
	@Override
	protected void onDestroy() {
		mediaPlayer.release();
		mediaPlayer = null;
		super.onDestroy();
	}

	public void mediaPlay(View v) {
		switch (v.getId()) {
		// 播放按钮
		case R.id.button_play:
			String fileName = file_name_Text.getText().toString();
			File audio = new File(Environment.getExternalStorageDirectory(),
					fileName);
			if (audio.exists()) {// 文件存在
				filePath = audio.getAbsolutePath(); // 文件绝对路径
				play(0); // 播放音乐
				textView.setText("音乐开始播放...");
			} else {
				filePath = null;
				Toast.makeText(getApplicationContext(), R.string.file_noexist,
						1).show();
			}
			break;
		// 暂停按钮
		case R.id.button_pause:
			if (mediaPlayer.isPlaying()) {// 如果正在播放
				mediaPlayer.pause();// 暂停
				pause = true;
				textView.setText("音乐暂停播放...");  
				((Button) v).setText(R.string.button_continue);// 文字:暂停-->继续
			} else {
				if (pause) {// 如果处于暂停状态
					mediaPlayer.start();// 继续播放
					pause = false;
					textView.setText("音乐继续播放...");  
					((Button) v).setText(R.string.button_pause);// 文字:继续-->暂停
				}
			}
			break;
		// 重播按钮
		case R.id.button_replay:
			if (mediaPlayer.isPlaying()) {
				textView.setText("音乐重新播放...");  
				mediaPlayer.seekTo(0);// 从开始位置开始播放音乐
			} else {
				if (filePath != null) {
					play(0);
				}
			}
			break;
		// 停止按钮
		case R.id.button_stop:
			if (mediaPlayer.isPlaying()) {
				textView.setText("音乐停止播放...");  
				mediaPlayer.stop();
			}
			break;
		}
	}

	/**
	 * 播放音乐
	 * @param playPosition 
	 */
	private void play(int playPosition) {
		try {
			mediaPlayer.reset();// 把各项参数恢复到初始状态
			/**
			 * 	通过MediaPlayer.setDataSource() 的方法,将URL或文件路径以字符串的方式传入.使用setDataSource ()方法时,要注意以下三点:
				1.构建完成的MediaPlayer 必须实现Null 对像的检查.
				2.必须实现接收IllegalArgumentException 与IOException 等异常,在很多情况下,你所用的文件当下并不存在.
				3.若使用URL 来播放在线媒体文件,该文件应该要能支持pragressive 下载.
			 */
			mediaPlayer.setDataSource(filePath);
			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 5:由于加入了监听电话的功能,所以要在AndroidManifest.xml中配置权限

<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
      package="cn.roco.mp3"
      android:versionCode="1"
      android:versionName="1.0">
    <uses-sdk android:minSdkVersion="8" />
    
    <!-- 注意:这里要加入一个监听电话的权限 -->
    <uses-permission android:name="android.permission.READ_PHONE_STATE"></uses-permission>

    <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 6: 运行效果如下,一首动听的Avril Lavigne - Complicated.mp3在播放...


  (1) (2)(3) (4)(5) (6)



如果想加入进度条等功能  可以参考 Android MediaPlayer播放网络音频的实例--网络mp3播放器    这篇文章




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

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

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

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


相关文章
|
18天前
|
编解码 网络协议 开发工具
Android平台RTSP|RTMP直播播放器技术接入说明
大牛直播SDK自2015年发布RTSP、RTMP直播播放模块,迭代从未停止,SmartPlayer功能强大、性能强劲、高稳定、超低延迟、超低资源占用。无需赘述,全自研内核,行业内一致认可的跨平台RTSP、RTMP直播播放器。本文以Android平台为例,介绍下如何集成RTSP、RTMP播放模块。
|
3月前
|
XML 存储 数据库
如何使用Android Studio创建一个基本的音乐播放器应用
如何使用Android Studio创建一个基本的音乐播放器应用
69 0
|
18天前
|
编解码 网络协议 开发工具
Android平台如何实现多路低延迟RTSP|RTMP播放?
本文档详细介绍了大牛直播SDK在Android平台上实现RTSP与RTMP流媒体播放及录像功能的技术细节。早在2015年,SDK的第一版就已经支持了多实例播放,并且通过简单的实例封装就能轻松实现。文档中提供了代码示例,展示了如何开启播放、停止播放以及开始和停止录像等功能。此外,SDK还提供了丰富的配置选项,例如设置录像目录、文件大小限制、转码选项等。总结部分列出了该SDK的关键特性,包括但不限于高稳定性和低延迟的播放能力、多实例支持、事件回调、硬解码支持、网络状态监控以及复杂的网络环境处理等。这些功能使得SDK能够应对各种应用场景,特别是在对延迟和稳定性有极高要求的情况下表现优异。
|
18天前
|
编解码 网络协议 vr&ar
Android平台下VR头显如何低延迟播放4K以上超高分辨率RTSP|RTMP流
这段内容讲述了VR头显中实现高分辨率视频播放的技术背景与实现方法,并强调了其重要性。高分辨率对于提升VR体验至关重要,它能提供更清晰的画面、增强沉浸感、补偿透镜放大效应,并维持宽广视场角下的图像质量。文中提到的大牛直播SDK具备极低的延迟(200-400ms),支持多种协议与格式,并具有丰富的功能特性,如多实例播放、事件回调、视频及音频格式支持等。此外,提供了基于Unity的播放器示例代码,展示了如何配置播放参数并开始播放。最后,作者指出此类技术在远程控制、虚拟仿真等应用场景中的重要意义。
|
18天前
|
编解码 开发工具 Android开发
Android平台RTSP|RTMP播放器如何实现TextureView渲染
本文介绍了在Android平台上使用TextureView进行RTSP和RTMP视频流渲染的技术背景和实现方法。TextureView相较于SurfaceView具备更高性能、更强功能性和更灵活的绘制方式等优势,但也有必须在硬件加速环境下运行和较高内存占用等局限。文中详细展示了如何在SmartPlayerV2工程中创建和配置TextureView,并通过代码示例解释了如何根据视频分辨率信息调整显示比例,以及处理TextureView的各种生命周期回调。此外,还列举了该播放器SDK支持的多项高级功能,如多实例播放、多种编码格式支持、硬解码能力等,旨在帮助开发者更好地理解和实现高性能的直播播放器。
|
19天前
|
算法 数据处理 开发工具
Android平台RTSP|RTMP播放器如何回调YUV或RGB数据
在开发Android平台上的RTSP或RTMP播放器时,开发者不仅追求低延迟播放,还希望获取解码后的视频数据(如YUV或RGB格式),以便进行视觉算法分析。使用大牛直播SDK中的SmartPlayer,可在确保播放流畅的同时,通过设置外部渲染器(`SmartPlayerSetExternalRender`)来高效地回调原始视频数据。例如,对于RGBA数据,需实现`NTExternalRender`接口,并重写相关方法以处理数据和尺寸变化。同样地,对于I420(YUV)数据,也需要相应地实现接口以满足需求。这种方式使得开发者能在不影响常规播放功能的情况下,进行定制化的视频处理任务。
|
2月前
|
API Android开发
Android 监听Notification 被清除实例代码
Android 监听Notification 被清除实例代码
|
3月前
|
安全 Java Android开发
使用Unidbg进行安卓逆向实例讲解
使用Unidbg进行安卓逆向实例讲解
64 2
|
3月前
|
存储 算法 Java
Android 进阶——代码插桩必知必会&ASM7字节码操作
Android 进阶——代码插桩必知必会&ASM7字节码操作
132 0
|
XML 缓存 Android开发
Android MediaPlayer 音乐播放器扫描 本地音乐、上一曲、下一曲切歌、播放本地音乐(下)
Android MediaPlayer 音乐播放器扫描 本地音乐、上一曲、下一曲切歌、播放本地音乐(下)
206 0
Android MediaPlayer 音乐播放器扫描 本地音乐、上一曲、下一曲切歌、播放本地音乐(下)