Android 多媒体MediaPlayer使用详解
现在的手机功能越来越丰富了,遥想10年前,MP3,MP4,MP5,还是很流行的,博主当时读高中时很想拥有一台,可以听音乐和看电影。可是条件有限,学校也禁止此东西,所以只能偷偷的玩。而现在我们的手机也很早以前就支持了这些功能,而且界面和功能也远远超过了MP4。好吧,说多了,今天本文介绍的是Andriod系统自带的Mediaplayer,和VideoView实现简单的音乐和视频的播放,至于想做出如酷狗音乐这样的APP的话,只要想做,应该也不难,都是基于此实现了功能的扩展。
Android的MediaPlayer包含了Audio和Video的播放功能,在Android的界面上,Music和Video两个应用程序都是调用MediaPlaer来实现的。
一、播放音频文件
首先看看MediaPlaer的生命周期
下面是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 | 停止播放 |
MediaPlayer的工作流程是这样的:
1,首先创建MediaPlaer对象; *
2,然后调用setDataSource()方法来设置音频文件的路径;**
3,再调用prepare()方法使MediaPlayer进入到准备状态;
4,调用start方法就可以播放音频。
* 创建MediaPlaer对象有两种方式
a 直接new出来
- MediaPlayer mp = new MediaPlayer();
b 使用create方式
- MediaPlayer mp = MediaPlayer.create(this, R.raw.test);//这时就不用调用setDataSource了
当然上面首先得在res文件夹下新建raw文件夹,并放置一个test文件
** 设置播放的文件
MediaPlayer要播放的文件主要包括3个来源:
a. 用户在应用中事先自带的resource资源
例如:MediaPlayer.create(this, R.raw.test);
b. 存储在SD卡或其他文件路径下的媒体文件
例如:mp.setDataSource("/sdcard/test.mp3");
c. 网络上的媒体文件
例如:mp.setDataSource("http://www.citynorth.cn/music/confucius.mp3");
MediaPlayer的setDataSource一共四个方法:
setDataSource (String path)
setDataSource (FileDescriptor fd)
setDataSource (Context context, Uri uri)
setDataSource (FileDescriptor fd, long offset, long length)
其中使用FileDescriptor时,需要将文件放到与res文件夹平级的assets文件夹里,然后使用:
AssetFileDescriptor fileDescriptor = getAssets().openFd("rain.mp3");
m_mediaPlayer.setDataSource(fileDescriptor.getFileDescriptor(),fileDescriptor.getStartOffset(), fileDescriptor.getLength());
来设置datasource
先简单看下效果图吧
上面的功能一看就知道了,就不用我说了吧
下面是实现代码
activity_main.xml
- <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
- android:layout_width="match_parent"
- android:layout_height="match_parent"
- android:layout_margin="3dp"
- android:orientation="vertical" >
- <LinearLayout
- android:layout_width="match_parent"
- android:layout_height="wrap_content"
- android:orientation="horizontal" >
- <Button
- android:id="@+id/play"
- android:layout_width="0dp"
- android:layout_height="wrap_content"
- android:layout_weight="1"
- android:text="播放" />
- <Button
- android:id="@+id/pause"
- android:layout_width="0dp"
- android:layout_height="wrap_content"
- android:layout_weight="1"
- android:text="暂停" />
- <Button
- android:id="@+id/stop"
- android:layout_width="0dp"
- android:layout_height="wrap_content"
- android:layout_weight="1"
- android:text="停止" />
- </LinearLayout>
- <SeekBar
- android:id="@+id/seekbar"
- android:layout_width="match_parent"
- android:layout_height="wrap_content"
- android:max="0"
- android:progress="0"
- android:secondaryProgress="0" />
- <RelativeLayout
- android:layout_width="match_parent"
- android:layout_height="wrap_content" >
- <TextView
- android:id="@+id/tv"
- android:layout_width="wrap_content"
- android:layout_height="wrap_content"
- android:layout_alignParentLeft="true"
- android:text="当前时间" />
- <TextView
- android:id="@+id/tv2"
- android:layout_width="wrap_content"
- android:layout_height="wrap_content"
- android:layout_alignParentRight="true"
- android:text="总时间" />
- </RelativeLayout>
- </LinearLayout>
MainActivity.java
- package com.example.musicplayer;
- import java.io.File;
- import java.io.IOException;
- import android.R.integer;
- import android.app.Activity;
- import android.media.MediaPlayer;
- import android.os.Bundle;
- import android.os.Environment;
- import android.os.Handler;
- import android.os.Message;
- import android.util.Log;
- import android.view.Menu;
- import android.view.MenuItem;
- import android.view.View;
- import android.view.View.OnClickListener;
- import android.widget.Button;
- import android.widget.SeekBar;
- import android.widget.SeekBar.OnSeekBarChangeListener;
- import android.widget.TextView;
- public class MainActivity extends Activity implements OnClickListener,
- OnSeekBarChangeListener {
- private Button play, pause, stop;
- private MediaPlayer player;
- private SeekBar mSeekBar;
- private TextView tv, tv2;
- private boolean hadDestroy = false;
- private Handler mHandler = new Handler() {
- public void handleMessage(android.os.Message msg) {
- switch (msg.what) {
- case 0x01:
- break;
- default:
- break;
- }
- };
- };
- Runnable runnable = new Runnable() {
- @Override
- public void run() {
- if (!hadDestroy) {
- mHandler.postDelayed(this, 1000);
- int currentTime = Math
- .round(player.getCurrentPosition() / 1000);
- String currentStr = String.format("%s%02d:%02d", "当前时间 ",
- currentTime / 60, currentTime % 60);
- tv.setText(currentStr);
- mSeekBar.setProgress(player.getCurrentPosition());
- }
- }
- };
- @Override
- protected void onCreate(Bundle savedInstanceState) {
- super.onCreate(savedInstanceState);
- setContentView(R.layout.activity_main);
- play = (Button) findViewById(R.id.play);
- pause = (Button) findViewById(R.id.pause);
- stop = (Button) findViewById(R.id.stop);
- mSeekBar = (SeekBar) findViewById(R.id.seekbar);
- tv = (TextView) findViewById(R.id.tv);
- tv2 = (TextView) findViewById(R.id.tv2);
- mSeekBar.setOnSeekBarChangeListener(this);
- play.setOnClickListener(this);
- pause.setOnClickListener(this);
- stop.setOnClickListener(this);
- player = new MediaPlayer();
- initMediaplayer();
- }
- /**
- * 初始化播放器
- */
- private void initMediaplayer() {
- try {
- File file = new File(Environment.getExternalStorageDirectory()
- + "/Download/", "aiqiu.mp3");
- player.setDataSource(file.getPath());
- Log.e("播放器", file.toString());
- player.prepare();
- } catch (Exception e) {
- e.printStackTrace();
- }
- }
- @Override
- public void onClick(View v) {
- switch (v.getId()) {
- case R.id.play:
- if (!player.isPlaying()) {
- player.start();
- int totalTime = Math.round(player.getDuration() / 1000);
- String str = String.format("%02d:%02d", totalTime / 60,
- totalTime % 60);
- tv2.setText(str);
- mSeekBar.setMax(player.getDuration());
- mHandler.postDelayed(runnable, 1000);
- }
- break;
- case R.id.pause:
- if (player.isPlaying()) {
- player.pause();
- }
- break;
- case R.id.stop:
- if (player.isPlaying()) {
- player.reset();
- initMediaplayer();
- }
- break;
- default:
- break;
- }
- }
- @Override
- public void onProgressChanged(SeekBar seekBar, int progress,
- boolean fromUser) {
- if (player != null) {
- player.seekTo(seekBar.getProgress());
- }
- }
- @Override
- public void onStartTrackingTouch(SeekBar seekBar) {
- // TODO 自动生成的方法存根
- }
- @Override
- public void onStopTrackingTouch(SeekBar seekBar) {
- // TODO 自动生成的方法存根
- }
- @Override
- protected void onDestroy() {
- // TODO 自动生成的方法存根
- super.onDestroy();
- if (player != null) {
- player.stop();
- hadDestroy = true;
- player.release();
- }
- }
- }
二、播放视频文件
播放视频文件相比播放音频文件并不比它复杂,这里使用VideoView类来实现。这个类将视频的显示和控制集于一身。
VideoView和MediaPlaer也比较类似,主要有以下常用方法
|
方法名 |
功能描述 |
|
setVideoPath() |
设置要播放的视频文件的位置。 |
|
start() |
开始或继续播放视频。 |
|
pause() |
暂停播放视频。 |
|
resume() |
将视频重头开始播放。 |
|
seekTo() |
从指定的位置开始播放视频。 |
|
isPlaying() |
判断当前是否正在播放视频。 |
|
getDuration() |
获取载入的视频文件的时长。 |
因为VideoView是包装过的MediaPlayer,所以使用起来很相似。
比如:
- private void initVideoPlayer() {
- File file = new File(Environment.getExternalStorageDirectory()
- + "/Download/", "Sample.3gp");
- videoPlayer.setVideoPath(file.getPath());// 指定视频文件的路径
- }
事件处理
- @Override
- public void onClick(View v) {
- switch (v.getId()) {
- case R.id.play:
- if (!videoPlayer.isPlaying()) {
- videoPlayer.start();
- }
- break;
- case R.id.pause:
- if (videoPlayer.isPlaying()) {
- videoPlayer.pause();
- }
- break;
- case R.id.stop:
- if (videoPlayer.isPlaying()) {
- videoPlayer.resume();
- }
- break;
- default:
- break;
- }
- }
三、常见的MediaPlayer错误
也就是它的错误状态。比如这样的错误 start called in state 0,0表示他的错误状态,下面是MediaPlayer的状态,源码中找到的:
- enum media_player_states {
- MEDIA_PLAYER_STATE_ERROR = 0, // 0状态
- MEDIA_PLAYER_IDLE = 1 << 0, // 1状态
- MEDIA_PLAYER_INITIALIZED = 1 << 1, // 2 状态
- MEDIA_PLAYER_PREPARING = 1 << 2, // 4 状态
- MEDIA_PLAYER_PREPARED = 1 << 3, // 8状态
- MEDIA_PLAYER_STARTED = 1 << 4, // 16状态
- MEDIA_PLAYER_PAUSED = 1 << 5, // 32状态
- MEDIA_PLAYER_STOPPED = 1 << 6, // 64 状态
- MEDIA_PLAYER_PLAYBACK_COMPLETE = 1 << 7, // 128 状态
- }
可以参照报错的状态和MediaPlayer的生命周期(上图)进行错误分析。
Android 多媒体MediaPlayer使用详解的更多相关文章
- Android JNI作用及其详解
Android JNI作用及其详解 Java Native Interface (JNI)标准是Java平台的一部分,它允许Java代码和其他语言写的代码进行交互.JNI 是本地编程接口,它使得在 J ...
- Android开发之MdiaPlayer详解
Android开发之MdiaPlayer详解 MediaPlayer类可用于控制音频/视频文件或流的播放,我曾在<Android开发之基于Service的音乐播放器>一文中介绍过它的使用. ...
- 《Android NFC 开发实战详解 》简介+源码+样章+勘误ING
<Android NFC 开发实战详解>简介+源码+样章+勘误ING SkySeraph Mar. 14th 2014 Email:skyseraph00@163.com 更多精彩请直接 ...
- Android开发之InstanceState详解
Android开发之InstanceState详解 本文介绍Android中关于Activity的两个神秘方法:onSaveInstanceState() 和 onRestoreInstanceS ...
- ANDROID L——Material Design详解(UI控件)
转载请注明本文出自大苞米的博客(http://blog.csdn.net/a396901990),谢谢支持! Android L: Google已经确认Android L就是Android Lolli ...
- android bundle存放数据详解
转载自:android bundle存放数据详解 正如大家所知道,Activity之间传递数据,是将数据存放在Intent或者Bundle中 例如: 将数据存放倒Intent中传递: 将数据放到Bun ...
- Cordova 打包 Android release app 过程详解
Cordova 打包 Android release app 过程详解 时间 -- :: SegmentFault 原文 https://segmentfault.com/a/119000000517 ...
- Android中Service(服务)详解
http://blog.csdn.net/ryantang03/article/details/7770939 Android中Service(服务)详解 标签: serviceandroidappl ...
- 给 Android 开发者的 RxJava 详解
我从去年开始使用 RxJava ,到现在一年多了.今年加入了 Flipboard 后,看到 Flipboard 的 Android 项目也在使用 RxJava ,并且使用的场景越来越多 .而最近这几个 ...
随机推荐
- docker images 详解
docker images 用于查看本地已下载的镜像 [root@localhost ~]$ docker images REPOSITORY TAG IMAGE ID CREATED SIZE ce ...
- win10下安装Oracle 11g 32位客户端遇到INS-13001环境不满足最低要求
在以管理员身份运行setup.exe之后,出现了:[INS-13001]环境不满足最低要求,通过网上搜索之后找到了解决途径 首先,打开你的解压后的database文件夹,找到stage,然后cvu,找 ...
- .net 防盗链
Global.asax 文件中 protected void Application_BeginRequest(object sender, EventArgs e) { //判断当前请求是否是访问 ...
- kubernetes 创建tomcat 容器
方案一: 使用k8s dashboard 创建rc 1. 界面操作 提示:暂时 忽略 查看: 2.测试 由于是外部服务 直接用 节点的ip访问: 同样也是 第二个端口可以访问.感觉 跟之前的提 ...
- EF批量添加,删除,修改的扩展
在EF各版本中,没有相应批量的添加,删除,修改,在用ORM 处理数据时直有个尴尬.在网上,也接到了很多网友的询问这方面的情况,特此今天把这方面的相关扩展分享一下,(这里只做批量删除的例子,添加和修改的 ...
- Python爬虫框架Scrapy实例(一)
目标任务:爬取腾讯社招信息,需要爬取的内容为:职位名称,职位的详情链接,职位类别,招聘人数,工作地点,发布时间. 一.创建Scrapy项目 scrapy startproject Tencent 命令 ...
- Jury Compromise---poj1015(动态规划,dp,)
题目链接:http://poj.org/problem?id=1015 大致题意: 在遥远的国家佛罗布尼亚,嫌犯是否有罪,须由陪审团决定.陪审团是由法官从公众中挑选的.先随机挑选n 个人作为陪审团的候 ...
- 《图解HTTP》书摘
图解HTTP 上野宣.于均良 1.3 网络基础 TCP/IP 2016-03-03 相互通信,双方就必须基于相同的方法.比如,如何探测到通信目标.由哪一边先发起通信.使用哪种语言进行通信.怎样结束通信 ...
- 深入理解flannel
1 概述 根据官网的描述,flannel是一个专为kubernetes定制的三层网络解决方案.它主要用于解决容器的跨主机通信问题.首先我们来简单看一下,它是如何工作的. 首先,flannel会利用Ku ...
- 【我的Android进阶之旅】解决sqlcipher库:java.lang.IllegalStateException: get field slot from row 0 col 0 failed.
一.背景 最近维护公司的大数据SDK,在大数据SDK里面加入了ANR的监控功能,并将ANR的相关信息通过大数据埋点的方式记录到了数据库中,然后大数据上报的时候上报到大数据平台,这样就可以实现ANR性能 ...