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

大家好我们今天研究的是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. */@Overridepublic 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{@Overridepublic 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;}}}/*// 当该窗口处于不可见的时候触发@Overrideprotected void onPause() {if (mediaPlayer.isPlaying()) {playPosition = mediaPlayer.getCurrentPosition();// 获得当前播放位置mediaPlayer.stop();}super.onPause();}// 当该窗口处于重新回到前台时候触发@Overrideprotected void onResume() {if (playPosition > 0 && filePath != null) {play();mediaPlayer.seekTo(playPosition);playPosition = 0;}super.onResume();}*/@Overrideprotected 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 implementsandroid.media.MediaPlayer.OnPreparedListener {private int playPosition;public MyPreparedListener(int playPosition) {this.playPosition=playPosition;}@Overridepublic 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

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


转载于:https://www.cnblogs.com/ouyangpeng/archive/2013/04/09/8538414.html

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/301526.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

AgileConfig轻量级配置中心1.3.0发布,支持多用户权限控制

AgileConfig 当初是设计给我自己用的一个工具&#xff0c;所以只设置了一道管理员密码&#xff0c;没有用户的概念。但是很多同学在使用过后都提出了需要多用户支持的建议。整个团队或者整个公司都使用同一个密码来管理非常的不方便。今天 AgileConfig 1.3.0 版本终于支持了多用…

每日一笑 | 马冬梅当上了百度投资董事???

全世界只有3.14 % 的人关注了数据与算法之美马东什么&#xff1f;&#xff08;图片来源于网络&#xff0c;侵权删&#xff09;

批处理解决局域网共享打印机问题

随着公司规模的扩大&#xff0c;人员流动性也越来越大。特别是业务这块&#xff0c;隔三差五的就来几个业务人员&#xff0c;一入职各种后勤工作都要给他们安排好。网络这块除了基本的网线&#xff0c;电话要通以外。最最后面的当然就是打印机的共享了。 先说说公司的网络环境。…

.NET MAUI 预览版 6 发布

原文&#xff1a;bit.ly/2SKad9g作者&#xff1a;.NET Blog - David译者&#xff1a;精致码农 - 王亮当我们还在从微软 Build 大会和 .NET 6 预览版 4 中缓过来的时候&#xff0c;我们在这里就开始分享我们在 .NET 6 预览版 5 中对 .NET 多平台应用程序开发框架(.NET MAUI)的持…

德国布线牛到不行?今天带你看看咱们中国的!

全世界只有3.14 % 的人关注了数据与算法之美相信不少人都有看过德国的布线&#xff0c;那整齐的感觉让人舒服。这是由BuzzFeed网站刊登的照片&#xff0c;从图片可以看出&#xff0c;德国工程师严谨的态度却是表现的淋漓尽致&#xff0c;让人大饱眼福&#xff0c;简直就是洁癖症…

Java进阶02 异常处理

作者&#xff1a;Vamei 出处&#xff1a;http://www.cnblogs.com/vamei 欢迎转载&#xff0c;也请保留这段声明。谢谢&#xff01; 程序很难做到完美&#xff0c;不免有各种各样的异常。比如程序本身有bug&#xff0c;比如程序打印时打印机没有纸了&#xff0c;比如内存不足。…

每日一笑 | 对不起,我还没下班...

全世界只有3.14 % 的人关注了数据与算法之美&#xff08;图片来源于网络&#xff0c;侵权删&#xff09;

差异分析定位Ring 3保护模块

差异分析定位Ring 3保护模块 由于保护模块通常会Hook操作系统的原生DLL接口来进行保护&#xff0c;所以可以采用差异比较原生DLL文件和加载到内存中的原生DLL直接的差别来定位Ring 3模块。 在分析的过程中&#xff0c;为了防止被Ring 3保护模块发现&#xff0c;暂时可以先把除了…

html 输入框自动缩短 一行内显示,JQuery UI组合框自动补全功能改进版(即时全部显示+input内容保存)...

JQuery UI Autocomplete(自动补全)功能在input前端设计中非常有用&#xff0c;最近一个项目正好用到&#xff0c;仔细研究了下组合框(combobox)的自动补全部分&#xff0c;官方地址是&#xff1a;https://jqueryui.com/autocomplete/#combobox。官方的功能需要一个额外下拉按钮…

Magicodes.IE 2.5.4.2发布

Magicode.IE&#xff0c;导入导出通用库&#xff0c;支持Dto导入导出、模板导出、花式导出以及动态导出&#xff0c;支持Excel、Csv、Word、Pdf和Html。Github&#xff1a;https://github.com/dotnetcore/Magicodes.IE码云&#xff08;手动同步&#xff0c;不维护&#xff09;&…

耗时6年的DK博物科普巨著,全面提升孩子的认知高度

▲数据汪特别推荐点击上图进入玩酷屋小木用真金白银来给大家送礼物啦&#xff0c;特别感谢这些年一直以来大家对我们的支持&#xff0c;才让我们越做越好。&#xff08;点我参与送礼活动&#xff09;小木每次带侄子去郊游时&#xff0c;侄子总是会不断地提问&#xff0c;“这是…

android fragmentstatepageradapter框架,安卓爬坑指南之FragmentStatePagerAdapter

一次开发中&#xff0c;用到了viewpager嵌套viewpager&#xff0c;结果就踩到了这么一个坑。先上图&#xff1a;image.png图片中显示的界面布局和遇到的问题是这样的&#xff1a;首页发现版块是一个fragment&#xff0c;这个fragment中放了一个viewpager&#xff0c;这个viewpa…

每日一笑 | 一个男人逐渐变心的过程

全世界只有3.14 % 的人关注了数据与算法之美&#xff08;图片来源于网络&#xff0c;侵权删&#xff09;

html 表格 左侧表头,左侧是表头的JS表格控件(自写,网上没有的)

今天&#xff0c;项目中要用到该表格&#xff0c;找了一遍&#xff0c;发现没有合适的&#xff0c;于是自己动手丰衣足食。最终呈现效果如上图&#xff0c;1、左侧是表头的表格数据展现&#xff0c;2、支持多行&#xff0c;多表头3、固定表头的功能4、能够支持标题5、获取表格中…

一个人的夜晚,让这些公众号来温暖你。

“外表的美只能取悦于人的眼睛&#xff0c;而内在的美却能感染人的灵魂”。阅读的内容决定了你的视野&#xff0c;转发的内容展现了你的底蕴。这些优质内容&#xff0c;你值得拥有&#xff0c;看下去你就知道。【关注方式&#xff1a;长按二维码&#xff0c;选择“识别图中二维…

grub参数介绍。

为什么80%的码农都做不了架构师&#xff1f;>>> grub的配置文件在/boot/grub/grub.conf。/etc/grub.conf和/boot/grub/menu.lst都是指向这个文件的软连接。 grub启动时&#xff0c;会寻找menu.lst文件&#xff0c;如果找不到&#xff0c;则进入grub>交互界面。…

又一次Task.Wait引起的教训

最近一用户在使用BeetleX.HttpClient组件并发访问延时比较高的https服务时引起了卡死现像。由于组件更多使用场景是内部服务和非https&#xff0c;一直没有这情况出现;但用户提供测试场景下这情况必现&#xff0c;所以翻查了一些相关代码。protected virtual void OnSslAuthent…

html盒模型向上浮动,HTML5盒模型、浮动和定位

在此之前我们先了解一下块级元素和行内元素的区别一、块级元素1、总是从新的一行开始2、高度、宽度都是可控的3、宽度没有设置时&#xff0c;默认为100%4、块级元素中可以包含块级元素和行内元素二、行内元素1、和其他元素都在一行2、高度、宽度以及内边距都是不可控的3、宽高就…

关于一个js栈溢出的异常

快一年没写web端的东西了&#xff0c;今天写了点东西。唉&#xff0c;快忘了&#xff0c;不过还好&#xff0c;基本的开发技能还是练出来了&#xff0c;这东西不能忘。 另外在这里贴点代码&#xff0c;预防以后会出现类似的情况。 javascript代码 //列表数据var appText new A…

科学中有故事,故事中有科学

▲数据汪特别推荐点击上图进入玩酷屋小木用真金白银来给大家送礼物啦&#xff0c;特别感谢这些年一直以来大家对我们的支持&#xff0c;才让我们越做越好。&#xff08;点我参与送礼活动&#xff09;孩子缺什么&#xff1f;不应该只是知识是独立思考意识、逻辑思维能力基于科学…