Android进程通信一之AIDL

AIDL概念

Android提供的一种快速实现binder进程通信的工具,也可以不用AIDL,自己实现binder来达到同样的效果,但是会比较复杂,后面我会写文章来细说,先给出demo地址

AIDL支持的数据类型 : String,int,long,boolean,float,double,ArrayList,HashMap,Parcelable等

为什么要用AIDL

因为可以让我们更轻松的使用binder,专注写client、service,而不必关心ServiceManager、Binder驱动,那么问题又来了,为什么要用binder来进程通信呢?后续有文章单独来说,那问题又又来了,Android为什么需要进程通信呢?进程通信的方式有哪些呢?一个个问题是不是纷至沓来,感觉压的自己透不过气,一定要知道个所以然呢?客官莫急,且听我细细道来。但是当前第一步就是要学会用AIDL实现跨进程的通信!

第一步

在这里插入图片描述

新建AIDL文件,会在src/main下面自动新建一个叫aidl的文件夹

// Declare any non-default types here with import statements
/**除了默认的基本类型,就是下面直接生成出来的方法自带的这6种类型不需要import之外,其他的都需要手动import
 - 其他类型包括下面几种:
*List 接口(会自动将List接口转为 ArrayList),且集合的每个元素都必须要么是基本类型,要么是Parcelable实现类
*Map 接口(会自动将 Map 接口转为 HashMap),且每个元素的 key 和 value 要么是基本类型,要么是Parcelable实现类
*Parcelable 的实现类
*AIDL 接口本身
*/
import com.ly.aidltest.Student;
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);
    //定义两个方法,也就是提供给客户端的服务
    List<Student> getStudent();
    //这里的in 是有讲究的
    void addStudent(in Student stu);
}
注意事项

所有非基本类型的参数都需要标签来表明这个数据的去向:

  • in,表示此变量由客户端设置
  • out,表示此变量由服务端设置
  • inout,表示此变量可由客户端和服务端设置

此时可以rebuild一下
在这里插入图片描述

第二步

定义上面AIDL文件用到的java对象

public class Student implements Parcelable {
    private String name;
    private int age;
    public Student(String name, int age) {
        this.name = name;
        this.age = age;
    }
    protected Student(Parcel in) {
        name = in.readString();
        age = in.readInt();
    }
    public static final Creator<Student> CREATOR = new Creator<Student>() {
        @Override
        public Student createFromParcel(Parcel in) {
            return new Student(in);
        }
        @Override
        public Student[] newArray(int size) {
            return new Student[size];
        }
    };
    public String getName() {
        return name;
    }
    public void setName(String name) {
        this.name = name;
    }
    public int getAge() {
        return age;
    }

    public void setAge(int age) {
        this.age = age;
    }
    @Override
    public int describeContents() {
        return 0;
    }
    @Override
    public void writeToParcel(Parcel dest, int flags) {
        dest.writeString(name);
        dest.writeInt(age);
    }
}

除了定义Java对象之外,还需要一步,复制第一步新建的xxx.aidl文件,重命名为java对象同样的名字:
在这里插入图片描述

第三步

新建service服务端

public class MyService extends Service {
    private List<Student> list = new ArrayList<>();
    private static final String TAG = "MyService";
    @Override
    public void onCreate() {
        super.onCreate();
        Log.e(TAG, "onCreate: ");
        list.add(new Student("小明", 12));
        list.add(new Student("小红", 13));
        list.add(new Student("小军", 14));
    }
    private IMyAidlInterface.Stub mBinder = new IMyAidlInterface.Stub() {
        @Override
        public void basicTypes(int anInt, long aLong, boolean aBoolean, float aFloat, double aDouble, String aString) throws RemoteException {

        }
        @Override
        public List<Student> getStudent() throws RemoteException {

            return list;
        }
        @Override
        public void addStudent(Student stu) throws RemoteException {
            Log.e(TAG, "setStudent: " );
            list.add(stu);
        }
    };
    @Nullable
    @Override
    public IBinder onBind(Intent intent) {
        Log.e(TAG, "onBind: " );
        return mBinder;
    }
}

并在manifest里面声明

<service android:name=".MyService"/>

第四步

客户端启动服务端

public class MainActivity extends AppCompatActivity {
    private static final String TAG = "MainActivity";
    private  IMyAidlInterface sub;

    private ServiceConnection connection = new ServiceConnection() {
        @Override
        public void onServiceConnected(ComponentName name, IBinder service) {
            sub =  IMyAidlInterface.Stub.asInterface(service);
            try {
                List<Student> list = sub.getStudent();
                for(Student s : list){
                    Log.e(TAG, "onServiceConnected: "+s.getName()+" age:"+s.getAge());
                }
            } catch (RemoteException e) {
                e.printStackTrace();
            }
        }
        @Override
        public void onServiceDisconnected(ComponentName name) {

        }
    };

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        bindService(new Intent(this,MyService.class),connection,BIND_AUTO_CREATE);
    }
}

达到的初步结果就是
客户端可以跨进程拿到服务端的数据
可以测试一下
在这里插入图片描述
在这里插入图片描述

补充点
//manifest中:
        <service
            android:name=".MyService"
            android:process=":another">
            <intent-filter>
                <action android:name="com.ly.aidltest.MyService" />
                <category android:name="android.intent.category.DEFAULT" />
            </intent-filter>
        </service>
        
        //activity中:
        Intent intent = new Intent();
        //5.0之后如果使用隐式启动service需要加上package,防止冲突,当然如果启动的是别的APP的service,要用目标的名字
        intent.setPackage(getPackageName());
        intent.setAction("com.ly.aidltest.MyService");
        bindService(intent,connection,BIND_AUTO_CREATE);
  1. Service可以通过隐式启动
  2. 若客户端组件和服务分开在不同APP,必须要把该Parcelable实现类.java文件拷贝到客户端所在的APP,包路径要一致
  3. demo地址
    https://github.com/YuxiangZhu/AIDLTest
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

Alex_ChuTT

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值