Android通过startService播放背景音乐
关于startservice的基本使用概述及其生命周期可参见《android中startservice基本使用方法概述》。
本文通过播放背景音乐的简单示例,演示startservice的基本使用流程,具体内容如下
系统界面如下:
界面上面就两个按钮,”播放音乐并退出activity” 和 “停止播放音乐”。我们在该示例中,通过操纵activity的按钮控制musicservice播放或停止播放音乐。
我将一个名为music.mp3的放到资源目录/res/raw文件夹下面,这样我们在程序中就可以通过r.raw.music引用该音乐文件,放入/res/raw文件夹中的资源文件会保持原来的面貌不会被编译成二进制。
musicservice是用于播放背景音乐的service,其代码如下所示:
package com.ispring.startservicedemo; import android.app.service; import android.content.intent; import android.media.mediaplayer; import android.os.ibinder; import android.widget.toast; import java.io.ioexception; public class musicservice extends service { private mediaplayer mediaplayer = null; private boolean isready = false; @override public void oncreate() { //oncreate在service的生命周期中只会调用一次 super.oncreate(); //初始化媒体播放器 mediaplayer = mediaplayer.create(this, r.raw.music); if(mediaplayer == null){ return; } mediaplayer.stop(); mediaplayer.setonerrorlistener(new mediaplayer.onerrorlistener() { @override public boolean onerror(mediaplayer mp, int what, int extra) { mp.release(); stopself(); return false; } }); try{ mediaplayer.prepare(); isready = true; } catch (ioexception e) { e.printstacktrace(); isready = false; } if(isready){ //将背景音乐设置为循环播放 mediaplayer.setlooping(true); } } @override public int onstartcommand(intent intent, int flags, int startid) { //每次调用context的startservice都会触发onstartcommand回调方法 //所以onstartcommand在service的生命周期中可能会被调用多次 if(isready && !mediaplayer.isplaying()){ //播放背景音乐 mediaplayer.start(); toast.maketext(this, "开始播放背景音乐", toast.length_long).show(); } return start_sticky; } @override public ibinder onbind(intent intent) { //该service中不支持bindservice方法,所以此处直接返回null return null; } @override public void ondestroy() { //当调用context的stopservice或service内部执行stopself方法时就会触发ondestroy回调方法 super.ondestroy(); if(mediaplayer != null){ if(mediaplayer.isplaying()){ //停止播放音乐 mediaplayer.stop(); } //释放媒体播放器资源 mediaplayer.release(); toast.maketext(this, "停止播放背景音乐", toast.length_long).show(); } } }
musicactivity的代码如下所示:
package com.ispring.startservicedemo; import android.app.activity; import android.content.intent; import android.os.bundle; import android.view.view; import android.widget.button; public class musicactivity extends activity implements button.onclicklistener { @override protected void oncreate(bundle savedinstancestate) { super.oncreate(savedinstancestate); setcontentview(r.layout.activity_music); } @override public void onclick(view v) { if(v.getid() == r.id.btnstart){ //播放背景音乐 intent intent = new intent(this, musicservice.class); startservice(intent); //退出当前activity this.finish(); }else if(v.getid() == r.id.btnstop){ //停止播放音乐 intent intent = new intent(this, musicservice.class); stopservice(intent); } } }
当我们单击了按钮”播放音乐并退出activity”之后,我们首先通过activity的startservice启动musicservice,然后我们立即调用了activity的finish方法销毁了当前的activity。可能大家会问为什么要销毁当前的activity?我们此处之所以调用activity的finish方法不是从功能的角度出发的,而是从理解代码运行的角度故意这么写的: 执行完activity的finish方法之后,当前的activity就销毁了, 在界面上看起来就是当前ui消失了,应用程序退出了,但稍等片刻你会听到背景音乐响起。这从侧面印证了service的一个特性: service与activity等一样,也是一种基本的应用程序组件,service无需依赖任何的activity便可独自在没有任何ui界面的情况下悠闲地在android后台默默运行。
调用了startservice之后,android framework接收到了intent信息,第一次会先创建musicservice的实例,执行musicservice的oncreate回调方法,oncreate在service的生命周期中只会调用一次,我们在其oncreate方法中将r.raw.music初始化为媒体播放器,并调用媒体播放器的prepare方法。然后我们将播放器设置为循环播放状态。需要注意的是,在实际生产环境中,我们应该注册播放器的setonpreparedlistener并调用prepareasync()方法,为了简化代码起见,我们只调用了播放器的同步方法prepare()。
调用了oncreate方法后,android会自动回调其onstartcommand方法,其实每次调用context的startservice都会触发onstartcommand回调方法,所以onstartcommand在service的生命周期中可能会被调用多次。所以我们在musicservice的onstartcommand中做了判断,判断播放器是否是在播放中,如果当前播放器没有播放我们才调用播放器的start方法播放背景音乐。
当我们单击了按钮”播放音乐并退出activity”之后,musicservice启动起来,播放背景音乐,但是activity却销毁了,程序的ui界面不见了。为了能够停止播放背景音乐,我们需要再次单击应用程序图标,重新打开musicactivity,然后单击界面上的”停止播放音乐”按钮,此时我们会调用activity的stopservice方法,android framework接收到要停止服务的intent之后会回调musicservice的ondestroy方法,在该方法中我们停止播放音乐并释放媒体播放器资源。
本文只是通过播放背景音乐这一简单示例演示通过startservice启动service基本使用流程,代码没有进行优化,希望对大家学习service有所帮助。