what
Android 四大组件之一,名为服务,可见与activity具有同等地位,看名字也只到,服务嘛,一般用于提供进行UI无关的等任务操作。和activity存在不一样,这家伙的存在是可以说是无声无息,甚至在有些流氓的软件中,你关掉了app,那还不一定关掉了服务[捂脸] ,不过这也正突出了service的特点,后台。开始知道是用来进行后台任务就行了,看看怎么用吧。
Service
是一个可以在后台执行长时间运行操作而不提供用户界面的应用组件。服务可由其他应用组件启动,而且即使用户切换到其他应用,服务仍将在后台继续运行。 此外,组件可以绑定到服务,以与之进行交互,甚至是执行进程间通信 (IPC)。 例如,服务可以处理网络事务、播放音乐,执行文件 I/O 或与内容提供程序交互,而所有这一切均可在后台进行。
特别:Service默认也是在主线程进行的。所以也会有ANR风险。
how
定义一个服务
继承Service
首先的肯定是要继承一个Service的咯
1 | public class TestService extends Service { |
Manifest声明
1 | <service android:enabled=["true" | "false"] |
开启服务
嗯,Intent又来了,哈哈,在持有context的地方调用,既然是用Intent,自然servie的也会有Intent-Filter标签来过滤。不过好像从来没用过类似activity的隐式启动,google发现原来是5.0以上就不允许。
1 | Intent intent = new Intent(context, TestService.class); |
首先的话必然先调用onCreate,然后就是onStartCommmand,这个服务就算是开启了,活了。后面再startService也只会调用onStartCommand了。
停止服务
1 | //第一种,通过context关闭 |
停止服务后系统会尽快销毁服务,当然也就会调用onDestroy咯
服务交互–绑定服务
好像之前使用开启服务和关闭服务,调用者和服务基本没什么耦合关系。各走各路了呃呃。为了能够保持调用者和服务之间的交互。使用绑定服务
,这也是开启服务的另一种方式,话句话说通过绑定的方式来开启服务。这就要用到onBind的方法了。
绑定本地服务
服务端
除了基本的使用扩展Binder,或者使用Messenger,AIDL(其实也是Binder,233)
1 | //服务端 |
客户端
准备ServiceConnection,发起绑定
1 | private MyBinder mMyBinder; |
通过这样的方法我们就能够拿到一个Binder对象,或者其它东西,这样就算和Service建立起了交互
取消绑定
1 | unBindService(serviceConnection); |
Flag : 关于绑定服务的Flag
1 | BIND_AUTO_CREATE,//若绑定服务时服务未启动,则会自动启动服务。 注意,这种情况下服务的onStartCommand,仍然未被调用(它只会在显式调用startService时才会被调用)。 |
一般使用第一个咯,这里我收集到的翻译的不明确,还是具体参看Context.java
源码的英文注释
绑定远程服务
也就是IPC,在android 系统中很多服务都是可以直接跨进程调用的,而这些服务也都是由某些组件应用提供的。通过绑定远程的服务可以调用其它的功能,比如蓝牙,wifi等等。进程间通信,这个我放在单独的IPC后面详细归纳
- Messenger
- AIDL
前台服务
这个算是用户主动意识到的一种服务,即使内存不足,也不会考虑终止
,优先级很高,其实说白点了,就是一个普通的服务通过开启通知栏的形式,讲明了服务在运行。
1 | //创键通知 |
Intent服务
what
类:IntentService,通过扩展这个类实现的服务,里面操作会在子线程中进行。而且不需要手动关闭服务,它自己就会关闭。那么看看怎么用吧
how
1 | public class HelloIntentService extends IntentService { |
开启服务还是和普通的没区别,但是所有的操作可以在onHandleIntent
中响应。而且此时这个方法内就是子线程了。还不用关心服务停止
why
那么为啥IntentService有这么大魔力呢,子线程,自带关闭,其实原理很简单,内部维护了简单的Looper和Handler操作(关于Handler和IntentService原理下次一起详细归纳下),使得所有的从onStartCommand的操作进入了一个HandlerThread中,然后每次调用都向提交任务给线程。最后也会执行完也会停止自己。
远程服务
在service配置声明中有一个属性process
1 | <service android:process=":remote" android:enable="true" andorid:exported="true"/> |
这样在运行的时候,这个service就和本应用位于不同的进程中了,那么就轮到IPC上场了。对咯,既然是IPC了,原来的开启服务的方式就行不通,那就的用AIDL咯
注意事项
小心ANR:常态下Service的代码是运行在主线程滴
不要过多的实现代码在这里,要把服务看成一个后台任务调用代理。。
关于onStartCommand返回值
1
2
3
4
5
6
7//该返回值描述了在杀死事件中如何继续这个服务
START_NOT_STICKY
杀死后不会重启
START_STICKY
杀死后会重启,但是第一次启动的startCommand()的Intent为null
START_REDELIVER_INTENT
杀死后会重启,并且会重传Intent
生命周期
普通启动
1 | call to start service |
绑定
1 | call to bind servie |
onStartCommand一定是在调用startServie才会调用的。即使是绑定服务,也不会调用它的。