AIDL笔记

AIDL

1. 什么是AIDL

AIDL(Android Interface Definition Language,即Android接口定义语言。)

IPC(Inter-Process Communication,进程间通信)。

在进程间通信不一定需要AIDL,因为两个进程间不能直接通信,需要Android系统底层间接实现通信,所以比较耗资源,能不用就不用。如下图:
这里写图片描述
进程间通讯可以分为下面几种:
AIDL
在IPC时,并且多个应用,多线程时才用到。
Binder
只有IPC,多个应用,没有多线程
Messager
只有IPC,没有多线程

2. 创建AIDL

官方文档上的例子:

// IRemoteService.aidl,//包名,文件必须放在指定的目录
package com.example.android;

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

/** Example service interface */
interface IRemoteService {
    /** Request the process ID of this service, to do evil things with it. */
    int getPid();

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

官方文档上写AIDL支持的数据类型包括:

  • 所有的基本数据类型;
  • String ,CharSequence
  • List,Map
    实际上基本数据类型的short类型不被支持,编译都通不过。
    还有Parcelable(序列化)。
  • Parcelable(序列化)

那AIDL文件我们怎么转成java文件呢?在sdk\build-tools\23.0.2(版本)下有个aidl.exe文件,我们就是用这个来转成java文件:

输入命令:aidl IRemoteService.aidl

就会生成一个同名的java文件。

在eclipse中创建AIDL

新建一个Android项目后,直接在java文件中new一个aidl文件
这里写图片描述

在eclipse中自动编译生成java,而java就和R文件在一起:
这里写图片描述
这样就可以直接在Activity中提示出来了
这里写图片描述

在Android studio中创建AIDL

而Android studio中和eclipse有点不同,是和java同级目录创建
这里写图片描述
这里写图片描述
编译后生成的java文件:这里写图片描述

3. 下面用一个案例

客户端传两个数字,调用服务端的计算方法求和
首先服务端的AIDL文件代码:

package com.hou.aidl;

interface IMyAidlInterface {

    int add(int num1,int num2);
}

然后服务端需要远程Service,代码:

package com.hou.aidl;

import android.app.Service;
import android.content.Intent;
import android.os.IBinder;
import android.os.RemoteException;
import android.util.Log;


public class IRemoteService extends Service {
    //当客户端绑定服务时,会返回iBinder对象
    @Override
    public IBinder onBind(Intent intent) {
        return iBinder;
    }

    private IBinder iBinder = new IMyAidlInterface.Stub() {

        @Override
        public int add(int num1, int num2) throws RemoteException {
            Log.e("111", "收到了远程传过来的值" + num1 + "和" + num2);
            return num1 + num2;
        }
    };
}
note:需要在清单文件中注册,并添加intent-filter
<service android:name=".IRemoteService">
      <intent-filter>
           <action android:name="com.hou.aidl.client" />
           <category android:name="android.intent.category.DEFAULT" />
      </intent-filter>
 </service>

客户端:

package com.hou.aidlclient;

import android.content.ComponentName;
import android.content.Context;
import android.content.Intent;
import android.content.ServiceConnection;
import android.os.Bundle;
import android.os.IBinder;
import android.os.RemoteException;
import android.support.v7.app.AppCompatActivity;
import android.util.Log;
import android.view.View;
import android.widget.Button;
import android.widget.EditText;

import com.hou.aidl.IMyAidlInterface;

public class MainActivity extends AppCompatActivity implements View.OnClickListener {


    private EditText et_num1;
    private EditText et_num2;
    private EditText et_sum;
    private Button btn_sum;
    private IMyAidlInterface iMyAidlInterface;
    private ServiceConnection conn = new ServiceConnection() {
        //服务绑定上的时候
        @Override
        public void onServiceConnected(ComponentName name, IBinder service) {
            Log.e("111", "绑定服务成功==" + name);
            iMyAidlInterface = IMyAidlInterface.Stub.asInterface(service);
        }

        //服务断开的时候
        @Override
        public void onServiceDisconnected(ComponentName name) {
            Log.e("111", "服务断开连接==" + name);
            iMyAidlInterface = null;
        }

    };

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

        initView();
        bindAidlService();
    }

    private void initView() {
        et_num1 = (EditText) findViewById(R.id.et_num1);
        et_num2 = (EditText) findViewById(R.id.et_num2);
        et_sum = (EditText) findViewById(R.id.et_sum);
        btn_sum = (Button) findViewById(R.id.btn_sum);
        btn_sum.setOnClickListener(this);
    }

    @Override
    public void onClick(View v) {
        int num1 = Integer.parseInt(et_num1.getText().toString());
        int num2 = Integer.parseInt(et_num2.getText().toString());
        try {
            int sum = iMyAidlInterface.add(num1, num2);
            et_sum.setText(sum + "");
        } catch (RemoteException e) {
            et_sum.setText("出错了");
            e.printStackTrace();
        }
    }

    //绑定服务
    private void bindAidlService() {
        Intent intent = new Intent();
        //在Android5.0以后只能已显示intent方式启动 绑定服务
        intent.setComponent(new ComponentName("com.hou.aidl", "com.hou.aidl.IRemoteService"));
//        Intent intent = new Intent("com.hou.aidl.client");//隐式意图方式
        bindService(intent, conn, Context.BIND_AUTO_CREATE);//Context.BIND_AUTO_CREATE自动创建
    }

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

现在就可以使用了,启动服务端,打开客户端就可以求和计算。

当然除过上边提到的类型外,我们经常会传递自定义类型的数据,比如一个对象Person。

服务端:

创建一个Person对象,实现Parcelable序列化:

package com.hou.aidl;

import android.os.Parcel;
import android.os.Parcelable;

/**
 * Created by hp on 2016/3/9.
 */
public class Person implements Parcelable {

    public String name;
    public int age;

    public Person(String name, int age) {
        this.name = name;
        this.age = age;
    }

    protected Person(Parcel in) {
        //必须和writeToParcel中写入的顺序一致;
        name = in.readString();
        age = in.readInt();
    }

    public static final Creator<Person> CREATOR = new Creator<Person>() {
        @Override
        public Person createFromParcel(Parcel in) {
            return new Person(in);
        }

        @Override
        public Person[] newArray(int size) {
            return new Person[size];
        }
    };

    @Override
    public int describeContents() {
        return 0;
    }

    @Override
    public void writeToParcel(Parcel dest, int flags) {
        dest.writeString(name);
        dest.writeInt(age);
    }

    @Override
    public String toString() {
        return "Person{" +
                "name='" + name + '\'' +
                ", age=" + age +
                '}';
    }
}

创建Person.aidl

package com.hou.aidl;

parcelable  Person;
package com.hou.aidl;
//需要引入Person
import com.hou.aidl.Person;
interface IMyAidlInterface {

    List<Person> add(in Person person);
}

Service:

package com.hou.aidl;

import android.app.Service;
import android.content.Intent;
import android.os.IBinder;
import android.os.RemoteException;

import java.util.ArrayList;
import java.util.List;

public class IRemoteService extends Service {

    List<Person> persons;

    //当客户端绑定服务时,会返回iBinder对象
    @Override
    public IBinder onBind(Intent intent) {
        persons = new ArrayList<>();
        return iBinder;
    }

    private IBinder iBinder = new IMyAidlInterface.Stub() {
        @Override
        public List<Person> add(Person person) throws RemoteException {
            persons.add(person);
            return persons;
        }
    };
}

客户端:

把IMyAidlInterface.aidl和Person.aidl都复制到客户端同名包下(aidl-com.hou.aidl)
把Person复制到客户端同名包下(com.hou.aidl)

package com.hou.aidlclient;

import android.content.ComponentName;
import android.content.Context;
import android.content.Intent;
import android.content.ServiceConnection;
import android.os.Bundle;
import android.os.IBinder;
import android.os.RemoteException;
import android.support.v7.app.AppCompatActivity;
import android.util.Log;
import android.view.View;
import android.widget.Button;
import android.widget.EditText;

import com.hou.aidl.IMyAidlInterface;
import com.hou.aidl.Person;

import java.util.List;

public class MainActivity extends AppCompatActivity implements View.OnClickListener {

    private Button btn_sum;
    private IMyAidlInterface iMyAidlInterface;
    private ServiceConnection conn = new ServiceConnection() {
        //服务绑定上的时候
        @Override
        public void onServiceConnected(ComponentName name, IBinder service) {
            Log.e("111", "绑定服务成功==" + name);
            iMyAidlInterface = IMyAidlInterface.Stub.asInterface(service);
        }

        //服务断开的时候
        @Override
        public void onServiceDisconnected(ComponentName name) {
            Log.e("111", "服务断开连接==" + name);
            iMyAidlInterface = null;
        }

    };

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

        initView();
        bindAidlService();
    }

    private void initView() {
        btn_sum = (Button) findViewById(R.id.btn_sum);
        btn_sum.setOnClickListener(this);
    }

    @Override
    public void onClick(View v) {
        try {
            List<Person> persons = iMyAidlInterface.add(new Person("李四", 18));
            Person person = persons.get(0);
            et_sum.setText(person.toString());
        } catch (RemoteException e) {
            et_sum.setText("出错了");
            e.printStackTrace();
        }
    }

    //绑定服务
    private void bindAidlService() {
        Intent intent = new Intent();
        //在Android5.0以后只能已显示intent方式启动 绑定服务
        intent.setComponent(new ComponentName("com.hou.aidl", "com.hou.aidl.IRemoteService"));
//        Intent intent = new Intent("com.hou.aidl.client");//隐式意图方式
        bindService(intent, conn, Context.BIND_AUTO_CREATE);//Context.BIND_AUTO_CREATE自动创建
    }

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

AIDL原理图

这里写图片描述

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值