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

來源:互聯網
上載者:User

android4.4組件分析--service組件-bindService源碼分析,android4大組件
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<ConnectionRecord> clist = r.connections.valueAt(conni);

                        for (int i=0; i<clist.size(); 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<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);

                }

            }

        }

 

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

}

 

 

這樣,在執行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的主要過程。

 

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





android中的service與開啟service的組件是否處於同一線程?

同一個進程,但是不是同一個線程,看你的樣子應該知道進程和線程的區別,但是仍然不建議做修改
 
android 中的採用bindService()啟動服務,為何沒有調用onServiceConnected()方法,

你這個寫的太奇葩了,我第一次看見這樣寫的。難道不應該有一個extends Service的class麼,我還真是第一次看見用Activity來實現serviceConnection的,都不好評價你這個到底是對是錯
 

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.