欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页  >  移动技术

详解Android中的Service

程序员文章站 2023-12-15 13:56:58
service简介: service是被设计用来在后台执行一些需要长时间运行的操作。 android由于允许service在后台运行,甚至在结束activity后,因此...

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,希望对大家有所帮助

上一篇:

下一篇: