作者:刘昊昱

博客: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. UNIX环境高级编程——TCP/IP网络编程

    常用网络信息检索函数 gethostname() getppername() getsockname() gethostbyname() gethostbyaddr() getprotobyname( ...

  2. 梳理一下重装sql2008R2sp1步骤

    我的电脑是这样,最早的时候装的是2005,后来公司用到2008,我就手动卸载,但是好像卸载的不够彻底,在装2008的时候,选择升级方式安装. 虽然成功了,但是在运行select @@version 时 ...

  3. js中with、this的用法

    with 语句 为一个或一组语句指定默认对象. 用法:with (<对象>) <语句>; with 语句通常用来缩短特定情形下必须写的代码量.在下面的例子中,请注意 Math ...

  4. CentOS6.5+php5.3听云安装过程

    听云安装过程请参考听云安装指导页面:http://doc.tingyun.com/help/html/doc/server_novice.html 根据自己的服务器系统和语言包下载对应的 安装包 安装 ...

  5. 用来解析,格式化,存储和验证国际电话号码:libphonenumber

    用来解析,格式化,存储和验证国际电话号码:libphonenumber libphonenumber是Google的公共Java.C++和Javascript库用来解析,格式化,存储和验证国际电话号码 ...

  6. WCF技术剖析之二十九:换种不同的方式调用WCF服务[提供源代码下载]

    原文:WCF技术剖析之二十九:换种不同的方式调用WCF服务[提供源代码下载] 我们有两种典型的WCF调用方式:通过SvcUtil.exe(或者添加Web引用)导入发布的服务元数据生成服务代理相关的代码 ...

  7. 基于visual Studio2013解决C语言竞赛题之0905文件读写显示

       题目

  8. BNU Box of Bricks

    http://www.bnuoj.com/bnuoj/problem_show.php?pid=1596 这个题一开始以为要求最少移动次数,把我吓到了,原来只要求最少移动几个方块就行了..这一下就变简 ...

  9. Hadoop源代码导入Eclipse

    须要进一步学习hadoop.须要看看内部源代码实现.因此须要将hadoop源代码导入都eclipse中,简单总结一下,详细过程例如以下: 首先确保已经安装了git.maven3.protobuf2.5 ...

  10. Action的返回值类型总结

    Action的返回值 MVC 中的 ActionResult是其他所有Action返回类型的基类,下面是我总结的返回类型,以相应的帮助方法: 下面是这些方法使用的更详细的例子 一.返回View     ...