一 前言
通过startservice来启动一个service,通常该service是无法返回结果的(这也是与bindservice的区别之一),服务开启, 这个服务和开启他的调用者之间就没有任何的关系了,调用者的生命周期和它的生命周期也没有关系(所以,service在任务完成的时调用stopSelf或stopsService来结束该服务)。
通过bindservice来和service绑定,绑定后可以和service交互,发送请求,得到结果甚至执行IPC通信。由于调用者和绑定者绑在一起,调用者一旦退出该服务也就终止了。
可以先看Android组件管理框架—后台服务Service之startService方式启动流程(Android P)。
二 图示调用流程
图示调用流程展示的是主要调用流程。
三 代码具体流程
调用者调用bindService后将会调用下面的方法。
1 frameworks/base/core/java/android/content/ContextWrapper.java
@Override
public boolean bindService(Intent service, ServiceConnection conn,
int flags) {
return mBase.bindService(service, conn, flags);
}
这里mBase变量是ContextImpl类型,是在创建activity的时候,new 一个ContextImpl对象,赋值给activity的。
2 frameworks/base/core/java/android/app/ContextImpl.java
@Override
public boolean bindService(Intent service, ServiceConnection conn,
int flags) {
warnIfCallingFromSystemProcess();
return bindServiceCommon(service, conn, flags, mMainThread.getHandler(), getUser());
}
看bindServiceCommon里的mMainThread.getHandler,其中mMainTharead是ActivityThread的实例,可以先看下 mMainThread.getHandler的方法。
3 frameworks/base/core/java/android/app/ActivityThread.java
final H mH = new H();
final Handler getHandler() {
return mH;
}
这个是ActivityThread的内部类H的实例,H类继承Hander。
接着看上面的bindServiceCommon方法。
private boolean bindServiceCommon(Intent service, ServiceConnection conn, int flags, Handler
handler, UserHandle user) {
// Keep this in sync with DevicePolicyManager.bindDeviceAdminServiceAsUser.
IServiceConnection sd;
if (conn == null) {
throw new IllegalArgumentException("connection is null");
}
if (mPackageInfo != null) {
//位置1
sd = mPackageInfo.getServiceDispatcher(conn, getOuterContext(), handler, flags);
} else {
throw new RuntimeException("Not supported in system context");
}
validateServiceIntent(service);
try {
IBinder token = getActivityToken();
if (token == null && (flags&BIND_AUTO_CREATE) == 0 && mPackageInfo != null
&& mPackageInfo.getApplicationInfo().targetSdkVersion
< android.os.Build.VERSION_CODES.ICE_CREAM_SANDWICH) {
flags |= BIND_WAIVE_PRIORITY;
}
service.prepareToLeaveProcess(this);
//位置2
int res = ActivityManager.getService().bindService(
mMainThread.getApplicationThread(), getActivityToken(), service,
service.resolveTypeIfNeeded(getContentResolver()),
sd, flags, getOpPackageName(), user.getIdentifier());
if (res < 0) {
throw new SecurityException(
"Not allowed to bind to service " + service);
}
return res != 0;
} catch (RemoteException e) {
throw e.rethrowFromSystemServer();
}
}
先看位置1的mPackageInfo.getServiceDispatcher 。
4 frameworks/base/core/java/android/app/LoadedApk.java
public final IServiceConnection getServiceDispatcher(ServiceConnection c,
Context context, Handler handler, int flags) {
synchronized (mServices) {
LoadedApk.ServiceDispatcher sd = null;
ArrayMap<ServiceConnection, LoadedApk.ServiceDispatcher> map = mServices.get(context);
if (map != null) {
if (DEBUG) Slog.d(TAG, "Returning existing dispatcher " + sd + " for conn " + c);
sd = map.get(c);
}
if (sd == null) {
sd = new ServiceDispatcher(c, context, handler, flags);
if (DEBUG) Slog.d(TAG, "Creating new dispatcher " + sd + " for conn " + c);
if (map == null) {
map = new ArrayMap<>();
mServices.put(context, map);
}
map.put(c, sd);
} else {
sd.validate(context, handler);
}
return sd.getIServiceConnection();
}
}
在getServiceDispatcher函数中,传进来的参数context是一个调用bindService的activity实例,先以它为Key值在mServices中查看是否已经存在相应的ServiceDispatcher实例,如果有则不用创建直接取出。在该情景中,需要创建一个新的ServiceDispatcher。在创建新的ServiceDispatcher实例过程中,将上面传下来ServiceConnection参数c和Hanlder参数保存在ServiceDispatcher实例的内部,并创建一个InnerConnection对象,它是一个Binder对象,会传递给ActivityM