Android 音乐(音效)播放方式总结
一、音效的分类
音效按照作用的不同,可以将音效分为即时音效和背景音乐。两种音效在Android中的实现技术是不同的。
主要的实现方式为:SoundPool、MediaPlayer。
区别在于,MediaPlayer会在播放音频的时候,会占用大量的系统资源,并且播放的时候,还需要缓冲,有较大的时延。但是SoundPool的机制是将声音资源加载到内存中,然后在需要播放的地方进行播放,几乎没有时延,但是也正是因为这样的机制,限制了加载的文件的大小,不然会出现加载失败或者内存占用过大的情况,原则上SoundPool播放的音效的长度不应该超过7S。
所有如果需要实时播放短时间音效的话,可以使用SoundPool,如果需要播放背景音乐的话,建议使用MediaPlayer。
二、即时音效的播放—SoundPool
相关API文档地址:https://developer.android.com/reference/android/media/SoundPool.html
具体实现代码为:
public class SampleActivity extends Activity {
SoundPool sp; // 声明SoundPool的引用
HashMap<Integer, Integer> hm; // 声明一个HashMap来存放声音文件
int currStreamId;// 当前正播放的streamId
@Override
// 重写onCreate方法
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.main); // 设置layout
initSoundPool(); // 初始化声音池的方法
Button b1 = (Button) this.findViewById(R.id.Button01); // 获取播放按钮
b1.setOnClickListener // 为播放按钮添加监听器
(new OnClickListener() {
@Override
public void onClick(View v) {
playSound(1, 0); // 播放1号声音资源,且播放一次
// 提示播放即时音效
Toast.makeText(getBaseContext(), "播放即时音效", Toast.LENGTH_SHORT)
.show();
}
});
Button b2 = (Button) this.findViewById(R.id.Button02); // 获取停止按钮
b2.setOnClickListener // 为停止按钮添加监听器
(new OnClickListener() {
@Override
public void onClick(View v) {
sp.stop(currStreamId); // 停止正在播放的某个声音
// 提示停止播放
Toast.makeText(getBaseContext(), "停止播放即时音效", Toast.LENGTH_SHORT)
.show();
}
});
}
// 初始化声音池的方法
public void initSoundPool() {
sp = new SoundPool(4, AudioManager.STREAM_MUSIC, 0); // 创建SoundPool对象
hm = new HashMap<Integer, Integer>(); // 创建HashMap对象
hm.put(1, sp.load(this, R.raw.musictest, 1)); // 加载声音文件musictest并且设置为1号声音放入hm中
}
// 播放声音的方法
public void playSound(int sound, int loop) { // 获取AudioManager引用
AudioManager am = (AudioManager) this
.getSystemService(Context.AUDIO_SERVICE);
// 获取当前音量
float streamVolumeCurrent = am
.getStreamVolume(AudioManager.STREAM_MUSIC);
// 获取系统最大音量
float streamVolumeMax = am
.getStreamMaxVolume(AudioManager.STREAM_MUSIC);
// 计算得到播放音量
float volume = streamVolumeCurrent / streamVolumeMax;
// 调用SoundPool的play方法来播放声音文件
currStreamId = sp.play(hm.get(sound), volume, volume, 1, loop, 1.0f);
}
}
三、背景音效的播放—MediaPlayer
因为SoundPool只适合播放不大于7秒的音效文件,限制较大。背景音乐一般用MediaPlayer来播放。想要很好的用MediaPlayer进行音/视频的播放,首先需要熟悉MediaPlayer的生命周期。这样不仅仅有利于开发人员开发出更加合理的代码,而且可以达到充分利用系统资源的目的。
MediaPlayer的生命周期
MediaPlayer的生命周期包括10种状态,每种状态下可以调用相应的方法来实现音/视频文件的管理或播放。其各个状态及状态间的关系可以用一个简单的流程图来表示,如图所示:
Idle 状态
使用new方法创建一个MediaPlayer对象或者调用了其reset方法时,改MediaPlayer对象处于Idle 状态。
但是通过两种方式进入的idle状态还是有些区别的,主要体现为:如果这个状态下调用了getDuration等方法,若通过reset进入idle状态的话会出发onErrorListener.onError,并且MediaPlayer会进入Error状态。如果是新创建的MediaPlayer对象,则不会触发onError,也不会进入Error状态
End 状态
通过release方法可以进入End状态,只要MediaPlayer对象不再被使用了,就应当尽快将其通过release方法释放掉,以释放其占用的软、硬件资源,这其中有些资源是互斥的(相当于临界资源)。如果MediaPlayer进入了End状态,则不会再进入其他的任何状态了。
Initialized 状态
这个状态比较简单,MediaPlayer调 用 setDataSource方法就进入了 Initialized状态,表示此时要播放的文件已经设置好了。
Prepared 状态
初始化完成之后还需要通过调用prepare或 prepareAsync方法进行准备,这两个方法一个是同 步的,一个是异步的。只有进入了 Prepared状态,才表明MediaPlayer到目前为止都工作正常,可以进行音乐文件的播放。
Preparing 状态
这个状态比较容易理解,主要是与prepareAsync异步准备方法配合,如果异步准备完成,会触发OnPreparedListener.onPrepared,进而进入Prepared状态。
Started 状态
MediaPlayer准备完成后,通过调用start方法,将进入Started状态。所谓Started状态 ,也就是播放中状态,开发中可以使用isPlaying方法测试MediaPlayer是否处于Started状态。 如果播放完毕,而又设置了循环播放,则 MediaPlayer仍然会处于Started状态。类似的,如果在该状态下MediaPlayer调用了 seekTo或 者 start方法均可以让MediaPlayer停 留 在 Started状态。
Pause 状态
Started状态下调用pause方法可以暂停播放,从而进入到Pause状态。MediaPlayer暂停后再次调用start方法则可以继续进行播放,并转到Started状态。暂停状态可以调用seekTo方法,这是不会改变状态的。
Stop状态
Started或Paused状态下均可以调用stop方法停止播放并进入Stop状态,而处于Stop状态的MediaPlayer想要重新播放,需要通过调用prepareAsync或prepare方法返回到先前的Prepared状态重新开始才可以。
Play backCompleted 状态
文件正常播放完毕,而又没有设置循环播放的话就进入该状态,并会触发OnCompletionListener 接口中的onCompletion方法。此时可以调用start方法重新从头播放文件,也可以调用stop方法停 止播放,或者调用seekTo方法来重新定位播放位置。
Error状态
由于某种原因 MediaPlayer出现了错误,则会触发OnErrorListener.onError回调方法,此时MediaPlayer即进入Error状态。及时捕捉并妥善处理这些错误是很重要的,这可以帮助应用程序及 时释放相关的软、硬件资源,也可以改善用户体验。如 果 MediaPlayer进入了 Error状态,可以通过调用reset方法来恢复,使得 MediaPlayer重新返 回 到 Idle状态。
总结
从上述对生命周期的总结介绍可以看出,某些情况发生的时候,MediaPlayer会回调特定监听接口中的事件处理方法。如果在开发中希望使用回调,则需要先向MediaPlayer注册实现了指定监听接口的监听器。
引申
从上述也可以看到,Ijkplayer和这个在方法名定义上,非常类似,目前看,生命周期这块的控制基本上也是和MediaPlayer一样的。或许这也就是为什么,现在播放器大家用Ijkplayer这么多的原因了。
四、音量控制—AudioManager
AudioManager类在Android系统中主要用来进行音/视频播放时的音量控制,使用时的基本步骤如下所列。
- 首先可以调用Activity对象的getSystemService(Context.AUDIO_SERVICE)方法获取AudioManager对象。
- 然后再调用AudioManager类中的相关方法进行音量控制。
Android 音乐(音效)播放方式总结的更多相关文章
- Android点赞音效播放
/** * 音效播放 */ private SoundPool mPool; /** * 音效id */ private int voiceID; voiceID = initSoundPool(); ...
- cocos2d安卓android长音效播放不完全
是因为安卓限制了音效的内存,一般把mp3的比特率压缩一下.就可以搞定了.
- iOS开发系列--音频播放(音效和音乐)播放本地的
音频 在iOS中音频播放从形式上可以分为音效播放和音乐播放.前者主要指的是一些短音频播放,通常作为 点缀音频,对于这类音频不需要进行进度.循环等控制.后者指的是一些较长的音频,通常是主音频,对于这些音 ...
- Android音乐播放器的开发实例
本文将引导大家做一个音乐播放器,在做这个Android开发实例的过程中,能够帮助大家进一步熟悉和掌握学过的ListView和其他一些组件.为了有更好的学习效果,其中很多功能我们手动实现,例如音乐播放的 ...
- iOS: 音效和音乐的播放,封装的工具类
在iOS中音频播放从形式上可以分为音效播放和音乐播放.前者主要指的是一些短音频播放,通常作为点缀音频,对于这类音频不需要进行进度.循环等控制.后者指的是一些较长的音频,通常是主音频,对于这些音频的播放 ...
- Android音乐播放器源码(歌词.均衡器.收藏.qq5.0菜单.通知)
一款Android音乐播放器源码,基本功能都实现了 qq5.0菜单(歌词.均衡器.收藏.qq5.0菜单.通知) 只有向右滑动出现,菜单键和指定按钮都还没有添加. 源码下载:http://code.66 ...
- iOS开发--音乐文件播放工具类的封装(包含了音效的封装)
一.头文件 #import <Foundation/Foundation.h> #import <AVFoundation/AVFoundation.h> @interface ...
- 一款非常简单的android音乐播放器源码分享给大家
一款非常简单的android音乐播放器源码分享给大家,该应用虽然很小,大家常用的播放器功能基本实现了,可能有点还不够完善,大家也可以自己完善一下,源码在源码天堂那里已经有了,大家可以到那里下载学习吧. ...
- Android命令行播放MP3音乐
/*************************************************************************** * Android命令行播放MP3音乐 * 说 ...
随机推荐
- [PAClient Error] Error: E4356 File does not exist armv7
[PAClient Error] Error: E4356 File does not exist: /Users/tt/PAServer/scratch-dir/Administrator-snIO ...
- 2.Yum仓库优化
1.[初始yum源备份]-[yum更换为国内源]-[添加epel扩展源] #!/bin/bash mkdir /etc/yum.repos.d/backup/ mv /etc/yum.repos.d/ ...
- 通过DMS连接RDS需要添加的DMS白名单地址
10.152.163.0/24,139.224.4.0/24,11.193.54.0/24,101.37.74.0/24,10.137.42.0/24,121.43.18.0/24
- mongodb mongod 启动参数
我们可以通过mongod --help查看mongod的所有参数说明,以下是各参数的中文解释. 基本配置 –quiet# 安静输出 –port arg# 指定服务端口号,默认端口27017 –bind ...
- URL和URI
(一)URL和URI是什么 1.URL(Universal Resource Locator) 是统一资源定位符,对可以从互联网上得到的资源的位置和访问方法的一种简洁的表示,是互联网上标准资源的地址. ...
- cdnbest如何让用户访问走最近最快的线路(分组线路)
用户访问网站有时网络有互通的问题,cdnbest的分组解析可以细分线路,让用户访问自动走最优线路,线路不细分都加默认里,访问的节点是随机分配的 下面我们讲下如何设置: 比如你有电信,移动,和国外的节点 ...
- Numpy三维数组的转置与交换轴
二维数组的转置应该都知道,就是行列交换 而在numpy中也可以对三维数组进行转置,np.T 默认进行的操作是将0轴与2轴交换 本文主要对三位数组轴交换的理解上发表本人的看法. a = np.array ...
- 100道c++面试题(上)
1. new, delete, malloc, free关系 new/delete是c++的运算符,delete会调用对象的析构函数: malloc/free是c/c++的标准库函数,free只释放内 ...
- 186. Reverse Words in a String II 翻转有空格的单词串 里面不变
[抄题]: Given an input string , reverse the string word by word. Example: Input: ["t"," ...
- 529. Minesweeper扫雷游戏
[抄题]: Let's play the minesweeper game (Wikipedia, online game)! You are given a 2D char matrix repre ...