安卓应用背景音乐使用 MediaPlayer实现。
MediaPlayer创建通过方法 MediaPlayer.create(context, resId);
context为音乐播放器的上下文,取用this.getApplication().getApplicationContext()的上下文可以防止持有外部类导致Activity无法回收。在调用create方法前必须保证MediaPlayer对象为状态为空。否则将会报错。可在调用前判断是否为空,不为空则调用MediaPlayer.reset()方法进行重置。
播放音乐 MediaPlayer.start()
暂停音乐 MediaPlayer.pause()
设置音乐播放完毕事件 mediaPlayer.setOnCompletionListener(new MediaPlayer.OnCompletionListener() {
@Override
public void onCompletion(MediaPlayer mp) {
//do something…
}
});
顺序播放:
重置创建播放器,资源使用列表下一首->设置播放完毕事件->音乐播放
在播放完毕事件中回调整个方法。
随机播放:
与顺序播放区别在于,在创建播放器时随机获取列表中的资源
上一曲、下一曲
手动调用上述的方法即可。
进度条
使用mediaPlayer.getCurrentPosition()获取当前播放位置, mediaPlayer.getDuration()获取歌曲总长度,使用Timer进行不断发请求获取当前位置并渲染进度条控件即可。
在写音乐播放器代码时,我想要音乐按钮不止在主界面可以使用,在数字选择界面,在数字书写界面等其他界面我也想能够随时控制音乐的播放与停止状态。即应用的所有界面共享同一个音乐播放器。
我的思路是定义一个BasicActivity类,将音乐播放器设置为静态对象,在所有Activity中均继承基本类,实现音乐播放器共享。布局文件中按钮有两种状态,音乐正在播放,音乐停止播放,当Activity切换时我们就需要根据当前播放状态去渲染音乐按钮,音乐按钮可以每个布局文件中定义,而我定义在了BasicActivity的布局文件中,并在其他布局文件中使用
当我们进入一个拥有音乐按钮的界面时,需要做三件事
1.调用setContentView设置布局文件 2.获取按钮并根据状态设置背景图片 3.播放音乐并设置播放完成切换歌曲事件
当进入主应用界面时第一次初始化音乐播放器开始播放音乐,在跳转后不改变音乐播放器状态,仅根据播放器状态渲染控件。
所以讲音乐播放和设置下一曲的调用放在主应用界面的Activity中,而渲染控件放在BasicActivity中进行。
效果是进入主界面即开始播放歌曲,之后任意切换界面都不影响音乐播放,并且每个界面都可以停止或播放歌曲。
若遇到程序报空指针错误,错误指向music_btn.setBackgroundResource(R.mipmap.btn_music1)等对控件操作的调用时,可能是在调用顺序上出了问题,在使用findViewById时还未调用setContentView,导致获取的控件是null。所以在使用findViewById时必须确认在此之前已经使用setContentView设置了主布局。
具体实现代码如下
BasicActivity
public class BasicActivity extends Activity {
static boolean isPlay = true; //播放状态
static MediaPlayer mediaPlayer; //音乐播放器
static int musicIndex = 0; //当前播放序号
static Context context; //上下文
static int[] musicList = {R.raw.high_hopes, R.raw.don_t_miss_now, R.raw.don_t_you_worry_child}; //播放歌曲列表
Button music_btn; //前台按钮控件
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
context = this.getApplication().getApplicationContext();
//通过id获取布局文件中按钮控件
music_btn = (Button) findViewById(R.id.btn_music);
//根据播放状态渲染按钮图片
if (isPlay) {
music_btn.setBackgroundResource(R.mipmap.btn_music1);
} else {
music_btn.setBackgroundResource(R.mipmap.btn_music2);
}
//内存监视器
RefWatcher refWatcher = App.getRefWatcher(this);
refWatcher.watch(this);
}
//点击事件,将播放器状态置反并渲染按钮图片
public void onClick(View v) {
if (isPlay) {
if (mediaPlayer != null) {
mediaPlayer.pause();
music_btn.setBackgroundResource(R.mipmap.btn_music2);
isPlay = false;
}
} else {
mediaPlayer.start();
music_btn.setBackgroundResource(R.mipmap.btn_music1);
isPlay = true;
}
}
//设置播放器播放完毕回调函数,进行歌曲切换
public static void setPlayList() {
try {
mediaPlayer.setOnCompletionListener(new MediaPlayer.OnCompletionListener() {
@Override
public void onCompletion(MediaPlayer mp) {
musicIndex++;
if (musicIndex >= musicList.length) {
musicIndex = 0;
}
playMusic(musicList[musicIndex]);
setPlayList();
}
});
} catch (Exception e) {
e.printStackTrace();
}
}
//播放歌曲,保证播放器为空后创建新的播放器,开始播放音乐
public static void playMusic(int resId) {
if (mediaPlayer != null) {
mediaPlayer.reset();
}
mediaPlayer = MediaPlayer.create(context, resId);
mediaPlayer.start();
}
}
-------------------------BasicLayout----------------------
------------------------MainActivity----------------------
//继承了BasicActivity
public class MainActivity extends BasicActivity {
@Override
protected void onCreate(Bundle savedInstanceState) {
//必须先设置视图,而后调用BasicActivity的onCreate函数
//若顺序反过来将会报空指针错误,因为没有渲染前台控件,则没有音乐按钮
setContentView(R.layout.activity_main);
super.onCreate(savedInstanceState);
playMusic(musicList[musicIndex]);
setPlayList();
}
//跳转游戏选择界面
public void OnPlay(View v) {
startActivity(new Intent(MainActivity.this, SelectActivity.class));
}
//跳转关于我们界面
public void OnAbout(View v) {
startActivity(new Intent(MainActivity.this, AboutActivity.class));
}
}
----------------------MainLayout----------------------