前言:

今天看AIDL基础和原理,在学习过程中遇到一些问题,寻找了好些文章都没有得到一些解决的方案,后来找到了解决的方案,因此在此整理下相关的知识,做个笔记,也分享给各位童鞋。

概要:

本文主要介绍AIDL的含义,作用以及入门的案例,本文还会涉及到Service,Binder等相关知识,本文不做详细介绍,请自行查找资料学习。这位大神写的Binder中transact和onTransact的区别可以开下:

一,什么是AIDL

AIDL是Android中进程间通信方式之一,Android interface definition language的简称。

二,AIDL的作用

进程间通信又叫IPC(Inter-Process Communication),因为进程间资源不能共享,所以每个系统都有自己的一套IPC机制,Android是基于Linux内核的操作系统,但是并没有继承Linux的IPC机制,有自己的一套IPC机制。AIDL作为IPC方式的一种,底层基于Binder机制,作用就是在自己的APP可以调用别的APP中的方法,简单的理解为在自己的APP里绑定别的APP的service,这样就可以实现和别的APP的交互。

三,AIDL实现原理

这里简单介绍下AIDL在android中是怎样实现一个APP调用另一个APP的Service的。客户端APP会通过bindService绑定服务端APP的一个Service,然后Android系统就会调用这个Service中的onBinder方法,该方法返回一个用于和Service交互的IBinder对象。bindService是异步执行的,bindService方法会立即返回,但是不会返回IBinder给客户端,客户端APP必须创建一个ServiceConnection对象,传给bindService。ServiceConnection包含一个回调方法onServiceConnected,系统调用这个返回IBinder对象,客户端APP使用这个IBinder对象调用Service。

四,简单示例

首先创建一个服务端的android项目,创建AIDL文件,右击MainActivity所在目录New->AIDL,输入文件名,就会生成一个AIDL文件,如图:

Android aidl inout报错_客户端

basicTypes方法是说明有哪些默认支持的类型,无视,自己定义一个供调用的接口方法:

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

    String getMessage();

}

然后sync project一下

(很重要),Tools -> Android ->Sync project ***。

现在我们新建一个Service,里面包含一个内部类,继承自刚才创建的AIDL中的Stub类,并实现接口方法,onBinder方法里面返回该内部类的对象。

public class MyService extends Service {

    @Nullable
    @Override
    public IBinder onBind(Intent intent) {
        return new MyBinder();
    }

    class MyBinder extends IMyAidlInterface.Stub{

        @Override
        public String getMessage() throws RemoteException {
            return "return success!";
        }

    }
}

然后在AndroidManifest.xml文件中注册隐式service并设置action。

<service android:name=".MyService">
            <intent-filter >
                <action android:name="com.example.liujibin.testaidl1.MyService"></action>
            </intent-filter>
        </service>

到此提供服务的APP创建完成了。然后我们新建一个客户端APP,并将刚才服务端APP中创建的AIDL文件连着整个aidl文件夹一起复制到客户端APP中,然后sync project一下

(很重要)。

Android aidl inout报错_客户端_02

AIDL文件的包名和服务端中AIDL文件的包名一样。

然后我们在客户端APP中的Activity中实现绑定服务端Service,调用实现的接口方法。

public class MainActivity extends AppCompatActivity {

    private Button btn;
    private IMyAidlInterface iMyAidlInterface;

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

        btn = (Button) findViewById(R.id.btn);

        Intent intent = new Intent();
        intent.setAction("com.example.liujibin.testaidl1.MyService");
        intent.setPackage("com.example.liujibin.testaidl1");
        bindService(intent,connection,BIND_AUTO_CREATE);

        btn.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View view) {
                try {
                    Toast.makeText(MainActivity.this,""+iMyAidlInterface.getMessage(),Toast.LENGTH_SHORT).show();
                } catch (RemoteException e) {
                    e.printStackTrace();
                }
            }
        });
    }

    private ServiceConnection connection = new ServiceConnection() {
        @Override
        public void onServiceConnected(ComponentName componentName, IBinder iBinder) {
            iMyAidlInterface = IMyAidlInterface.Stub.asInterface(iBinder);
        }

        @Override
        public void onServiceDisconnected(ComponentName componentName) {
            iMyAidlInterface = null;
        }
    };


}




在这过程中遇到过一个坑,很多基础教程介绍的Intent只调用了setAction,这样我在android4.4的系统上运行没有问题,但是在android5.0上bindService就报错,需要添加一个setPackage设置服务端APP的包名才能正常使用。因为android5.0版本以后隐式启动被禁止,需要实现setPackage。

然后先安装下服务端APP,在运行客户端APP,点击按钮,success。

Android aidl inout报错_客户端_03