知識點-----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)

服務端


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://blog.csdn.net/guanhang89/article/details/51386404

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