1.什么是AIDL

AIDL全称是Android Interface Definition Language,中文译为Android接口定义语言,AIDL的提出是为了解决进程间通讯,我们知道,在Android系统中,每个进程在内存中是相互独立的,类似一个个独立王国,一个进程通常情况下无法访问其他进程的内存,但进程之间不是老死不相往来的状态,他们之间有许多数据交互的需求,为此提出了AIDL,通过AIDL,定义双方认可的数据交互接口,再由AIDL翻译成操作系统理解的底层语言,进而实现进程间通讯。

2.AIDL的使用

进程间通讯转换成具体业务逻辑则是一个服务端和客户端的会话。服务端和客户端约定好AIDL接口,服务端实现接口的具体逻辑并暴露给客户端,客户端再调用接口。既然涉及到两方,则在工程中也创建服务端和客户端两个项目,见图2,我的是服务端和客户端放在一个工程下,分开放在两个工程目录下也是可行的。

具体的开发步骤如下:

1.服务端创建.aidl文件

AIDL接口和日常生活的合同比较相似,服务端和客户端约定AIDL接口相当于双方草拟业务合作合同,开发过程中一般都在服务端这边准备合同,也即在服务端创建.aidl文件,方法为:

a.在service模块下的main目录下,新建aidl文件,在其之下新建一个包(package),包名自定义,然后右键新建.aidl文件,如图所示,aidl文件名字自定义,确定之后,AS帮我们新建一个.aidl文件。

b.点开新建的aidl文件会发现不是空白,而是有了内容,这是AS自动生成帮忙填写的内容,其中basicTypes接口是演示AIDL可直接使用的基本数据类型,如果想用自己定义的数据类型,还需要做一些操作,这将在另一篇博客说明。删掉basicType后,填上要实现的接口,这里填写ServiceGreet,表示服务端跟客户端打个招呼,代码内容如下,添加之后记得同步一下工程,否则在调用还是默认的basicType函数,这样aidl文件创建好了。

package com.pm.service;interface ServiceAidlInterface {String ServiceGreet();
}

2.服务端实现接口

aidl文件创建成功后,也就是草拟好了合同,接下来就是履行合同的过程,即服务端这边根据aidl文件实现接口。

我们注意到,aidl文件有别于java格式文件,aidl文件那怎么和java联系起来呢,毕竟开发语言是java。实际上在创建aidl文件时,Android SDK工具自动生成一个同名的java接口,例如ServiceAidlInterface.aidl生成的文件名是ServiceAidlInterface.java,服务端调用接口实际是和该java文件打交道,这也是为什么创建或者更改aidl文件要及时同步的原因,如果同步不及时,SDK工具可能不及时自动生成的更新java接口

AS根据aidl文件自动生成的java接口里有一个名为 Stub 的内部抽象类,Stub意思是存根,根据百度百科,存根意思是票据、证件等开出后所留的底子,这个抽象类的确有这个意思,具体需要另外展开文章来说明了,这里可先简单理解一下,我们把aidl进程间通讯理解成银行汇款过程,服务端通过该银行汇款(数据交互)给客户端,在aidl里声明的各种接口相当于汇款单,实现接口相当于打入钱的过程,从这个角度可勉强理解存根的意义,现实中拿到存根已经汇完钱了,而这里是拿到存根再汇钱(即实现接口),实际上,实现 .aidl 生成的接口是扩展生成的YourInterface.Stub接口的过程,实现接口的代码如下:

package com.pm.service;import android.app.Service;
import android.content.Intent;
import android.os.IBinder;
import android.os.RemoteException;public class MyService extends Service {private ServiceAidlInterface.Stub serviceAidlInterface= new ServiceAidlInterface.Stub() {@Overridepublic String ServiceGreet() throws RemoteException {return "Hello Client!";}};@Overridepublic IBinder onBind(Intent intent) {return serviceAidlInterface.asBinder();}
}

最后别忘了在AndroidManifest.xml注册服务,内容如下

 <serviceandroid:name=".MyService"android:exported="true"><intent-filter><action android:name="com.pm.service.MyService" /><category android:name="android.intent.category.DEFAULT" /></intent-filter>

这样服务端工作就完成了。

3.客户端调用接口
现实中合同都是一式两份的,这里也不例外,客户端也要拿到aidl文件,而且要求aidl所在的包名必须和服务端aidl所在的包名一致,最稳妥的办法是直接整个拷贝服务端的aidl目录,同样的,拷贝完aidl文件之后,也要及时同步一下项目,AS才能及时自动生成对应的java接口。

3.1 首先,建立一个服务连接,在连接上时,初始化接口,代码如下,我们注意到,这里还是用的Stub,这样和服务端的存根对得上

    private ServiceConnection connection=new ServiceConnection() {@Overridepublic void onServiceConnected(ComponentName name, IBinder service) {serviceAidlInterface = ServiceAidlInterface.Stub.asInterface(service);}@Overridepublic void onServiceDisconnected(ComponentName name) {}};

3.2 传入第一步创建的连接,绑定服务,这样客户端和服务端同呼吸共命运了

  private void bindService() {Intent intent = new Intent();intent.setAction("com.pm.service.MyService");intent.setPackage("com.pm.service");this.bindService(intent, connection, BIND_AUTO_CREATE);}

3.3 最后一步是调用接口了,这一步比较简单,调用服务器打招呼接口

String greet= serviceAidlInterface.ServiceGreet();tvInfo.setText(greet);

3.总结

把aidl当成一个合同文件来理解,有助于理解aidl的作用,其中因为存根概念,又从银行汇款来理解。aidl创建后,Android SDK工具,这里是Android Studio自动帮忙生成对应的java接口,前提是要及时同步工程,工程不及时同步的话,aidl文件更新了,对应的java接口还是旧数据。aidl创建之后,服务器实现Stub存根里的方法,之后aidl拷贝给客户端,客户端创建连接,在连接里实例化存根,这样便取出了存根里的方法,最后绑定服务后调用即可。

最后附上完整客户端代码和布局

package com.pm.myaidldemo;import androidx.appcompat.app.AppCompatActivity;import android.content.ComponentName;
import android.content.Intent;
import android.content.ServiceConnection;
import android.os.Bundle;
import android.os.IBinder;
import android.os.RemoteException;
import android.util.Log;
import android.view.View;
import android.widget.Button;
import android.widget.TextView;import com.pm.service.ServiceAidlInterface;public class MainActivity extends AppCompatActivity {private Button bServiceGreet;private TextView tvInfo;private ServiceAidlInterface serviceAidlInterface;private ServiceConnection connection=new ServiceConnection() {@Overridepublic void onServiceConnected(ComponentName name, IBinder service) {serviceAidlInterface = ServiceAidlInterface.Stub.asInterface(service);}@Overridepublic void onServiceDisconnected(ComponentName name) {}};@Overrideprotected void onCreate(Bundle savedInstanceState) {super.onCreate(savedInstanceState);setContentView(R.layout.activity_main);bindService();bServiceGreet=findViewById(R.id.btnServiceGreet);tvInfo=findViewById(R.id.tvInfo);bServiceGreet.setOnClickListener(new View.OnClickListener() {@Overridepublic void onClick(View v) {try {String greet= serviceAidlInterface.ServiceGreet();tvInfo.setText(greet);} catch (RemoteException e) {e.printStackTrace();}}});}private void bindService() {Intent intent = new Intent();intent.setAction("com.pm.service.MyService");intent.setPackage("com.pm.service");this.bindService(intent, connection, BIND_AUTO_CREATE);}
}

客户端布局文件

<?xml version="1.0" encoding="utf-8"?>
<androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"xmlns:app="http://schemas.android.com/apk/res-auto"xmlns:tools="http://schemas.android.com/tools"android:layout_width="match_parent"android:layout_height="match_parent"tools:context=".MainActivity"><TextViewandroid:id="@+id/tvInfo"android:layout_width="wrap_content"android:layout_height="wrap_content"android:text="Hello World!"app:layout_constraintBottom_toBottomOf="parent"app:layout_constraintLeft_toLeftOf="parent"app:layout_constraintRight_toRightOf="parent"app:layout_constraintTop_toTopOf="parent" /><Buttonandroid:id="@+id/btnServiceGreet"android:layout_width="wrap_content"android:layout_height="wrap_content"android:text="Button"app:layout_constraintStart_toStartOf="parent"app:layout_constraintTop_toTopOf="parent" /></androidx.constraintlayout.widget.ConstraintLayout>

Android AIDL使用介绍(1)基本使用相关推荐

  1. Android AIDL使用介绍(3) 浅说AIDL背后的Binder

    1.背景 在前面的博客中,我们已经学会了使用AIDL进行跨进程通信,AIDL的使用比较简单,可实际上跨进程通信是一个相当复杂的过程,例如进程A是怎么找到进程B的,如果有一个进程C冒充进程A,进程B又该 ...

  2. Android AIDL使用介绍(2)自定义数据类型的传递

    1.背景 默认情况下,AIDL只支持下列数据类型: Java八种基础数据类型(如 int.long.char.boolean 等); String字符串: CharSequence字符序列: List ...

  3. Android AIDL使用详解

    一.概述 AIDL 意思即 Android Interface Definition Language,翻译过来就是Android接口定义语言,是用于定义服务器和客户端通信接口的一种描述语言,可以拿来 ...

  4. ANDROID AIDL 1

    也可参考:http://buaadallas.blog.51cto.com/399160/372090 的Android AIDL(Android Interface Definition Langu ...

  5. (转载)你真的理解Android AIDL中的in,out,inout么?

    前言 这其实是一个很小的知识点,大部分人在使用AIDL的过程中也基本没有因为这个出现过错误,正因为它小,所以在大部分的网上关于AIDL的文章中,它都被忽视了--或者并没有,但所占篇幅甚小,且基本上都是 ...

  6. ANDROID SDK体系介绍

    本章介绍了Android SDK的相关内容,包括其文档解读,示例讲解,以及相关API的介绍,通过本章的学习,可以比较清晰地把握Android SDK的全貌,熟悉其提供的相关示例,以及附带的工具使用.另 ...

  7. android驱动框架介绍

    android驱动框架介绍 了解android驱动框架: 1.方法1--jni调用底层驱动 在android框架中写入c/c++直接调用底层linux驱动,并向上提供jni接口给应用程序: 优点:简单 ...

  8. Android Fragment 基本介绍

    Android Fragment 基本介绍 Android Fragment 基本介绍 Fragment Android是在Android 3.0 (API level 11)开始引入Fragment ...

  9. Android Pmem相关介绍

    http://fangjian0518.blog.163.com/blog/#m=0 Android Pmem相关介绍 2011-10-18 09:40:26|  分类: Android PMEM | ...

最新文章

  1. R 包 pathview 代谢通路可视化
  2. Linux服务器通过LVM扩展其磁盘空间
  3. (转)Arcgis for Js之Graphiclayer扩展详解
  4. Django Book 2.0 笔记——会话、用户和注册
  5. 如何从Internet Explorer或Edge迁移到Chrome(以及为什么要迁移)
  6. LeetCode 1033. 移动石子直到连续
  7. python调用jar字典类型_LWPCookieJar的使用-将requests存储的cookie转换成字典
  8. CSS 实现必填项前/后添加红色星号
  9. 2021李宏毅机器学习课程笔记——Recurrent Neural Network
  10. Python写出一个字节,一个YouTube,我用Python怎么了!
  11. sql中的join问题
  12. Unity播放声音的两种方式以及相关遇到的
  13. PhotoShop如何给字体添加下划线
  14. TCP 和 UDP 的区别 TCP 和 UDP 详解
  15. Win10不相邻的磁盘怎么合并,一学就会
  16. java中intern_Java中的intern()方法是什么?
  17. background 属性介绍
  18. EasyPoi Excel简单导出导入
  19. 经济基础知识(初级)【5】
  20. 我国构建物联网基础安全标准体系的时间表确定

热门文章

  1. boost::hof::always用法的测试程序
  2. boost::hof::apply_eval用法的测试程序
  3. boost::geometry::strategy::transform::matrix_transformer用法的测试程序
  4. boost::foreach模块右值const的测试程序
  5. GDCM:gdcm::ByteValue的测试程序
  6. DCMTK:OFVec类的测试程序
  7. VTK:可视化算法之DisplacementPlot
  8. VTK:图片之Colored2DImageFusion
  9. OpenCV使用神经网络检测颜色检查器
  10. Qt创建Android服务