service 8.0+ (app处于后台)延迟调用startService会报异常。31的源码。
8.0 新特性
IntentService,startService,BindService
startService
startService--> ContextImpl::startService--> startServiceCommon()
--> service.prepareToLeaveProcess() 离开当前进程。
AMS是system_server进程。 通过IActivityManager通信 app。// 跨进程通信1。app调用AMS.
ComponentName cn = ActivityManager.getService.startService(). // 调用AMS启动服务。跨进程调用
ActivityManagerService.java
ComponentName res = mServices.startServiceLocked()
ActiveService.java 真正启动对应的service。
startServiceLocked()--startServiceLocked()
mAm.getRecordForAppLOSP() // 通过AMS 找对应的app进程。
ActivityManagerService.java
appRestrictedInBackgroundLOSP() // app在后台。8.0以后抛异常。
if(packageTargetSdk >= Build.VERSION_CODES_O) {
return ActivityManager.APP_START_MODE_DELAYED_RIGID;
}
return new ComponentName("?", "app is in background uid " + uinRec)
startService 在哪里调用。
startServiceLocked-- startServiceInnerLocked-- startServiceInnerLocked
bringUpServiceLocked-- sendServiceArgsLocked
realStartServiceLocked
thread.scheduleCreateService()--> ActivityThread(IApplicationThread)::scheduleCreateService() // 跨进程通信2:ams调用app。调用service的onCreate
--sendMessage(H.CREATE_SERVICE, s);
--handleCreateService()
--LoadedApk packageInfo = getPackageInfoNoCheck();
--Application app = packageInfo.makeApplication(); // 通过LoadedApk,拿到Application
--service = packageInfo.getAppFactory().instantiateService(); // 真正生产service
-- return (Service)cl.loadClass(className).newInstance(); // 类加载器,生成Service,Service一定要有无参的构造方法。
--service.attach(); //
--service.onCreate(); // 执行生命周期onCreate。
--mServices.put(data.token, service); 缓存service
ActiveServices.java
--sendServiceArgcLocked()
-- r.app.getThread().scheduleServiceArgs(); // 跨进程通信3。
ActivityThread.java
-- scheduleServiceArgs-- sendMessage(H.SERVICE_ARGS, s) // handler 发消息,处理多线程问题。
-- handleServiceArgs()-- Service s = mServices.get(data.token) // 拿到service
res = s.onStartCommand()
总结:
app进程(service进程 ), ams进程。三次跨进程通信。
- app通过startService 去调用AMS.app通过startService()。
- AMS通过一些操作后,调用IApplicationThread,调用scheduleCreate,调用onCreate
- 又调用onStartCommand。
stopService()
ContextWrapper--stopService()-- mBase.stopService(name)
ContextImpl -- stopService-- stopServiceCommon(service, mUser)
-- service.prepareToLeaveProcess() 准备离开当前进程,进入AMS
-- int res = ActivityManager.getService().stopService()
ActivityManagerService::
stopService()-- mServices.stopServiceLocked()
ActiveService::
stopServiceLocked-- mAm.getRecordForAppLOSP(caller) // 找对应的进程。
--stopServiceLocked()
--bringDownServiceIfNeededLocked() // 真正停止service
--bringDownServiceLocked()
// r.app.getThread.scheduleUnbindService() // unbind 解绑service
--r.app.getThread().scheduleStopService(r) // 又一次跨进程通信。
ActivityThread::ApplicationThread 内部类 ,进入app进程(service)
scheduleStopService--> sendMessage(H.STOP_SERVICE, token)
-- handleStopService()
--mServiceData.remove(token)
--mServices.remove(token)
--s.onDestroy(); // 执行生命周期。
bindService 流程分析,onCreate流程同上。service是新的进程。
app进程; AMS进程;Service进程(新的进程)。
bindService -- mBase.bindService(service, conn, flag); // 1. 传递conn 方便service进程与app进程通信。
ContextImpl:: bindServiceCommon // 将IServiceConnection 传递给AMS里面。
为什么传IServiceConnection, 因为不知道service是不是在新的进程,只能把它当一个新进程。
---int res = ActivityManager.getService().bindIsolatedService()
ActivityManagerService::
bindIsolatedService-- mServices.bindServiceLocked()
ActiveService::
bindServiceLocked-- mAm.getRecordForAppLOSP()
activity = mAm.mAtmInternal.getServiceConnectionsHolder(token) // 保证一定是Activity binderService。
bringUpServiceLocked()
requestServiceBindingsLocked()--> requestServiceBindingsLocked
r.app.getThread().scheduleBindService() // 2.通过AMS,进入Service进程。
ActivityThread::
scheduleBindService-- sendMessage(H.BIND_SERVICE, s)
-- handleBindService()
Service s = mServices.get(data.token);
IBinder binder = s.onBinder(data.intent) // 执行onBind生命周期。
ActivityManager.getService().publishService() // 3.跨进程通信:service进程,通信给ams。
AMS:
publishService()-- mServices.publishServiceLocked()
ActiveService:: // 4.跨进程通信,AMS,通信给App进程。
c.conn.connected();---> ServiceConnection:onServiceConnected // 执行什么周期函数。
UnbindService
mBase.unbindService(conn)--ContextImpl.unbindService
IServiceConnection sd = mPackageInfo.forgetServiceDispatcher(getOuterContext(), conn);
ActivityManager.getService().unbindService(sd);
ActivityManagerService::
unbindService()-- mServices.unbindServiceLocked()
ActiveService::
unbindServiceLocked()--removeConnectionLocked
-- b.connections.remove(c) 移除
c.activity.removeConnections(c)
s.app.getThread().scheduleUnbindService(s, b.intent.intent.getIntent());
进入ActivityThread
scheduleUnbindService-- sendMessage(H.UNBIND_SERVICE, s);
-- handleUnbindService()
-- boolean doRebind = s.onUnbind(); // 调用onUnbind方法
--ActivityManager.getService().unbindFinished()
--ActivityManager.getService().serviceDoneExecuting()
service 启用新进程的几种情况
- 配置android:process=":remote"
- aidl
- 隐式启动Service,使用包名启动service。
所属的service就是新进程。
几个通信的关键类:
AMS中的类:ActivityManagerService
App中的类:ApplicationThread
Service: IServiceConnection
AMS 与zygote通信,使用的 socket通信。
Manifest中配置参数。
android:enable="true" 能否被系统实例化
android:exported="true" 能否可别别的应用隐式启动。
android:isolatedProcess="true"
android:label="service" 别名
android:process=" :remote" service使用新的进程,前面补齐报名
android:process=":remote" 不补齐报名
IntentService
onHandleIntent 执行在子线程中。
IntentService 的handleMessage在子线程中。
onCreate-- HandlerThread
进程保活:
- 开启一个1像素activity
- 后台播放一个没声音的音频
- 守护进程
- 定时启动,
- 加白名单。