知识点: 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类
其中的MyBind就是需要自定义的返回类,如果需要外部调用service中的方法,就需要写一个接口将该接口的实现去调用内部service方法。这个新写的接口WritetoOut需要自定义类MyBind去实现。
通过上面代码接下来就是Activity的调用了。在Activity中创建 MyServiceConnection继承ServiceConnection 然后将返回的IBinder代理取出来,这个IBinder就是之前service我们自定义的一个类,通过IBinder里面的sayHello()方法我们就能调用Service中的outputString。其实就是代理IBinder类似看成Service主体。由于IBinder实现了自定义接口,自定义接口又调用了servicer中的方法,从而实现了我们再Activity中调用方法。
总结:虽然有些绕 但是 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添加到队列中;
注意startService 会调用onHandleIntent()还有就是构造器需要填写参数super("xxx");
三 aidl远程绑定Service
绑定远程服务
远程服务是位于另一个项目中的一个对外开放的服务,区别于本地服务。
- 远程服务:调用者和服务在不同的工程代码里面。
- 本地服务:调用者和服务在同一个工程代码里面。
绑定远程服务的步骤:
- 在服务的内部创建一个内部类,提供一个方法,可以间接调用服务的方法
- 把暴露的接口文件的扩展名改为
.aidl
文件 去掉访问修饰符 - 实现服务的
onbind
方法,继承Bander
和实现aidl定义的接口,提供给外界可调用的方法 - 在
activity
中绑定服务。bindService()
- 在服务成功绑定的时候会回调
onServiceConnected
方法 传递一个IBinder
对象 -
aidl定义的接口.Stub.asInterface(binder)
调用接口里面的方法
.aidl
:android interface definition language 安卓接口定义语言。
aidl文件都是公有的,没有访问权限修饰符。
我们要测试远程服务,就必须有两个不同的程序来进行交互。
假设我们用A来调用B的Service
首先创建aidl接口文件 需要在B中创建aidl文件
图1
创建好的文件放在一个文件下如:
图2
此时A中调用的应用也应该创建一样的aidl文件要求文件对应的包名必须相同
com.example.tnsap10.testservice.service下
图3
此时在B的AndroidManifest.xml文件中注册service,注意必须要写好action如下图
图4
这个action在 A调用绑定服务时候写入Intent
图5
在A中调用bindService时候的Intent需要填写B中service的注册action还有service的Package名称这样属于隐形调用。
在B中Service创建里需要在onBind()return 一个Binder对象,这个Binder对象需要实现
IMyAidlInterface.Stub这个接口,IMyAidlInterface是我们aidl文件的对外暴露的接口。
图6
此时B的代码已经完成。在看A的代码 A中需在调用的Activity中去BindService,如上图5,bindService(intent,ServiceConnection,type);需要创建一个ServiceConnection如下图
图7
通过传入的Ibinder用于转化成 IMyAidlInterface myAidlInterface;//aidl暴露的接口。此时可以将myAidlInterface调用其对应接口方法调用B中的方法如:
完成。