摘要:本节主要来讲解Android10.0 Binder中如何使用AIDL

阅读本文大约需要花费20分钟。

文章首发微信公众号:IngresGe

专注于Android系统级源码分析,Android的平台设计,欢迎关注我,谢谢!

欢迎关注我的公众号!

[Android取经之路] 的源码都基于Android-Q(10.0) 进行分析

[Android取经之路] 系列文章:

《系统启动篇》

  1. Android系统架构
  2. Android是怎么启动的
  3. Android 10.0系统启动之init进程
  4. Android10.0系统启动之Zygote进程
  5. Android 10.0 系统启动之SystemServer进程
  6. Android 10.0 系统服务之ActivityMnagerService
  7. Android10.0系统启动之Launcher(桌面)启动流程
  8. Android10.0应用进程创建过程以及Zygote的fork流程
  9. Android 10.0 PackageManagerService(一)工作原理及启动流程
  10. Android 10.0 PackageManagerService(二)权限扫描
  11. Android 10.0 PackageManagerService(三)APK扫描
  12. Android 10.0 PackageManagerService(四)APK安装流程

《日志系统篇》

  1. Android10.0 日志系统分析(一)-logd、logcat 指令说明、分类和属性
  2. Android10.0 日志系统分析(二)-logd、logcat架构分析及日志系统初始化
  3. Android10.0 日志系统分析(三)-logd、logcat读写日志源码分析
  4. Android10.0 日志系统分析(四)-selinux、kernel日志在logd中的实现​

《Binder通信原理》

  1. Android10.0 Binder通信原理(一)Binder、HwBinder、VndBinder概要
  2. Android10.0 Binder通信原理(二)-Binder入门篇
  3. Android10.0 Binder通信原理(三)-ServiceManager篇
  4. Android10.0 Binder通信原理(四)-Native-C\C++实例分析
  5. Android10.0 Binder通信原理(五)-Binder驱动分析
  6. Android10.0 Binder通信原理(六)-Binder数据如何完成定向打击
  7. Android10.0 Binder通信原理(七)-Framework binder示例
  8. Android10.0 Binder通信原理(八)-Framework层分析
  9. Android10.0 Binder通信原理(九)-AIDL Binder示例
  10. Android10.0 Binder通信原理(十)-AIDL原理分析-Proxy-Stub设计模式
  11. Android10.0 Binder通信原理(十一)-Binder总结

  《HwBinder通信原理》

  1. HwBinder入门篇-Android10.0 HwBinder通信原理(一)
  2. HIDL详解-Android10.0 HwBinder通信原理(二)
  3. HIDL示例-C++服务创建Client验证-Android10.0 HwBinder通信原理(三)
  4. HIDL示例-JAVA服务创建-Client验证-Android10.0 HwBinder通信原理(四)
  5. HwServiceManager篇-Android10.0 HwBinder通信原理(五)
  6. Native层HIDL服务的注册原理-Android10.0 HwBinder通信原理(六)
  7. Native层HIDL服务的获取原理-Android10.0 HwBinder通信原理(七)
  8. JAVA层HIDL服务的注册原理-Android10.0 HwBinder通信原理(八)
  9. JAVA层HIDL服务的获取原理-Android10.0 HwBinder通信原理(九)
  10. HwBinder驱动篇-Android10.0 HwBinder通信原理(十)
  11. HwBinder原理总结-Android10.0 HwBinder通信原理(十一)

《编译原理》

  1. 编译系统入门篇-Android10.0编译系统(一)
  2. 编译环境初始化-Android10.0编译系统(二)
  3. make编译过程-Android10.0编译系统(三)
  4. Image打包流程-Android10.0编译系统(四)
  5. Kati详解-Android10.0编译系统(五)

0.什么是AIDL

AIDL:Android Interface Definition Language,即Android接口定义语言。

Android系统中的进程之间不能共享内存,因此,需要提供一些机制在不同进程之间进行数据通信。为了使其他的应用程序也可以访问本应用程序提供的服务,Android系统采用了远程过程调用(Remote Procedure Call,RPC)方式来实现。与很多其他的基于RPC的解决方案一样,Android使用一种接口定义语言(Interface Definition Language,IDL)来公开服务的接口。我们知道4个Android应用程序组件中的3个(Activity、BroadcastReceiver和ContentProvider)都可以进行跨进程访问,另外一个Android应用程序组件Service同样可以。因此,可以将这种可以跨进程访问的服务称为AIDL(Android Interface Definition Language)服务。

下面将通过一个示例来说明两个APP之间的AIDL通信。

1.工程环境准备

1)通过Android Studio 首先创建一个项目  New Project ->Empty Activity,Name:AIDLDemo, Pakcage:com.android.myservice ,用作Server

2)在项目中再创建一个Module,用来做Client, 在项目文件上 右键 ->New-> Module -> Phone & Tablet Module, 名称填client  -> Empty Activity

3)这样Server和Client的两个环境就准备好了

接下来开始填代码

2.服务端设计

2.1 创建一个AIDL 文件 IMyService

在服务的文件夹app 中,执行下面的步骤:

右键 -> New -> AIDL->AIDL File, 名称为IMyService

AIDL创建完成

填入一个add的函数,我们用来做加法计算:

Code:

// IMyService.aidl
package com.android.myservice;// Declare any non-default types here with import statementsinterface IMyService {/*** 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);int add(int num1, int num2);
}

选择 Build -> Make Module "app",会把AIDL进行编译,会自动生成IMyService 这个服务接口,其中实现了stub、proxy的class,以及TRANSACTION的code,用来通信处理

2.2 服务实现

在Framework层我们还可以使用addService进行服务注册,但是在应用层,我们不具备相应的权限,只能通过集成Service,开放Service,让Client进行bind。

在JAVA->com.android.myservice 上新建一个Java Class---MyService

package com.android.myservice;
import android.app.Service;
import android.content.Intent;
import android.os.IBinder;
import android.os.RemoteException;
import android.util.Log;public class MyService extends Service {
static final String TAG = "MyTestService";
//服务实体IMyService.Stub mStub = new IMyService.Stub() {@Overridepublic void basicTypes(int anInt, long aLong, boolean aBoolean, float aFloat, double aDouble, String aString) throws RemoteException {}@Overridepublic int add(int num1, int num2) throws RemoteException {Log.d(TAG,"add");//服务的接口实现,这里做一个加法运算return num1 + num2;}};@Overridepublic void onCreate() {super.onCreate();Log.d(TAG, "onCreate");}@Overridepublic IBinder onBind(Intent intent) {Log.d(TAG,"onBind");return mStub;//通过ServiceConnection在activity中拿到MyService}
}

2.3 AndroidManifest.xml配置

在AndroidManifest.xml中配上Service的信息,其中enable:ture设置可用,exported:ture对外暴露, 这样其他的Activity才能访问。


<service android:name=".MyService"android:enabled="true"android:exported="true"><!--enable:ture设置可用exported:ture对外暴露 --><intent-filter><action android:name="com.android.myservice.myservice"/></intent-filter>
</service>

执行编译,服务端准备完成,编译一个APK进入手机\模拟器

3.Client端设计

3.1 AIDL拷贝

把服务端的AIDL以及包目录完整的拷贝到client的mian目录下,让Client和Server的服务对象对等。

接着执行编译 Build-> Make Module "Client",对应的IMyService.java也在client中编译出来

3.2 Client的UI实现

在layout->activity_main.xml 中添加相应的控件,效果如下:

布局:


<?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"><Buttonandroid:id="@+id/toAdd"android:layout_width="wrap_content"android:layout_height="wrap_content"android:text="计算"app:layout_constraintEnd_toEndOf="parent"app:layout_constraintStart_toStartOf="parent"app:layout_constraintTop_toBottomOf="@+id/result" /><Buttonandroid:id="@+id/bindbtn"android:layout_width="wrap_content"android:layout_height="wrap_content"android:text="绑定服务"app:layout_constraintStart_toStartOf="@+id/toAdd"app:layout_constraintTop_toBottomOf="@+id/toAdd" /><Buttonandroid:id="@+id/unbindbtn"android:layout_width="wrap_content"android:layout_height="wrap_content"android:text="解除绑定"app:layout_constraintStart_toStartOf="@+id/bindbtn"app:layout_constraintTop_toBottomOf="@+id/bindbtn" /><EditTextandroid:id="@+id/num1"android:layout_width="0dp"android:layout_height="wrap_content"android:background="#ececec"app:layout_constraintEnd_toEndOf="parent"app:layout_constraintStart_toStartOf="parent"app:layout_constraintTop_toTopOf="parent" /><EditTextandroid:id="@+id/num2"android:layout_width="0dp"android:layout_height="wrap_content"android:background="#ececec"app:layout_constraintEnd_toEndOf="parent"app:layout_constraintStart_toStartOf="parent"app:layout_constraintTop_toBottomOf="@+id/add" /><EditTextandroid:id="@+id/result"android:layout_width="0dp"android:layout_height="wrap_content"android:background="#eceaea"android:inputType="none"app:layout_constraintEnd_toEndOf="parent"app:layout_constraintStart_toStartOf="parent"app:layout_constraintTop_toBottomOf="@+id/value" /><TextViewandroid:id="@+id/add"android:layout_width="0dp"android:layout_height="wrap_content"android:text="+"android:textSize="25sp"app:layout_constraintEnd_toEndOf="parent"app:layout_constraintStart_toStartOf="parent"app:layout_constraintTop_toBottomOf="@+id/num1" /><TextViewandroid:id="@+id/value"android:layout_width="0dp"android:layout_height="wrap_content"android:layout_marginTop="1dp"android:text="="android:textSize="25sp"app:layout_constraintEnd_toEndOf="parent"app:layout_constraintStart_toStartOf="parent"app:layout_constraintTop_toBottomOf="@+id/num2" /></androidx.constraintlayout.widget.ConstraintLayout>

3.3 Client服务绑定和功能实现

通过bindService进行服务的绑定,unbindService 进行服务的解绑


package com.android.client;import androidx.appcompat.app.AlertDialog;
import androidx.appcompat.app.AppCompatActivity;import android.content.ComponentName;
import android.content.DialogInterface;
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.EditText;import com.android.myservice.IMyService;public class MainActivity extends AppCompatActivity implements View.OnClickListener {static final String TAG = "AIDLClient";IMyService myService;private EditText num1;private EditText num2;private EditText result;@Overrideprotected void onCreate(Bundle savedInstanceState) {super.onCreate(savedInstanceState);Log.d(TAG, "onCreate ");setContentView(R.layout.activity_main);initView();}private void initView() {num1 = (EditText) findViewById(R.id.num1);num2 = (EditText) findViewById(R.id.num2);result = (EditText) findViewById(R.id.result);Button toAdd = (Button) findViewById(R.id.toAdd);Button bindbtn = (Button) findViewById(R.id.bindbtn);Button unbindbtn = (Button) findViewById(R.id.unbindbtn);toAdd.setOnClickListener(this);bindbtn.setOnClickListener(this);unbindbtn.setOnClickListener(this);}private ServiceConnection connection = new ServiceConnection() {//绑定上服务的时候@Overridepublic void onServiceConnected(ComponentName componentName, IBinder service) {//接受到了远程的服务Log.d(TAG, "onServiceConnected: ");myService = IMyService.Stub.asInterface(service);}// 当服务断开的时候调用@Overridepublic void onServiceDisconnected(ComponentName componentName) {Log.d(TAG, "onServiceDisconnected: ");//回收资源myService = null;}};@Overridepublic void onClick(View v) {switch (v.getId()) {case R.id.bindbtn://绑定服务Log.d(TAG, "start to bindMyServce");bindMyService();break;case R.id.unbindbtn://解除绑定Log.d(TAG, "start to unbindMyServce");unbindMyService();break;case R.id.toAdd://计算数据int number1 = Integer.valueOf(num1.getText().toString());int number2 = Integer.valueOf(num2.getText().toString());try {Log.d(TAG, "start to add");int valueRes = myService.add(number1, number2);result.setText(valueRes + "");} catch (RemoteException e) {e.printStackTrace();}break;}}private void bindMyService() {Intent intent = new Intent();intent.setAction("com.android.myservice.myservice");intent.setPackage("com.android.myservice"); // server's package namebindService(intent, connection, BIND_AUTO_CREATE);new AlertDialog.Builder(this).setTitle("Tips").setMessage("绑定成功!").setPositiveButton("确定",new DialogInterface.OnClickListener() {public void onClick(DialogInterface dialog,int whichButton) {}}).show();Log.d("AIDLClient", "bindMyService: bind on end");}private void unbindMyService() {unbindService(connection);new AlertDialog.Builder(this).setTitle("Tips").setMessage("解除绑定成功!").setPositiveButton("确定",new DialogInterface.OnClickListener() {public void onClick(DialogInterface dialog,int whichButton) {}}).show();Log.d("AIDLClient", "unbindMyService: unbind on end");}
}

执行编译,生成client.apk,在手机\模拟器中展示

4.测试:

点击“绑定服务”,成功后弹出“绑定成功”:

log:
   Client:

03-21 19:32:49.986 30794 30794 D AIDLClient: start to bindMyServce
03-21 19:32:50.023 30794 30794 D AIDLClient: bindMyService: bind on end
03-21 19:32:50.044 30794 30794 D AIDLClient: onServiceConnected:
03-21 19:32:57.062 30794 30794 D AIDLClient: start to add

Server:

03-21 19:32:49.996 31091 31091 D MyTestService: onCreate
03-21 19:32:49.997 31091 31091 D MyTestService: onBind

在输入框分别输入1,2, 点击计算,执行“1+2”,结果为3,从服务端返回成功

log:
Client:

 03-21 19:32:57.062 30794 30794 D AIDLClient: start to add

Server:

03-21 19:32:57.063 31091 31160 D MyTestService: add

点击“解除绑定”,成功后弹出“解除绑定成功”:

log:
Client:

03-21 19:35:57.109 30794 30794 I AIDLClient: start to unbindMyServce
03-21 19:35:57.147 30794 30794 D AIDLClient: unbindMyService: unbind on end

下一节专门来讲一讲AIDL的原理

我的微信公众号:IngresGe

Android10.0 Binder通信原理(九)-AIDL Binder示例相关推荐

  1. Android10.0 Binder通信原理(七)-Framework binder示例

    摘要:本节主要来讲解Android10.0 Binder在Framework中的示例 阅读本文大约需要花费15分钟. 文章首发微信公众号:IngresGe 专注于Android系统级源码分析,Andr ...

  2. JAVA层HIDL服务的获取原理-Android10.0 HwBinder通信原理(九)

    摘要:本节主要来讲解Android10.0 JAVA层HIDL服务的获取原理 阅读本文大约需要花费19分钟. 文章首发微信公众号:IngresGe 专注于Android系统级源码分析,Android的 ...

  3. HwBinder原理总结-Android10.0 HwBinder通信原理(十一)

    摘要:本节主要来进行Android10.0 HwBinder的原理总结 阅读本文大约需要花费14分钟. 文章首发微信公众号:IngresGe 专注于Android系统级源码分析,Android的平台设 ...

  4. HwBinder驱动篇-Android10.0 HwBinder通信原理(十)

    摘要:本节主要来讲解Android10.0 HwBinder驱动的流程 阅读本文大约需要花费24分钟. 文章首发微信公众号:IngresGe 专注于Android系统级源码分析,Android的平台设 ...

  5. JAVA层HIDL服务的注册原理-Android10.0 HwBinder通信原理(八)

    摘要:本节主要来讲解Android10.0 JAVA层HIDL服务的注册原理 阅读本文大约需要花费22分钟. 文章首发微信公众号:IngresGe 专注于Android系统级源码分析,Android的 ...

  6. Native层HIDL服务的获取原理-Android10.0 HwBinder通信原理(七)

    摘要:本节主要来讲解Android10.0 Native层HIDL服务的获取原理 阅读本文大约需要花费23分钟. 文章首发微信公众号:IngresGe 专注于Android系统级源码分析,Androi ...

  7. Native层HIDL服务的注册原理-Android10.0 HwBinder通信原理(六)

    摘要:本节主要来讲解Android10.0 Native层HIDL服务的注册原理 阅读本文大约需要花费23分钟. 文章首发微信公众号:IngresGe 专注于Android系统级源码分析,Androi ...

  8. HwServiceManager篇-Android10.0 HwBinder通信原理(五)

    摘要:本节主要来讲解Android10.0 HwServiceManager的通信原理 阅读本文大约需要花费34分钟. 文章首发微信公众号:IngresGe 专注于Android系统级源码分析,And ...

  9. HIDL示例-JAVA服务创建-Client验证-Android10.0 HwBinder通信原理(四)

    摘要:本节主要来讲解Android10.0 JAVA层的HIDL服务创建和JAVA层的Client验证 阅读本文大约需要花费15分钟. 文章首发微信公众号:IngresGe 专注于Android系统级 ...

最新文章

  1. Py之pandas:利用where、replace等函数对dataframe格式数据按照条件进行数据替换
  2. 16行代码AC——紫书| 例题7-3 Fractions Again?! (UVA - 10976)_时间复杂度O(n)
  3. 微型计算机物理地址转换,微型计算机及接口技术2015年4月真题试题(04732)
  4. MADDPG中环境怎么配置,multiagent包解决
  5. 保驾护航金三银四,吐血整理
  6. pytest自动化6:pytest.mark.parametrize装饰器--测试用例参数化
  7. [概率论]如何通俗地理解“最大似然估计法”?
  8. java怎么访问私有类_如何从Java类的外部访问类的私有方法?
  9. Vue学习笔记(九) Vue CLI
  10. 类名引用static变量好处
  11. jdbc 批量insert_037 深入JDBC中PreparedStatement对象使用
  12. bzoj 相似回文串 3350 3103 弦图染色+manacher
  13. mysql多对多表设计_数据库怎么设计多对多的数据表
  14. (十七)关于安装智能家居3大方面你需要注意的
  15. 清华EMBA课程系列思考之九 -- 中国经济前沿问题解读
  16. windows远程桌面登录不允许空密码
  17. ide模式ahci模式_IDE的完整形式是什么?
  18. 使用 matplotlib绘制简单图形,保存图片的方法
  19. 双端影视APP后台搭建及前端安装编译大概流程
  20. 诺基亚java模拟器exe,无需模拟器!骁龙810手机成功运行Win10:可开exe程序

热门文章

  1. openssh windows_WINDOWS环境配置SSH服务
  2. OpenMV生成AprilTag码
  3. pta l2-7(家庭房产)
  4. 山西晋城学籍“失踪”解决方案:可参加高考或转职高
  5. ArtemisMQ的“未消费之谜”
  6. MySQL Connector/C++ 接口实例
  7. CentOS 7无线网卡驱动解决方法
  8. mysql日常错误信息解决方法:InnoDB: and force InnoDB to continue crash recovery here.
  9. VBScript 之文件 IO 篇
  10. 大型企业网络配置系列课程详解(五) --Frame-Relay配置与相关概念的理解