Denua 博客

Andrioid 中 Service 组件详解

发布时间: 2018-03-27 18:47   分类 : 笔记    标签: Android 浏览: 2809   

Service 作为安卓四大组件之一, 使用非常频繁, 几乎每个APP中都需要用到它. 它主要是用于处理与 UI 之外的业务逻辑, 比如 网络请求, 下载文件, 监视器, 后台播放等等耗时操作或者解耦合业务逻辑.

特点:

  • 运行在后台, 没有用户界面, 对用户不可见.
  • 可由其他组件启动(如 Activity), 启动后非手动停止则一直运行, 除非绑定到组件, 否则即使启动服务的组件销毁也不停止.
  • 不是进程, 也不是线程, 运行在主线程, 除非在mainifest清单中声明android: process="".
  • Service 的两种状态: 启动状态, 绑定状态.
  • 优先级低于前台应用高于后台应用, 不易被系统销毁

一. Service 的创建

1 .将类继承于Service, 并重写onBind方法, 一个最基本的例子:

public class MyService extends Service{
    @Override
    public IBinder onBind(Intent intent){
        return null;
    }
}

2 .在 AndroidManifest 中注册 Service

<service android:name=".MyService"/>

Service 在清单中的语法和属性声明:

<service android:enabled=["true" | "false"]
    android:exported=["true" | "false"]
    android:icon="drawable resource"
    android:isolatedProcess=["true" | "false"]
    android:label="string resource"
    android:name="string"
    android:permission="string"
    android:process="string" >
    . . .
</service>
  1. enabled: 是否可被实例化, 默认为 true, 否则不能启动
  2. exproted: 能不能被其他应用隐式启动, 默认为 true
  3. icon: 运行时图标
  4. isolatedPrecess: true 则在一个特殊进程执行, 与其他进程分开, 且没有权限.
  5. label: 标签
  6. name: Service 类名
  7. permission: 所需权限
  8. process: 当不为空则在单独的进程运行, 前缀加上 ":"当前代表包名

二. Service 的启动和绑定

Service 有两种方式启动:

startService 方法启动服务

void Context.startService(Intent intent)

通过这种方法启动服务启动后则 服务与启动的组件生命周期不关联,即使启动该服务的组件已销毁服务继续无期限执行, 直到被系统杀死, 或者手动调用代码 context.stopService() 或者在S ervice 内部调用 stopSelf().

bindService方法启动服务

在清单中设置了 process 属性后, 服务不在同一检查, 绑定服务将无法获取回调IBinder

void Context.bindService(Intent intent, ServiceConnection conn, int flag)

该方法启动服务后服务与启动该服务的组件生命周期关联, 启动服务的组件销毁则服务也销毁. 当绑定了多个组件时所有组件都销毁了, 则服务销毁.

这个法传入三个参数, 第一个为启动服务的intent, 第二个为实现了 ServiceConnection 接口的对象, 第三个为启动方式

第二个参数 ServiceConnection 接口如下:

public interface ServiceConnection {

    void onServiceConnected(ComponentName var1, IBinder var2);
    // 与服务绑定成功后回调, ComponentName 为组件名称, IBinder 为服务 onBind 方法返回的 Binder
    void onServiceDisconnected(ComponentName var1);
    // 与服务解绑后回调
    default void onBindingDied(ComponentName name) {
    // 与服务绑定失败后回调
    }
}

第三个参数, 启动方式:

Service.BIND_AUTO_CREATE 只要绑定则存在则自动创建服务. 否则只绑定不启动服务, 当后续 启动服务继续绑定

Service.BIND_NOT_FORGROUND 不让绑定将服务的进程提升到前台调度优先级.

Service.BIND_ABOVE_CLIENT 服务比绑定的组件更重要

Service.BIND_WAIVE_PRIORITY 不要影响服务的托管进程的调度或内存管理优先级

三. Service 的生命周期

通过 startService 方法启动 : onCreate -> onStartCommand -> onDestroy

通过 bindService 方法启动 : onCreate -> onBind -> onUnbind -> onDestroy

示例代码:

public class MyService extends Service{
    // 当通过 bindService 与组件绑定时调用
    public IBinder onBind(){
        return null;
        //return new MyBinder();
    }  
    // 被第一次被创建时调用, 服务在运行则不调用
    public void onCreate(){
        super.onCreate();
    }
    // 调用 startService() 方法都会被回调, bindService() 方法不回调
    public int onStartCommand(Intent intent, int flags, int startId){
       return super.onStartCommand(intent, flags, startId);  
    }
    // 被销毁时回调
    public void onDestroy(){
        super.onDestroy();
    }
    // 用户自定义的 IPC 通信的 Binder, 实例化后在 onBind 中返回给调用 bindService 的组件
    class MyBinder extends Binder{
        public MyService getService(){
            //返回 服务 实例, 供其他组件调用服务方法
            return MyService.this;
        }
    }
}

其中 onStartCommand() 方法返回一个 int 数据, 用于描述当系统销毁服务后如何处理

START_NOT_STICKY : 销毁后不重启

START_STICKY : 销毁后自动重启, intent = null

START_REDELIVER_INTENT : 销毁后重启

四. 与 Service 通信

Binder bindService 默认

这个方式必须调用 bindService

在Service 中定义一个类继承 Binder, 在 onBind 中返回该类实例, 在绑定服务的组件中实现 ServiceConnection 接口, 当绑定服务成功后将返回该 Binder 实例并回调 onServiceConnected

方法, 将 IBinder 强制转换为 Service.Binder 即可,

public class MyService extends Service{
    public IBinder onBind(){
        return new MyBinder();
    }
    class MyBinder extends Binder{
        public MyService getService(){
            return MyService.this;
        }
    }
}

public class MyActivity extends AppcompactActivity implements ServiceConnection{
    Binder binder = null;
    ...
    public void onServiceConnected(ComponentName var1, IBinder var2){
        this.binder = (MyServic.MyBinder)IBinder;
        binder.getService();
    }
}

Messager 跨进程, 安全, 非并发

Broadcast 广播, 方便

AIDL

(完)

评论    

Copyright denua denua.cn