Android教程網
  1. 首頁
  2. Android 技術
  3. Android 手機
  4. Android 系統教程
  5. Android 游戲
 Android教程網 >> Android技術 >> 關於Android編程 >> android4.4組件分析--service組件-bindService源碼分析

android4.4組件分析--service組件-bindService源碼分析

編輯:關於Android編程

6.1.1. bindService

因為有前面分析startService的代碼實現過程,則對於bindService的代碼分析就不用那麼詳細介紹,在介紹流程的同時更關注一些細節上的部分。

首先,bindService也是通過 ContextWrapper.bindService,再到ContextImpl的bindService,然後是bindServiceCommon,需要注意的是,傳入的ServiceConnection被轉換成IServiceConnection類型,

private boolean bindServiceCommon(Intent service, ServiceConnection conn, int flags,

UserHandle user) {

IServiceConnection sd;

sd = mPackageInfo.getServiceDispatcher(conn, getOuterContext(),

mMainThread.getHandler(), flags);

int res = ActivityManagerNative.getDefault().bindService(

mMainThread.getApplicationThread(), getActivityToken(),

service, service.resolveTypeIfNeeded(getContentResolver()),

sd, flags, user.getIdentifier());

}

接下去是進入AMS的bindService,再調用ActiveServices.java 的bindServiceLocked,它會把IServiceConnection實例存放到ConnectionRecord裡面,並執行bringUpServiceLocked,

int bindServiceLocked(IApplicationThread caller, IBinder token,

Intent service, String resolvedType,

IServiceConnection connection, int flags, int userId) {

ConnectionRecord c = new ConnectionRecord(b, activity,

connection, flags, clientLabel, clientIntent);

IBinder binder = connection.asBinder();

if ((flags&Context.BIND_AUTO_CREATE) != 0) {

s.lastActivity = SystemClock.uptimeMillis();

if (bringUpServiceLocked(s, service.getFlags(), callerFg, false) != null){

return 0;

}

}

if (s.app != null && b.intent.received) {

// Service is already running, so we can immediately

// publish the connection.

try {

c.conn.connected(s.name, b.intent.binder);

} catch (Exception e) {

Slog.w(TAG, "Failure sending service " + s.shortName

+ " to connection " + c.conn.asBinder()

+ " (in " + c.binding.client.processName + ")", e);

}

// If this is the first app connected back to this binding,

// and the service had previously asked to be told when

// rebound, then do so.

if (b.intent.apps.size() == 1 && b.intent.doRebind) {

requestServiceBindingLocked(s, b.intent, callerFg, true);

}

} else if (!b.intent.requested) {

requestServiceBindingLocked(s, b.intent, callerFg, false);

}

}

根據之前的分析ServiceLocked會調用realStartServiceLocked,而realStartServiceLocked則先調用scheduleCreateService,完成service的創建和Oncreate()的執行,然後執行requestServiceBindingsLocked,這個是bind服務相關處理,最後是sendServiceArgsLocked,這個是Start服務的處理。

private final void realStartServiceLocked(ServiceRecord r,

ProcessRecord app, boolean execInFg) throws RemoteException {

app.thread.scheduleCreateService(r, r.serviceInfo, mAm.compatibilityInfoForPackageLocked(r.serviceInfo.applicationInfo), app.repProcState);

requestServiceBindingsLocked(r, execInFg);

sendServiceArgsLocked(r, execInFg, true);

}

requestServiceBindingsLocked再調用ActivityThread的方法scheduleBindService,在ActivityThread.java 中,它發出一個BIND_SERVICE事件,被handleBindService處理,

private void handleBindService(BindServiceData data) {

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, 0, 0, 0);

}

這裡先調用服務的onBind方法,因為服務是重載的,所以會執行具體服務類的方法,並返回服務裡的binder實例,這個binder隨後會被使用到,

其中AMS的publishService方法被調用,在 ActivityManagerService.java中又會調用 ActiveServices.java 的publishServiceLocked,

void publishServiceLocked(ServiceRecord r, Intent intent, IBinder service) {

for (int conni=r.connections.size()-1; conni>=0; conni--) {

ArrayList clist = r.connections.valueAt(conni);

for (int i=0; i

ConnectionRecord c = clist.get(i);

try {

c.conn.connected(r.name, service);

} …

serviceDoneExecutingLocked(r, mDestroyingServices.contains(r), false);

這裡主要調用到c.conn.connected,c就是ConnectionRecord,其成員conn是一個IServiceConnection類型實例,這在前面有提到,connected則是其實現類的方法。

對於IServiceConnection,它是一個接口,位置在(frameworks\base): core/java/android/app/IServiceConnection.aidl,aidl定義如下,它只有一個接口方法connected,

oneway interface IServiceConnection {

void connected(in ComponentName name, IBinder service);

}

其服務端的實現在LoadedApk.java,如下,InnerConnection類是在ServiceDispatcher的內部類,並在ServiceDispatcher的構造函數裡面實例化的,其方法connected也是調用的ServiceDispatcher的方法connected,

private static class InnerConnection extendsIServiceConnection.Stub {

final WeakReference mDispatcher;

InnerConnection(LoadedApk.ServiceDispatcher sd) {

mDispatcher = new WeakReference(sd);

}

public void connected(ComponentName name, IBinder service) throws RemoteException {

LoadedApk.ServiceDispatcher sd = mDispatcher.get();

if (sd != null) {

sd.connected(name, service);

}

}

}

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;

}

這裡就再回到我們前面的ContextImpl裡面bindServiceCommon方法裡面,這裡進行ServiceConnection轉化為IServiceConnection時,調用了mPackageInfo.getServiceDispatcher,mPackageInfo就是一個LoadedApk實例,

/*package*/ LoadedApk mPackageInfo;

private boolean bindServiceCommon(Intent service, ServiceConnection conn, int flags,

UserHandle user) {

IServiceConnection sd;

sd = mPackageInfo.getServiceDispatcher(conn, getOuterContext(),

mMainThread.getHandler(), flags);

}

所以,getServiceDispatcher會創建一個ServiceDispatcher實例,並將ServiceDispatcher實例和ServiceConnection實例形成KV對,並在ServiceDispatcher的構造函數裡將ServiceConnection實例c賦值給ServiceConnection的成員變量mConnection,

public final IServiceConnection getServiceDispatcher(ServiceConnection c,

Context context, Handler handler, int flags) {

synchronized (mServices) {

LoadedApk.ServiceDispatcher sd = null;

ArrayMap 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();

mServices.put(context, map);

}

map.put(c, sd);

}

這樣,在執行ServiceDispatcher的connected方法時,就會調用到ServiceConnection的

onServiceConnected,完成綁定ServiceConnection的觸發。

public void doConnected(ComponentName name, IBinder service) {

if (old != null) {

mConnection.onServiceDisconnected(name);

}

// If there is a new service, it is now connected.

if (service != null) {

mConnection.onServiceConnected(name, service);

}

}

至此,就執行完了bindService的主要過程。

我們下面用一張圖來總結這個流程,




  1. 上一頁:
  2. 下一頁:
熱門文章
閱讀排行版
Copyright © Android教程網 All Rights Reserved