AIDL笔记
2016-03-09 15:54
423 查看
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原理图
相关文章推荐
- failed: Access denied for user 'root'@'localhost' (using password: YES) at /usr/bin/innobackupex lin
- Crunching Cruncher xx.png failed, see logs
- Keepailved详细介绍
- Codeforces Round #338 (Div. 2)B. Longtail Hedgehog(DP)
- I‘m not Afraid
- 【LeetCode】70. Climbing Stairs
- CodeForces 630A:Again Twenty Five!【水题】
- Codeforces 651B Beautiful Paintings【思维】
- 【Training Contest】2016.03.08
- hdu 1021Fibonacci Again
- WPF 从Main函数启动
- 提交git push 时failed to push some refs to
- 解决httpd: Could not reliably determine the server's fully qualified domain name
- Xcode提交图片出错:Commit failed not under version control (1)
- rails 限制上传图片大小出现 Errno::ENOENT in MicropostsController#create 错误
- 40页Pacific Trails Resort案例分析
- aix用命令查监听端口对应的进程
- BC31pairs&&hdoj5178&&hdoj5179
- HUST 1606 - Naive
- HUST 1606 - Naive