为 Android 应用添加背景音乐






3.89/5 (9投票s)
本文解释了如何在开发 Android 应用(例如游戏)时添加背景音乐。
引言
Android 应用开发的大部分内容是游戏开发。背景音乐是游戏应用的重要组成部分。本文将介绍如何使用 Android SDK 库提供的 MediaPlayer 为任何 Android 应用添加音乐。假定您熟悉 Android Activity 和 Service。
背景
MediaPlayer
类控制音频/视频文件和流的播放。
它的生命周期以状态机图的形式实现。官方 Android 开发页面对它的生命周期有很好的解释。我建议您通过阅读该页面来熟悉 MediaPlayer 的生命周期。MediaPlayer 必须处于准备状态才能播放音乐。通常,媒体源可以是:本地资源、内部 URI,例如您可能从 Content Resolver 获取的 URI、外部 URL(流式传输)。
我们感兴趣的是使用本地资源。因此,请将您的应用程序的音乐文件保存在 /res/raw 目录中。支持的各种音乐音频文件如下:
MP3、MIDI、WAV、MP4、MP4A、3GP、FLAC、ADTS Raw AAC(.aac 仅解码)。
将 Service 与 MediaPlayer 一起使用
为了在用户与您的应用交互时在后台播放媒体,您必须从应用程序的主 Activity 启动一个 Service,该 Service 将包含所有与播放相关的函数。为了让 Activity 与 Service 交互,还需要一个 Service 连接。简而言之,我们需要实现一个绑定 Service。
总的来说,由于各种原因,播放控制操作可能会失败,例如不支持的音视频格式、音视频交错不良、分辨率过高、流式传输超时、编程错误等。因此,请包含足够多的错误处理和恢复机制。在所有这些错误条件下,如果之前通过 setOnErrorListener(android.media.MediaPlayer.OnErrorListener)
注册了 OnErrorListener
,内部播放器引擎将调用用户提供的 OnErrorListener.onError()
方法。即使没有注册错误监听器,MediaPlayer 也会进入“Error
”状态。因此,对于媒体播放器的错误处理机制,必须充分理解媒体播放器的状态图。
Using the Code
以下是实现媒体播放器的基本 Service 的代码。代码使用 Eclipse IDE 中的 Android SDK 用 Java 编写。将此代码复制为名为 MusicService.class 的单独 Java 文件,放在您的 Android 应用程序的 src 目录下。我在应用程序中播放的示例音乐也可作为“jingle.mp3”下载,应存储在“res/raw”目录下。
由于这是一个允许其他应用程序组件绑定和与之交互的绑定 Service,因此我们必须实现 onBind()
回调方法。有关绑定 Service 的更多详细信息超出了本文档的范围,因为它主要处理 MediaPlayer 的实现,并假定您对 Service 有良好的理解。
以下是此处实现的重要术语和函数,其余内容不言自明
- Service 实现
onErrorListener
以进行错误处理和恢复。 mBinder
:一个IBinder
对象,客户端将使用它与 Service 交互。- 构造函数是空的,因为我在这里只演示背景音乐功能。但是,根据您的应用程序,您可以在此处执行一些初始化。
Class ServiceBinder
:由于此 Service 对应用程序是私有的,并且与客户端在同一进程中运行,因此您应该通过扩展Binder
类来创建自己的接口,并在onBind()
中返回它的实例。客户端接收Binder
并可以使用它来直接访问Binder
实现或甚至Service
中可用的public
方法。onCreate()
:在这里,我们通过调用mPlayer.create()
并将音乐文件的路径作为参数来创建 MediaPlayer。调用 create 时,MediaPlayer 已处于准备状态,因此无需显式准备播放器。
此外,由于音乐需要不间断播放,因此将其设置为循环播放,并使用 setVolume 设置初始音量。还注册了errorListener
,并在出现错误时调用onError()
函数。您可以在此处编写错误处理代码。在我的代码中,发生错误时会停止播放器并释放对象。onStartCommand
:在此处开始播放器,我们返回START_STICKY
,因为音乐必须在整个应用程序中持续播放,除非用户暂停或停止。
其余函数简单明了。
import android.app.Service;
import android.content.Intent;
import android.media.MediaPlayer;
import android.media.MediaPlayer.OnErrorListener;
import android.os.Binder;
import android.os.IBinder;
import android.widget.Toast;
public class MusicService extends Service implements MediaPlayer.OnErrorListener{
private final IBinder mBinder = new ServiceBinder();
MediaPlayer mPlayer;
private int length = 0;
public MusicService() { }
public class ServiceBinder extends Binder {
MusicService getService()
{
return MusicService.this;
}
}
@Override
public IBinder onBind(Intent arg0){return mBinder;}
@Override
public void onCreate (){
super.onCreate();
Player = MediaPlayer.create(this, R.raw.jingle);
mPlayer.setOnErrorListener(this);
if(mPlayer!= null)
{
mPlayer.setLooping(true);
mPlayer.setVolume(100,100);
}
mPlayer.setOnErrorListener(new OnErrorListener() {
public boolean onError(MediaPlayer mp, int what, int
extra){
onError(mPlayer, what, extra);
return true;
}
});
}
@Override
public int onStartCommand (Intent intent, int flags, int startId)
{
mPlayer.start();
return START_STICKY;
}
public void pauseMusic()
{
if(mPlayer.isPlaying())
{
mPlayer.pause();
length=mPlayer.getCurrentPosition();
}
}
public void resumeMusic()
{
if(mPlayer.isPlaying()==false)
{
mPlayer.seekTo(length);
mPlayer.start();
}
}
public void stopMusic()
{
mPlayer.stop();
mPlayer.release();
mPlayer = null;
}
@Override
public void onDestroy ()
{
super.onDestroy();
if(mPlayer != null)
{
try{
mPlayer.stop();
mPlayer.release();
}finally {
mPlayer = null;
}
}
}
public boolean onError(MediaPlayer mp, int what, int extra) {
Toast.makeText(this, "music player failed", Toast.LENGTH_SHORT).show();
if(mPlayer != null)
{
try{
mPlayer.stop();
mPlayer.release();
}finally {
mPlayer = null;
}
}
return false;
}
将 Activity 绑定到 Service
在您的应用程序的 Activity 类(Java 文件)中,使用以下代码建立 Service 连接:
private boolean mIsBound = false;
private MusicService mServ;
private ServiceConnection Scon =new ServiceConnection(){
public void onServiceConnected(ComponentName name, IBinder
binder) {
mServ = ((MusicService.ServiceBinderbinder).getService();
}
public void onServiceDisconnected(ComponentName name) {
mServ = null;
}
};
void doBindService(){
bindService(new Intent(this,MusicService.class),
Scon,Context.BIND_AUTO_CREATE);
mIsBound = true;
}
void doUnbindService()
{
if(mIsBound)
{
unbindService(Scon);
mIsBound = false;
}
}
在上面的代码中,我创建了一个 Service 连接 Scon
,它在 onServiceConnected()
中获取要调用的 Service 到 mServ
变量中,并在 Service 断开连接后将其设置为 null
。doBindService
和 doUnbindService
分别用于绑定和解除绑定到 Service。有一个布尔标志 mIsBound
,在 Service 绑定到 Activity 时会被设置。
开始、暂停、恢复和停止音乐
请按照以下步骤操作:
第 1 步:首先,通过在 Activity 的 onCreate
中调用 doBindService
并将 Intent 传递给 Service 来绑定 Service。
第 2 步:通过显式 Intent
启动 Service。
Intent music = new Intent();
music.setClass(this,MusicService.class);
startService(music);
第 3 步:在您的 Activity 中,无论何时想暂停、恢复或停止音乐,请按如下方式调用相应的 Service 函数:
mServ.pauseMusic();
mServ.resumeMusic();
mServ.stopMusic();
第 4 步:不要忘记在您想将 Service 从 Activity 解绑的地方调用 doUnbindService
。理想的位置是调用 Activity 的 onDestroy()
方法。
第 5 步:在您的应用程序的 androidmanifest 文件中,粘贴以下 XML 代码:
"service android:name="MusicService"android:enabled="true"
历史
- 2011 年 9 月 19 日:初始版本
- 2011 年 9 月 22 日:添加了第 5 步