1. 程式人生 > >知識點-----AIDL(一)簡單的aidl實現

知識點-----AIDL(一)簡單的aidl實現

AIDL是什麼

AIDL(Android Interface Definition Language)是Android系統自定義的介面描述語言。可以用來實現程序間的通訊。

AIDL 支援的資料型別

共 4 種:

  1. Java 的基本資料型別
  2. List 和 Map 
    • 元素必須是 AIDL 支援的資料型別
    • Server 端具體的類裡則必須是 ArrayList 或者 HashMap
  3. 其他 AIDL 生成的介面
  4. 實現 Parcelable 的實體

aidl實現步驟(案例一:簡單的add)

        此次的demo,服務端也進行了除錯,如果服務端調通了啟動服務與呼叫方法,客戶端啟動服務和呼叫方法可直接複製過去。

服務端


1、建立專案:建立DemoAidlService專案(跟正常一樣)
2、建立aidl檔案

        在app(Android預覽目錄下)上右鍵 New -> AIDL -> AIDL File。此時自動建立aidl資料夾,並在aidl資料夾下建立跟DemoAidlService包名一樣的路徑,且建立aidl結尾的檔案,
點選build後,發現build資料夾下自動生成debug資料夾下的aidl編譯檔案
3、新增aidl裡的抽象方法:在aidl檔案下新增方法(如add(in int x, in int y)

interface IAddAidlInterface {
    /**
     * 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);

    int add(in int x, in int y);
}

4、 建立服務:建立自定義服務AddService繼承自Service,在生命週期onBind()中返回值返回 aidl物件mBinder,mBinder = InAddAidlInterface.Stub(){ 可重寫抽象方法,並實現邏輯 }

public class AddService extends Service {


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

    IAddAidlInterface.Stub mBinder = new IAddAidlInterface.Stub() {
        @Override
        public void basicTypes(int anInt, long aLong, boolean aBoolean, float aFloat, double aDouble, String aString) throws RemoteException {

        }

        @Override
        public int add(int x, int y) throws RemoteException {
            return x + y;//具體的實現邏輯
        }
    };

}

5、啟動服務:啟動服務時要用繫結式啟動bindService,bindService(intent, mConn, Context.BIND_AUTO_CREATE),
關鍵是第二個mConn引數,mConn  = ServiceConnection(){ 預設兩個抽象方法,在連線成功方法onServiceConnected中賦值aidl物件mService = IAddAidlInterface.Stub.asInterface(service) }
注意要asInterface,不然會報錯。

public class MainActivity extends AppCompatActivity {

    private IAddAidlInterface mService;

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

        aboutService();

        findViewById(R.id.btn_add).setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {

                int x = Integer.parseInt(((EditText) findViewById(R.id.et_add_x)).getText().toString());
                int y = Integer.parseInt(((EditText) findViewById(R.id.et_add_y)).getText().toString());
                try {
                    Log.d("baibai", "服務端 相加結果:" + mService.add(x, y));
                } catch (RemoteException e) {
                    e.printStackTrace();
                }

            }
        });

    }

    ServiceConnection mConn = new ServiceConnection() {

        @Override
        public void onServiceConnected(ComponentName name, IBinder service) {
            Log.d("baibai", "服務端:連線 Service 成功");
            mService = IAddAidlInterface.Stub.asInterface(service);
        }

        @Override
        public void onServiceDisconnected(ComponentName name) {

        }
    };

    private void aboutService() {
        Intent intent = new Intent(this, AddService.class);
        bindService(intent, mConn, Context.BIND_AUTO_CREATE);
    }


}

6、呼叫方法:實際呼叫mService的裡的方法。

客戶端


1、建立專案:建立DemoAidlClient專案(跟正常一樣)
2、建立aidl檔案(但是跟服務端建立的方式)


        不能右鍵New -> ……,因為如果這麼建立會建立跟DemoAidlClient的包名是一樣的,而我們需要的是跟服務端的包名一樣,所以要自己手動建立跟服務端一樣的包名路徑,並把服務端的aidl複製到改包名下,build一下,客戶端專案就可以引用到服務端aidl檔案的抽象方法。
3、啟動服務

public class MainActivity extends AppCompatActivity {

    private IAddAidlInterface mService;

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

        aboutService();

        findViewById(R.id.btn_add_client).setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {

                int x = Integer.parseInt(((EditText) findViewById(R.id.et_add_client_x)).getText().toString());
                int y = Integer.parseInt(((EditText) findViewById(R.id.et_add_client_y)).getText().toString());
                try {
                    Log.d("baibai", "客戶端 相加結果:" + mService.add(x, y));
                } catch (RemoteException e) {
                    e.printStackTrace();
                }

            }
        });


    }

    private void aboutService() {
        Intent intent = new Intent();
        intent.setAction("bai.bai.bai.aidl.service_add");//5.0出現以後必須使用顯示啟動,不然會報錯(加了下一行程式碼可解決這個問題)
        intent.setPackage("bai.bai.bai.demoaidlservice");//加了這行程式碼,就可以解決5.0版本後隱式啟動服務報錯的問題
        Log.d("baibai", "aboutService");
        bindService(intent, mConn, Context.BIND_AUTO_CREATE);
    }

    ServiceConnection mConn = new ServiceConnection() {

        @Override
        public void onServiceConnected(ComponentName name, IBinder service) {
            Log.d("baibai", "客戶端:連線 Service 成功");
            mService = IAddAidlInterface.Stub.asInterface(service);
        }

        @Override
        public void onServiceDisconnected(ComponentName name) {
        }
    };

    @Override
    protected void onDestroy() {
        super.onDestroy();
        unbindService(mConn);
    }
}

啟動服務時要用繫結式啟動bindService,bindService(intent, mConn, Context.BIND_AUTO_CREATE),
    第一個引數initent:intent裡沒有引數,要intent.setAction(過濾條件),即隱式呼叫,所以要在服務端的清單檔案裡給service新增acton,以便客戶端使用
        ps:a、要在onDestory()方法裡解除繫結,不然會報錯。
            b、繫結的時候,必須有Intent.setPackage(伺服器的包名),不然會報錯(5.0後必須使用顯示啟動服務,新增這一行程式碼可解決這一報錯問題)。
            c、只有在連線成功的時候才會呼叫onServiceConnected()方法,此時mBinder才不為空,型別轉換的時候最好用IAddService.Stub.asInterface()方法,不要直接強制轉換。
    第二個引數mConn:mConn  = ServiceConnection(){ 預設兩個抽象方法,在連線成功方法onServiceConnected中賦值aidl物件mService = IAddAidlInterface.Stub.asInterface(service) }
        注意要asInterface,不然會報錯。
4、呼叫方法:實際呼叫mService的裡的方法。

 

 

 

 

 

 

 

 

 

 

 

 

 

 

參考git程式碼:服務端:https://github.com/baiyun1234/DemoAidlService

                     客戶端:https://github.com/baiyun1234/DemoAidlClient

參考網址:https://blog.csdn.net/guanhang89/article/details/51386404