当前位置: 移动技术网 > IT编程>移动开发>Android > 详解Android中的Service

详解Android中的Service

2019年07月24日  | 移动技术网IT编程  | 我要评论

无限挑战130615,黄鳝门琪琪主播照片,华北包装机械网

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

如对本文有疑问,请在下面进行留言讨论,广大热心网友会与你互动!! 点击进行留言回复

相关文章:

验证码:
移动技术网