AIDL 進程間通訊的一個小小的總結

 

需求

  項目須要,將作好的項目做爲一個服務提供給另外一個公司。咱們須要提供一個apk,因此設計到進程間交互,不得不瞭解一下AIDL了。java

 

 

瞭解一下AIDL

  以前準備面試的時候,或多或少的瞭解了一點AIDL,不過如今忘記得差很少了。android

  因此網上隨便找了幾篇不錯的文章。git

  1.進程通訊之AIDL的使用。github

  2.學習AIDL,這一篇就夠了。面試

 

 

一個簡單的demo

  本身搞了一個簡單的demo。服務器

  實現了進程間通訊,能夠傳輸普通類型和實體類型。app

  首先是服務端。dom

  1.第一個aidl接口。ide

// IMyAidlInterface.aidl
package com.xf.test1;

import com.xf.test1.IAidlCallBack;
import com.xf.test1.Entity;
// Declare any non-default types here with import statements

interface IMyAidlInterface {
    /**
     * Demonstrates some basic types that you can use as parameters
     * and return values in AIDL.
     */
    void basicTypes(int anInt, long aLong, boolean aBoolean, float aFloat,
            double aDouble, String aString);


    String getStr(String str);

    int getPid();

    Entity getEntity();

    Entity setEntity(in Entity entity);

    void registerCallBack(IAidlCallBack callback);

    void unregisterCallBack(IAidlCallBack callback);
}
View Code

  2.第二個aidl接口。佈局

// IAidlCallBack.aidl
package com.xf.test1;

import com.xf.test1.Entity;

// Declare any non-default types here with import statements

interface IAidlCallBack {

    void callBack(String name);

    void callBackEntity(in Entity entity);
}
View Code

  3.第三個aidl接口。

// Person.aidl
package com.xf.test1;

parcelable Entity;
View Code

  4.封裝的一個IBinder。

package com.xf.test1;

import android.app.Service;
import android.content.Intent;
import android.os.IBinder;
import android.support.annotation.Nullable;

public class AIDLService extends Service {


    private AIDLImp mBinder;


    @Override
    public void onCreate() {
        super.onCreate();
        mBinder = new AIDLImp(this);
    }

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


    @Override
    public void onDestroy() {
        super.onDestroy();
        mBinder.KillAll();
    }
}
View Code

  5.AIDL服務。

package com.xf.test1;

import android.app.Service;
import android.content.Intent;
import android.os.IBinder;
import android.support.annotation.Nullable;

public class AIDLService extends Service {


    private AIDLImp mBinder;


    @Override
    public void onCreate() {
        super.onCreate();
        mBinder = new AIDLImp(this);
    }

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


    @Override
    public void onDestroy() {
        super.onDestroy();
        mBinder.KillAll();
    }
}
View Code

  6.實體類型。

package com.xf.test1;

import android.os.Parcel;
import android.os.Parcelable;

/**
 * Description: 簡單實體類
 *
 * @version V1.0.0
 * Createdate: 2018/6/22
 * @author: wja 1211241203@qq.com
 */
public class Entity implements Parcelable {

    private String name;

    private int parameter1;

    private double parameter2;

    public Entity(String name){
        this.name=name;
    }

    public Entity(String name, int parameter1, double parameter2) {
        this.name = name;
        this.parameter1 = parameter1;
        this.parameter2 = parameter2;
    }

    public int getParameter1() {
        return parameter1;
    }

    public void setParameter1(int parameter1) {
        this.parameter1 = parameter1;
    }

    public double getParameter2() {
        return parameter2;
    }

    public void setParameter2(double parameter2) {
        this.parameter2 = parameter2;
    }

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    @Override
    public int describeContents() {
        return 0;
    }

    @Override
    public void writeToParcel(Parcel dest, int flags) {
        dest.writeString(this.name);
        dest.writeInt(this.parameter1);
        dest.writeDouble(this.parameter2);
    }

    protected Entity(Parcel in) {
        this.name = in.readString();
        this.parameter1 = in.readInt();
        this.parameter2 = in.readDouble();
    }

    public static final Creator<Entity> CREATOR = new Creator<Entity>() {
        @Override
        public Entity createFromParcel(Parcel source) {
            return new Entity(source);
        }

        @Override
        public Entity[] newArray(int size) {
            return new Entity[size];
        }
    };

    @Override
    public String toString() {
        return "Entity{" +
                "name='" + name + '\'' +
                ", parameter1=" + parameter1 +
                ", parameter2=" + parameter2 +
                '}';
    }
}
View Code

  7.清單文件。

<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
    package="com.xf.test1">

    <application
        android:allowBackup="true"
        android:icon="@mipmap/ic_launcher"
        android:label="@string/app_name"
        android:roundIcon="@mipmap/ic_launcher_round"
        android:supportsRtl="true"
        android:theme="@style/AppTheme">
        <activity android:name=".MainActivity">
            <!--<intent-filter>
                <action android:name="android.intent.action.MAIN" />

                <category android:name="android.intent.category.LAUNCHER" />

                <data android:scheme="com.xf.aidl.test" />
            </intent-filter>-->
        </activity>


        <service android:name=".AIDLService">
            <intent-filter>
                <action android:name="com.xf.aidl" />
                <category android:name="android.intent.category.DEFAULT" />
                <!--<action android:name="android.intent.action.MAIN" />-->

                <!--<category android:name="android.intent.category.LAUNCHER" />-->
            </intent-filter>
        </service>
    </application>

</manifest>
View Code

  8.服務端如何運行(不使用啓動圖標的方式)

   

  而後點擊進去

  

  9.最後點擊運行,服務就安裝在手機啦。

  

  其次,是客戶端。

  1.客戶端的aidl文件和服務端的徹底同樣。(固然路徑能夠不同,爲了方便我直接copy的,路徑不同也是能夠的,測試過的)

  2.而後注意實體類型所在的包必定要和服務端的一致,負責找不到這個實體的。

  3.最後是客戶端的主頁面。

package com.xf.test2;

import android.content.ComponentName;
import android.content.Context;
import android.content.Intent;
import android.content.ServiceConnection;
import android.os.Bundle;
import android.os.IBinder;
import android.os.RemoteException;
import android.support.v7.app.AppCompatActivity;
import android.util.Log;
import android.view.View;

import com.xf.test1.Entity;
import com.xf.test1.IAidlCallBack;
import com.xf.test1.IMyAidlInterface;

import java.util.Random;

public class MainActivity extends AppCompatActivity {

    private IMyAidlInterface mIMyAidlInterfaceService;


    private ServiceConnection mServiceConnection = new ServiceConnection() {
        @Override
        public void onServiceConnected(ComponentName name, IBinder service) {
            mIMyAidlInterfaceService = IMyAidlInterface.Stub.asInterface(service);
            try {
                mIMyAidlInterfaceService.registerCallBack(mIAidlCallBack);
            } catch (RemoteException e) {
                e.printStackTrace();
            }
        }

        @Override
        public void onServiceDisconnected(ComponentName name) {
            try {
                mIMyAidlInterfaceService.unregisterCallBack(mIAidlCallBack);
            } catch (RemoteException e) {
                e.printStackTrace();
            }
            mIMyAidlInterfaceService = null;
        }
    };


    private IAidlCallBack mIAidlCallBack = new IAidlCallBack.Stub() {
        @Override
        public void callBack(String name) throws RemoteException {
            Log.e("info---->","服務端給我發消息啦:"+name);
            ToastUtil.showShort(MainActivity.this,"服務端給我發消息啦:"+name);
        }

        @Override
        public void callBackEntity(Entity entity) {
            Log.e("info---->","服務端給我發實體消息啦:"+entity.toString());
            ToastUtil.showShort(MainActivity.this,"服務端給我發實體消息啦:"+entity.toString());
        }
    };


    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
    }

    @Override
    protected void onDestroy() {
        super.onDestroy();
        if (mServiceConnection != null)
            unbindService(mServiceConnection);
    }

    /**
     * 綁定服務
     * @param view
     */
    public void doClick(View view) {
        Intent intent = new Intent();
        intent.setAction("com.xf.aidl");
        intent.setPackage("com.xf.test1");
        bindService(intent, mServiceConnection, Context.BIND_AUTO_CREATE);
    }


    /**
     * 獲取服務器發送過來的消息
     * @param v
     */
    public void doAction(View v) {
        if (mIMyAidlInterfaceService != null) {
            try {
                String newstr = mIMyAidlInterfaceService.getStr("Hello world");
                int pid = mIMyAidlInterfaceService.getPid();
                Log.e("info---->", newstr + " pid:" + pid);
            } catch (RemoteException e) {
                e.printStackTrace();
            }
        }
    }

    /**
     * 客戶端本身設置實體,發送給服務端
     * 經過隨機數設置實體參數
     * @param v
     */
    public void doActionSetEntity(View v){
        if (mIMyAidlInterfaceService != null) {
            try {
               Random random=new Random();
               mIMyAidlInterfaceService.setEntity(new Entity("客戶端",random.nextInt(100),random.nextDouble()));

            } catch (RemoteException e) {
                e.printStackTrace();
            }
        }
    }
}
View Code

    下面是佈局文件。

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:orientation="vertical"
    tools:context=".MainActivity">

    <RelativeLayout
        android:layout_marginTop="100dp"
        android:layout_width="match_parent"
        android:layout_height="wrap_content">

        <Button
            android:layout_width="300dp"
            android:layout_height="wrap_content"
            android:onClick="doClick"
            android:text="綁定服務"
            android:layout_centerInParent="true"
             />

    </RelativeLayout>

    <RelativeLayout
        android:layout_width="match_parent"
        android:layout_height="wrap_content">

        <Button
            android:layout_width="300dp"
            android:layout_height="wrap_content"
            android:onClick="doAction"
            android:text="獲取消息"
            android:layout_centerInParent="true"
            />

    </RelativeLayout>

    <RelativeLayout
        android:layout_width="match_parent"
        android:layout_height="wrap_content">

        <Button
            android:layout_width="300dp"
            android:layout_height="wrap_content"
            android:onClick="doActionSetEntity"
            android:text="客戶端設置實體"
            android:layout_centerInParent="true"
            />

    </RelativeLayout>

</LinearLayout>
View Code

  

  運行效果是這樣的:

        

 

   這裏客戶端首先須要綁定服務

  點擊了獲取消息:直接獲取服務端建立好的實體類。

  點擊了客戶端設置實體:經過產生隨機數,客戶端調用aidl接口設置實體。

  若是再次點擊獲取消息:在服務端進行判斷,若是客戶端設置過實體,就把該實體發送回客戶端。

 

  demo地址:https://github.com/JasonToJan/AIDLDemo

 

 

我的小結

  1.首先要理解aidl是幹什麼的:進程間交互。不一樣apk實現通訊。

  2.爲何能夠作到進程間通訊了,誰給兩個進程之間搭起了一座橋樑呢?AIDL,其實就是一個接口,實現進程之間對接的功能。

  3.兩個進程要作到通訊,aidl必定要保證一致,否則就是牛頭不對馬嘴了。

  4.aidl如何實現數據傳輸了,binder。因此demo就把binder直接封裝起來,基本全部邏輯都在這個封裝類中進行便可。

  5.再深刻底層,binder是如何實現數據傳輸的呢?這就涉及到操做系統的知識了,binder處於一個內存共享區域,能夠實現進程間通訊。

相關文章
相關標籤/搜索