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可以写在类库中!

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