Android应用开发学习笔记之播放音频
作者:刘昊昱
博客:http://blog.csdn.net/liuhaoyutz
Android支持常用音视频格式文件的播放,本文我们来学习怎样开发Android应用程序对音视频进行操作。
Android提供了MediaPlayer和SoundPool两个类能够用来播放音频,MediaPlayer类通常用来播放较大的文件,比如一首MP3歌曲,这种文件通常保存在SD卡上,而不是保存在资源文件中,当然如果有必要,也可以保存在资源文件中。SoundPool类通常用来播放体积较小的文件,比如游戏中的炸弹爆炸声,这种文件通常保存在资源文件目录res/raw中。MediaPlayer一次只能播放一个文件,而SoundPool可同时播放多个音频文件。
一、用MediaPlayer播放音频
下面我们先来怎样看用MediaPlayer来控制音频播放。
(1)关联MediaPlayer对象与音频文件
用MediaPlayer播放音频文件,首先需要做的是把MediaPlayer对象与音频文件相关联,关联有两种方式,一是直接使用MediaPlayer.create()函数创建关联好音频文件的MediaPlayer对象;二是先创建一个MediaPlayer对象,然后再使用MediaPlayer.setDataSource()关联音频文件。
我们先来看MediaPlayer.create(),create()函数有以下几种格式:
static MediaPlayer |
create(Context context, Uri uri, SurfaceHolder holder) Convenience method to create a MediaPlayer for a given Uri. |
static MediaPlayer |
create(Context context, int resid) Convenience method to create a MediaPlayer for a given resource id. |
static MediaPlayer |
create(Context context, Uri uri) Convenience method to create a MediaPlayer for a given Uri. |
例如:
MediaPlayer player =MediaPlayer.create(this, R.raw.r);
MediaPlayer player =MediaPlayer.create(this, Uri.parse(“http://www.music.com/song/1.mp3”));
注意在访问网络资源时,要获得网络权限,即在AndroidManifest.xml文件中增加如下语句:
<uses-permissionandroid:name="android.permission.INTERNET" />
MediaPlayer类有一个无参数的构造函数,我们可以使用这个构造函数创建一个MediaPlayer对象,再使用MediaPlayer.setDataSource()函数关联MediaPlayer对象与音频文件。
setDataSource()函数有如下几种形式:
void |
setDataSource(String path) Sets the data source (file-path or http/rtsp URL) to use. |
void |
setDataSource(Context context, Uri uri, Map<String, String> headers) Sets the data source as a content Uri. |
void |
setDataSource(Context context, Uri uri) Sets the data source as a content Uri. |
void |
setDataSource(FileDescriptor fd, long offset, long length) Sets the data source (FileDescriptor) to use. |
void |
setDataSource(FileDescriptor fd) Sets the data source (FileDescriptor) to use. |
需要注意的是,在使用setDataSource关联MediaPlayer对象和音频资源后,还不能直接对音频资源进行播放等操作,还需要调用MediaPlayer.prepare方法真正装载音频文件。
例如:
MediaPlayer player = new MediaPlayer();
try{
player.setDataSource(“/sdcard/s.wav”);
}catch(IOException e){
e.printStackTrace();
}
try{
player.prepare();
}catch(IOException e){
e.printStackTrace();
}
(2)使用MediaPlayer对音频资源进行控制操作
常用的控制函数如下:
MediaPlayer.start():开始播放音频或恢复播放已经暂停的音频。
MeidaPlayer.stop():停止正在播放的音频。
MediaPlayer.pause():暂停正在播放的音频。
(3)MediaPlayer播放实例
下面我们来看一个使用MediaPlayer播放音频文件的具体例子,该程序运行效果如下:
主布局文件内容如下:
<?xml version="1.0"encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="fill_parent"
android:layout_height="fill_parent"
android:orientation="vertical" > <TextView
android:id="@+id/hint"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:padding="10px"
android:text="单击“播放”按钮播放音频" /> <LinearLayout
android:id="@+id/linearLayout1"
android:layout_width="match_parent"
android:layout_height="wrap_content" >
<Button
android:id="@+id/button1"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="播放" /> <Button
android:id="@+id/button2"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:enabled="false"
android:text="暂停" /> <Button
android:id="@+id/button3"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:enabled="false"
android:text="停止" />
</LinearLayout>
</LinearLayout>
主Activity文件内容如下:
package com.liuhaoyu; import java.io.File; import android.app.Activity;
import android.media.MediaPlayer;
import android.media.MediaPlayer.OnCompletionListener;
import android.net.Uri;
import android.os.Bundle;
import android.view.View;
import android.view.View.OnClickListener;
import android.widget.Button;
import android.widget.TextView; public classMainActivity extends Activity {
private MediaPlayer player;
private boolean isPause = false;
private File file;
private TextView hint; @Override
public void onCreate(BundlesavedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.main);
final Button button1 =(Button) findViewById(R.id.button1);
final Button button2 =(Button) findViewById(R.id.button2);
final Button button3 =(Button) findViewById(R.id.button3);
hint = (TextView)findViewById(R.id.hint);
file = new File("/sdcard/1.mp3");
if (file.exists()) {
player = MediaPlayer
.create(this, Uri.parse(file.getAbsolutePath()));
}else{
hint.setText("要播放的音频文件不存在!");
button1.setEnabled(false);
return;
} player.setOnCompletionListener(new OnCompletionListener(){ @Override
public voidonCompletion(MediaPlayer mp) {
play();
}
}); button1.setOnClickListener(new OnClickListener() { @Override
public void onClick(View v) {
play();
if (isPause) {
button2.setText("暂停");
isPause = false;
}
button2.setEnabled(true);
button3.setEnabled(true);
button1.setEnabled(false);
}
}); button2.setOnClickListener(new OnClickListener() { @Override
public void onClick(View v) {
if (player.isPlaying() &&!isPause){
player.pause();
isPause = true;
((Button)v).setText("继续");
hint.setText("暂停播放音频...");
button1.setEnabled(true);
}else{
player.start();
((Button)v).setText("暂停");
hint.setText("继续播放音频...");
isPause = false;
button1.setEnabled(false);
}
}
}); button3.setOnClickListener(new OnClickListener() { @Override
public void onClick(View v) {
player.stop();
hint.setText("停止播放音频...");
button2.setEnabled(false);
button3.setEnabled(false);
button1.setEnabled(true);
}
});
} private void play() {
try {
player.reset();
player.setDataSource(file.getAbsolutePath());
player.prepare();
player.start();
hint.setText("正在播放音频...");
}catch(Exception e) {
e.printStackTrace();
}
} @Override
protected void onDestroy() {
if(player.isPlaying()){
player.stop();
}
player.release();
super.onDestroy();
} }
二、用SoundPool播放音频
用MediaPlayer播放音频存在一些不足,例如,资源占用量较高、延迟时间较长、不支持多个音频同时播放等等。这些缺点决定了MediaPlayer在某些场合下不适合使用,例如在对时间精度要求相对较高的游戏开发中。游戏开发中我人经常要播放一些游戏音效(比如子弹爆炸,物体撞击等等),这些音效的特点是短促、密集、延迟程度小。这时,我们可以使用SoundPool代替MediaPlayer来播放这些音效。
SoundPool,顾名思义是声音池的意思,主要用于播放一些较短的声音片段,支持从程序的资源或文件系统加载。与MediaPlayer相比,SoundPool的优势在于CPU资源占用量低和反应延迟小。另外,SoundPool还支持自行设置声音的品质、音量、播放比特率等参数,支持通过ID对多个音频流进行管理。
SoundPool最大只能申请1M的内存空间,这就意味着我们只能用它来播放一些很短的声音片断,而不是用它来播放歌曲或者做游戏背景音乐。
使用SoundPool播放音频,首先需要创建SoundPool对象,然后加载需要播放的音频,最后调用SoundPool.play()函数播放音频。
(1) 创建一个SoundPool对象
SoundPool类构造函数格式如下:
SoundPool(int maxStreams, int streamType,int srcQuality)
第一个参数maxStreams指定该SoundPool最多可以同时播放多少个音频流。
第二个参数streamType指定音频流类型,音频流类型是在AudioManager类中定义的。
第三个参数srcQuality指定音频流的品质,默认值为0。
例如,要创建一个可同时播放10个音频流的SoundPool对象,可以使用下面的代码:
SoundPool soundpool = new SoundPool(10,AudioManager.STREAM_SYSTEM, 0);
(2) 加载所要播放的音频
创建了SoundPool对象后,可以调用SoundPool.load()函数来加载要播放的音频,其格式如下:
int |
load(AssetFileDescriptor afd, int priority) Load the sound from an asset file descriptor. |
int |
load(Context context, int resId, int priority) Load the sound from the specified APK resource. |
int |
load(String path, int priority) Load the sound from the specified path. |
int |
load(FileDescriptor fd, long offset, long length, int priority) Load the sound from a FileDescriptor. |
例如,如果要通过资源ID来加载音频文件audio.wav,可以使用下面的代码:
soundpool.load(this, R.raw.audio, 1);
(3) 播放音频
加载了音频文件后,就可以调用SoundPool.play()函数来播放指定的音频,其格式如下:
final int |
play(int soundID, float leftVolume, float rightVolume, int priority, int loop, float rate) Play a sound from a sound ID. |
参数soundID指定要播放的音频ID,该ID是由load()函数返回的。
参数leftVolume指定左声道的音量,取值范围是0.0 – 1.0。
参数rightVolume指定右声道的音量,取值范围是0.0 – 1.0。
参数priority指定播放音频的优先级,数值越大,优先级越高。
参数loop指定循环次数,0为不循环,-1为一直循环。
参数rate指定播放速率,正常为1,最低为0.5,最高为2。
(4) SoundPool播放实例
下面我们来看一个使用SoundPool播放音频的实例,该程序运行效果如下图所示,可以同时播放多个音频:
先来看主布局文件,其内容如下:
<?xml version="1.0"encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="fill_parent"
android:layout_height="fill_parent"
android:orientation="horizontal" > <Button
android:id="@+id/button1"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="Audio1" /> <Button
android:id="@+id/button2"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="Audio2" /> <Button
android:id="@+id/button3"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="Audio3" /> <Button
android:id="@+id/button4"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="Audio4" /> </LinearLayout>
下面看主Activity文件,其内容如下:
package com.liuhaoyu; import java.util.HashMap; import android.app.Activity;
import android.media.AudioManager;
import android.media.SoundPool;
import android.os.Bundle;
import android.view.KeyEvent;
import android.view.View;
import android.view.View.OnClickListener;
import android.widget.Button; public classMainActivity extends Activity {
private SoundPool soundpool;
private HashMap<Integer,Integer> soundmap= newHashMap<Integer, Integer>(); //创建一个HashMap对象 @Override
public void onCreate(BundlesavedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.main);
Buttonchimes = (Button) findViewById(R.id.button1);
Buttonenter = (Button) findViewById(R.id.button2);
Buttonnotify = (Button) findViewById(R.id.button3);
Buttonringout = (Button) findViewById(R.id.button4);
soundpool = new SoundPool(5,AudioManager.STREAM_SYSTEM, 0);
//将要播放的音频流保存到HashMap对象中
soundmap.put(1, soundpool.load(this, R.raw.chimes, 1));
soundmap.put(2, soundpool.load(this, R.raw.enter, 1));
soundmap.put(3, soundpool.load(this, R.raw.notify, 1));
soundmap.put(4, soundpool.load(this, R.raw.ringout, 1));
soundmap.put(5, soundpool.load(this, R.raw.ding, 1));
//为各按钮添加单击事件监听器
chimes.setOnClickListener(new OnClickListener() { @Override
public void onClick(View v) {
soundpool.play(soundmap.get(1), 1, 1, 0, 0, 1);
}
});
enter.setOnClickListener(new OnClickListener() { @Override
public void onClick(View v) {
soundpool.play(soundmap.get(2), 1, 1, 0, 0, 1); }
});
notify.setOnClickListener(new OnClickListener() { @Override
public void onClick(View v) {
soundpool.play(soundmap.get(3), 1, 1, 0, 0, 1); }
});
ringout.setOnClickListener(new OnClickListener() { @Override
public void onClick(View v) {
soundpool.play(soundmap.get(4), 1, 1, 0, 0, 1);
}
}); } @Override
public boolean onKeyDown(int keyCode, KeyEventevent) {
soundpool.play(soundmap.get(5), 1, 1, 0, 0, 1);
return true;
}
}
Android应用开发学习笔记之播放音频的更多相关文章
- Android应用开发学习笔记之播放视频
作者:刘昊昱 博客:http://blog.csdn.net/liuhaoyutz 在Android中,我们可以通过使用VideoView类或者MediaPlayer类来播放视频. 一.使用Video ...
- Android应用开发学习笔记之Intent
作者:刘昊昱 博客:http://blog.csdn.net/liuhaoyutz Intent是什么呢?来看Android官网上的定义: An intent is an abstractdescri ...
- android移动开发学习笔记(二)神奇的Web API
本次分两个大方向去讲解Web Api,1.如何实现Web Api?2.如何Android端如何调用Web Api?对于Web Api是什么?有什么优缺点?为什么用WebApi而不用Webservice ...
- Android应用开发学习笔记之事件处理
作者:刘昊昱 博客:http://blog.csdn.net/liuhaoyutz Android提供的事件处理机制分为两类:一是基于监听的事件处理:二是基于回调的事件处理.对于基于监听的事件处理,主 ...
- Android应用开发学习笔记之AsyncTask
作者:刘昊昱 博客:http://blog.csdn.net/liuhaoyutz 在上一篇文章中我们学习了多线程和Handler消息处理机制,如果有计算量比较大的任务,可以创建一个新线程执行计算工作 ...
- Android应用开发学习笔记之BroadcastReceiver
作者:刘昊昱 博客:http://blog.csdn.net/liuhaoyutz 一.BroadcastReceiver机制概述 Broadcast Receiver是Android的一种“广播发布 ...
- [Android游戏开发学习笔记]View和SurfaceView
本文为阅读http://blog.csdn.net/xiaominghimi/article/details/6089594的笔记. 在Android游戏中充当主要角色的,除了控制类就是显示类.而在A ...
- Android应用开发学习笔记之Fragment
作者:刘昊昱 博客:http://blog.csdn.net/liuhaoyutz Fragment翻译成中文就是“碎片”.“片断”的意思,Fragment通常用来作为一个Activity用户界面的一 ...
- Android应用开发学习笔记之菜单
作者:刘昊昱 博客:http://blog.csdn.net/liuhaoyutz Android中的菜单分为选项菜单(OptionMenu)和上下文菜单(Context Menu).通常使用菜单资源 ...
随机推荐
- wxWidgets刚開始学习的人导引(4)——wxWidgets学习资料及利用方法指导
wxWidgets刚開始学习的人导引全文件夹 PDF版及附件下载 1 前言2 下载.安装wxWidgets3 wxWidgets应用程序初体验4 wxWidgets学习资料及利用方法指导5 用wx ...
- Android SurfaceView实战 带你玩转flabby bird (下)
转载请标明出处:http://blog.csdn.net/lmj623565791/article/details/43063331,本文出自:[张鸿洋的博客] 1.概述 在Android Surfa ...
- Hadoop伪分布式模式部署
Hadoop的安装有三种执行模式: 单机模式(Local (Standalone) Mode):Hadoop的默认模式,0配置.Hadoop执行在一个Java进程中.使用本地文件系统.不使用HDFS, ...
- c,assert 宏的实现
预备知识:#define _VAL(x) #x //#x的作用就是把x表达式变成一个字符串.(注意 : 不带换行符'\n' , 换行符ascii==10).如:_STR(i<100)printf ...
- sencha touch(7)——list组件
1.list组件是一个很强大的组件.用于以一览表的形式或者列表的形式展示应用程序中的大量的数据.该组件使用XTemplate模版来显示数据,同时与数据仓库进行绑定.所以当数据仓库中的数据发生变化的时候 ...
- [转]linux下iftop工具的安装与使用详解(图文)——实时的网络流量,监控TCP/IP连接(单机)
原文链接:http://www.jbxue.com/LINUXjishu/10735.html 在linux中监控系统资源.进程.内存占用等信息,可以使用top命令.查看网络状态可以使用netstat ...
- Java--格式化输出
Java的格式化输出等同于String.Format,与C有很大的相似,比如 System.out.printf("%8.2f", x); 在printf中,可以使用多个参数,例如 ...
- 简要解析XMPP框架及iOS-Objective-C的使用
前言:这两天看了XMPP框架,查阅了一些资料,写下这篇文章记录一下学习笔记 一.简要解析XMPP核心部分 XMPP框架分为两个部分 1.核心部分 2.扩展部分 扩展部分主要讲好友列表(roster). ...
- mysql basic operation,mysql总结
mysql> select * from wifi_data where dev_id like "0023-AABBCCCCBBAA" ; 1.显示数据库列表.show d ...
- 解决基于BAE python+bottle开发上的一系列问题 - artwebs - 博客频道 - CSDN.NET
解决基于BAE python+bottle开发上的一系列问题 - artwebs - 博客频道 - CSDN.NET 解决基于BAE python+bottle开发上的一系列问题 分类: python ...