安卓進程間通信AIDL

今天介紹下安卓跨進程同時AIDL基本使用和需要注意的地方,我以登錄爲例,

新建個項目MyAidl,新建一個IMyAidlInterface 的AIDL接口,


 

在interface Nmae輸入接口名稱

 

//再在aidl文件夾下新建一個Bean對象,(注意自定義bean對象,需要現在aidl新建編譯,再建Java類bean,要不你在aidl會報類名衝突

Bean.adil代碼如下

// Bean.aidl
package cn.zdh.myaidl;

// Declare any non-default types here with import statements
//導入對應的Bean對象
parcelable Bean;

再在Java文件夾新建個Bean對象代碼如下(注意自定義bean類需要實現parcelable,如果aidl接口使用out 或者inout需要寫readFromParcel(Parcel reply)方法; 注意Java的bean類的包名必須和aidl的包名一致

public class Bean implements Parcelable {

    private String name;

    private String password;

    public Bean() {
    }

    public Bean(String name, String password) {
        this.name = name;
        this.password = password;
    }

    public String getName() {
        return name;
    }

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

    public String getPassword() {
        return password;
    }

    public void setPassword(String password) {
        this.password = password;
    }


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

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


    protected Bean(Parcel in) {
        this.name = in.readString();
        this.password = in.readString();
    }

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

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


    /**
     * adil 使用out 或者inout 需要寫這個方法
     */

    public void readFromParcel(Parcel reply) {
        this.name = reply.readString();
        this.password = reply.readString();

    }
}

 

//下面寫aidl接口

//使用AIDL需要注意下面幾點

//1:同包也要導包
//2: 支持基礎類型數據傳遞,自定義類需要實現parcelable序列化
//3:自定義的類名和包名必須和 AIDL的類名包名一致
//4:in 服務端 不能修改客服端的入參數數據(bean),但是可以獲取參數數據
//5:out 服務端 能修改客服端的入參數據(bean),但是並不可以獲取參數數據
//6:inout 服務 能修改客服端的入參數據(bean),也可以獲取參數數據 ,但是消耗性能最大
//7:注意 使用out inout Java的bean對象需要寫 readFromParcel(Parcel reply){}方法,在方法裏面把字段讀取出來

import cn.zdh.myaidl.Bean;

interface IMyAidlInterface {

void login(in Bean bean);


}

 

 

//Java對應service代碼

/**
 * 實現aidl接口方法
 */
public class AidlService extends Service {

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


    private Handler handler = new Handler(Looper.getMainLooper()) {
        @Override
        public void handleMessage(Message msg) {
            super.handleMessage(msg);
            if (msg.what == 1) {
                Toast.makeText(getApplicationContext(), "登錄成功", Toast.LENGTH_SHORT).show();
            } else {
                Toast.makeText(getApplicationContext(), "登錄失敗", Toast.LENGTH_SHORT).show();
            }

        }
    };


    /**
     * 獲取aidl的binder對象
     * 注意在子線程
     */
    private IBinder iBinder = new IMyAidlInterface.Stub() {
        @Override
        public void login(Bean bean) throws RemoteException {
            //判斷用戶賬戶是的正確
            String name = bean.getName();
            String password = bean.getPassword();
            Message message = handler.obtainMessage();
            if (name.equals("張三") && password.equals("123456")) {
                message.what = 1;
                handler.sendMessage(message);
            } else {
                Log.e("zdh", "------" + Thread.currentThread().getName());
                message.what = 0;
                handler.sendMessage(message);
            }


        }
    };
}

 

 

//創建一個activity測試登錄,代碼如下,(注意 在mainfest添加process 新建個進程)

public class TextActivity extends AppCompatActivity {

    private IMyAidlInterface iMyAidlInterface;
    private ServiceConnection conn;
    private EditText etName, etPassword;

    @Override
    protected void onCreate(@Nullable Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_text);
        etName = findViewById(R.id.et_name);
        etPassword = findViewById(R.id.et_password);


        //bindService啓動服務
        Intent intent = new Intent();
        intent.setComponent(new ComponentName("cn.zdh.myaidl", "cn.zdh.myaidl.AidlService"));
        conn = new MyServiceConnection();
        bindService(intent, conn, BIND_AUTO_CREATE);
    }

    @Override
    protected void onDestroy() {
        super.onDestroy();
        //解除服務綁定
        unbindService(conn);
    }

    //登錄
    public void load(View view) {
        Bean bean = new Bean();
        bean.setName(etName.getText().toString());
        bean.setPassword(etPassword.getText().toString());
        try {
            //添加數據
            iMyAidlInterface.login(bean);
        } catch (Exception e) {
            e.printStackTrace();
        }

    }

    private class MyServiceConnection implements ServiceConnection {

        @Override
        public void onServiceConnected(ComponentName name, IBinder service) {
            //獲取aidl接口對象
            iMyAidlInterface = IMyAidlInterface.Stub.asInterface(service);
        }

        @Override
        public void onServiceDisconnected(ComponentName name) {

        }
    }

}

 

  //mainfest代碼

//注意 process 需要使用雙引號 :
<activity android:name=".TextActivity"  android:process=":t"/>
//不要忘記註冊服務        
<service android:name=".AidlService" />

代碼運行效果如下

 

總結:使用aidl需要注意的

//1:同包也要導包
//2: 支持基礎類型數據傳遞,自定義類需要實現parcelable序列化
//3:自定義的類名和包名必須和 AIDL的類名包名一致
//4:in 服務端 不能修改客服端的入參數數據(bean),但是可以獲取參數數據
//5:out 服務端 能修改客服端的入參數據(bean),但是並不可以獲取參數數據
//6:inout 服務 能修改客服端的入參數據(bean),也可以獲取參數數據 ,但是消耗性能最大
//7:注意 使用out inout Java的bean對象需要寫 readFromParcel(Parcel reply){}方法,在方法裏面把字段讀取出來
//8:Java是service 是在子線程

 

源碼地址 https://github.com/zhudaihao/MyAIDL

 

 

 

 

 

 

 

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章