知识点: service生命周期 和service的2种启动方式、aidl远程绑定Service、IntentService使用

一 service生命周期和2种启动方式

Service是一种可以在后台执行长时间运行操作的而没有用户界面的应用

说到service的生命周期一定要讲到service的2种启动方式。

1通过 startService: onCreate() --> onStartCommand() 然后处于运行状态,调用stopService() 或者stopSelf()停止服务 ,执行 onDestroyed()。注意:调用者自己直接退出而没有调用 停止服务的方法,Service 会一直在后台 

2通过 bindService : onCreate() --> onBind() 这个时候调用者和 Service 绑定在一起。当绑定的Activity的
Context不存在了(Activity被finish())或者断开连接(Context.unbindService()), onUnbind() -->
onDestroyed() 方法

3注意被启动又被绑定的服务的生命周期:如果一个服务又被绑定又被启动,OnCreate()方法只会被执行一
次,startService()调用多少次,onStartCommand()也会被调用多少次,且只有调用 stopService()或
Service的 stopSelf() 来停止服务,当服务被停止时(1、调用stopService;2、调用stopSelf;3、不再有绑定
的连接(没有被启动)),在这里你应当做一些清除工作,如停止在Service中创建并运行的线程。

第一种启动方式:

通过start方式开启服务.
使用service的步骤:

1,定义一个类继承service
2,manifest.xml文件中配置service
3,使用context的startService(Intent)方法启动service
4,不在使用时,调用stopService(Intent)方法停止服务

第二种启动方式

采用bind的方式开启服务
使用service的步骤:

1,定义一个类继承Service
2,在manifest.xml文件中注册service
3,使用context的bindService(Intent,ServiceConnection,int)方法启动service
4,不再使用时,调用unbindService(ServiceConnection)方法停止该服务

Service类编写中主要注意点:

使用bindService时候 onBind需要返回自定义的Bingder类

Android service startactivity无效 android service启动方式及生命周期_远程服务

其中的MyBind就是需要自定义的返回类,如果需要外部调用service中的方法,就需要写一个接口将该接口的实现去调用内部service方法。这个新写的接口WritetoOut需要自定义类MyBind去实现。 

Android service startactivity无效 android service启动方式及生命周期_自定义_02

通过上面代码接下来就是Activity的调用了。在Activity中创建 MyServiceConnection继承ServiceConnection 然后将返回的IBinder代理取出来,这个IBinder就是之前service我们自定义的一个类,通过IBinder里面的sayHello()方法我们就能调用Service中的outputString。其实就是代理IBinder类似看成Service主体。由于IBinder实现了自定义接口,自定义接口又调用了servicer中的方法,从而实现了我们再Activity中调用方法。

Android service startactivity无效 android service启动方式及生命周期_远程服务_03

 

Android service startactivity无效 android service启动方式及生命周期_远程服务_04

总结:虽然有些绕  但是   activity====通过创建ServiceConnection得到====》IBinder====通过接口方法调用Service的方法====》Servicer 类似这个结构。

 

二 IntentService

IntentService是Service的子类,比普通的Service增加了额外的功能。先看Service本身存在两个问题

  • Service不会专门启动一条单独的进程,Service与它所在应用位于同一个进程中;
  • Service也不是专门一条新线程,因此不应该在Service中直接处理耗时的任务;

IntentService特征:

  • 会创建独立的worker线程来处理所有的Intent请求;
  • 会创建独立的worker线程来处理onHandleIntent()方法实现的代码,无需处理多线程问题;
  • 所有请求处理完成后,IntentService会自动停止,无需调用stopSelf()方法停止Service;
  • 为Service的onBind()提供默认实现,返回null;
  • 为Service的onStartCommand提供默认实现,将请求Intent添加到队列中;

Android service startactivity无效 android service启动方式及生命周期_远程服务_05

注意startService 会调用onHandleIntent()还有就是构造器需要填写参数super("xxx");

Android service startactivity无效 android service启动方式及生命周期_service启动_06

三 aidl远程绑定Service

绑定远程服务

远程服务是位于另一个项目中的一个对外开放的服务,区别于本地服务。

  • 远程服务:调用者和服务在不同的工程代码里面。
  • 本地服务:调用者和服务在同一个工程代码里面。

绑定远程服务的步骤:

  1. 在服务的内部创建一个内部类,提供一个方法,可以间接调用服务的方法
  2. 把暴露的接口文件的扩展名改为.aidl文件 去掉访问修饰符
  3. 实现服务的onbind方法,继承Bander和实现aidl定义的接口,提供给外界可调用的方法
  4. activity 中绑定服务。bindService()
  5. 在服务成功绑定的时候会回调 onServiceConnected方法 传递一个 IBinder对象
  6. aidl定义的接口.Stub.asInterface(binder) 调用接口里面的方法

.aidl:android interface definition language 安卓接口定义语言。
aidl文件都是公有的,没有访问权限修饰符。

我们要测试远程服务,就必须有两个不同的程序来进行交互。

假设我们用A来调用B的Service

首先创建aidl接口文件 需要在B中创建aidl文件

Android service startactivity无效 android service启动方式及生命周期_启动方式_07

                                                                                              图1 

创建好的文件放在一个文件下如:

Android service startactivity无效 android service启动方式及生命周期_service的理解_08

                                     图2 

此时A中调用的应用也应该创建一样的aidl文件要求文件对应的包名必须相同

com.example.tnsap10.testservice.service下

Android service startactivity无效 android service启动方式及生命周期_service启动_09

                               图3 

此时在B的AndroidManifest.xml文件中注册service,注意必须要写好action如下图

Android service startactivity无效 android service启动方式及生命周期_service启动_10

                                                                       图4 

这个action在 A调用绑定服务时候写入Intent

Android service startactivity无效 android service启动方式及生命周期_service启动_11

                                                                                              图5

在A中调用bindService时候的Intent需要填写B中service的注册action还有service的Package名称这样属于隐形调用。

在B中Service创建里需要在onBind()return 一个Binder对象,这个Binder对象需要实现

IMyAidlInterface.Stub这个接口,IMyAidlInterface是我们aidl文件的对外暴露的接口。

Android service startactivity无效 android service启动方式及生命周期_启动方式_12

                                                                                                图6 

此时B的代码已经完成。在看A的代码  A中需在调用的Activity中去BindService,如上图5,bindService(intent,ServiceConnection,type);需要创建一个ServiceConnection如下图

Android service startactivity无效 android service启动方式及生命周期_启动方式_13

                                                                                                图7 

通过传入的Ibinder用于转化成 IMyAidlInterface myAidlInterface;//aidl暴露的接口。此时可以将myAidlInterface调用其对应接口方法调用B中的方法如:

Android service startactivity无效 android service启动方式及生命周期_service启动_14

完成。