Service进阶篇(bindService)
来源:互联网 发布:知贤装饰怎么样 编辑:程序博客网 时间:2024/06/05 15:41
附上一张流程图:
Service的绑定过程从ContextWrapper开始,如下:
@Override public boolean bindService(Intent service, ServiceConnection conn, int flags) { return mBase.bindService(service, conn, flags); }
和启动Service的过程一样,直接看ContextImpl的bindService方法、bindServiceCommon方法。
@Override public boolean bindService(Intent service, ServiceConnection conn, int flags) { warnIfCallingFromSystemProcess(); return bindServiceCommon(service, conn, flags, mMainThread.getHandler(), Process.myUserHandle()); }private boolean bindServiceCommon(Intent service, ServiceConnection conn, int flags, Handler handler, UserHandle user) { IServiceConnection sd; if (conn == null) { throw new IllegalArgumentException("connection is null"); } if (mPackageInfo != null) { 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); int res = ActivityManagerNative.getDefault().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(); } }
bindServiceCommon方法完成两件事:
首先要把客户端的ServiceConnection对象转换为ServiceDispatcher.InnerConnection。不直接使用ServiceConnection,服务的绑定有可能是跨进程的。ServiceConnection必须借助Binder让远程服务端回调自己的方法,ServiceDispatcher的内部类InnerConnection可以充当Binder角色。ServiceDispatcher的作用就是连接ServiceConnection与InnerConnection。查看getServiceDispatcher源码:
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) { sd = map.get(c); } if (sd == null) { sd = new ServiceDispatcher(c, context, handler, flags); if (map == null) { map = new ArrayMap<ServiceConnection, LoadedApk.ServiceDispatcher>(); mServices.put(context, map); } map.put(c, sd); } else { sd.validate(context, handler); } return sd.getIServiceConnection(); } } static final class ServiceDispatcher { private final ServiceDispatcher.InnerConnection mIServiceConnection; private final ServiceConnection mConnection; private final Context mContext; private final Handler mActivityThread; private final ServiceConnectionLeaked mLocation; private final int mFlags; private RuntimeException mUnbindLocation; private boolean mForgotten; private static class ConnectionInfo { IBinder binder; IBinder.DeathRecipient deathMonitor; }ServiceDispatcher(ServiceConnection conn, Context context, Handler activityThread, int flags) { mIServiceConnection = new InnerConnection(this); mConnection = conn; mContext = context; mActivityThread = activityThread; mLocation = new ServiceConnectionLeaked(null); mLocation.fillInStackTrace(); mFlags = flags; } IServiceConnection getIServiceConnection() { return mIServiceConnection; } private final ArrayMap<Context, ArrayMap<ServiceConnection, LoadedApk.ServiceDispatcher>> mServices = new ArrayMap<Context, ArrayMap<ServiceConnection, LoadedApk.ServiceDispatcher>>();
在上面的代码中,mServices是一个ArrayMap,它存储了一个应用当前活动的ServiceConnection和ServiceDispatcher的映射关系。
系统会先查找是否有相同的ServiceConnection,不存在就重建一个ServiceDispatcher对象,并将其存在mServices中,key是ServiceConnection,value是ServiceDispatcher,在ServiceDispatcher的内部保存了ServiceConnection和InnerConnection对象。当客户端和Service建立联系后,系统通过InnerConnection来调用ServiceConnection的onServiceConnected方法(后面会单独讲解这个联系),这个过程可能是夸进程的。当ServiceDispatcher建好以后,getServiceDispatcher方法返回的就是其保存的InnerConnection对象。
在看AMS的bindService方法:
public int bindService(IApplicationThread caller, IBinder token, Intent service, String resolvedType, IServiceConnection connection, int flags, String callingPackage, int userId) throws TransactionTooLargeException { enforceNotIsolatedCaller("bindService"); // Refuse possible leaked file descriptors if (service != null && service.hasFileDescriptors() == true) { throw new IllegalArgumentException("File descriptors passed in Intent"); } if (callingPackage == null) { throw new IllegalArgumentException("callingPackage cannot be null"); } synchronized(this) { return mServices.bindServiceLocked(caller, token, service, resolvedType, connection, flags, callingPackage, userId); } }
AMS调用ActiveServices的bindServiceLocked方法:
int bindServiceLocked(IApplicationThread caller, IBinder token, Intent service, String resolvedType, final IServiceConnection connection, int flags, String callingPackage, final int userId) throws TransactionTooLargeException {……. try { bringUpServiceLocked(serviceRecord, serviceIntent.getFlags(), callerFg, false, false); } catch (RemoteException e) { /* ignore - local call */ }…….}
ActiveServices调用bringUpServiceLocked方法,在调用realStartServiceLocked方法,realStartServiceLocked方法又调用ApplicationThread的scheduleCreateService方法,这里的逻辑和Service进阶篇(startService),就不在复述。和startService不同的是,Service的绑定过程会调用requestServiceBindingLocked。
private final boolean requestServiceBindingLocked(ServiceRecord r, IntentBindRecord i, boolean execInFg, boolean rebind) throws TransactionTooLargeException { if (r.app == null || r.app.thread == null) { // If service is not currently running, can't yet bind. return false; } if ((!i.requested || rebind) && i.apps.size() > 0) { try { bumpServiceExecutingLocked(r, execInFg, "bind"); r.app.forceProcessStateUpTo(ActivityManager.PROCESS_STATE_SERVICE); r.app.thread.scheduleBindService(r, i.intent.getIntent(), rebind, r.app.repProcState); if (!rebind) { i.requested = true; } i.hasBound = true; i.doRebind = false; } catch (TransactionTooLargeException e) { // Keep the executeNesting count accurate. if (DEBUG_SERVICE) Slog.v(TAG_SERVICE, "Crashed while binding " + r, e); final boolean inDestroying = mDestroyingServices.contains(r); serviceDoneExecutingLocked(r, inDestroying, inDestroying); throw e; } catch (RemoteException e) { if (DEBUG_SERVICE) Slog.v(TAG_SERVICE, "Crashed while binding " + r); // Keep the executeNesting count accurate. final boolean inDestroying = mDestroyingServices.contains(r); serviceDoneExecutingLocked(r, inDestroying, inDestroying); return false; } } return true; }
ApplicationThread调用scheduleBindService方法,有Handle处理,最终由Activity的handleBindService方法来处理。
public final void scheduleBindService(IBinder token, Intent intent, boolean rebind, int processState) { updateProcessState(processState, false); BindServiceData s = new BindServiceData(); s.token = token; s.intent = intent; s.rebind = rebind; if (DEBUG_SERVICE) Slog.v(TAG, "scheduleBindService token=" + token + " intent=" + intent + " uid=" + Binder.getCallingUid() + " pid=" + Binder.getCallingPid()); sendMessage(H.BIND_SERVICE, s); } public void handleMessage(Message msg) {…..case BIND_SERVICE: Trace.traceBegin(Trace.TRACE_TAG_ACTIVITY_MANAGER, "serviceBind"); handleBindService((BindServiceData)msg.obj); Trace.traceEnd(Trace.TRACE_TAG_ACTIVITY_MANAGER); break;…….}private void handleBindService(BindServiceData data) { Service s = mServices.get(data.token); if (DEBUG_SERVICE) Slog.v(TAG, "handleBindService s=" + s + " rebind=" + data.rebind); if (s != null) { try { data.intent.setExtrasClassLoader(s.getClassLoader()); data.intent.prepareToEnterProcess(); try { if (!data.rebind) { IBinder binder = s.onBind(data.intent); ActivityManagerNative.getDefault().publishService( data.token, data.intent, binder); } else { s.onRebind(data.intent); ActivityManagerNative.getDefault().serviceDoneExecuting( data.token, SERVICE_DONE_EXECUTING_ANON, 0, 0); } ensureJitEnabled(); } catch (RemoteException ex) { throw ex.rethrowFromSystemServer(); } } catch (Exception e) { if (!mInstrumentation.onException(s, e)) { throw new RuntimeException( "Unable to bind to service " + s + " with " + data.intent + ": " + e.toString(), e); } } } }
在handleBindService方法中,首先根据Service的token数据取出Service对象,然后调用Service的onBind方法,返回一个Binder对象给客户端。Service调用了onBind方法,Service就处于绑定状态了,但是客户端不知道已成功连接Service,所以要调用客户端的ServiceConnection的onServiceConnected方法,这个过程是由ActivityManagerNative.getDefault().publishService来完成,也就是AMS的publishService方法。
Service有一个特性,多次绑定同一个Service,onBind方法只会执行一次,除非Service终止。Service绑定成功,系统还需要通知客户端。
public void publishService(IBinder token, Intent intent, IBinder service) { // Refuse possible leaked file descriptors if (intent != null && intent.hasFileDescriptors() == true) { throw new IllegalArgumentException("File descriptors passed in Intent"); } synchronized(this) { if (!(token instanceof ServiceRecord)) { throw new IllegalArgumentException("Invalid service token"); } mServices.publishServiceLocked((ServiceRecord)token, intent, service); } }
AMS的publishService方法由ActiveServices的publishServiceLocked来处理。
void publishServiceLocked(ServiceRecord r, Intent intent, IBinder service) { final long origId = Binder.clearCallingIdentity();…… ConnectionRecord c = clist.get(i);…… E) Slog.v(TAG_SERVICE, "Publishing to: " + c); try { c.conn.connected(r.name, service) } catch (Exception e) { Slog.w(TAG, "Failure sending service " + r.name + " to connection " + c.conn.asBinder() + " (in " + c.binding.client.processName + ")", e); } } } } serviceDoneExecutingLocked(r, mDestroyingServices.contains(r), false); } } finally { Binder.restoreCallingIdentity(origId); } }final class ConnectionRecord { final AppBindRecord binding; // The application/service binding. final ActivityRecord activity; // If non-null, the owning activity. final IServiceConnection conn; ……}
核心代码: c.conn.connected(r.name, service)。c代表的是ConnectionRecord,c.conn的类型是ServiceDispatcher.InnerConnection。service是返回的Binder对象。查看ServiceDispatcher.InnerConnection:
private static class InnerConnection extends IServiceConnection.Stub { final WeakReference<LoadedApk.ServiceDispatcher> mDispatcher; InnerConnection(LoadedApk.ServiceDispatcher sd) { mDispatcher = new WeakReference<LoadedApk.ServiceDispatcher>(sd); } public void connected(ComponentName name, IBinder service) throws RemoteException { LoadedApk.ServiceDispatcher sd = mDispatcher.get(); if (sd != null) { sd.connected(name, service); } } }
InnerConnection的connected方法,调用了ServiceDispatcher的connected方法:
public void connected(ComponentName name, IBinder service) { if (mActivityThread != null) { mActivityThread.post(new RunConnection(name, service, 0)); } else { doConnected(name, service); } }
对于Service的绑定过程来说,ServiceDispatcher的mActivityThread是一个Handle,就是ActivityThread的H,从ServiceDispatcher的创建过程可知mActivityThread不为null,RunConnection由Handle的post方法运行在主线程。由此可知客户端的ServiceConnection是在主线程被回调的。
private final class RunConnection implements Runnable { RunConnection(ComponentName name, IBinder service, int command) { mName = name; mService = service; mCommand = command; } public void run() { if (mCommand == 0) { doConnected(mName, mService); } else if (mCommand == 1) { doDeath(mName, mService); } } final ComponentName mName; final IBinder mService; final int mCommand; }
RunConnection的run方法调用了ServiceDispatcher的doConnectes方法。ServiceDispatcher内部保存了ServiceConnection对象,很方便调用它的onServiceConnected方法。
public void doConnected(ComponentName name, IBinder service) { ServiceDispatcher.ConnectionInfo old; ServiceDispatcher.ConnectionInfo info;……. // If there was an old service, it is not disconnected. if (old != null) { mConnection.onServiceDisconnected(name); } // If there is a new service, it is now connected. if (service != null) { mConnection.onServiceConnected(name, service); } }
客户端的onServiceConnected方法执行后,Service的绑定过程也就完成了。
- Service进阶篇(bindService)
- Service组件 startService() bindService()
- Service之bindService
- Service和bindService生命周期
- Service之BindService
- Android Service之bindService
- 绑定Service bindService
- Android Service(绑定BindService)
- Service进阶篇(startService)
- android 之 Service(Context BindService())
- Android SERVICE(详解二 Bindservice)
- Service之startservice与bindservice
- Service (bindService音乐播放器)
- Android中Service使用bindService
- Service之BindService(三)
- (详细)Service、IntentService、BindService
- android Service---bindService和remoteService
- 使用bindService方式启动Service
- 迭代维护
- 自动更新组件
- android shape
- JSP 动作元素
- 关于String类型遗漏点与StringBuilder、StringBuffer
- Service进阶篇(bindService)
- HibernateTemplate常用方法详解
- onunload、onbeforeunload事件详解
- Android插件化开发之动态加载本地皮肤包进行换肤
- easyUi排序
- Android代码入侵原理解析(一)
- 微信扫码
- C#中的值传递
- 页面jQuery和controller