Android 应用中添加背景音乐的指南

Android应用开发中,背景音乐是增强用户体验的重要元素。本文将介绍如何使用Android SDK提供的MediaPlayer类来为Android应用添加背景音乐。假设读者已经熟悉Android的活动(Activity)和服务(Service)的概念。

MediaPlayer类是AndroidSDK中用于控制音频/视频文件和流播放的类。它的生命周期以状态机图的形式实现。官方的Android开发页面对其生命周期有详细的解释。在播放音乐之前,MediaPlayer需要处于准备(prepared)状态。媒体源可以是本地资源、内部URI或者外部URL(流媒体)。本文主要关注使用本地资源。因此,需要将应用的音乐文件保存在/res/raw目录下。支持的音乐文件格式包括MP3、MIDI、WAV、MP4、MP4A、3GP、FLAC、ADTS Raw AAC(仅解码.aac)。

使用Service和MediaPlayer

为了让媒体在用户与应用交互时在后台播放,必须从应用的主活动启动一个服务,并且该服务包含所有与播放相关的函数。为了允许活动与服务交互,还需要一个服务连接。简而言之,需要实现一个绑定服务。

播放控制操作可能会因为各种原因失败,例如不支持的音视频格式、音视频交错不良、分辨率过高、流媒体超时、编程错误等。因此,需要包含足够的错误处理和恢复机制。在所有这些错误条件下,如果事先通过setOnErrorListener(android.media.MediaPlayer.OnErrorListener)注册了OnErrorListener,内部播放器引擎将调用用户供应的OnErrorListener.onError()方法。即使没有注册错误监听器,MediaPlayer也会进入"错误"状态。因此,对于MediaPlayer的错误处理机制,必须对MediaPlayer的状态图有良好的理解。

代码实现

以下是实现MediaPlayer的基本服务的代码。代码是用Java编写的,使用AndroidSDK在Eclipse IDE中编写。将此代码复制为一个名为MusicService.class的单独Java文件,放在Android应用的src目录下。示例音乐文件"jingle.mp3"也可以下载,并应存储在"res/raw"目录下。

这是一个允许其他应用组件绑定并与之交互的绑定服务,因此必须实现onBind()回调方法。关于绑定服务的更多细节超出了本文的范围,因为本文主要处理MediaPlayer的实现,并且假设读者对服务有良好的理解。

以下是这里实现的重要术语和函数,其余的都是自解释的:

  • 服务实现了onErrorListener用于错误处理和恢复
  • mBinder: 一个IBinder对象,客户端将使用它与服务交互
  • 构造函数为空,因为这里只演示背景音乐功能。但是根据应用,可以在这里执行一些初始化。
  • ServiceBinder类:由于此服务是私有的,并且与客户端在同一个进程中运行,因此应该通过扩展Binder类并从onBind()返回它的实例来创建接口。客户端接收Binder,并可以使用它直接访问Binder实现或甚至服务中的public方法。
  • OnCreate(): 在这里通过调用mPlayer.create()并给出音乐文件的路径作为参数来创建MediaPlayer。当调用create时,MediaPlayer已经在准备状态,因此不需要显式准备播放器。
  • OnStartCommand: 在这里启动播放器,并返回START_STICKY,因为音乐需要在整个应用中连续播放,除非用户暂停或停止。

以下是Java代码示例:

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(); mPlayer = 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()) { 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

在应用的活动类(Java文件)中,使用以下代码进行服务连接:

private boolean mIsBound = false; private MusicService mServ; private ServiceConnection Scon = new ServiceConnection() { public void onServiceConnected(ComponentName name, IBinder binder) { mServ = ((MusicService.ServiceBinder) binder).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; } }

在上面的代码中,创建了一个服务连接Scon,它在onServiceConnected()中获取服务并将其设置为mServ变量,并在服务断开连接时将其设置为null。doBindService()和doUnbindService()分别用于绑定和解绑服务。有一个布尔标志mIsBound,当服务绑定到活动时,将其设置。

开始、暂停、恢复和停止音乐

  1. 首先,通过调用doBindService()将服务绑定到活动上,作为将Intent传递给服务的一部分。
  2. 通过显式Intent启动服务:
  3. Intent music = new Intent(); music.setClass(this, MusicService.class); startService(music);
  4. 在活动需要暂停、恢复或停止音乐的地方,调用相应的服务函数:
  5. mServ.pauseMusic(); mServ.resumeMusic(); mServ.stopMusic();
  6. 不要忘记在想要解绑服务的地方调用doUnbindService()。一个理想的地方是在调用活动的onDestroy()方法的地方。
  7. 在应用的AndroidManifest.xml文件中,粘贴以下XML代码:
  8. <service android:name="MusicService" android:enabled="true">
沪ICP备2024098111号-1
上海秋旦网络科技中心:上海市奉贤区金大公路8218号1幢 联系电话:17898875485