Android Service要点
1. 什么是Service以及描述下它的生命周期;Service有哪些启动方法,有什么区别;怎样停用Service?
startService
生命周期onCreate()--->onStartCommand()--->onStart()--->onDestroy()
可以多次调用,不会重复创建,oncreate()只执行一次,会多次调用onStart
以start方式开启的服务也只能停止一次,多次调用stopservice()是无效的,只会调用一次onDestroyed。
以start方式开启的服务,调用者退出,服务仍然可以正常运行
不能调用服务中的方法
外部调用stopService可以停止服务,停止的时候调用onDestroy方法。
bindService
生命周期onCreate() --->onBind() -->onUnbind()---->onDestry()。
可以调用服务中的方法。
与绑定的Activity一同销毁,调用者在onDestroy()的时,系统会调用服务的onUnbind()
-->onDestroy()。
Activity调用bindService绑定服务(同一个Activity只能成功绑定一次,之后的绑定无效,onBind不再重复执行,onServiceConnected也不会再次回调)。
MainActivy中通过bindService绑定了KLService ,按返回退出MainActivy,执行流程如下:
03-24 21:14:30.558 22847-22847/com.klfront.platform.debug I/kl: KLService -> onCreate
03-24 21:14:30.559 22847-22847/com.klfront.platform.debug I/kl: KLService -> onBind, from:MainActivity
03-24 21:14:30.644 22847-22847/com.klfront.platform.debug I/kl: MainActivity ->onServiceConnected num=-1995123560
03-24 21:14:41.431 22847-22847/com.klfront.platform.debug I/kl: MainActivity -> onDestroy
03-24 21:14:41.457 22847-22847/com.klfront.platform.debug I/kl: KLService -> onUnbind, from:MainActivity
03-24 21:14:41.459 22847-22847/com.klfront.platform.debug I/kl: KLService -> onDestroy, Thread: main
绑定的Activity调用unbindService解绑,Srevice就会调用onUnbind- >onDestroyed,然后Service销毁(同一个绑定者不可多次调用,会报异常)。
MainActivy中通过bindService绑定了KLService ,先调用unbindService,再按返回退出MainActivy,执行流程如下:
03-24 21:17:32.344 25798-25798/com.klfront.platform.debug I/kl: KLService -> onCreate
03-24 21:17:32.344 25798-25798/com.klfront.platform.debug I/kl: KLService -> onBind, from:MainActivity
03-24 21:17:32.492 25798-25798/com.klfront.platform.debug I/kl: MainActivity ->onServiceConnected num=1022166858
03-24 21:17:36.349 25798-25798/com.klfront.platform.debug I/kl: KLService -> onUnbind, from:MainActivity
03-24 21:17:36.349 25798-25798/com.klfront.platform.debug I/kl: KLService -> onDestroy, Thread: main
03-24 21:17:42.123 25798-25798/com.klfront.platform.debug I/kl: MainActivity -> onDestroy
多个Activity绑定一个Service,及unbindServie流程:
已经被bindService方式启动后,新的Activity 再bindService时,没有调用onBind(),但服务会回调onServiceConnected ,将IBind对象传递回来
当前Activity与Service解除绑定时,Service先检测是否还与其他Activity连接
如果没有,Service执行onUnbind方法,然后在执行onDestroy方法,正常销毁。
如果有,Service不会执行onUnbind和onDestroy方法,Service继续运行。
start MainActvity->bindService->start DialogActivty->bindService->unbindService->DialogActivty 退出->回到MainActvity->调用unbindService,日记如下(DialogActivty中unbindService没有Service并没有销毁):
03-24 21:01:25.045 16945-16945/com.klfront.platform.debug I/kl: KLService -> onCreate
03-24 21:01:25.045 16945-16945/com.klfront.platform.debug I/kl: KLService -> onBind, from:MainActivity
03-24 21:01:25.188 16945-16945/com.klfront.platform.debug I/kl: MainActivity ->onServiceConnected num=1459452050
03-24 21:01:42.358 16945-16945/com.klfront.platform.debug I/kl: DialogActivity -> onServiceConnected num=-1292470555
03-24 21:01:58.694 16945-16945/com.klfront.platform.debug I/kl: DialogActivity -> onDestroy, Thread: main
03-24 21:02:15.391 16945-16945/com.klfront.platform.debug I/kl: KLService -> onUnbind, from:MainActivity
03-24 21:02:15.391 16945-16945/com.klfront.platform.debug I/kl: KLService -> onDestroy, Thread: main
2.混合方式使用Service
按以下顺序使用
startService(保证服务的长期后台运行)
bindService(保证调用服务的方法)
unbindService(解除绑定,保证调用stopService时能正常停止服务)
stopService
如果bindService,使用完后没有unbindService,会导致stopService
执行失败。
Service只被创建一次,onCreate只被调用一次,无论多少次的startService又bindService,第二次都会跳过onCreate,直接走后面的生命周期。
3. service是否在main thread中执行,service里面是否能执行耗时的操作?
默认Service和activity是运行在当前app所在进程的main thread(UI主线程)。
service里面不能执行耗时的操作(网络请求,拷贝数据库,大文件)。
可以在清单文件配置android:process,service 执行所在的进程 ,让service在另外的进程中执行。如:<service android:name="MyService" android:process=":my_process" />
4. 怎么在activity中启动自己对应的service?Activity怎么和service绑定?
startService() 一旦被创建,与调用者无关,没法使用service里面的方法
bindService () 把service 与调用者绑定,让activity能够访问到 service里面的方法。
如果调用者都被销毁, service会销毁。
Intent service = new Intent(this,MyService.class);
bindService(intent,new MyConn(), BIND_AUTO_CREATE);//BIND_AUTO_CREATE
private class MyConn implements ServiceConnection {
// 重写onServiceConnected和OnServiceDisconnected方法
publicvoid onServiceConnected(ComponentName name, IBinder service) {
// 可以通过IBinder的对象 去使用service里面的方法
}
publicvoid onServiceDisconnected(ComponentName name) {
}
}
5.不同应用Activity绑定另一个App的Service的情况
前提:App B的Service已经启动。
第一次:App A绑定Service,创建了IntentBindRecord实例,记录在AppBindRecord中。
执行onBind()后,App B进程通过publishService()将binder传给了AMS,记录在IntentBindRecord实例中,并设置标志位received。
第二次:App C绑定Service时,获取之前的IntentBindRecord实例。
判断标志位received为true,直接调用App C的onServiceConnected()将binder对象传给App C。
所以第二次没有调用onBind()。
6. 说说Activity,Intent,Service是什么关系
职责上各自负责不同的功能。
activity和service通过intent去激活组件,传递数据.
笔记网络更新功能,显示界面用的activity, 后台有个service每隔10分钟访问下服务器同步数据(上传和下载),用的是intent来开启服务。
7. 什么是IntentService?有何优点?
普通的service ,默认运行在ui main 主线程。
IntentService是Sdk给我们提供的方便的,带有异步处理的service类,
OnHandleIntent()处理耗时的操作。
8. 什么时候使用Service?
startForeground(id, notification)
拥有service的进程具有较高的优先级
Android系统会尽量保持拥有service的进程运行,只要在该service已经被启动(start)或者客户端连接(bindService)到它。当内存不足时,需要保持,拥有service的进程具有较高的优先级。
1. 如果service正在调用onCreate, onStartCommand或者onDestory方法,那么用于当前service的进程相当于前台进程以避免被killed。
2. 如果当前service已经被启动(start),拥有它的进程则比那些用户可见的进程优先级低一些,但是比那些不可见的进程更重要,这就意味着service一般不会被killed.
3. 如果客户端已经连接到service (bindService),那么拥有Service的进程则拥有最高的优先级,可以认为service是可见的。
4. 如果service可以使用startForeground(int, Notification)方法来将service设置为前台状态,那么系统就认为是对用户可见的,并不会在内存不足时killed。
如果有其他的应用组件作为Service,与Activity等运行在相同的进程中,那么将会增加该进程的重要性。
1.Service的特点可以让他在后台一直运行,可以在service里面创建线程去完成耗时的操作.
2.Broadcastreceiver捕获到一个事件之后,可以起一个service来完成一个耗时的操作.
3.远程的service如果被启动起来,可以被多次bind,但不会重新create.索爱手机X10i的人脸识别的service可以被图库使用,可以被摄像机,照相机等程序使用.
9. 不用service,B页面为音乐播放,从A跳转到B,再返回,如何使音乐继续播放?
默认不做任何处理,B里面的音乐都能播放。
A开启B的时候,用startActivityForResult()方法, B返回的时候把播放的状态信息返回给A ,A继续播放音乐。
3进程间通信示例:
代码来源:Android中bindService的细节之二:从进程的角度分析绑定Service的流程【Service所在进程已存在】
IAnyService.aidl
package com.galian.app_b;
interface IAnyService {
String getData();
}
App B的代码
AnyService.java(IAnyService接口的具体实现)
public class AnyService extends IAnyService.Stub {
@Override
public String getData() throws RemoteException {
return "Any String";
}
}
MyService.java
public class MyService extends Service {
AnyService service = null;
@Override
public void onCreate() {
super.onCreate();
service = new AnyService();
}
@Override
public IBinder onBind(Intent intent) {
return service;
}
}
App A的代码
点击button,绑定service
Intent intent = new Intent();
intent.setClassName("com.galian.app_b", "com.galian.app_b.MyService");
bindService(intent, mSvcConn, Context.BIND_AUTO_CREATE);
ServiceConnection:
private IAnyService mAnyService = null;
private ServiceConnection mSvcConn = new ServiceConnection() {
@Override
public void onServiceConnected(ComponentName componentName, IBinder iBinder) {
mAnyService = IAnyService.Stub.asInterface(iBinder);
if (mAnyService != null) {
try {
String data = mAnyService.getData();
}
}
}
};