Android笔记之Service

相对于应用的界面,Service则是一个看不见的后台。
一个正常的Service需要满足:

  • 依附的上下文(必选)
    通常是继承自Service,开发者只关心自己需要实现的效果
  • 清单的声明(必选)
    需要在AndroidManifest.xml中告诉系统存在某个Service。
  • 细节的过滤(可选)
    可以设置IntentFilter来过滤哪些命令才是Service自己关心的。

Service的正常使用

启动Servie

public ComponentName startService(Intent service)

停止Service

public boolean stopService(Intent name)
//Service中可以调用stopSelf来停止

生命周期
onCreate
onStartCommand //多次启动会回调这个方法
onDestroy

Service的绑定使用

绑定Service

public boolean bindService(Intent service, ServiceConnection conn,int flags) 

BindServiceFlags:

  • BIND_AUTO_CREATE //只要绑定存在,系统就会自动启动相应的Service
  • BIND_DEBUG_UNBIND //调试时方便打印绑定的信息
  • BIND_NOT_FOREGROUND //不允许绑定到前台进程
  • BIND_ABOVE_CLIENT //如果app被杀,系统尽可能的保留绑定
  • BIND_ALLOW_OOM_MANAGEMENT//低内存下尽可能保留绑定
  • BIND_WAIVE_PRIORITY//使绑定像后台进程一样被管理
  • BIND_IMPORTANT//当客户端是前台进程时,提高其等到同前台进程
  • BIND_ADJUST_WITH_ACTIVITY//忽略其他标志,不管其绑定的Activity是否对用户可见,都相应的提高其权重。

解绑Service

public void unbindService(ServiceConnection conn)

生命周期
onCreate
onBind
onUnbind
onDestroy

public interface ServiceConnection {
    //当连接到Service时
    public void onServiceConnected(ComponentName name, IBinder service);
  //当连接的Service宿主出现崩溃或者被杀掉时
    public void onServiceDisconnected(ComponentName name);
}

注:

  • onCreate只有在Service不存在的时候才会调用
  • 如果是通过bindService启动的,调用unbindService会触发销毁,否则只会触发onUnbind,onDestroy则是谁启动的谁关闭,因为系统要确保这个服务最终已经无人使用了。
  • 绑定的上下文销毁时Service也会跟着销毁。

IntentService

IntentService本质上是对Service的扩展
优势:

  • 为了异步消息处理
  • 处理消息后自动停止服务
protected void onHandleIntent(final Intent intent)

开发者只需要关心自己的异步实现就可以了。

AIDL

Android接口定义语言(Android Interface Definition Language)
用来实现跨进程的通讯

跨进程方式 对比
BrodcastReceiver 实现简单但跨进程比较耗时
Messenger 请求队列是同步进行的,无法并发执行
AIDL 书写稍微麻烦,但是借助工具可以简化,相对Messenger更灵活

如果是其他进程提供服务的Service,记得配置Manifest的时候导出

android:process=""//指定进程
android:exported="true"//向外暴露

数据类型

  • 基本类型
  • Java中的八种基本数据类型,包括 byte,short,int,long,float,double,boolean,char。
  • String 类型。
  • CharSequence类型。
  • List/Map (元素是其他基本类型或parcelable)
  • Parcelable
    需要写一份对象的aidl,但是只是做声明即可
package xxxPackage;
parcelable xxxClass;

有个bug,可能是不同版本的问题,我这个版本生成的类会调用readFromParcel,而Parcelable已经去掉了该方法,所以对象类中自己手动写了个。

数据流向
adil中非基本参数都需要指明数据流向,不管是 in , out , 还是 inout 。基本参数的定向tag默认是并且只能是 in

  • in 服务端只读该参数,不做修改
  • out 服务端只对该参数进行修改,不读取传进来的参数
  • inout 服务端先读取参数,再对其做修改
    可以查看生成的源码,当然其实这个也好理解,上面的基本类型是无法对其地址上的数据做修改的(类似深浅拷贝问题),一般情况下指定in/out即可,没必要做无谓的开销。

总结:其实adil可以看做的bindService的强化版,只需要做以下几步。

  1. 需要用到自定义的实体,就申明一个实体的aidl,然后写好相应的实体。
  2. 定义adil接口的方法,如果引用到自定义的类型,就导入相应的类并指定数据流向。
  3. 在服务端书写Binder继承接口的Stub
  4. bindService后,在ServiceConnection中获取Binder的实例即可。

你可能感兴趣的:(Android笔记之Service)