AIDL初探、使用常见错误
来源:互联网 发布:免费cc顶级域名2016 编辑:程序博客网 时间:2024/06/02 14:15
1.前言 AIDL的的应用场景
这是AIDL谷歌官方文档的解释,当每列下面的条件都满足,就是合适的使用场景。
可以看到AIDL的处理的情况是最复杂的:只有允许不同应用的客户端用 IPC 方式访问服务,并且想要在服务中处理多线程时,才有必要使用 AIDL。
2.AIDL的简单使用-基本类型
服务端:
首先新建一个AIDL文件夹,里面新建AIDL文件
AIDL接口文件里可以简单写一个求和的函数,注意这里参数的类型是默认支持所有常见的基本类型。(8种基本类型除了short、String、List、map等)如下:
interface IMyAidlInterface { /** * Demonstrates some basic types that you can use as parameters * and return values in AIDL. */ int addSum(int a,int b); //List<Person> addPerson(in Person person);}
然后编译一下(会自动生成AIDL对应的java文件),新建服务端服务如下:
public class MyService extends Service { public MyService() { } @Override public IBinder onBind(Intent intent) { //返回binder return iBinder; } //IMyAidlInterface.Stub()是AIDL自动生成java文件里的,涉及原理先不讲 //在这里我们自己实现了这个addSum(int a, int b) private IBinder iBinder=new IMyAidlInterface.Stub(){ @Override public int addSum(int a, int b) throws RemoteException { return a+b; } };}
注意注册你的服务等细节,服务段这里就完成了。
客户端:
复制服务端的AIDL文件,并让他在客户端项目中处于一样的包名下。因为我们要保证生成的java文件是一模一样的。
如图:
然后在主activity中,创建拷贝AIDL的实例,并绑定服务,具体逻辑不说了。
private IMyAidlInterface iMyAidlInterface; private ServiceConnection conn=new ServiceConnection() { @Override public void onServiceConnected(ComponentName componentName, IBinder iBinder) { iMyAidlInterface=IMyAidlInterface.Stub.asInterface(iBinder); } @Override public void onServiceDisconnected(ComponentName componentName) { iMyAidlInterface =null; } }; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); Intent intent=new Intent(); intent.setComponent(new ComponentName("android.com.server","android.com.server.MyService")); // 绑定服务,可设置或触发一些特定的事件 bindService(intent,conn,BIND_AUTO_CREATE); TextView textView= (TextView) findViewById(R.id.AIDL); textView.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View view) { if(iMyAidlInterface!=null) { try { int i = iMyAidlInterface.addSum(1, 2); Toast.makeText(MainActivity.this, i + "", Toast.LENGTH_SHORT).show(); } catch (RemoteException e) { e.printStackTrace(); } }}
这里有两个容易犯的错误:
第一个是绑定服务创建Intent的时候必须显式声明,否则会报错 IllegalArgumentException: Service Intent must be explicit
//报错bindService(new Intent("com.wcc.androiddevelopartexplore.service.MyAidl"), conn, BIND_AUTO_CREATE); //必须显式声明:Intent intent=new Intent(); intent.setComponent(new ComponentName("android.com.server","android.com.server.MyService"));//或者下面这种写法,并在服务端service注册时添加过滤 // <intent-filter> // <action android:name="android.com.server.MyService" /> // </intent-filter> Intent intent = new Intent("android.com.server.MyService"); intent.setPackage("android.com.server");
第二个是在 onCreate()方法中bindService(intent,conn,BIND_AUTO_CREATE);绑定服务后,
直接调用实例iMyAidlInterface.addSum(1, 2);
bindService()是异步执行的,并不会直接执行,而是先执行onCreate中其他代码,此时会报空指针错误,因为iMyAidlInterface还没有被赋值。
iMyAidlInterface的赋值在服务成功连接ServiceConnection回调时。
所以要么在onServiceConnected方法中写调用,或者写到点击事件里。参考前面代码片
private ServiceConnection conn=new ServiceConnection() { @Override public void onServiceConnected(ComponentName componentName, IBinder iBinder) { iMyAidlInterface=IMyAidlInterface.Stub.asInterface(iBinder);// int i = 0;// try {// i = iMyAidlInterface.addSum(6, 2);// } catch (RemoteException e) {// e.printStackTrace();// }// Toast.makeText(MainActivity.this, i + "", Toast.LENGTH_SHORT).show(); } @Override public void onServiceDisconnected(ComponentName componentName) { iMyAidlInterface =null; } };
最后结果:先启动服务端,再启动客户端,客户端调用服务端服务计算1+2返回结果
3.AIDL的简单使用-自定义类型
- 服务端
首先自定义Person类,实现Parcelable接口
public class Person implements Parcelable{ @Override public String toString() { return name+"/"+age; } public Person(String name, int age){ this.name=name; this.age=age; } public Person(Parcel in){ this.name=in.readString(); this.age=in.readInt(); } private String name; private int age; @Override public int describeContents() { return 0; } public static final Parcelable.Creator<Person> CREATOR= new Parcelable.Creator<Person>(){ @Override public Person createFromParcel(Parcel parcel) { return new Person(parcel); } @Override public Person[] newArray(int size) { return new Person[size]; } }; @Override public void writeToParcel(Parcel parcel, int i) { parcel.writeString(name); parcel.writeInt(age); } public String getName() { return name; } public void setName(String name) { name = name; } public int getAge() { return age; } public void setAge(int age) { this.age = age; }}
修改AIDL接口添加方法
package android.com.server;// Declare any non-default types here with import statements//此处手动引入Personimport android.com.server.Person;interface IMyAidlInterface { /** * Demonstrates some basic types that you can use as parameters * and return values in AIDL. */ int addSum(int a,int b); //此处必须指定自定义类型是输入修改(in) 还是输出修改(out) 还是都行(inout) List<Person> addPerson(in Person person);}
所有非原语参数都需要指示数据走向的方向标记。可以是 in、out 或 inout。
原语默认为 in,不能是其他方向。
注意:您应该将方向限定为真正需要的方向,因为编组参数的开销极大。
再新建Person.aidl
内容
package android.com.server;
parcelable Person;
编译保证无错误
最后修改服务端service实现addPerson()
public class MyService extends Service { private ArrayList<Person> persons; public MyService() { } @Override public IBinder onBind(Intent intent) { persons=new ArrayList<>(); return iBinder; } private IBinder iBinder=new IMyAidlInterface.Stub(){ @Override public int addSum(int a, int b) throws RemoteException { return a+b; } @Override public List<Person> addPerson(Person person) throws RemoteException { persons.add(person); return persons; } };}
- 客户端
复制AIDL新文件以及Person类到客户端,并保证其都和服务端处于一样的包名下
public void onClick(View view) { if(iMyAidlInterface!=null) { try { int i = iMyAidlInterface.addSum(1, 2); Toast.makeText(MainActivity.this, i + "", Toast.LENGTH_SHORT).show(); } catch (RemoteException e) { e.printStackTrace(); } try { ArrayList<Person> list= (ArrayList<Person>) iMyAidlInterface.addPerson(new Person("name",1)); Toast.makeText(MainActivity.this, list.toString()+ "", Toast.LENGTH_SHORT).show(); } catch (RemoteException e) { e.printStackTrace(); } } }
结果:每次点击添加一个人显示
>
源码例子:下载链接
- AIDL初探、使用常见错误
- android aidl常见错误
- AIDL初探
- AIDL初探以及学习
- pureMVC使用常见错误
- findViewById()使用常见错误
- Eclipse使用常见错误
- findViewById()使用常见错误
- github使用常见错误
- Eclipse使用常见错误
- NSCache使用常见错误
- caffe 使用常见错误
- Cocoapods 使用常见错误
- maven 使用常见错误
- 安卓IPC之aidl使用(一)--aidl常见使用
- AIDL初探(本地、进程)
- android学习之AIDL初探
- 使用AIDL
- 读书笔记-----Java中的引用
- 编译时连接与运行时链接及静态库链接
- putty 通过key连接服务器
- matlab基础学习_数据类型
- Android misc
- AIDL初探、使用常见错误
- 使用LVS+TUN搭建集群实现负载均衡
- mongoose:嵌入式Web服务器
- jdk1.7下载地址
- 768E Game of Stones[Nim游戏][博弈]
- 画布项目
- 530. Minimum Absolute Difference in BST
- Practice3_5_vector_sort_struct_gold_silver_bronze_playerName1
- ArchLinux 简单安装步骤总结