初涉IPC,了解AIDL的工作原理及使用方法


今天来讲讲AIDL,这个神秘的AIDL,也是最近在学习的,看了某课大神的讲解写下的blog,希望结合自己的看法给各位同价通俗易懂的讲解

官方文档:http://developer.android.com/guide/components/aidl.html

一.What is AIDL?(什么是AIDL)

AIDL:Android Interface Definition Language (Android接口定义语言)

首先,我们要知道,进程1和进程2,我们要如何让他通讯?

在Android系统的虚拟机中,每一个app运行都是在一个独立的沙箱里面的,这样的话,一个应用崩溃也不会影响到其他应用,这样我们就提出了一个问题,跨进程如如何进行通讯?如何传递数据?其实两个进程是不能直接通讯的,他需要Android系统底层的帮助来进行通讯!那就是我们每个人都知道的四大组件

我们首先还是先进Google的API看看

他大概的意思是他允许你去定义一个自己的标准,使用的是IPC(进程间通讯)进制,跨进程通讯,有兴趣的可以去翻译一下,不过值得注意的是他的第二段标记

这里提到了两个东西

  • Binder
  • Messenger

我们继续往下看话就知道

  • Binder
  • Messenger

翻译:如果您不需要执行并发IPC在不同的应用程序中 你就用Binder ,或者如果你想执行IPC,但不需要处理多线程,实现你的接口Messenger,无论如何,确保你了解实现AIDL之前绑定服务。

所以我们就能理清楚AIDL的概念了

  • AIDL //IPC 多应用 多线程

二.Defining an AIDL Interface(语法)

文档中强调。你必须定义一个.aidl的文件,那我们怎样去创建尼?

1. Create the .aidl file(创建一个.aidl文件)

官方提供的语法

  1. // IRemoteService.aidl
  2. package 包名(com.lgl.android);
  3. // Declare any non-default types here with import statements
  4. /** Example service interface 接口*/
  5. interface IRemoteService {
  6. /** Request the process ID of this service, to do evil things with it. 方法*/
  7. int getPid();
  8. /** Demonstrates some basic types that you can use as parameters
  9. * and return values in AIDL.
  10. */
  11. void basicTypes(int anInt, long aLong, boolean aBoolean, float aFloat,
  12. double aDouble, String aString);
  13. }

我们来做一个简单的演示

我们要使用的编译工具在我们的SDK/buidl-tools/android版本/aidl.bat,不过实际开发中也不需要手动编译,我们新建一个项目ForAIDL,这里我们使用的开发工具是Android Studio,其实Eclipse可能更加让人熟悉,不过用AS也是大势所趋了,而且AS的目录结构我也很喜欢

我们直接java-new - folder - AIDL folder

然后你就会发现多了一个aidl的文件夹

我们继续新建一个包名,新建一个文件文件new - AIDL - file

大致的内容

  1. // IMyAidlInterface.aidl
  2. package com.lgl.foraidl;
  3. // Declare any non-default types here with import statements
  4. interface IMyAidlInterface {
  5. /**
  6. * Demonstrates some basic types that you can use as parameters
  7. * and return values in AIDL.
  8. */
  9. void basicTypes(int anInt, long aLong, boolean aBoolean, float aFloat,
  10. double aDouble, String aString);
  11. }

AS默认是不会去重新构建Gradle,我们点击一下构建按钮

然后我们就可以在MainActivity中调用了

三.AIDL Client And Service(客户端和服务端)

现在就好玩了,我们先来理理思路,一般是这样的,我们一个软件有某个功能,也就是服务端,然后客户端通过AIDL去访问

这里可以看到服务端只是处理一些操作,我们客户端去请求,这样的话,那我创建一个AIDLService,同样的,我们需要去创建AIDL文件,命名-ServiceAidlInterface

ServiceAidlInterface

  1. // ServiceAidlInterface.aidl
  2. package com.lgl.aidlservice;
  3. // Declare any non-default types here with import statements
  4. interface ServiceAidlInterface {
  5. /*
  6. *计算两数之和
  7. */
  8. int add(int num1,int num2);
  9. }

现在我们处理的就不是默认的东西了,AIDL的原理就是你自定义语言接口,对的,我们也来

2. Implement the interface(实现一个AIDL)

根据我们的Google文档,第一步Create the .aidl file已经完成了,现在就来进行第二步了,我们这里需要使用到Service,看文档

这样的话我们新建一个IRemoteService继承service,我们实现计算的逻辑处理

  1. package com.lgl.aidlservice;
  2. import android.app.Service;
  3. import android.content.Intent;
  4. import android.os.IBinder;
  5. import android.os.RemoteException;
  6. import android.util.Log;
  7. /**
  8. *
  9. * 监听服务
  10. * Created by lgl on 16/3/13.
  11. */
  12. public class IRemoteService extends Service{
  13. /**
  14. * 当客户端绑定到该服务的时候启动onBind
  15. * @param intent
  16. * @return
  17. */
  18. @Override
  19. public IBinder onBind(Intent intent) {
  20. //绑定之后就计算
  21. return iBinder;
  22. }
  23. /**
  24. * 开始处理结果
  25. */
  26. private IBinder iBinder = new ServiceAidlInterface.Stub(){
  27. @Override
  28. public int add(int num1, int num2) throws RemoteException {
  29. Log.i("AIDL","收到了请求,參數1"+num1+"參數2"+num2);
  30. return num1+num2;
  31. }
  32. };
  33. }

3. Expose the interface to clients(客户端的实现)

OK,写完了服务端就可以写客户端了,我们直接new一个Module-AIDLClients

我們先按剛才的逻辑,把界面写了

  1. <?xml version="1.0" encoding="utf-8"?>
  2. <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
  3. android:layout_width="match_parent"
  4. android:layout_height="match_parent"
  5. android:orientation="vertical"
  6. android:gravity="center"
  7. android:padding="15dp">
  8. <TextView
  9. android:text="AIDL"
  10. android:textSize="50sp"
  11. android:layout_width="wrap_content"
  12. android:layout_height="wrap_content" />
  13. <EditText
  14. android:hint="请输入数字1"
  15. android:id="@+id/et_num1"
  16. android:layout_width="match_parent"
  17. android:layout_height="wrap_content" />
  18. <TextView
  19. android:layout_marginBottom="15dp"
  20. android:layout_marginTop="15dp"
  21. android:textSize="20sp"
  22. android:text="+"
  23. android:layout_width="wrap_content"
  24. android:layout_height="wrap_content" />
  25. <EditText
  26. android:hint="请输入数字2"
  27. android:id="@+id/et_num2"
  28. android:layout_width="match_parent"
  29. android:layout_height="wrap_content" />
  30. <TextView
  31. android:layout_marginBottom="15dp"
  32. android:layout_marginTop="15dp"
  33. android:textSize="20sp"
  34. android:text="="
  35. android:layout_width="wrap_content"
  36. android:layout_height="wrap_content" />
  37. <TextView
  38. android:id="@+id/tv_result"
  39. android:text="结果:"
  40. android:layout_width="wrap_content"
  41. android:layout_height="wrap_content" />
  42. <Button
  43. android:textColor="#fff"
  44. android:background="@android:color/holo_blue_light"
  45. android:layout_marginTop="30dp"
  46. android:id="@+id/btn_ok"
  47. android:text="计算"
  48. android:layout_width="match_parent"
  49. android:layout_height="wrap_content" />
  50. </LinearLayout>

我们要想客户端调用服务端的内容,那么就一定要定义标准的语言,所以客户端的aidl和服务端必须一致

记住,每次不通过的时候先编译一遍

MainActivity(客户端)

  1. package com.lgl.aidlclients;
  2. import android.content.ComponentName;
  3. import android.content.Context;
  4. import android.content.Intent;
  5. import android.content.ServiceConnection;
  6. import android.os.IBinder;
  7. import android.os.RemoteException;
  8. import android.support.v7.app.AppCompatActivity;
  9. import android.os.Bundle;
  10. import android.view.View;
  11. import android.widget.Button;
  12. import android.widget.EditText;
  13. import android.widget.TextView;
  14. import com.lgl.aidlservice.ServiceAidlInterface;
  15. /**
  16. * AIDL 客户端
  17. * @author lgl
  18. */
  19. public class MainActivity extends AppCompatActivity implements View.OnClickListener {
  20. //输入
  21. private EditText et_num1,et_num2;
  22. //结果
  23. private TextView tv_result;
  24. //AIDL远程访问
  25. private Button btn_ok;
  26. private ServiceAidlInterface aidl;
  27. private ServiceConnection conn = new ServiceConnection() {
  28. //连接上
  29. @Override
  30. public void onServiceConnected(ComponentName componentName, IBinder iBinder) {
  31. //拿到远程服务
  32. aidl = ServiceAidlInterface.Stub.asInterface(iBinder);
  33. }
  34. //断开时
  35. @Override
  36. public void onServiceDisconnected(ComponentName componentName) {
  37. //回收
  38. aidl = null;
  39. }
  40. };
  41. @Override
  42. protected void onCreate(Bundle savedInstanceState) {
  43. super.onCreate(savedInstanceState);
  44. setContentView(R.layout.activity_main);
  45. initView();
  46. bindServices();
  47. }
  48. private void initView() {
  49. et_num1 = (EditText) findViewById(R.id.et_num1);
  50. et_num2 = (EditText) findViewById(R.id.et_num2);
  51. tv_result = (TextView) findViewById(R.id.tv_result);
  52. btn_ok = (Button) findViewById(R.id.btn_ok);
  53. btn_ok.setOnClickListener(this);
  54. }
  55. @Override
  56. public void onClick(View view) {
  57. switch (view.getId()){
  58. case R.id.btn_ok:
  59. int num1 = Integer.parseInt(et_num1.getText().toString());
  60. int num2 = Integer.parseInt(et_num2.getText().toString());
  61. try {
  62. //结果
  63. int res = aidl.add(num1,num2);
  64. tv_result.setText("结果:"+res);
  65. } catch (RemoteException e) {
  66. e.printStackTrace();
  67. }
  68. break;
  69. }
  70. }
  71. /**
  72. * 开启服务
  73. */
  74. private void bindServices() {
  75. //获取服务端
  76. Intent intent = new Intent();
  77. //5.0之后的改变
  78. intent.setComponent(new ComponentName("com.lgl.aidlservice","com.lgl.aidlservice.IRemoteService"));
  79. //绑定服务
  80. bindService(intent,conn, Context.BIND_AUTO_CREATE);
  81. }
  82. /**
  83. * 销毁服务
  84. */
  85. @Override
  86. protected void onDestroy() {
  87. super.onDestroy();
  88. unbindService(conn);
  89. }
  90. }

这里逻辑也是十分的清晰,你创建了之后启动服务,我调用方法来计算,我们来演示一下,我们先启动服务端,再启动客户端

记得注册

  1. <service android:name=".IRemoteService"
  2. android:process=":remote"
  3. android:exported="true" >
  4. <intent-filter>
  5. <category android:name="android.intent.category.DEFAULT" />
  6. <action android:name="com.lgl.aidlservice.IRemoteService" />
  7. </intent-filter>
  8. </service>

写到这里才看到玉刚也写了相关的信息,这边android:exported=”true”为权限问题,具体可以看下:

android跨进程通信(IPC):使用AIDL

不过这终究也只是一些小菜,我们项目中也不可能用到这么low的方法,毕竟AIDL还是很强大的,既然这样,那我们来玩玩高级一点的

四.AIDL数据传递

我们不能传递很大的数据这是总所周知的,那AIDL默认支持什么类型的尼?我们可不可以自定义尼?当然可以

1.默认数据类型

我们可以看一下官方文档

  • 1.基本数据类型
  • 2.String
  • 3.CharSequence
  • 4.List
  • 5.Map
  • 6.Parcelable(序列化)

我们新建一个aidl文件,他都会自己生成一个方法

  1. void basicTypes(int anInt, long aLong, boolean aBoolean, float aFloat,
  2. double aDouble, String aString);

意指的就是基础类型

然而在我们的实际测试中,你会发现他是不支持short的,我们做这样的小测试

  1. void basicTypes(byte b,short s, int anInt, long aLong, boolean aBoolean, float aFloat,
  2. double aDouble, String aString);

然后编译

  1. /Users/lgl/Documents/Android/ASCode/AIDLService/app/src/main/aidl/com/lgl/aidlservice/IMyAidlInterface.aidl:11 parameter s (2) unknown type short

他报的错误就是不支持short

再比如说,你想写一个List< String>list的数据,你必须指定他是in还是out类型的

  1. in List< String>list

2.自定义类型

这里我们先在服务端新建一个aidl文件-IMyAidlInterface,然后写入我们的方法

  1. //我们返回的数据是一个List集合
  2. List<Person>add(in Person person);

这里报错是毋庸置疑的,因为他不识别我们的Person,但是就算我们新建一个Person类也是无用的,因为aidl不支持这个类型,上面也说了,他只支持基本类型和其他有限的几种数据类型,这样的话,我们就需要自定义了,怎么来呢?让他implements Parcelable就可以

  1. package com.lgl.aidlservice;
  2. import android.os.Parcel;
  3. import android.os.Parcelable;
  4. /**
  5. * 序列化实体类
  6. * Created by lgl on 16/3/15.
  7. */
  8. public class Person implements Parcelable{
  9. private String name;
  10. private int age;
  11. //构造方法
  12. public Person(String name,int age){
  13. this.name =name;
  14. this.age = age;
  15. }
  16. protected Person(Parcel in) {
  17. name = in.readString();
  18. age = in.readInt();
  19. }
  20. public int getAge() {
  21. return age;
  22. }
  23. public void setAge(int age) {
  24. this.age = age;
  25. }
  26. public String getName() {
  27. return name;
  28. }
  29. public void setName(String name) {
  30. this.name = name;
  31. }
  32. @Override
  33. public int describeContents() {
  34. return 0;
  35. }
  36. @Override
  37. public void writeToParcel(Parcel parcel, int i) {
  38. parcel.writeString(name);
  39. parcel.writeInt(age);
  40. }
  41. public static final Creator<Person> CREATOR = new Creator<Person>() {
  42. @Override
  43. public Person createFromParcel(Parcel in) {
  44. return new Person(in);
  45. }
  46. @Override
  47. public Person[] newArray(int size) {
  48. return new Person[size];
  49. }
  50. };
  51. }

这里值得注意的就是读写部分了,你是怎么写的就得怎么读,顺序错了就没用了,那我们编译一下,你会发现他还是提示错误,依然是位置的List数据类型

  1. /Users/lgl/Documents/Android/ASCode/AIDLService/app/src/main/aidl/com/lgl/aidlservice/IMyAidlInterface.aidl:9 unknown return type List<Person>

这里就需要我们手动导入这个Person了不然人家也不认识啊!那要怎么做?还是需要创建一个Person的AIDL文件,内容十分的简单,说明文件

  1. // IMyAidlInterface.aidl
  2. package com.lgl.aidlservice;
  3. parcelable Person;

可以看到,里面就一句话,好的,现在编译通过了,那我们重新来修改一下IRemoteService了,这次就不是返回计算数据的和了

  1. package com.lgl.aidlservice;
  2. import android.app.Service;
  3. import android.content.Intent;
  4. import android.os.IBinder;
  5. import android.os.RemoteException;
  6. import java.util.ArrayList;
  7. import java.util.List;
  8. /**
  9. *
  10. * 监听服务
  11. * Created by lgl on 16/3/13.
  12. */
  13. public class IRemoteService extends Service{
  14. private ArrayList<Person>persons;
  15. /**
  16. * 当客户端绑定到该服务的时候启动onBind
  17. * @param intent
  18. * @return
  19. */
  20. @Override
  21. public IBinder onBind(Intent intent) {
  22. persons = new ArrayList<Person>();
  23. //绑定之后就计算
  24. return iBinder;
  25. }
  26. /**
  27. * 开始处理结果
  28. */
  29. // private IBinder iBinder = new ServiceAidlInterface.Stub(){
  30. //
  31. // @Override
  32. // public int add(int num1, int num2) throws RemoteException {
  33. // Log.i("AIDL","收到了请求,參數1"+num1+"參數2"+num2);
  34. // return num1+num2;
  35. // }
  36. // };
  37. /**
  38. * 序列化
  39. */
  40. private IBinder iBinder = new IMyAidlInterface.Stub(){
  41. @Override
  42. public List<Person> add(Person person) throws RemoteException {
  43. //每增加一个人都能得到返回
  44. persons.add(person);
  45. return persons;
  46. }
  47. };
  48. }

好的,服务端部分写完了,刚开始可能是有点混乱的,不过当你确实已经理解之后你会发现,也就这么点东西的逻辑,那我们继续来写客户端,看他是怎么进行序列化的处理的。

还是一样,我们把Person.aidl和IMyAidlInterface.aidl复制过去,顺便把Person类拷贝过来,这里要注意的事就是包名要一致

然后我们就开启服务了

  1. package com.lgl.aidlclients;
  2. import android.content.ComponentName;
  3. import android.content.Context;
  4. import android.content.Intent;
  5. import android.content.ServiceConnection;
  6. import android.os.Bundle;
  7. import android.os.IBinder;
  8. import android.os.RemoteException;
  9. import android.support.v7.app.AppCompatActivity;
  10. import android.util.Log;
  11. import android.view.View;
  12. import android.widget.Button;
  13. import android.widget.EditText;
  14. import android.widget.TextView;
  15. import com.lgl.aidlservice.IMyAidlInterface;
  16. import com.lgl.aidlservice.Person;
  17. import com.lgl.aidlservice.ServiceAidlInterface;
  18. import java.util.ArrayList;
  19. /**
  20. * AIDL 客户端
  21. * @author lgl
  22. */
  23. public class MainActivity extends AppCompatActivity implements View.OnClickListener {
  24. //输入
  25. private EditText et_num1,et_num2;
  26. //结果
  27. private TextView tv_result;
  28. //AIDL远程访问
  29. private Button btn_ok;
  30. private ServiceAidlInterface aidl;
  31. private IMyAidlInterface imy;
  32. private ServiceConnection conn = new ServiceConnection() {
  33. //连接上
  34. @Override
  35. public void onServiceConnected(ComponentName componentName, IBinder iBinder) {
  36. //拿到远程服务
  37. aidl = ServiceAidlInterface.Stub.asInterface(iBinder);
  38. imy = IMyAidlInterface.Stub.asInterface(iBinder);
  39. }
  40. //断开时
  41. @Override
  42. public void onServiceDisconnected(ComponentName componentName) {
  43. //回收
  44. aidl = null;
  45. imy = null;
  46. }
  47. };
  48. @Override
  49. protected void onCreate(Bundle savedInstanceState) {
  50. super.onCreate(savedInstanceState);
  51. setContentView(R.layout.activity_main);
  52. bindServices();
  53. initView();
  54. }
  55. private void initView() {
  56. et_num1 = (EditText) findViewById(R.id.et_num1);
  57. et_num2 = (EditText) findViewById(R.id.et_num2);
  58. tv_result = (TextView) findViewById(R.id.tv_result);
  59. btn_ok = (Button) findViewById(R.id.btn_ok);
  60. btn_ok.setOnClickListener(this);
  61. }
  62. @Override
  63. public void onClick(View view) {
  64. switch (view.getId()){
  65. case R.id.btn_ok:
  66. // int n1 = Integer.parseInt(et_num1.getText().toString());
  67. // int n2 = Integer.parseInt(et_num2.getText().toString());
  68. //
  69. // try {
  70. // //结果
  71. // int res = aidl.add(n1,n2);
  72. // tv_result.setText("结果:"+res);
  73. // } catch (RemoteException e) {
  74. // e.printStackTrace();
  75. // tv_result.setText("Error");
  76. // }
  77. try{
  78. ArrayList<Person>persons = (ArrayList<Person>) imy.add(new Person("name",21));
  79. Log.i("Person",persons.toString());
  80. }catch (RemoteException e){
  81. e.printStackTrace();
  82. }
  83. break;
  84. }
  85. }
  86. /**
  87. * 开启服务
  88. */
  89. private void bindServices() {
  90. //获取服务端
  91. Intent intent = new Intent();
  92. //5.0之后的改变
  93. intent.setComponent(new ComponentName("com.lgl.aidlservice","com.lgl.aidlservice.IRemoteService"));
  94. //绑定服务
  95. bindService(intent,conn, Context.BIND_AUTO_CREATE);
  96. }
  97. /**
  98. * 销毁服务
  99. */
  100. @Override
  101. protected void onDestroy() {
  102. super.onDestroy();
  103. unbindService(conn);
  104. }
  105. }

这样的话,只要我们点击了计算按钮,Log打印一条消息,那事实是如此吗?我们运行一下

不会发现,我们每一次添加都是多增加了一行,相当于我们远程添加了一行

五.AIDL的工作原理

我们每次编译AIDL的文件的时候,都会编译成一个JAVA文件,具体是什么,我们一起研究研究,借用大神的一张图,你现在可能看不懂,等讲完原理你就懂了

编译好的JAVA文件在

  1. /*
  2. * This file is auto-generated. DO NOT MODIFY.
  3. * Original file: /Users/lgl/Documents/Android/ASCode/AIDLService/aidlclients/src/main/aidl/com/lgl/aidlservice/IMyAidlInterface.aidl
  4. */
  5. package com.lgl.aidlservice;
  6. //他是继承系统的接口,也就是说他本身就是一个接口
  7. public interface IMyAidlInterface extends android.os.IInterface
  8. {
  9. /** 存根,并且实现了自己的接口*/
  10. public static abstract class Stub extends android.os.Binder implements com.lgl.aidlservice.IMyAidlInterface
  11. {
  12. private static final java.lang.String DESCRIPTOR = "com.lgl.aidlservice.IMyAidlInterface";
  13. /**自己的构造方法*/
  14. public Stub()
  15. {
  16. this.attachInterface(this, DESCRIPTOR);
  17. }
  18. /**
  19. * Cast an IBinder object into an com.lgl.aidlservice.IMyAidlInterface interface,
  20. * generating a proxy if needed.
  21. */
  22. public static com.lgl.aidlservice.IMyAidlInterface asInterface(android.os.IBinder obj)
  23. {
  24. if ((obj==null)) {
  25. return null;
  26. }
  27. android.os.IInterface iin = obj.queryLocalInterface(DESCRIPTOR);
  28. if (((iin!=null)&&(iin instanceof com.lgl.aidlservice.IMyAidlInterface))) {
  29. return ((com.lgl.aidlservice.IMyAidlInterface)iin);
  30. }
  31. return new com.lgl.aidlservice.IMyAidlInterface.Stub.Proxy(obj);
  32. }
  33. @Override public android.os.IBinder asBinder()
  34. {
  35. //返回的this是Stub
  36. return this;
  37. }
  38. @Override public boolean onTransact(int code, android.os.Parcel data, android.os.Parcel reply, int flags) throws android.os.RemoteException
  39. {
  40. switch (code)
  41. {
  42. case INTERFACE_TRANSACTION:
  43. {
  44. reply.writeString(DESCRIPTOR);
  45. return true;
  46. }
  47. case TRANSACTION_add:
  48. {
  49. data.enforceInterface(DESCRIPTOR);
  50. com.lgl.aidlservice.Person _arg0;
  51. if ((0!=data.readInt())) {
  52. //如果拿到传过来数值封装成一个data
  53. _arg0 = com.lgl.aidlservice.Person.CREATOR.createFromParcel(data);
  54. }
  55. else {
  56. _arg0 = null;
  57. }
  58. java.util.List<com.lgl.aidlservice.Person> _result = this.add(_arg0);
  59. reply.writeNoException();
  60. //最后通过这个又写回去了,这样就完成了整个的通讯
  61. reply.writeTypedList(_result);
  62. return true;
  63. }
  64. }
  65. return super.onTransact(code, data, reply, flags);
  66. }
  67. //代理,他是Stud的内部类
  68. private static class Proxy implements com.lgl.aidlservice.IMyAidlInterface
  69. {
  70. private android.os.IBinder mRemote;
  71. Proxy(android.os.IBinder remote)
  72. {
  73. mRemote = remote;
  74. }
  75. @Override public android.os.IBinder asBinder()
  76. {
  77. return mRemote;
  78. }
  79. public java.lang.String getInterfaceDescriptor()
  80. {
  81. return DESCRIPTOR;
  82. }
  83. //我们返回的数据是一个List集合
  84. @Override public java.util.List<com.lgl.aidlservice.Person> add(com.lgl.aidlservice.Person person) throws android.os.RemoteException
  85. {
  86. android.os.Parcel _data = android.os.Parcel.obtain();
  87. android.os.Parcel _reply = android.os.Parcel.obtain();
  88. java.util.List<com.lgl.aidlservice.Person> _result;
  89. try {
  90. //写入了类名
  91. _data.writeInterfaceToken(DESCRIPTOR);
  92. if ((person!=null)) {
  93. //写了一个1,同时add数据,当你拿到了远程服务的时候,其实你拿到的只是远程服务的代理
  94. _data.writeInt(1);
  95. person.writeToParcel(_data, 0);
  96. }
  97. else {
  98. _data.writeInt(0);
  99. }
  100. //传入到onTransact
  101. mRemote.transact(Stub.TRANSACTION_add, _data, _reply, 0);
  102. _reply.readException();
  103. _result = _reply.createTypedArrayList(com.lgl.aidlservice.Person.CREATOR);
  104. }
  105. finally {
  106. _reply.recycle();
  107. _data.recycle();
  108. }
  109. return _result;
  110. }
  111. }
  112. static final int TRANSACTION_add = (android.os.IBinder.FIRST_CALL_TRANSACTION + 0);
  113. }
  114. //我们返回的数据是一个List集合
  115. //我们创建AIDL命名的这个方法
  116. public java.util.List<com.lgl.aidlservice.Person> add(com.lgl.aidlservice.Person person) throws android.os.RemoteException;
  117. }

Ok,AIDL这边算是讲完了,如果有兴趣的话,可以再去深入研究一下,我这边也只是学习了大神的视频,然后做的一个小总结和小笔记

Demo下载:http://download.csdn.net/detail/qq_26787115/9462515

初涉IPC,了解AIDL的工作原理及使用方法的更多相关文章

  1. 初涉IPC,了解AIDL的工作原理及用法

    初涉IPC,了解AIDL的工作原理及用法 今天来讲讲AIDL.这个神奇的AIDL,也是近期在学习的,看了某课大神的解说写下的blog,希望结合自己的看法给各位同价通俗易懂的解说 官方文档:http:/ ...

  2. AIDL 的工作原理

    当创建AIDL文件并Clean Project 代码后,会生成相应的Java文件: 先来一段伪代码:类整体结构 /* * This file is auto-generated. DO NOT MOD ...

  3. linux命令管道工作原理与使用方法

    一.管道定义 管道是一种两个进程间进行单向通信的机制.因为管道传递数据的单向性,管道又称为半双工管道.管道的这一特点决定了器使用的局限性.管道是Linux支持的最初Unix IPC形式之一,具有以下特 ...

  4. Docker镜像提交命令commit的工作原理和使用方法

    在本地创建一个容器后,可以依据这个容器创建本地镜像,并可把这个镜像推送到Docker hub中,以便在网络上下载使用. 下面我们来动手实践. docker pull nginx:1.15.3 用命令行 ...

  5. 浅析AIDL的使用和工作原理

    AIDL是一种接口定义语言,用于生成可在Android设备上两个进程之间进行进程间通信(IPC)的代码. AIDL的使用 新建一个aidl文件,定义进程间通信的接口 // IStudentManage ...

  6. 100天搞定机器学习|Day56 随机森林工作原理及调参实战(信用卡欺诈预测)

    本文是对100天搞定机器学习|Day33-34 随机森林的补充 前文对随机森林的概念.工作原理.使用方法做了简单介绍,并提供了分类和回归的实例. 本期我们重点讲一下: 1.集成学习.Bagging和随 ...

  7. android service 的各种用法(IPC、AIDL)

    http://my.oschina.net/mopidick/blog/132325 最近在学android service,感觉终于把service的各种使用场景和用到的技术整理得比较明白了,受益颇 ...

  8. AIDL使用以及原理分析

    AIDL使用以及IPC原理分析(进程间通信) 概要 为了大家能够更好的理解android的进程间通信原理,以下将会从以下几个方面讲解跨进程通讯信: 1. 必要了解的概念 2. 为什么要使用aidl进程 ...

  9. NameNode和SecondaryNameNode工作原理剖析

    NameNode和SecondaryNameNode工作原理剖析 作者:尹正杰 版权声明:原创作品,谢绝转载!否则将追究法律责任. 一.NameNode中的元数据是存储在那里的? 1>.首先,我 ...

随机推荐

  1. JVM垃圾回收总结

    来自Oracle官方文档,对JVM GC知识整理的清晰易懂,查资料还是看官方的好! 1 GC步骤简述 步骤1:标记 (Marking) 根据对象引用关系,将未被任何对象引用的对象实例标记出来,如下图中 ...

  2. String、StringBuffer、StringBuilder对比

    1.String 用于存放字符的数组被声明为final的,因此只能赋值一次,不可再更改.这就导致每次对String的操作都会生成新的String对象,不仅效率低下,而且大量浪费有限的内存空间. Str ...

  3. DBoW2应用

    图像对应的bag-of-words向量\(v_t\) 假设词典总共有\(W\)个单词,那么每一幅图像能够用一个\(W\)维的向量表示 \((t_1, t_2, t_3, ..., t_W)\)其中 \ ...

  4. Android开发学习之路--RxAndroid之初体验

    学了一段时间android,看了部分的项目代码,然后想想老是学基础也够枯燥乏味的,那么就来学习学习新东西吧,相信很多学java的都听说过RxJava,那么android下也有RxAndroid. Rx ...

  5. 详解EBS接口开发之销售订单导入

     步骤 1. 创建一个订单导入来源.       - 导航到 OM -> 设置 -> 订单 -> 导入来源       - 输入一个新的订单导入来源名称和描述 - 选择启用来激活 ...

  6. 随机采样和随机模拟:吉布斯采样Gibbs Sampling实现高斯分布参数推断

    http://blog.csdn.net/pipisorry/article/details/51539739 吉布斯采样的实现问题 本文主要说明如何通过吉布斯采样来采样截断多维高斯分布的参数(已知一 ...

  7. Linux之mailx的使用

    mailx是UNIX系统上用来处理邮件的工具,使用它可以发送,读取邮件.下面看看如何使用它来发送邮件. 发送格式 mailx -s subject user@xxx.com < message_ ...

  8. Android初级教程启动定时器详解

    本案例知识是:后台执行定时任务. Alarm机制: 一.创建LongRunningService类 package com.example.servicebestpractice; import ja ...

  9. Android的TabHost组件-android的学习之旅(四十)

    TabHost简介 虽然,官方建议用Fagment取代TabHost,但是我们还是大概的介绍一下.TabHost是一种非常简单的组件,TabHost可以很方便的在窗口放置多个标签页,每一个标签页相当于 ...

  10. 深入分析Spring混合事务

    在ORM框架的事务管理器的事务内,使用JdbcTemplate执行SQL是不会纳入事务管理的. 下面进行源码分析,看为什么必须要在DataSourceTransactionManager的事务内使用J ...