Android 程式間通訊 AIDL詳解

mymdeep發表於2017-03-23

最近專案有程式間通訊的需求,我使用的是IPC通訊的方式,這是Android中很傳統的一種程式間通訊的方式,在這裡分享給大家。


程式間通訊意義

我們為什麼要使用程式間通訊。我說一個場景,比如我們有兩個App,其中一個App(名字為A),有授權登陸,我們還有一個App(名字為B)可能是A的附屬App,或者同期產品,我們希望有相同的賬號,也就是A登陸了,B就自動登入了。那麼B在進入的時候需要從A中拿登陸資訊,比如姓名性別,暱稱等。這時候就涉及到程式間通訊了。或者B中需要一些加密演算法,我們不想在B中暴露,可以把值傳給A,然後A計算完再傳遞回來。
當然還有其它場景,這裡不再贅述了。

建立個工程

首先我們當然要建立一個工程,最普通的工程就可以。

服務端App

這個工程中的第一個module服務端module,也就是上面提到的A app,內容提供的app
我們在src/main中建立一個aidl資料夾:

Android 程式間通訊 AIDL詳解

右鍵點選aidl資料夾,new一個aidl檔案:

Android 程式間通訊 AIDL詳解

在裡面建立一個檔案,比如我們想獲取使用者資訊:

interface IPeople {
    /**
     * Demonstrates some basic types that you can use as parameters
     * and return values in AIDL.
     */
     String getName();
     String getSex();
}複製程式碼

然後rebuild一下工程,這時,會在build資料夾下生成一個檔案

Android 程式間通訊 AIDL詳解

這個檔案就是aidl生成的對應的介面檔案,沒有這個檔案,我們之後在引用介面的時候會報錯。你不用給它轉移地方,放在這就行了。
然後我們寫一個服務Service,提供資料:

public class AidlService extends Service{
    private PeopleBinder peopleBinder;
    @Override
    public void onCreate() {
        super.onCreate();
            peopleBinder = new  PeopleBinder();
    }

    @Override
    public IBinder onBind(Intent intent) {
        return peopleBinder;
    }

    public class PeopleBinder extends IPeople.Stub
    {


        @Override
        public String getName() throws RemoteException {
            return "deep";
        }

        @Override
        public String getSex() throws RemoteException {
            return "man";
        }
    }
}複製程式碼

其中PeopleBinder是程式間傳遞資料的媒介,如果你想傳一個資料類,那麼這個資料類一定要序列化。PeopleBinder實現的介面,就是剛才我們生成的那個檔案中的介面。所以一定要等aidl介面檔案生成我們再去寫這個類。
然後將Service註冊在AndroidManifest中,注意要加一個action,方便客戶端App啟動:

   <service android:name=".AidlService">
            <intent-filter>
                <action android:name="deep.testaidl.AidlService"/>
            </intent-filter>
        </service>複製程式碼

要注意app要安裝到手機上啊,否則後面怎麼獲取……

客戶端App

我們新建一個module,這個module就是客戶端App,也就是我們上文中提到的B App,內容索取者。
用同樣的方式建立一個aidl檔案,這個aidl檔案要與上面的一樣,且路徑也要一樣,如圖所示:

Android 程式間通訊 AIDL詳解

可以看到路徑一樣,檔名一樣,當然內容也一樣。
這樣才能保證協議一致。然後還是rebuild一下。生成對應的介面檔案。
然後我們在Activity中,隨便寫一個佈局(這個不多說了,與本文主旨無關),有個按鈕,有個顯示就行。
然後開始獲取使用者資料了,首先,我們需要定義一個協議介面,也就是你獲取使用者資料的介面:

  private IPeople people;//協議介面複製程式碼

接著需要建立一個服務連線,與服務端App剛寫的那個Service進行連線通訊:

private ServiceConnection conn = new ServiceConnection() {
        @Override
        public void onServiceConnected(ComponentName name, IBinder service) {
            people = IPeople.Stub.asInterface(service);//連線建立成功,讀取資料
            try {

               textView.setText("name ="+people.getName()+" sex="+people.getSex());
            } catch (RemoteException e) {
                e.printStackTrace();
            }

        }

        @Override
        public void onServiceDisconnected(ComponentName name) {
            people = null;

        }
    };複製程式碼

剛才不是寫了一個按鈕嗎,新增一個點選事件,開啟服務端寫好的Service,進行通訊:

  button.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View view) {
                Intent intent = new Intent();
                intent.setAction("deep.testaidl.AidlService");
                intent.setPackage("deep.testaidl");
                bindService(intent,conn, Service.BIND_AUTO_CREATE);
            }
        });複製程式碼

由於我們剛才在服務連線的回撥中,將使用者資訊設定到了textview上,這樣就可以顯示出來了。
好了,這樣一次通訊就完成了,是不是沒有想象的複雜。

總結

這種程式間通訊的方式還是比較傳統的,用的也比較多,瞭解一下對於以後的學習很有幫助,如有其它問題可以關注我的公眾號留言給我,我會第一時間回覆。
更多的開發知識,可以關注我的公眾號:

Android 程式間通訊 AIDL詳解

相關文章