Android教程網
  1. 首頁
  2. Android 技術
  3. Android 手機
  4. Android 系統教程
  5. Android 游戲
 Android教程網 >> Android技術 >> 關於Android編程 >> Android Studio 2.2下AIDL完全配置解析入手

Android Studio 2.2下AIDL完全配置解析入手

編輯:關於Android編程

前言

模擬:我們需要外部進程服務提供一個計算地點橫縱坐標的方法來顯示到我們自己的Textview上。

步驟

第一步創建相對應Aidl文件與需要自定義的類型

創建自定義類型

首先新建一個項目
這裡我們需要定義一個自定義類型LocationData 為了記錄橫眾坐標與服務Pid,創建!
LocationData.java 實現ParceLable借口,代碼注釋挺明白。具體可另行百度。

public class LocationData implements Parcelable {
    int width;//代表橫
    int heigth;//代表縱
    public LocationData(){

    }

    public LocationData(Parcel in){
        readFromParcel(in);//對象通過Binder從Parcel返回拿到
    }
    @Override
    public int describeContents() {
        return 0;//描繪類型信息一般不用管
    }
    @Override
    public void writeToParcel(Parcel dest, int flags) {
        dest.writeInt(width);//數據寫入容器Parcel
        dest.writeInt(heigth);
    }
    public static final Creator CREATOR = new Creator() {
        //內部類實現對象反序列化
        @Override
        public LocationData createFromParcel(Parcel in) {
            return new LocationData(in);
        }
        @Override
        public LocationData[] newArray(int size) {
            return new LocationData[size];
        }
    };
    /** 從Parcel中讀取數據 **/
    public void readFromParcel(Parcel in){
        width = in.readInt();
        heigth = in.readInt();
    }
    public int getHeigth() {
        return heigth;
    }
    public void setHeigth(int heigth) {
        this.heigth = heigth;
    }
    public int getWidth() {
        return width;
    }
    public void setWidth(int width) {
        this.width = width;
    }
    @Override
    public String toString() {
        return "width = "+ width + ", heigth="+ heigth;
    }
}

自定義類型LocationData.aidl文件很簡單無需過多聲明只要聲明出類型即可。
AS2.2創建Aidl文件
這裡寫圖片描述
LocationData.aidl

package com.ljs.testfitsystem;
parcelable LocationData;

默認Aidl支持原生類型只支持如下,所以需要我們自定義類型。

void basicTypes(int anInt, long aLong, boolean aBoolean, float aFloat,
            double aDouble, String aString);

聲明創建aidl接口

創建AIDL接口,提供接口IMyAidlInterface.aidl;
// IMyAidlInterface.aidl
package com.ljs.aidltest;
import com.ljs.aidltest.LocationData;// 導入自定義類型
// Declare any non-default types here with import statements

interface IMyAidlInterface {
             int getPid();//獲得當前服務進程ID
      LocationData getMyData();//提供LocationData對象給予我們Client

}

這裡我們最初的文件准備得到如下
這裡寫圖片描述
最後再編譯項目,
這裡寫圖片描述

得到我們接口文件。內部含1個內部類stub。stub內部含有Proxy類。具體就是對Binder的一些控制與數據操作,由於此文件自動生成,我們也不需要過多關心。
這裡寫圖片描述

編寫RPC中的遠程服務,

創建RemoteService.java 繼承service,

這裡我們為了模擬跨進程通信使用 android:process=“”來替代生成一個IPC通信的遠程服務。

  //隨意設置只是一個進程名稱
            
                //用來啟動服務
            
    

具體service文件如下已經作注釋:

public class RemoteService extends Service {
    private static final String TAG = "server"; //Log觀察生命周期
    LocationData mMyData;
    @Override
    public void onCreate() {
        super.onCreate();
        Log.i(TAG, "[server] onCreate");
        initMyData();//初始化Location
    }
    @Override
    public IBinder onBind(Intent intent) {
        Log.i(TAG,"[server] onBind");
        return mBinder;

    }
    @Override
    public boolean onUnbind(Intent intent) {
        Log.i(TAG, "[server] onUnbind");
        return super.onUnbind(intent);
    }
    @Override
    public void onDestroy() {
        Log.i(TAG, "[server] onDestroy");
        super.onDestroy();
    }
    //通過Aidl生成文件中Stub類實現我們生成接口中的方法
    IMyAidlInterface.Stub mBinder = new IMyAidlInterface.Stub() {
        @Override
        public int getPid() throws RemoteException {
            Log.i(TAG,"[server] getPid()="+android.os.Process.myPid());
            return android.os.Process.myPid();
        }
        @Override
        public LocationData getMyData() throws RemoteException {
            Log.i(TAG,"[server] getMyData()  "+ mMyData.toString());
            return mMyData;
        }
        //Binder驅動底層調用傳送數據,由於server ,1對多,一般不設置也可以做權限設置,判斷是否需要傳遞速度給Client。
        @Override
        public boolean onTransact(int code, Parcel data, Parcel reply, int flags) throws RemoteException {
            return super.onTransact(code, data, reply, flags);
        }
    };
    /**
     * 初始化MyData數據
     **/
    private void initMyData() {
        mMyData = new LocationData();
        mMyData.setWidth((int)(Math.random()*100));//隨機給予位置信息
        mMyData.setHeigth((int)(Math.random()*100));
    }
}

客戶端編寫

得到接口,服務端准備好,我們客戶端Bind服務就可以進行IPC通信了。

client編寫

MainActivity.java 重要部分已經注釋

public class MainActivity extends AppCompatActivity {
    private static final String TAG = "Client";
    private IMyAidlInterface mRemoteService;
    private boolean mIsBound =false;//是否已經綁定
    private TextView mTv;
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        Log.i(TAG, "[Client] onCreate");
        setContentView(R.layout.activity_main);
        mTv = (TextView) findViewById(R.id.tv);
        mTv.setText("還未連接");
    }
    //監控遠程服務狀態鏈接,ServiceConnection
    private ServiceConnection mConnection = new ServiceConnection() {
        @Override
        public void onServiceConnected(ComponentName name, IBinder service) {
            mRemoteService = IMyAidlInterface.Stub.asInterface(service);//鏈接上了才會調用
            String pidInfo = null;
            try {
                LocationData myData = mRemoteService.getMyData();
                pidInfo ="客戶端Pid"+ Process.myPid()+
                        "服務Pid="+ mRemoteService.getPid() +
                        ", 橫坐標 = "+ myData.getWidth() +
                        ", 縱坐標="+ myData.getHeigth();
            } catch (RemoteException e) {
                e.printStackTrace();
            }
            Log.i(TAG, "[Client] onServiceConnected  "+pidInfo);
            mTv.setText(pidInfo);
            Toast.makeText(MainActivity.this, "綁定上了哦", Toast.LENGTH_SHORT).show();
        }
        @Override
        public void onServiceDisconnected(ComponentName name) {
            //正常順序默認不調用意外情況銷毀調用
            Log.i(TAG, "[Client] onServiceDisconnected");
            mTv.setText("服務與客戶端斷開");
            mRemoteService = null;
            Toast.makeText(MainActivity.this, "已經斷開服務", Toast.LENGTH_SHORT).show();
        }
    };
    public void clickButton(View view){
        switch (view.getId()){
            case R.id.btn_bind:
                bindRemoteService();
                break;
            case R.id.btn_unbind:
                unbindRemoteService();
                break;
            case R.id.btn_kill:
                killRemoteService();
                break;
        }
    }
//綁定遠程服務
    private void bindRemoteService(){
        Log.i(TAG, "[Client] bindRemoteService");
        Intent intent = new Intent(MainActivity.this, RemoteService.class);
        intent.setAction("com.ljs.adiltestAction");
        intent.setPackage(getPackageName());//Android5.0不允許直接隱式啟動,需要加包名
        bindService(intent, mConnection, Context.BIND_AUTO_CREATE);
        mIsBound = true;
        mTv.setText("開始綁定服務");
    }
    //解除綁定
    private void unbindRemoteService(){
        Log.i(TAG, "[Client] unbindRemoteService ==>");
        if(!mIsBound){
            Toast.makeText(MainActivity.this, "不需要解綁已經沒有綁定服務", Toast.LENGTH_SHORT).show();
            return;
        }
        unbindService(mConnection);
        mIsBound = false;
        mTv.setText("解除綁定服務");
    }
    //kill遠程服務
    private void killRemoteService(){
        Log.i(TAG, "[Client] killRemoteService");
        try {
            android.os.Process.killProcess(mRemoteService.getPid());
            mTv.setText("Kill掉遠程服務所在進程");
            Toast.makeText(MainActivity.this, "遠程服務殺掉了哦", Toast.LENGTH_SHORT).show();
        } catch (RemoteException e) {
            e.printStackTrace();
            Toast.makeText(MainActivity.this, "服務進程不存在,殺死服務進程失敗", Toast.LENGTH_SHORT).show();

        }
    }
}

程序Bind服務調用服務方法接口獲得服務端隨機算出來的LocationData對象與服務進程Pid截圖

這裡寫圖片描述

依次執行生成Log信息

Client下順序

 2570-2570/com.ljs.aidltest I/Client: [Client] onCreate
 2570-2570/com.ljs.aidltest I/Client: [Client] bindRemoteService
 2570-2570/com.ljs.aidltest I/Client: [Client] onServiceConnected  客戶端Pid2570服務Pid=3579, 橫坐標 = 31, 縱坐標=8
 2570-2570/com.ljs.aidltest I/Client: [Client] unbindRemoteService ==>
 2570-2570/com.ljs.aidltest I/Client: [Client] killRemoteService

server下順序

3579-3579/com.ljs.aidltest:Remoteserver I/Server: [server] onCreate
3579-3579/com.ljs.aidltest:Remoteserver I/Server: [server] onBind
3579-3592/com.ljs.aidltest:Remoteserver I/Server: [server] getMyData()  width = 31, heigth=8
3579-3591/com.ljs.aidltest:Remoteserver I/Server: [server] getPid()=3579
 3579-3579/com.ljs.aidltest:Remoteserver I/Server: [server] onUnbind
3579-3579/com.ljs.aidltest:Remoteserver I/Server: [server] onDestroy

Github具體源代碼地址

https://github.com/anderson9/AIDLnewDemo

  1. 上一頁:
  2. 下一頁:
熱門文章
閱讀排行版
Copyright © Android教程網 All Rights Reserved