作者:刘昊昱

博客: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<StringString> 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应用开发学习笔记之播放音频的更多相关文章

  1. Android应用开发学习笔记之播放视频

    作者:刘昊昱 博客:http://blog.csdn.net/liuhaoyutz 在Android中,我们可以通过使用VideoView类或者MediaPlayer类来播放视频. 一.使用Video ...

  2. Android应用开发学习笔记之Intent

    作者:刘昊昱 博客:http://blog.csdn.net/liuhaoyutz Intent是什么呢?来看Android官网上的定义: An intent is an abstractdescri ...

  3. android移动开发学习笔记(二)神奇的Web API

    本次分两个大方向去讲解Web Api,1.如何实现Web Api?2.如何Android端如何调用Web Api?对于Web Api是什么?有什么优缺点?为什么用WebApi而不用Webservice ...

  4. Android应用开发学习笔记之事件处理

    作者:刘昊昱 博客:http://blog.csdn.net/liuhaoyutz Android提供的事件处理机制分为两类:一是基于监听的事件处理:二是基于回调的事件处理.对于基于监听的事件处理,主 ...

  5. Android应用开发学习笔记之AsyncTask

    作者:刘昊昱 博客:http://blog.csdn.net/liuhaoyutz 在上一篇文章中我们学习了多线程和Handler消息处理机制,如果有计算量比较大的任务,可以创建一个新线程执行计算工作 ...

  6. Android应用开发学习笔记之BroadcastReceiver

    作者:刘昊昱 博客:http://blog.csdn.net/liuhaoyutz 一.BroadcastReceiver机制概述 Broadcast Receiver是Android的一种“广播发布 ...

  7. [Android游戏开发学习笔记]View和SurfaceView

    本文为阅读http://blog.csdn.net/xiaominghimi/article/details/6089594的笔记. 在Android游戏中充当主要角色的,除了控制类就是显示类.而在A ...

  8. Android应用开发学习笔记之Fragment

    作者:刘昊昱 博客:http://blog.csdn.net/liuhaoyutz Fragment翻译成中文就是“碎片”.“片断”的意思,Fragment通常用来作为一个Activity用户界面的一 ...

  9. Android应用开发学习笔记之菜单

    作者:刘昊昱 博客:http://blog.csdn.net/liuhaoyutz Android中的菜单分为选项菜单(OptionMenu)和上下文菜单(Context Menu).通常使用菜单资源 ...

随机推荐

  1. Codeforces 435B. Pasha Maximizes

    简单贪心.... B. Pasha Maximizes time limit per test 1 second memory limit per test 256 megabytes input s ...

  2. 最简单也最难——如何获取到Android控件的高度

    问题 如何获取一个控件的长和高,相信很多朋友第一眼看见这个问题都会觉得很简单,直接在onCreate里面调用getWidth.getMeasuredWidth不就可以获得了吗,但是,事实上是并没有简单 ...

  3. 菜鸟学习SSH(二)——Struts国际化

    国际化(internationalization,i18n)和本地化(localization,l10n)指让产品(出版物,软件,硬件等)能够适应非本地环境,特别是其他的语言和文化.程序在不修改内部代 ...

  4. Linux开机启动十步骤

    启动第一步--加载BIOS 启动第二步--读取MBR 启动第三步--Boot Loader 启动第四步--加载内核 启动第五步--用户层init依据inittab文件来设定运行等级 启动第六步--in ...

  5. 自定义的Server

    自定义的Server 我们在上面对ASP.NET Core默认提供的具有跨平台能力的KestrelServer进行了详细介绍(<聊聊ASP.NET Core默认提供的这个跨平台的服务器——Kes ...

  6. Qt 多线程与数据库操作需要注意的几点问题

    源地址:http://blog.csdn.net/goldenhawking/article/details/10811409 彻底抛弃MFC, 全面应用Qt 已经不少时间了.除了自己看书按步就班做了 ...

  7. 分享非常有用的Java程序 (关键代码) (一)

    原文:分享非常有用的Java程序 (关键代码) (一)   分享一些非常有用的Java程序 (关键代码) ,希望对你有所帮助. 1.  得到当前方法的名字 String methodName = Th ...

  8. MUI AJAX Raw请求数据

    提交接口数据,接口方提供的是post请求,body - raw ; 我尝试过JQuery ajax raw 的方式,但是始终无法成功 然后我回想到我用的是mui我就开始考虑用mui.ajax结果就成功 ...

  9. Myeclipse 设定文件的默认打开方式

    Myeclipse 设定文件的默认打开方式.今天下载了一个properties的中文插件,希望.property的文件能默认以这个程序打卡.说一下设置方法. Window -> Preferen ...

  10. poj 1990

    题目链接 借鉴cxlove大神的思路 题意:听力v,位置x,2个牛交流声音为max(v1,v2)*(x1-x2),求总的 10000^2 tle 用的树状数组做的,排序,2个,小于vi的牛的总数和距离 ...