android的AIDL(Android Interface Definition Language),也就是Android的接口定义语言,用于IPC通信的一套协议。凡是要通过AIDL方式进行IPC通信的,就必须遵守该规范。今天实测魅族部分机型默认不支持AIDL,官方答复是防止app互相唤醒,提高用户体验……哎呀我去
总结一下AIDL实现遇到的问题
1.在AndroidStudio的环境下如何新建一个AIDL文件?
2.AIDL的文件格式是怎样的?
3.AIDL如何和本地服务联系起来?
4.客户端如何绑定(唤醒)服务端的Service?
5.如何为javaBean声明AIDL?
6.如何解决AndroidStudio环境下,无法获取非java包下面的class?**
问题1 在AndroiStudio环境下,只需要选择创建AIDL文件即可。
问题2
(1)必须要引入包名;
(2)除了基本数据类型,String,List,Map,其它的都需要手动import;
(3)接口的方法的参数上,基本数据类型除外,其它都要设置Tag(一般是in,out);
问题3
/*
* This file is auto-generated. DO NOT MODIFY.
* Original file: E:\\ASWS\\AIDLDemoClient\\app\\src\\main\\aidl\\com\\yzz\\android\\aidlserver\\ITest.aidl
*/
package com.yzz.android.aidlserver;
public interface ITest extends android.os.IInterface
{
public static abstract class Stub extends android.os.Binder implements com.yzz.android.aidlserver.ITest
{
/** ***省略*** */
public int getNum(int a, int b) throws android.os.RemoteException;
public void add(com.yzz.android.aidlserver.Student stu) throws android.os.RemoteException;
public java.util.List<com.yzz.android.aidlserver.Student> getList() throws android.os.RemoteException;
}
}
在重新编译App是会生成这个类,会生成一个静态内部类Stub,继承Binder,实现了用户定义的接口,那么我们可以想到在Service中的onBind()方法中,返回的是一个IBinder对象。那么我们可以怎么做呢?很简单,让onBind()返回我们的ITest.Stub对象即可。
package com.yzz.android.aidlserver;
import android.app.Service;
import android.content.Intent;
import android.os.IBinder;
import android.os.RemoteException;
import android.support.annotation.Nullable;
import android.util.Log;
import java.util.ArrayList;
import java.util.List;
/**
* Created by yzz on 2017/3/19 0019.
*/
public class MyService extends Service {
private static Test mTest;
public static final String TGA = "Service:";
@Override
public void onCreate() {
super.onCreate();
mTest = new Test();
}
@Nullable
@Override
public IBinder onBind(Intent intent) {
Log.e(TGA,"绑定成功"+Thread.currentThread().getName());
return mTest;
}
public static class Test extends ITest.Stub {
private List<Student> list;
public Test() {
list = new ArrayList<>();
}
@Override
public int getNum(int a, int b) throws RemoteException {
return a + b;
}
@Override
public void add(Student stu) throws RemoteException {
list.add(stu);
}
@Override
public List<Student> getList() throws RemoteException {
return list;
}
}
}
问题4
首先我们要将aidl文件夹全部拷贝到客户端的main下面,然后运行App,生成AIDL对应的class,客户端的AIDL文件必须和远程服务端要一致。接下来,我们采用动态绑定的方式去唤醒远程的Service。
Intent intent = new Intent();
//设置action,表明intent的动作
intent.setAction("yzz");
intent.setPackage("com.yzz.android.aidlserver");
//要明确Intent要访问的进程的包名(唯一性)
bindService(intent, mServerCon, BIND_AUTO_CREATE);
public class MyServerCon implements ServiceConnection {
//服务绑定的过程是异步的,在绑定成功后会回调onServiceConnected()方法,在该方法中,我们拿到返回的ITest对象
@Override
public void onServiceConnected(ComponentName name, IBinder service) {
//asInterface有些复杂,直接得到ITest对象
test = ITest.Stub.asInterface(service);
}
问题5
1.首先要写一个JavaBean实现Parcelable接口。
2.要为这个Bean建立AIDl文件来告诉系统该Bean用于IPC通信。
// Student.aidl
package com.yzz.android.aidlserver;
// Declare any non-default types here with import statements
parcelable Student;
问题6
这个有两种做法,一种是在将JavaBean放在src/main/java中,但是服务端和客户端的包名要一致。还有就是更改app下的 build.gradle文件的sourceSets属性,来告诉gradle那些包下有java源文件。
sourceSets{
main{
java.srcDirs('src/main/java','src/main/aidl');
}
}