详解Android中的Service
service简介:
service是被设计用来在后台执行一些需要长时间运行的操作。
android由于允许service在后台运行,甚至在结束activity后,因此相对来说,service相比activity拥有更高的优先级。
创建service:
要创建一个最基本的service,需要完成以下工作:1)创建一个java类,并让其继承service 2)重写oncreate()和onbind()方法
其中,oncreate()方法是当该service被创建时执行的方法,onbind()是该service被绑定时执行的方法。
public class exampleservice extends service{ @override public ibinder onbind(intent intent) { return null; } @override public void oncreate() { super.oncreate(); } }
当创建了一个新的service后,还必须在androidmanifest.xml文件中对他进行配置,需要在application节点内包含一个service标记。
<service android:name=".exampleservice" android:enabled="true" android:permission="exam02.chenqian.com.servicedemo"></service>
当然,如果你想要你自定义的service仅能被自己编写的该应用程序使用,还可以在标签内添加:
android:permission="exam02.chenqian.com.servicedemo"
让service执行特定的任务:
如果想要service执行特定的任务,可以复写service的onstartcommand()方法,注意在api15之前为onstart()方法,现已不推荐,onstartcommand()方法的执行为该service oncreate()之后。
@override public int onstartcommand(intent intent, int flags, int startid) { return super.onstartcommand(intent, flags, startid); }
启动和停止service:
显式启动一个service:
// 显示启动exampleservice intent intent = new intent(this,exampleservice.class); // 启动exampleservice startservice(intent);
为了方便观察,我们可以在之前创建的自定义的service类中的onstartcommand()方法中添加log.i("servicestate","-------------->is running");
当我们从mainactivity调用运行时,可以在logcat中观察到输出: i/servicestate: is running
当然,我们也可以停止一个service,为了让我们更清晰的观察到效果,我们可以在exampleservice类中复写ondestroy()方法:
@override public void ondestroy() { log.i("servicestate","------------------>destroy"); super.ondestroy(); }
可以在mainactivity中通过以下方式停止一个service:
显示停止一个service:注意,写这里时更换了一个service,并将该自定义的service定位myservice,已经不是之前的exampleservice,不过您认可按照自己之前的继续编写,毕竟方法都是一样的;-)
//显示关闭service intent serviceintent = new intent(mainactivity.this,myservice.class); //关闭service stopservice(serviceintent);
注意service的调用不可嵌套,因此无论service被调用了多少次,对stopservice()停止的一次调用就会终止它所匹配运行中的service。
由于service具有较高的优先级,通常不会被运行时终止,因此可以通过自终止来避免后台运行service耗费系统的资源。具体方法为在onstartcommand()方法中加入stopself();但是要注意的是这里的stopself()并不是直接终止service,而是当service的所有功能或请求执行完后,将service停止掉,而不是等待系统回收,停止会调用ondestroy()销毁该service。
将service绑定到activity:
当一个service在一个activity中被调用的时候,并不会随着activity的销毁而销毁,而是仍有可能继续在后台运行着继续占用系统的资源,因此如果实现当activity销毁时自动停止与其相关的服务,将会极大的节约系统的资源占用,我们可以通过以下方式实现activity与service的绑定:
xml布局文件:在该布局文件中实现了四个按钮,分别执行启动service、停止service、绑定service和解除绑定service,清楚了吧:-)
<?xml version="1.0" encoding="utf-8"?> <linearlayout xmlns:android="http://schemas.android.com/apk/res/android" xmlns:tools="http://schemas.android.com/tools" android:id="@+id/activity_main" android:layout_width="match_parent" android:layout_height="match_parent" android:orientation="vertical" tools:context="demo.chenqian.com.androidserverdemo.mainactivity"> <!-- 开启service --> <button android:id="@+id/btnstartservice" android:layout_width="match_parent" android:layout_height="wrap_content" android:layout_margin="20dp" android:text="@string/startservice"/> <!-- 关闭service --> <button android:id="@+id/btnstopservice" android:layout_width="match_parent" android:layout_height="wrap_content" android:layout_margin="20dp" android:text="@string/stopservice"/> <!-- 绑定service --> <button android:id="@+id/btnbindservice" android:layout_width="match_parent" android:layout_height="wrap_content" android:layout_margin="20dp" android:text="@string/bindservice"/> <!-- 解绑service --> <button android:id="@+id/btnunbindservice" android:layout_width="match_parent" android:layout_height="wrap_content" android:layout_margin="20dp" android:text="@string/unbindservice"/> </linearlayout>
myservice类:
package demo.chenqian.com.androidserverdemo; import android.app.service; import android.content.intent; import android.os.binder; import android.os.ibinder; import android.support.annotation.nullable; import android.util.log; public class myservice extends service{ /* 1、在下方我们定义了内部类mybinder,这就是为什么我们这里现在能定义binder的原因 2、这里我们定义binder成员变量的目的是为了在下文的mainactivity中实现转型*/ private mybinder binder = new mybinder(); @override public void oncreate() { log.d("serviceinfo","创建成功"); super.oncreate(); } @nullable @override public ibinder onbind(intent intent) { log.d("serviceinfo","绑定成功"); return null; } @override public int onstartcommand(intent intent, int flags, int startid) { log.d("serviceinfo","开始执行"); return super.onstartcommand(intent, flags, startid); } @override public boolean onunbind(intent intent) { log.d("serviceinfo","解绑成功"); return super.onunbind(intent); } @override public void ondestroy() { log.d("serviceinfo","销毁成功"); super.ondestroy(); }
/*我们知道android系统为了安全防护和整体的稳定性,将每一个应用程序隔离在相应的独立的“沙盒”之中,因此我们自定义的service实际上是运行在
用户空间的,那么我们又有许多服务需要引用系统的service,那么一个在用户空间一个系统空间,他们之间如何实现通信呢,这就需要binder了,
binder是android系统中实现不同进程之间通信的一种方式,binder本身有粘合剂的意思,binder可以粘合android系统中的四大组件,因此下方我 们在myservice类中新建了一个mybinder内部类,并让其继承binder类,用来实现对myservice的获取,这样,你该知道为什我们上文要新建一个my-binder的成员变量了吧 ^_^,在下方的mainactivity中你也可以看到相关实例的运用,
例如
public void onserviceconnected(componentname name, ibinder service),注意这里的service是ibinder类型的,我们下方获取myservice将会用到他*/ class mybinder extends binder{ myservice getservice(){ log.d("serviceinfo","成功得到当前服务实例"); return myservice.this; } } }
mainactivity类:
package demo.chenqian.com.androidserverdemo; import android.content.componentname; import android.content.context; import android.content.intent; import android.content.serviceconnection; import android.os.binder; import android.os.ibinder; import android.support.v7.app.appcompatactivity; import android.os.bundle; import android.util.log; import android.view.view; import android.widget.button; import android.widget.toast; public class mainactivity extends appcompatactivity implements view.onclicklistener{ private context mcontext; private button btnstartservice; private button btnstopservice; private button btnbindservice; private button btnunbindservice; private myservice myservice; private intent serviceintent; private boolean isbond; /*isbond该变量用来标识当前的activity与service是否正在绑定,因为如果不进行标识,如果activity没有 与service进行绑定,而执行解除绑定的操作,会照成错误或抛出异常,因为当接触绑定时android不允许绑定为null */ /*注意,这里我们新建了一个connection并重写了相关方法,为什么我们要新建这个连接,那是因为在下方的绑定和解绑 方法即bind和unbind需要一个connection。我们复写相关方法一是为了方便观察,另一个是为了在连接成功或失去关闭 连接时,执行相关的自定义的任务或操作*/ private serviceconnection connection = new serviceconnection() { @override public void onserviceconnected(componentname name, ibinder service) { log.d("servicestate","连接成功"); myservice = ((myservice.mybinder)service).getservice(); } @override public void onservicedisconnected(componentname name) { log.d("servicestate","关闭连接"); //当连接指向实例为null没有指引的连接的实例时,好被虚拟机回收,降低占用的资源 myservice = null; } }; @override protected void oncreate(bundle savedinstancestate) { super.oncreate(savedinstancestate); setcontentview(r.layout.activity_main); //初始化数据 mcontext = this; isbond = false; //引入需要用到的组件 btnstartservice = (button) findviewbyid(r.id.btnstartservice); btnstopservice = (button) findviewbyid(r.id.btnstopservice); btnbindservice = (button) findviewbyid(r.id.btnbindservice); btnunbindservice = (button) findviewbyid(r.id.btnunbindservice); //为按钮添加单击事件 btnstartservice.setonclicklistener(this); btnstopservice.setonclicklistener(this); btnbindservice.setonclicklistener(this); btnunbindservice.setonclicklistener(this); } @override protected void onstart() { serviceintent = new intent(this,myservice.class); super.onstart(); } @override public void onclick(view v) { switch (v.getid()){ case r.id.btnstartservice: //开启service startservice(serviceintent); break; case r.id.btnstopservice: //关闭service stopservice(serviceintent); break; case r.id.btnbindservice: //绑定service isbond = bindservice(serviceintent,connection,context.bind_auto_create); break; case r.id.btnunbindservice: //解绑service,当连接为null是解绑会报错 if(isbond){ unbindservice(connection); //如果解绑成功,则修改连接标识为假 isbond = false; } break; } } }
androidmanifest.xml
<?xml version="1.0" encoding="utf-8"?> <manifest xmlns:android="http://schemas.android.com/apk/res/android" package="demo.chenqian.com.androidserverdemo"> <application android:allowbackup="true" android:icon="@mipmap/ic_launcher" android:label="@string/app_name" android:supportsrtl="true" android:theme="@style/apptheme"> <activity android:name=".mainactivity"> <intent-filter> <action android:name="android.intent.action.main" /> <category android:name="android.intent.category.launcher" /> </intent-filter> </activity> <service android:name=".myservice" android:enabled="true" android:permission="demo.chenqian.com.androidserverdemo"></service> </application> </manifest>
关于以后:
1、感觉binder那块还给大家解释的不太清楚,以后再深入研究下补充完整
2、有时间会编写一个简单的后台播放音乐的实例提供给大家参考一下
以上所述是小编给大家介绍的详解android中的service,希望对大家有所帮助