跨進(jìn)程通信之:AIDL

Android應(yīng)用是獨立的進(jìn)程、獨立的內(nèi)存,所以在不同進(jìn)程間傳遞數(shù)據(jù)會稍微麻煩些,基于這種情況Android SDK提供了4種通信方式,分別為:AIDL、Content Provider、Broadcast、Activity。今天介紹AIDL通信方式的實現(xiàn)。

AIDL

aidl是一種Service通信,通過定義aidl接口實現(xiàn)數(shù)據(jù)的傳輸,首先定義服務(wù)端和客戶端,服務(wù)端即Service,客戶端即服務(wù)端Service的綁定實現(xiàn)。

支持的數(shù)據(jù)類型:基本數(shù)據(jù)類型、自定義類型(Parcelable接口的實現(xiàn))

基本數(shù)據(jù)類型的實現(xiàn)

在main文件夾下創(chuàng)建aidl文件夾,再新建aidl接口文件

代碼結(jié)構(gòu)

aidl接口里定義調(diào)用方法,如下:

interface IMyAidlInterface {

    int getInt();
    float getFloadt();
    double getDouble();
    long getLong();
    boolean getBoolean();
    String getString();

    void setData(int aInt,float aFloat,double aDouble,long aLong,boolean aBoolean,String aString);
}

定義完后需要Make Project一下工程,接著在服務(wù)端Service里實現(xiàn)該aidl接口的Stub內(nèi)部類,并在onBind()里返回,Stub就是一個Binder的子類,所以AIDL歸根結(jié)底就是Binder通信。

/**
 * Created by 你的樣子 on 2018/8/3.
 * 服務(wù)端
 */
public class AService extends Service {

    private int a;
    private float b;
    private double c;
    private long d;
    private boolean e;
    private String f;

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

    private class MyBinder extends IMyAidlInterface.Stub {

        @Override
        public int getInt() throws RemoteException {
            return a;
        }

        @Override
        public float getFloat() throws RemoteException {
            return b;
        }

        @Override
        public double getDouble() throws RemoteException {
            return c;
        }

        @Override
        public long getLong() throws RemoteException {
            return d;
        }

        @Override
        public boolean getBoolean() throws RemoteException {
            return e;
        }

        @Override
        public String getString() throws RemoteException {
            return f;
        }

        @Override
        public void setData(int aInt, float aFloat, double aDouble, long aLong, boolean aBoolean, String aString) throws RemoteException {
            a = aInt;
            b = aFloat;
            c = aDouble;
            d = aLong;
            e = aBoolean;
            f = aString;
        }
    }
}

到此基本數(shù)據(jù)類型服務(wù)端實現(xiàn)編寫完畢。

接下來是客戶端實現(xiàn),把a(bǔ)idl文件拷貝到另一個工程中,再次Make project一下,需注意的是aidl文件的包名必須一致,然后在Activity中綁定服務(wù)端Service即可。

public class MainActivity extends AppCompatActivity {

    private IMyAidlInterface iMyAidlInterface;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        bindService(new Intent("ni.de.yang.zi"),new ServiceConnection() {
            @Override
            public void onServiceConnected(ComponentName name, IBinder service) {
                iMyAidlInterface = IMyAidlInterface.Stub.asInterface(service);
            }

            @Override
            public void onServiceDisconnected(ComponentName name) {

            }
        },BIND_AUTO_CREATE);
        findViewById(R.id.add).setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                try {
                    iMyAidlInterface.setData(8, 0.9f, 9, 1000000, true, "示例");
                } catch (RemoteException e) {
                    e.printStackTrace();
                }
            }
        });
        findViewById(R.id.get).setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                try {
                    Log.i("==TAG==","獲取字符串 :" + iMyAidlInterface.getString());
                } catch (RemoteException e) {
                    e.printStackTrace();
                }
            }
        });
    }
}

end.

自定義類型的實現(xiàn)

首先在Java目錄下創(chuàng)建自定義類型實體類,并實現(xiàn)Parcelable接口。

public class User implements Parcelable {

    private String name;

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

    public String getName() {
        return name;
    }

    protected User(Parcel in) {
        name = in.readString();
    }

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

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

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

    @Override
    public void writeToParcel(Parcel dest, int flags) {
        dest.writeString(name);
    }

    public void readFromParcel(Parcel dest) {
        //注意,此處的讀值順序應(yīng)當(dāng)是和writeToParcel()方法中一致的
        name = dest.readString();
    }
}

接下來在aidl目錄下新建跟User.java類同包同名aidl文件,再導(dǎo)入User完整包名,聲明自定義類型parcelable,

注意:

1.User.java跟User.aidl必須是相同包名,名字也一樣,不然編譯不通過。
2.parcelable為小寫

// User.aidl
package com.yscall.testt.bean;
parcelable User;

到此新類型已定義完了,接下來是服務(wù)端的實現(xiàn),具體流程跟基本類型的實現(xiàn)一樣,先建立一個邏輯操作aidl文件,并導(dǎo)入自定義類型完整包名,再Make project一下。

package com.yscall.testt;

//完整包名
import com.yscall.testt.bean.User;

interface CustomAidlInterface {

    User getUser();

    void addUser(inout User user);

}

創(chuàng)建服務(wù)端Service

public class BService extends Service {

    private User user;

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

    class MyBinder extends CustomAidlInterface.Stub{

        @Override
        public User getUser() throws RemoteException {
            return user;
        }

        @Override
        public void addUser(User user) throws RemoteException {
            BService.this.user = user;
        }
    }}

項目結(jié)構(gòu)如下:
項目結(jié)構(gòu)

接著是客戶端的實現(xiàn),把CustomAidlIterface.aidl、User.aidl拷貝到另一個工程中,包名需一致,再Make project一下。最后在Activity里綁定調(diào)用即可。

public class ClientActivity extends Activity {

    private CustomAidlInterface customAidlInterface;

    @Override
    protected void onCreate(@Nullable Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        bindService(new Intent("ni.de.yang.zi"), new ServiceConnection() {
            @Override
            public void onServiceConnected(ComponentName name, IBinder service) {
                customAidlInterface = CustomAidlInterface.Stub.asInterface(service);
            }

            @Override
            public void onServiceDisconnected(ComponentName name) {

            }
        }, BIND_AUTO_CREATE);
        findViewById(R.id.add).setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                try {
                    customAidlInterface.addUser(new User("迷糊"));
                } catch (RemoteException e) {
                    e.printStackTrace();
                }
            }
        });
        findViewById(R.id.get).setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                try {
                    User user = customAidlInterface.getUser();
                } catch (RemoteException e) {
                    e.printStackTrace();
                }
            }
        });
    }
}

到此自定義類型的使用就基本實現(xiàn)了。

結(jié)語:AIDL傳輸數(shù)據(jù)的前提是兩個進(jìn)程必須是運行狀態(tài)。否無法傳輸。

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時請結(jié)合常識與多方信息審慎甄別。
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點,簡書系信息發(fā)布平臺,僅提供信息存儲服務(wù)。

友情鏈接更多精彩內(nèi)容