作者:刘昊昱

博客: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. 用shell脚本爬取网页信息

    有个小需求,就是爬取一个小网站一些网页里的某些信息,url是带序号的类似的,不需要写真正的spider,网页内容也是差不多的 需要取出网页中<h1></h1>中间的字符串,而且 ...

  2. HDU1878 欧拉回路 - from lanshui_Yang

    Problem Description 欧拉回路是指不令笔离开纸面,可画过图中每条边仅一次,且可以回到起点的一条回路.现给定一个图,问是否存在欧拉回路?   Input 测试输入包含若干测试用例.每个 ...

  3. DHCP的工作原理

    什么是dhcp?它是如何实现的? DHCP称为动态主机配置协议.DHCP服务允许工作站连接到网络并且自动获取一个IP地址.配置DHCP服务的服务器可以为每一个网络客户提供一个IP地址.子网掩码.缺省网 ...

  4. 网页制作之html基础学习2-标签

    一.html结构组成 <html> --开始标签 <head> 网页上的控制信息 <title>页面标题</title> </head> & ...

  5. 简单描述RAID级别:

    简单描述RAID级别: RAID 0 是俩盘一起读写,如果一个坏了那么数据全丢失: RAID 1是一块写,一块用来备份,坏一块无所谓: RAID 2 ,3 ,4 不常用: 最常用的就是RAID 5和R ...

  6. m2eclipse简单使用,创建Maven项目 ,运行mvn命令(转)

    前面介绍了如何安装m2eclipse,现在,我们使用m2ecilpse导入Hello World项目. 选择菜单项File,然后选择Import,我们会看到一个Import对话框,在该对话框中选择Ge ...

  7. python去掉html标签

    s = '<SPAN style="FONT- SIZE: 9pt">开始1~3<SPAN lang=EN-US>& lt;?xml:namespa ...

  8. IE6 png图片实现半透明的方法

    IE6中支持PNG半透明图片完美解决方法-divcss5亲測 从IE7及IE7以上版本号都支持PNG半透明格式图片,而只有IE6不支持png格式透明图片,而GIF半透明效果不及png半透明格式图片,由 ...

  9. swift 自定义TabBarItem

    1.效果图     2.NewsViewController.swift // // NewsViewController.swift // NavigationDemo // // Created ...

  10. telerik 控件 SCRIPT5007: 无法获取未定义或 null 引用的属性“documentElement” (IE 文档模式)

    IE对盒模型的渲染在 Standards Mode和Quirks Mode是有很大差别的,在Standards Mode下对于盒模型的解释和其他的标准浏览器是一样,但在Quirks Mode模式下则有 ...