Android AIDL的使用,進程間的通訊;

AIDL

Android使用AIDL來實現進程間的通訊; 

最簡單的進程,兩個APP(APP1(app_server) , APP2(app_client)),這裏app_server可以看作一個進程 , app_client也可以看作一個進程;  所以AIDL可以來實現兩個APP之間的通訊;

先來寫一個最簡單的AIDL進程間的通訊;

app_client要調用app_server中的數據,首先app_server先把數據暴露出去;

app_server端:

1、新建AIDL文件;

輸入名稱後 , 會自動創建一個aidl結尾的文件;

// Declare any non-default types here with import statements

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

basicTypes文件只是告訴你參數的基礎類型 , 直接刪了;然後創建一個新的方法;

interface ICbAidlInterface {
    String getName();
}

2、創建完成AIDL文件後 , 重新構建一下項目(sycn project)會自動生成一個新文件,如下

然後新建一個Service,新建一個內部類繼承AIDL中的Stub類 , 然後重寫AIDL中的方法;

public class MyService extends Service {
    public MyService() {
    }

    @Override
    public IBinder onBind(Intent intent) {
        // TODO: Return the communication channel to the service.
        return new CbBinder();
    }

    class CbBinder extends ICbAidlInterface.Stub{

        @Override
        public String getName() throws RemoteException {
            return "CCB呀";
        }
    }
}

AndroidManifest文件也要注意一下:

        <service
            android:name=".MyService"
            android:enabled="true"
            android:exported="true">
            <intent-filter>
                <action android:name="com.cuichen.mvvmdemo.service"/>
            </intent-filter>
        </service>

這樣app_server中的aidl已經完成了;

 

app_client端:

app_client要調用app_service的getName()方法;

1、app_service中的aidl文件原封不動的複製過來 , 注意包名也和app_service中的一樣;

2、在Activity中使用;綁定service , onServiceConnected方法中通過ICbAidlInterface.Stub.asInterface(iBinder)實例,然後就可以調用aidl中的getName()方法啦;

private ICbAidlInterface iCbAidlInterface;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_m);
         findViewById(R.id.btClick2).setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View view) {
                try {
                    Log.i("ccb", "onClick: "+iCbAidlInterface.getName());
                } catch (RemoteException e) {
                    e.printStackTrace();
                }
            }
        });

         Intent intent = new Intent();
         intent.setAction("com.cuichen.mvvmdemo.service");
         intent.setPackage("com.cuichen.mvvmdemo");
         bindService(intent, new ServiceConnection() {
             @Override
             public void onServiceConnected(ComponentName componentName, IBinder iBinder) {
                 iCbAidlInterface = ICbAidlInterface.Stub.asInterface(iBinder);
             }

             @Override
             public void onServiceDisconnected(ComponentName componentName) {

             }
         }, Service.BIND_AUTO_CREATE);
    }

這樣就可以完成實現進程間的通訊了 , APP2調用APP1中的方法;

注意:出現'Process 'command 'D:\AndroidStudio\sdk\build-tools\29.0.0\aidl.exe'' finished with non-zero exit value -1073741819' ,類似這樣的報錯,查看項目中的buildToolsVersion是否都一致 , 主Moudle和其它類庫的版本號要保持一致;

 

AIDL使用自定義類型:

除了已定義的基礎類型 , aidl還可以傳遞自定義類型,前提是該類必須序列化(Parcelable);下面是APP1 的 代碼和結構;

注意:自定義類型 java文件夾下的.java文件和 aidl文件夾下的.aidl文件 , 要保證包名相同;

AidlBean.java 如下:

public class AidlBean implements Parcelable {
    private String name;
    private Integer age;
    ......
}

AidlBean.aidl 如下:

// AidlBean.aidl
package com.cuichen.mvvmdemo;

parcelable AidlBean;

ICbAidlInterface.aidl 如下:

package com.cuichen.mvvmdemo;

import com.cuichen.mvvmdemo.AidlBean;

interface ICbAidlInterface {
    String getName();
    AidlBean getBean();
}

完成後 , 把新增和修改的文件複製到第二個(APP2)項目;

APP2(app_client)結構如下:

注意:包名要和APP1中的包名保持一致:

AIDL可以寫在類庫中!

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