【Android】播放音频的几种方式介绍

时间:2023-02-22 23:39:53

接下来笔者介绍一下Android中播放音频的几种方式,android.media包下面包含了Android开发中媒体类,当然笔者不会依次去介绍,下面介绍几个音频播放中常用的类:

1.使用MediaPlayer播放音频

MediaPlayer的功能很强大,下面附上一张该类封装音频的生命周期图:

【Android】播放音频的几种方式介绍

MediaPlayer支持AAC、AMR、FLAC、MP3、MIDI、OGG、PCM等格式,MediaPlayer可以通过设置元数据和播放源来音频。

1.1播放Raw文件夹下面音频的元数据

//直接创建,不需要设置setDataSource
MediaPlayer mMediaPlayer;
mMediaPlayer=MediaPlayer.create(this, R.raw.audio);
mMediaPlayer.start();

1.2通过设置播放源来播放音频文件

setDataSource(String path)

//如果从sd卡中加载音乐
//经过笔者的测试,需要加载sd卡的读权限,这里明明是从sd卡中读取文件
// <uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE"/>
//然后就可以利用 Environment.getExternalStorageDirectory() 获取SD卡的根目录了,一般为/storage/emulated/0
//接下来把xxx.wav放到SD的根目录下,就可以获得文件的路径了 String path=Environment.getExternalStorageDirectory()+"/xxx.wav";
mMediaPlayer.setDataSource(path) ;
//如果从网络加载音乐,如果是从网络中加载那么需要设置网络权限
//<uses-permission android:name="android.permission.INTERNET"/>
mMediaPlayer.setDataSource("http://..../xxx.mp3") ;
//需使用异步缓冲
mMediaPlayer.prepareAsync() ;

setDataSource(FileDescriptor fd)

//需将资源文件放在assets文件夹
AssetFileDescriptor fd = getAssets().openFd("samsara.mp3");
mMediaPlayer.setDataSource(fd.getFileDescriptor());//经过笔者的测试,发现这个方法有时候不能播放成功,尽量使用该方法的另一个重载方法 setDataSource(FileDescptor fd,long offset,long length)
mMediaPlayer.prepare() ; Ps:此方法系统需大于等于android

setDataSource(Context context,Uri uri)

这个方法没什么好说的,一般通过ContentProvider获取Android系统提供
的共享music获取uri,然后设置数据播放

setDataSource(FileDescptor fd,long offset,long length)

 //需将资源文件放在assets文件夹
AssetFileDescriptor fd = getAssets().openFd("samsara.mp3");
mMediaPlayer.setDataSource(fd.getFileDescriptor(), fd.getStartOffset(), fd.getLength());
mMediaPlayer.prepare();

设置完数据源,不要忘记prepare(),尽量使用异步prepareAync(),这样不会阻塞UI线程。

1.3 MediaPlayer的常用方法

start();//开始播放
pause();//暂停播放
reset()//清空MediaPlayer中的数据
setLooping(boolean);//设置是否循环播放
seekTo(msec)//定位到音频数据的位置,单位毫秒
stop();//停止播放
relase();//释放资源

2.使用SoundPool播放音频

SoundPool支持多个音频文件同时播放(组合音频也是有上限的),延时短,比较适合短促、密集的场景,是游戏开发中音效播放的福音。

2.1 SoundPool实例化方式

1. new SoundPool(适用与5.0以下)

SoundPool(int maxStreams, int streamType, int srcQuality)
    从android5.0开始此方法被标记为过时,稍微说以下几个参数。
      1.maxStreams :允许同时播放的流的最大值

  2.streamType :音频流的类型描述,
                   在Audiomanager中有种类型声明,游戏应用通常会使用流媒体音乐(AudioManager.STREAM_MUSIC)
                   
      3. srcQuality:采样率转化质量,默认值为0 。

2. SoundPool.Builder(从5.0开始支持)

//设置描述音频流信息的属性
    AudioAttributes abs = new AudioAttributes.Builder()
                    .setUsage(AudioAttributes.USAGE_MEDIA)
                    .setContentType(AudioAttributes.CONTENT_TYPE_MUSIC)
                    .build() ;
    SoundPool mSoundPoll =  new SoundPool.Builder()
                    .setMaxStreams(100)   //设置允许同时播放的流的最大值
                    .setAudioAttributes(abs)   //完全可以设置为null
                    .build() ;

2.2 SoundPool的几个重要的方法

// 几个load方法和上文提到的MediaPlayer基本一致,这里的每个load都会返回一个SoundId值,这个值可以用来播放和卸载音乐。
//------------------------------------------------------------ int load(AssetFileDescriptor afd, int priority) int load(Context context, int resId, int priority) int load(String path, int priority) int load(FileDescriptor fd, long offset, long length, int priority) //------------------------------------------------------------- // 通过流id暂停播放
final void pause(int streamID) // 播放声音,soundID:音频id(这个id来自load的返回值); left/rightVolume:左右声道(默认1,1);loop:循环次数(-1无限循环,0代表不循环);rate:播放速率(1为标准),该方法会返回一个streamID,如果StreamID为0表示播放失败,否则为播放成功
final int play(int soundID, float leftVolume, float rightVolume, int priority, int loop, float rate) //释放资源(很重要)
final void release() //恢复播放
final void resume(int streamID) //设置指定id的音频循环播放次数
final void setLoop(int streamID, int loop) //设置加载监听(因为加载是异步的,需要监听加载,完成后再播放)
void setOnLoadCompleteListener(SoundPool.OnLoadCompleteListener listener) //设置优先级(同时播放个数超过最大值时,优先级低的先被移除)
final void setPriority(int streamID, int priority) //设置指定音频的播放速率,0.5~2.0(rate>1:加快播放,反之慢速播放)
final void setRate(int streamID, float rate) //停止指定音频播放
final void stop(int streamID) //卸载指定音频,soundID来自load()方法的返回值
final boolean unload(int soundID) //暂停所有音频的播放
final void autoPause() //恢复所有暂停的音频播放
final void autoResum()

下面简单演示一下SoundPool如何播放音乐:

    protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
SoundPool soundPool=new SoundPool(100,AudioManager.STREAM_MUSIC,0);//构建对象
int soundId=soundPool.load(context,R.raw.test,1);//加载资源,得到soundId
int streamId= soundPool.play(soundId, 1,1,1,-1,1);//播放,得到StreamId
// soundPool.stop(streamId);//暂停
}

利用上面的播放方式可能会播放不成功,这是因为把一段音频加载到内存在还需要一段时间,所以如果在Load方法后立即调用play,可能会播放不成功。对于这种的解决方案:

a.加载音频在OnCreate方法完成,播放在按钮中完成。

b.设置OnLoadCompleteListener监听。

栗子:

        SoundPool soundPool=new  SoundPool(100,AudioManager.STREAM_MUSIC,5);//构建对象
soundPool.setOnLoadCompleteListener(new OnLoadCompleteListener() {
@Override
public void onLoadComplete(SoundPool soundPool, int sampleId, int status) {
soundPool.play(sampleId,1,1,1,0,1);//播放
}
});
soundPool.load(this,R.raw.victory,1);//加载资源

3.使用AudioTrack播放音频

AudioTrack属于更偏底层的音频播放,MediaPlayerService的内部就是使用了AudioTrack。

AudioTrack用于单个音频播放和管理,相比于MediaPlayer具有:精炼、高效的优点。
更适合实时产生播放数据的情况,如加密的音频,
MediaPlayer是束手无策的,AudioTrack却可以。

AudioTrack用于播放PCM(PCM无压缩的音频格式)音乐流的回放,
如果要播需放其它格式音频,需要响应的解码器,
这也是AudioTrack用的比较少的原因,需要自己解码音频。

AudioTreack的2种播放模式
静态模式—static
静态的言下之意就是数据一次性交付给接收方。好处是简单高效,只需要进行一次操作就完成了数据的传递;缺点当然也很明显,对于数据量较大的音频回放,显然它是无法胜任的,因而通常只用于播放铃声、系统提醒等对内存小的操作

流模式streaming
流模式和网络上播放视频是类似的,即数据是按照一定规律不断地传递给接收方的。理论上它可用于任何音频播放的场景,不过我们一般在以下情况下采用:
    音频文件过大
    音频属性要求高,比如采样率高、深度大的数据
    音频数据是实时产生的,这种情况就只能用流模式了

通过write(byte[], int, int), write(short[], int, int)等方法推送解码数据到AudioTrack

4.使用Ringtone播放音频

Ringtone为铃声、通知和其他类似声音提供快速播放的方法,这里还不得不提到一个管理类”RingtoneManager”,提供系统铃声列表检索方法,并且,Ringtone实例需要从RingtoneManager获取。

1. 获取实例

//获取实例方法,均为RingtoneManager类提供

//1.通过铃声uri获取
static Ringtone getRingtone(Context context, Uri ringtoneUri) //2.通过铃声检索位置获取
Ringtone getRingtone(int position)

2. RingtoneManager几个重要的方法

1. // 两个构造方法
RingtoneManager(Activity activity)
RingtoneManager(Context context) 2. // 获取指定声音类型(铃声、通知、闹铃等)的默认声音的Uri
static Uri getDefaultUri(int type) 3. // 获取系统所有Ringtone的cursor
Cursor getCursor() 4. // 获取cursor指定位置的Ringtone uri
Uri getRingtoneUri(int position) 5. // 判断指定Uri是否为默认铃声
static boolean isDefault(Uri ringtoneUri) 6. //获取指定uri的所属类型
static int getDefaultType(Uri defaultRingtoneUri) 7. //将指定Uri设置为指定声音类型的默认声音
static void setActualDefaultRingtoneUri(Context context, int type, Uri ringtoneUri)

从api看,Ringtone和RingtoneManager还是比较简单的,不多做解释了,直接放上一段使用代码。

/**
* 播放来电铃声的默认音乐
*/
private void playRingtoneDefault(){
Uri uri = RingtoneManager.getDefaultUri(RingtoneManager.TYPE_RINGTONE) ;
Ringtone mRingtone = RingtoneManager.getRingtone(this,uri);
mRingtone.play();
} /**
* 随机播放一个Ringtone(有可能是提示音、铃声等)
*/
private void ShufflePlayback(){
RingtoneManager manager = new RingtoneManager(this) ;
Cursor cursor = manager.getCursor();
int count = cursor.getCount() ;
int position = (int)(Math.random()*count) ;
Ringtone mRingtone = manager.getRingtone(position) ;
mRingtone.play();
}

最后记得添加权限:

<uses-permission android:name="android.permission.MEDIA_CONTENT_CONTROL"/>
    <uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE"/>

其实,Rington这个类比较简单,只需要掌握,播放、停止(paly(),stop())等方法就可以了,而RingtoneManager却是比较重要的。

5.总结

1.对于延迟度要求不高,并且希望能够更全面的控制音乐的播放,MediaPlayer比较适合
2.声音短小,延迟度小,并且需要几种声音同时播放的场景,适合使用SoundPool
3.播放大文件音乐,如WAV无损音频和PCM无压缩音频,可使用更底层的播放方式AudioTrack。它支持流式播放,可以读取(可来自本地和网络)音频流,却播放延迟较小。
ps:据我测试AudioTrack直接支持WAV和PCM,其他音频需要解码成PCM格式才能播放。(其他无损格式没有尝试,有兴趣可以使本文提供的例子测试一下)
4. .jet的音频比较少见(有的游戏中在使用),可使用专门的播放器JetPlayer播放
5.对于系统类声音的播放和操作,Ringtone更适合、

原文连接:Android中播放音频的几种方式

【Android】播放音频的几种方式介绍的更多相关文章

  1. Android播放音频的两种方式

    一种使用MediaPlayer,使用这种方式通常是播放比较长的音频,如游戏中的背景音乐. 代码如下: private MediaPlayer mPlayer = null; mPlayer = Med ...

  2. Android录制音频的三种方式

    对于录制音频,Android系统就都自带了一个小小的应用,可是使用起来可能不是特别的灵活.所以有提供了另外的俩种. 下边来介绍下这三种录制的方式; 1.通过Intent调用系统的录音器功能,然后在录制 ...

  3. 【转】Android播放音频MediaPlayer的几种方式介绍

    接下来笔者介绍一下Android中播放音频的几种方式,android.media包下面包含了Android开发中媒体类,当然笔者不会依次去介绍,下面介绍几个音频播放中常用的类: 1.使用MediaPl ...

  4. android 定位的几种方式介绍

    [地理位置] android 定位的几种方式介绍 开发中对于地图及地理位置的定位是我们经常要用地,地图功能的使用使得我们应用功能更加完善,下面 www.androidkaifa.com 总结了一下网络 ...

  5. uni-app&amp&semi;H5&amp&semi;Android混合开发三 &vert;&vert; uni-app调用Android原生方法的三种方式

    前言: 关于H5的调用Android原生方法的方式有很多,在该片文章中我主要简单介绍三种与Android原生方法交互的方式. 一.H5+方法调用android原生方法 H5+ Android开发规范官 ...

  6. Spark部署三种方式介绍:YARN模式、Standalone模式、HA模式

    参考自:Spark部署三种方式介绍:YARN模式.Standalone模式.HA模式http://www.aboutyun.com/forum.php?mod=viewthread&tid=7 ...

  7. Mysql查看版本号的五种方式介绍

    Mysql查看版本号的五种方式介绍 作者: 字体:[增加 减小] 类型:转载 时间:2013-05-03   一.使用命令行模式进入mysql会看到最开始的提示符;二.命令行中使用status可以看到 ...

  8. MySQL查看版本号的五种方式介绍1111111

    MySQL查看版本号的五种方式介绍 1 命令行模式登录MySQL [root@localhost ~]# mysql -uroot -p Enter password: Welcome to the ...

  9. Android中播放音乐的几种方式

    前言 前几天一直在研究RxJava2,也写了记录了几篇博客,但因为工作任务原因,需要研究音频相关的知识,暂时放下Rxjava,本文的demo中,MediaPalyer 部分使用RxJava编写一点逻辑 ...

随机推荐

  1. C&num;写爬虫,版本V1&period;0

    之前看了Sql Server中的基本数据类型,发现image这个类型还是比较特殊的. 于是乎就做了一个将图片以二进制流形式存储的程序http://www.cnblogs.com/JsonZhangAA ...

  2. 安装好php后,配置httpd以便支持php3脚本

    Apache是目前应用最广的Web服务器,PHP是一种类似ASP的易学的脚本语言,而且性能和功能都比ASP要强,而MySQL又是一个Linux上应用最多的数据库系统,特别是用于网站建设,这3个软件均是 ...

  3. C&num;之属性

    在C#类中有属性这个成员,C#属性用来读写类的字段.实际上是通过get和set访问器实现的.

  4. mysql解决错误的方法-MySQL日志

    1.使用ps -ef|grep mysql查询是否有与MySQL相关的僵尸进程,如果有则强制杀掉 2.在配置文件my.cnf中配置启动错误日志: log_error = /var/log/mysql/ ...

  5. MyBatis学习总结&lowbar;14&lowbar;Mybatis使用技巧总结

    1. 区分 #{} 和 ${}的不同应用场景 1)#{} 会生成预编译SQL,会正确的处理数据的类型,而${}仅仅是文本替换.对于SQL: select * from student where xC ...

  6. Java解析XMl文件之SAX和DOm方法

    如题,这两种方法的jar包都在jdk中,不需要下载. 先来说下目录结构: 首先建一个Peron类封装person.xml的属性:DomParseService和SaxParseService分别为两种 ...

  7. 2016030207 - sql50题练习&lpar;脚本&rpar;

    我的mysql版本是5.下面是要进行sql练习题使用的脚本.脚本是我整理出来的,在我本地直接复制执行就可以使用! 参考网址是:http://blog.csdn.net/zhangyulin54321/ ...

  8. &lbrack;原创&rsqb;抢先DriverStudio夺取机器控制权&lpar;下篇&rpar;

    原文链接:抢先DriverStudio夺取机器控制权(下篇) 上篇仅仅说到如何抢先DriverStudio,并在结尾留给大家一个遐想.现在我进一步拓展这个遐想,从而给大家更多的遐想.: ) 那么现在我 ...

  9. MVC EF 修改 封装类 通用泛型方法&lpar;二&rpar;

    修改 这个 方法 如下. 排除 null 值. /// <summary> /// 修改 多数 数据, 个别数据除外, proNames 不写 则是 修改全部 /// </summa ...

  10. Ubuntu下删除VMware的方法

    一般我们都装的是Vmware workstation版的,所以,我们在终端下输入 sudo vmware-installer -u vmware-workstation 然后就会弹出vmware的卸载 ...