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).通常使用菜单资源 ...
随机推荐
- 用shell脚本爬取网页信息
有个小需求,就是爬取一个小网站一些网页里的某些信息,url是带序号的类似的,不需要写真正的spider,网页内容也是差不多的 需要取出网页中<h1></h1>中间的字符串,而且 ...
- HDU1878 欧拉回路 - from lanshui_Yang
Problem Description 欧拉回路是指不令笔离开纸面,可画过图中每条边仅一次,且可以回到起点的一条回路.现给定一个图,问是否存在欧拉回路? Input 测试输入包含若干测试用例.每个 ...
- DHCP的工作原理
什么是dhcp?它是如何实现的? DHCP称为动态主机配置协议.DHCP服务允许工作站连接到网络并且自动获取一个IP地址.配置DHCP服务的服务器可以为每一个网络客户提供一个IP地址.子网掩码.缺省网 ...
- 网页制作之html基础学习2-标签
一.html结构组成 <html> --开始标签 <head> 网页上的控制信息 <title>页面标题</title> </head> & ...
- 简单描述RAID级别:
简单描述RAID级别: RAID 0 是俩盘一起读写,如果一个坏了那么数据全丢失: RAID 1是一块写,一块用来备份,坏一块无所谓: RAID 2 ,3 ,4 不常用: 最常用的就是RAID 5和R ...
- m2eclipse简单使用,创建Maven项目 ,运行mvn命令(转)
前面介绍了如何安装m2eclipse,现在,我们使用m2ecilpse导入Hello World项目. 选择菜单项File,然后选择Import,我们会看到一个Import对话框,在该对话框中选择Ge ...
- python去掉html标签
s = '<SPAN style="FONT- SIZE: 9pt">开始1~3<SPAN lang=EN-US>& lt;?xml:namespa ...
- IE6 png图片实现半透明的方法
IE6中支持PNG半透明图片完美解决方法-divcss5亲測 从IE7及IE7以上版本号都支持PNG半透明格式图片,而只有IE6不支持png格式透明图片,而GIF半透明效果不及png半透明格式图片,由 ...
- swift 自定义TabBarItem
1.效果图 2.NewsViewController.swift // // NewsViewController.swift // NavigationDemo // // Created ...
- telerik 控件 SCRIPT5007: 无法获取未定义或 null 引用的属性“documentElement” (IE 文档模式)
IE对盒模型的渲染在 Standards Mode和Quirks Mode是有很大差别的,在Standards Mode下对于盒模型的解释和其他的标准浏览器是一样,但在Quirks Mode模式下则有 ...