Android MediaPlayer 播放音频的方式
作者:Android_note 发布时间:2021-09-07 07:27:09
主要介绍使用MediaPlayer播放音频的方式。关于MediaPlayer的基础知识,比如状态,可以参考Android MediaPlayer 基础简介。
为了方便表达,定义变量名为mediaPlayer。
MediaPlayer的使用方式
创建MediaPlayer
可以直接 new MediaPlayer,也可以用MediaPlayer提供的create方法创建。
mediaPlayer = new MediaPlayer();
使用create方法创建成功后,mediaPlayer处于Prepared状态。可以直接start播放。
mediaPlayer = MediaPlayer.create(getApplicationContext(), Uri.fromFile(file));
mediaPlayer.start();
设置音源 - setDataSource
通过调用setDataSource来设置音源。setDataSource有多个重载方法,我们来看常用的几种。
例如设置使用assets里的资源。实际情况可能需要try catch。
AssetFileDescriptor fd = null;
MediaPlayer mediaPlayer = new MediaPlayer();
fd = context.getApplicationContext().getAssets().openFd(name);
mediaPlayer.setDataSource(fd.getFileDescriptor(), fd.getStartOffset(), fd.getLength());
本地文件,需要文件的绝对路径。
mediaPlayer.setDataSource(file.getAbsolutePath());
或者获取文件的Uri来创建mediaPlayer。
mediaPlayer = MediaPlayer.create(getApplicationContext(), Uri.fromFile(file));
设置网络音频,也是用setDataSource方法,设置url。
mediaPlayer.setDataSource("https://demo.com/sample.mp3"));
播放网络音频时,如果使用的是http,有可能会报错
java.io.IOException: Cleartext HTTP traffic to demo.com not permitted
可以简单地设置一下manifest,设置usesCleartextTraffic=”true”
<application
android:usesCleartextTraffic="true">
准备 - prepare
同步和异步准备音频资源。prepareAsync()
是异步的方式,prepare是同步的。注意线程调度问题,同时不要阻塞UI线程。
使用异步方式准备音频,经常与MediaPlayer.OnPreparedListener
* 配合使用。异步准备时,也可以进行其他的设置。
mediaPlayer.prepareAsync();
mediaPlayer.setOnPreparedListener(new MediaPlayer.OnPreparedListener() {
@Override
public void onPrepared(MediaPlayer mediaPlayer) {
mediaPlayer.start(); // 准备好了就播放
}
});
循环播放 - Looping
设置循环播放setLooping。
mediaPlayer.setLooping(true);
播放完毕后,不会回调OnCompletionListener,而是从头播放当前音频。
播放 - start
播放音频,调用start方法。
mediaPlayer.start();
处于Prepared,Pause和PlaybackComplete状态时,可以调用start方法,进入Started状态。
暂停 - pause
暂停播放,使用pause方法。在暂停前先判断一下mediaPlayer的是否在播放。
if (mediaPlayer.isPlaying()) {
mediaPlayer.pause();
}
暂停成功则处于Paused状态。
停止 - stop
回顾一下MediaPlayer状态切换的图示,我们可以得知在播放中,暂停,播放完成这3个状态下,可以调用stop方法,进入Stopped状态。
mediaPlayer.stop();
调进度 - seekTo
调整播放进度。我们平时使用音乐播放软件一般都会有这个功能。
seekTo方法接受一个毫秒参数。
int targetMS = (int) (percent * mediaPlayer.getDuration());
mediaPlayer.seekTo(targetMS);
seekTo并不会改变MediaPlayer的状态。
int targetMS = (int) (percent * mediaPlayer.getDuration());
mediaPlayer.seekTo(targetMS);
reset后的mediaPlayer进入Idle状态。需要重新设置音源与准备。
释放 - release
不再使用这个mediaPlayer时,应当尽快释放掉,以释放相关的资源。
调用release后,mediaPlayer进入End状态。此时这个mediaPlayer就不能再使用了。
常用 *
缓冲 * OnBufferingUpdateListener
比如我们加载网络音频的时候,常用这个 * 来监听缓冲进度。显示缓冲进度,也可以提高用户体验。
mMediaPlayer.prepareAsync();
mMediaPlayer.setOnBufferingUpdateListener(new MediaPlayer.OnBufferingUpdateListener() {
@Override
public void onBufferingUpdate(MediaPlayer mp, int percent) {
// percent代表缓冲百分比
}
});
错误 * OnErrorListener
mediaPlayer.setOnErrorListener(new MediaPlayer.OnErrorListener() {
@Override
public boolean onError(MediaPlayer mediaPlayer, int i, int i1) {
return true; // 返回true表示在此处理错误,不会回调onCompletion
}
});
注意onError的返回值。可以选择自己处理error。
* @return True if the method handled the error, false if it didn't.
* Returning false, or not having an OnErrorListener at all, will
* cause the OnCompletionListener to be called.
*/
boolean onError(MediaPlayer mp, int what, int extra);
播放完毕 * OnCompletionListener
mediaPlayer.setOnCompletionListener(new MediaPlayer.OnCompletionListener() {
@Override
public void onCompletion(MediaPlayer mediaPlayer) {
// 播放完毕
}
});
使用示例
播放assets里的音频
播放assets里的音频文件,使用到AssetFileDescriptor类。使用后记得关闭AssetFileDescriptor。
private void playAssetsAudio(final String name, Context context) {
Log.d(TAG, "playAssetWordSound: try to play assets sound file. -> " + name);
AssetFileDescriptor fd = null;
try {
MediaPlayer mediaPlayer;
Log.v(TAG, "Looking in assets.");
fd = context.getApplicationContext().getAssets().openFd(name);
mediaPlayer = new MediaPlayer();
mediaPlayer.reset();
mediaPlayer.setDataSource(fd.getFileDescriptor(), fd.getStartOffset(), fd.getLength());
mediaPlayer.prepareAsync();
mediaPlayer.setOnPreparedListener(new MediaPlayer.OnPreparedListener() {
@Override
public void onPrepared(MediaPlayer mediaPlayer) {
Log.d(TAG, "onPrepared: " + name);
mediaPlayer.start();
}
});
mediaPlayer.setOnCompletionListener(new MediaPlayer.OnCompletionListener() {
@Override
public void onCompletion(MediaPlayer mp) {
mp.release();
Log.d(TAG, "onCompletion: " + name);
}
});
mediaPlayer.setOnErrorListener(new MediaPlayer.OnErrorListener() {
@Override
public boolean onError(MediaPlayer mp, int i, int i1) {
mp.release();
return true;
}
});
} catch (Exception e) {
try {
if (fd != null) {
fd.close();
}
} catch (Exception e1) {
Log.e(TAG, "Exception close fd: ", e1);
}
} finally {
if (fd != null) {
try {
fd.close();
} catch (IOException e) {
Log.e(TAG, "Finally, close fd ", e);
}
}
}
}
播放本地音频文件
尝试播放音频文件。仅播放一次。
private void playAudioFile(final File file) {
Log.d(TAG, "playAudioFile: " + file.getAbsolutePath());
MediaPlayer mediaPlayer;
try {
mediaPlayer = new MediaPlayer();
mediaPlayer.setLooping(false);
mediaPlayer.setDataSource(file.getAbsolutePath());
mediaPlayer.prepare();
mediaPlayer.start();
mediaPlayer.setOnCompletionListener(new MediaPlayer.OnCompletionListener() {
@Override
public void onCompletion(MediaPlayer mp) {
mp.release();
}
});
mediaPlayer.setOnErrorListener(new MediaPlayer.OnErrorListener() {
@Override
public boolean onError(MediaPlayer mediaPlayer, int i, int i1) {
Log.d(TAG, "Play local sound onError: " + i + ", " + i1);
return true;
}
});
} catch (Exception e) {
Log.e(TAG, "playAudioFile: ", e);
}
}
播放在线音频
设置url,播放在线音频
private void playOnlineSound(String soundUrlDict) {
try {
MediaPlayer mediaPlayer = new MediaPlayer();
mediaPlayer.setDataSource(soundUrlDict);
mediaPlayer.prepareAsync();
mediaPlayer.setOnPreparedListener(new MediaPlayer.OnPreparedListener() {
@Override
public void onPrepared(MediaPlayer mediaPlayer) {
mediaPlayer.start();
}
});
mediaPlayer.setOnCompletionListener(new MediaPlayer.OnCompletionListener() {
@Override
public void onCompletion(MediaPlayer mp) {
if (mp != null) {
mp.release();
}
Log.d(TAG, "onCompletion: play sound.");
}
});
mediaPlayer.setOnErrorListener(new MediaPlayer.OnErrorListener() {
@Override
public boolean onError(MediaPlayer mediaPlayer, int i, int i1) {
Log.d(TAG, "Play online sound onError: " + i + ", " + i1);
return false;
}
});
} catch (IOException e1) {
Log.e(TAG, "url: ", e1);
}
}
代码可以参考示例工程: https://github.com/RustFisher/android-MediaPlayer
总结
以上所述是小编给大家介绍的Android MediaPlayer 播放音频的方式,网站的支持!
如果你觉得本文对你有帮助,欢迎转载,烦请注明出处,谢谢!
来源:https://rustfisher.com/2019/09/22/Android/Android-MediaPlayer_use_play_audio/


猜你喜欢
- 前言StringJoiner是Java里1.8新增的类,主要是帮助我们把一个列表拼接字符串, 或许有一部分人没有接触过. 所以本文将从使用例
- C# 关于Invoke首先说下,invoke和begininvoke的使用有两种情况:control中的invoke、begininvoke
- 之前写过一篇获取properties文件里面的值:Springboot 指定获取自己写的配置properties文件的值www.jb51.n
- tcp客户端示例#include <errno.h> #include <sys/socket.h> #includ
- 本文描述了TCP协议,首先简单介绍了TCP完成了一些什么功能;介绍了TCP报文格式,以及典型报文的数据格式;接着从链路控制和数据传输两个方面
- Android ActionBarActivity设置全屏无标题实现方法总结前言:新建的Activity继承自ActionBar
- 自用项目中统一Eclipse格式化Java、JavaScript、JSP、HTML代码设置1.Window->Preferences
- 引言二分查找底层依赖的是数组随机访问的特性,所以只能用数组来实现。如果数据存储在链表中,就真的没法用二分查找算法了吗?实际上,只需要对链表稍
- 在J2EE项目的开发中,不管是对底层的数据库操作过程,还是业务层的处理过程,还是控制层的处理过程,都不可避免会遇到各种可预知的、不可预知的异
- 前言:最近公司在项目开发中,由于华为手机存在部分的问题。所以购买了部分新款的华为手机。在真机调试项目APP时,老是无法出现Logcat打印出
- 本文实例讲述了C#判断日期是否到期的方法,在C#程序开发中非常具有实用价值。分享给大家供大家参考之用。具体方法如下:一般在用户权限系统中,有
- 前言在开发过程中,使用模板引擎是很有必要的。jsp已经明显跟不上时代发展了,freemarker用的够够的?换thymeleaf试试吧。sp
- session超时退到登录页面最近发现使用的工程居然没有session超时机制,功能太欠缺了,现在把追加方法分享出来,里面有一些坑,大家自由
- 前言今天给大家带来一个新的控件–轮播图,网上已经有很多这类的博客来讲解如何实现的,那么我的这个有哪些特点呢?或是说有哪些不同呢?满足了轮播图
- 什么是AppWidget?AppWidget就是我们平常在桌面上见到的那种一个个的小窗口,利用这个小窗口可以给用户提供一些方便快捷的操作。
- Android 调用系统应用的方法总结1、调用系统拍照Intent intent = new Intent("andr
- 前不久看到鸿洋大大的圆形菜单,就想开始模仿,因为实在是太酷了,然后自己根据别人(zw哥)给我讲的一些思路、一些分析,就开始改造自己的圆形菜单
- 本文实例讲述了C#操作注册表的方法。分享给大家供大家参考,具体如下:下面我们就来用.NET下托管语言C#注册表操作,主要内容包括:注册表项的
- 一、前言我们经常会遇到业务想看debug日志的问题,但是debug日志频繁打印会对日志查看有影响,且日志多对系统也会有一定的压力,因此,如果
- 最近碰到这个问题,在使用spring提供的JpaTemplate进行查询时,如果数据量超过100 条,查询效率就会明显降低。由于开始时使用J