android AIDL使用demo

背景

最近打算学习一下如何在framework层添加一个自定义service。
了解到自定义service需要使用aidl,为了加强对aidl的了解和使用过程,特意又温习了一下aidl的使用,并用博客的形式记录下来。
aidl官方参考:https://developer.android.google.cn/develop/background-work/services/aidl?hl=en

AIDL是什么

官方解释:Android 接口定义语言 (AIDL) 类似于其他 IDL:它允许您定义客户端和服务使用进程间通信 (IPC) 进行相互通信时都认可的编程接口。

定义 AIDL 接口

project结构图
这里我使用的ide是Android Studio Iguana版本。
首先创建一个project,里面创建两个app一个叫client,另一个叫server。
在server app的src/main目录创建一个aidl文件IMyAidlInterface.aidl,内容如下

// IMyAidlInterface.aidl
package com.hai.server;
// Declare any non-default types here with import statements
//aidl说明参考:https://developer.android.google.cn/develop/background-work/services/aidl?hl=en
interface IMyAidlInterface {/*** 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 getPid();oneway void getThreadId();
}

IMyAidlInterface.aidl中定义了三个接口供客户端调用。

然后编译一下project,就会在server的build目录下自动生成IMyAidlInterface.java接口文件,内容如下

/** This file is auto-generated.  DO NOT MODIFY.*/
package com.hai.server;
// Declare any non-default types here with import statements
//aidl说明参考:https://developer.android.google.cn/develop/background-work/services/aidl?hl=en
public interface IMyAidlInterface extends android.os.IInterface
{/** Default implementation for IMyAidlInterface. */public static class Default implements com.hai.server.IMyAidlInterface{/*** Demonstrates some basic types that you can use as parameters* and return values in AIDL.*/@Override public void basicTypes(int anInt, long aLong, boolean aBoolean, float aFloat, double aDouble, java.lang.String aString) throws android.os.RemoteException{}@Override public int getPid() throws android.os.RemoteException{return 0;}@Override public void getThreadId() throws android.os.RemoteException{}@Overridepublic android.os.IBinder asBinder() {return null;}}/** Local-side IPC implementation stub class. */public static abstract class Stub extends android.os.Binder implements com.hai.server.IMyAidlInterface{/** Construct the stub at attach it to the interface. */public Stub(){this.attachInterface(this, DESCRIPTOR);}/*** Cast an IBinder object into an com.hai.server.IMyAidlInterface interface,* generating a proxy if needed.*/public static com.hai.server.IMyAidlInterface asInterface(android.os.IBinder obj){if ((obj==null)) {return null;}android.os.IInterface iin = obj.queryLocalInterface(DESCRIPTOR);if (((iin!=null)&&(iin instanceof com.hai.server.IMyAidlInterface))) {return ((com.hai.server.IMyAidlInterface)iin);}return new com.hai.server.IMyAidlInterface.Stub.Proxy(obj);}@Override public android.os.IBinder asBinder(){return this;}@Override public boolean onTransact(int code, android.os.Parcel data, android.os.Parcel reply, int flags) throws android.os.RemoteException{java.lang.String descriptor = DESCRIPTOR;if (code >= android.os.IBinder.FIRST_CALL_TRANSACTION && code <= android.os.IBinder.LAST_CALL_TRANSACTION) {data.enforceInterface(descriptor);}switch (code){case INTERFACE_TRANSACTION:{reply.writeString(descriptor);return true;}}switch (code){case TRANSACTION_basicTypes:{int _arg0;_arg0 = data.readInt();long _arg1;_arg1 = data.readLong();boolean _arg2;_arg2 = (0!=data.readInt());float _arg3;_arg3 = data.readFloat();double _arg4;_arg4 = data.readDouble();java.lang.String _arg5;_arg5 = data.readString();this.basicTypes(_arg0, _arg1, _arg2, _arg3, _arg4, _arg5);reply.writeNoException();break;}case TRANSACTION_getPid:{int _result = this.getPid();reply.writeNoException();reply.writeInt(_result);break;}case TRANSACTION_getThreadId:{this.getThreadId();break;}default:{return super.onTransact(code, data, reply, flags);}}return true;}private static class Proxy implements com.hai.server.IMyAidlInterface{private android.os.IBinder mRemote;Proxy(android.os.IBinder remote){mRemote = remote;}@Override public android.os.IBinder asBinder(){return mRemote;}public java.lang.String getInterfaceDescriptor(){return DESCRIPTOR;}/*** Demonstrates some basic types that you can use as parameters* and return values in AIDL.*/@Override public void basicTypes(int anInt, long aLong, boolean aBoolean, float aFloat, double aDouble, java.lang.String aString) throws android.os.RemoteException{android.os.Parcel _data = android.os.Parcel.obtain();android.os.Parcel _reply = android.os.Parcel.obtain();try {_data.writeInterfaceToken(DESCRIPTOR);_data.writeInt(anInt);_data.writeLong(aLong);_data.writeInt(((aBoolean)?(1):(0)));_data.writeFloat(aFloat);_data.writeDouble(aDouble);_data.writeString(aString);boolean _status = mRemote.transact(Stub.TRANSACTION_basicTypes, _data, _reply, 0);_reply.readException();}finally {_reply.recycle();_data.recycle();}}@Override public int getPid() throws android.os.RemoteException{android.os.Parcel _data = android.os.Parcel.obtain();android.os.Parcel _reply = android.os.Parcel.obtain();int _result;try {_data.writeInterfaceToken(DESCRIPTOR);boolean _status = mRemote.transact(Stub.TRANSACTION_getPid, _data, _reply, 0);_reply.readException();_result = _reply.readInt();}finally {_reply.recycle();_data.recycle();}return _result;}@Override public void getThreadId() throws android.os.RemoteException{android.os.Parcel _data = android.os.Parcel.obtain();try {_data.writeInterfaceToken(DESCRIPTOR);boolean _status = mRemote.transact(Stub.TRANSACTION_getThreadId, _data, null, android.os.IBinder.FLAG_ONEWAY);}finally {_data.recycle();}}}static final int TRANSACTION_basicTypes = (android.os.IBinder.FIRST_CALL_TRANSACTION + 0);static final int TRANSACTION_getPid = (android.os.IBinder.FIRST_CALL_TRANSACTION + 1);static final int TRANSACTION_getThreadId = (android.os.IBinder.FIRST_CALL_TRANSACTION + 2);}public static final java.lang.String DESCRIPTOR = "com.hai.server.IMyAidlInterface";/*** Demonstrates some basic types that you can use as parameters* and return values in AIDL.*/public void basicTypes(int anInt, long aLong, boolean aBoolean, float aFloat, double aDouble, java.lang.String aString) throws android.os.RemoteException;public int getPid() throws android.os.RemoteException;public void getThreadId() throws android.os.RemoteException;
}

IMyAidlInterface.java结构图
IMyAidlInterface.java结构图

可以看到IMyAidlInterface.java也定义了和aidl相同的三个接口,并且定义了DefaultStub两个静态内部类去实现IMyAidlInterface接口。

  • Default类默认空实现且没有继承Binder,实际无意义。
  • Stub是一个继承Binder抽象类,实际是要在server端写一个Stub的实现类去实现实际的接口功能
  • Stub.Proxy一般用于client端。

Server端实现服务

接下来就是在server端的service中实现aidl接口服务,这里我写了一个ServerService类,内容如下

package com.hai.server;import android.app.Service;
import android.content.Intent;
import android.os.IBinder;
import android.os.RemoteException;
import android.os.SystemClock;
import android.system.Os;
import android.util.Log;public class ServerService extends Service {private static final String TAG = "ServiceService";IMyAidlInterface.Stub binder = new IMyAidlInterface.Stub() {@Overridepublic void basicTypes(int anInt, long aLong, boolean aBoolean, float aFloat, double aDouble, String aString) throws RemoteException {Log.d(TAG, "basicTypes() called with: anInt = [" + anInt + "], aLong = [" + aLong + "], aBoolean = [" + aBoolean + "], aFloat = [" + aFloat + "], aDouble = [" + aDouble + "], aString = [" + aString + "]");}@Overridepublic int getPid() throws RemoteException {SystemClock.sleep(2000);return Os.getpid();}@Overridepublic void getThreadId() throws RemoteException {SystemClock.sleep(2000);}};@Overridepublic IBinder onBind(Intent intent) {Log.d(TAG, "onBind() called with: intent = [" + intent + "]");return binder;}@Overridepublic boolean onUnbind(Intent intent) {Log.d(TAG, "onUnbind() called with: intent = [" + intent + "]");return super.onUnbind(intent);}
}

为了client端可以通过隐式服务绑定服务,还需要在AndroidManifest.xml做一下配置

<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"><applicationandroid:allowBackup="true"android:icon="@mipmap/ic_launcher"android:label="@string/app_name"android:roundIcon="@mipmap/ic_launcher_round"android:supportsRtl="true"android:theme="@style/Theme.AidlDemo"><serviceandroid:name=".ServerService"android:enabled="true"android:exported="true"><intent-filter><action android:name="com.hai.server.ServerService" /><category android:name="android.intent.category.DEFAULT" /></intent-filter></service></application>
</manifest>

当client端通过bindservice绑定成功后,服务端就会返回server端的binder对象给到client端。

Client端使用服务

首先需要把server端的aidl整个文件夹拷贝到client端的src目录,以便client端能够获得aidl的访问权限。client端的代码结构如图
在这里插入图片描述
编译一下project,就会在client的build目录下自动生成IMyAidlInterface.java接口文件。
接下来就是bindservice,bindservice服务成功后就可以获得binder的代理对象,进而调用aidl接口服务。如下是在activity中通过bindservice的方式调用aidl接口服务。

package com.hai.aidldemo;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.util.Log;
import android.view.View;import androidx.activity.EdgeToEdge;
import androidx.appcompat.app.AppCompatActivity;import com.hai.server.IMyAidlInterface;public class MainActivity extends AppCompatActivity {private static final String TAG = "MainActivity";IMyAidlInterface myAidlInterface;ServiceConnection serviceConnection = new ServiceConnection() {@Overridepublic void onServiceConnected(ComponentName name, IBinder service) {Log.d(TAG, "onServiceConnected() called with: name = [" + name + "], service = [" + service + "]");myAidlInterface = IMyAidlInterface.Stub.asInterface(service);}@Overridepublic void onServiceDisconnected(ComponentName name) {Log.d(TAG, "onServiceDisconnected() called with: name = [" + name + "]");}};@Overrideprotected void onCreate(Bundle savedInstanceState) {super.onCreate(savedInstanceState);EdgeToEdge.enable(this);setContentView(R.layout.activity_main);}public void clk(View view) {switch (view.getId()) {case R.id.btn_bind:if (myAidlInterface == null) {boolean b = bindService(new Intent("com.hai.server.ServerService").setPackage("com.hai.server"), serviceConnection, Context.BIND_AUTO_CREATE);Log.d(TAG, "bindService: " + b);}break;case R.id.btn_unbind:if (myAidlInterface != null) {unbindService(serviceConnection);}break;case R.id.btn_basicType:try {myAidlInterface.basicTypes(1, 2, true, 4, 5, "6");} catch (RemoteException e) {throw new RuntimeException(e);}break;case R.id.btn_getPid:try {long start = System.currentTimeMillis();int pid = myAidlInterface.getPid();Log.d(TAG, "getPid: " + pid + ", cost:" + (System.currentTimeMillis() - start));} catch (RemoteException e) {throw new RuntimeException(e);}break;case R.id.btn_getThreadId:try {long start = System.currentTimeMillis();myAidlInterface.getThreadId();Log.d(TAG, "getThreadId: cost:" + (System.currentTimeMillis() - start));} catch (RemoteException e) {throw new RuntimeException(e);}break;}}
}

项目源码:

https://gitee.com/menty/aidl-demo/blob/master/client/src/main/java/com/hai/aidldemo/MainActivity.java

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/pingmian/36879.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

【C++ 初阶路】--- 类和对象(末)

目录 一、const成员1.1 取地址及const取地址操作符重载 二、再谈构造函数2.1 构造函数体赋值2.2 初始化列表2.3 explicit关键字 三、static成员3.1 概念3.2 特性 四、友元4.1 友元函数4.2 友元类 五、内部类六、匿名对象 一、const成员 将const修饰的“成员函数”称之为const成…

多行业预约门店服务小程序源码系统 支持多门店预约 带完整的安装代码包以及搭建教程

系统概述 该系统基于先进的云计算和大数据技术&#xff0c;采用模块化设计&#xff0c;具有高度的可扩展性和可定制性。无论是餐饮、美容美发、健身房还是其他服务行业&#xff0c;都可以通过该系统轻松实现多门店预约功能。同时&#xff0c;我们还提供了丰富的接口和插件&…

Appium+python自动化(二十九)- 模拟手指在手机上多线多点作战 - 多点触控(超详解)

简介 在网页中我们经常使用缩放操作来便利的查看具体的信息&#xff0c;在appium中使用MultiAction多点触控的类来实现。MultiAction是多点触控的类&#xff0c;可以模拟用户多点操作。主要包含加载add()和执行perform()两个方法. 问题思考 在使用地图App中&#xff0c;我们…

Embedding 、词嵌入、向量模型说的是一回事么?AI是如何理解世界?AI人不能不看的Embedding白话科普!

在AI理解世界的过程中&#xff0c;向量模型扮演着一个至关重要的角色&#xff0c;甚至可以说它是AI大模型用以构建和理解复杂数据的基础&#xff0c;也是对不同形态数据的一种标准化的“浓缩”。它能够将语言、图像、声音等多样化的信息&#xff0c;转化为一种通用的、数学化的…

基于51单片机的银行排队呼叫系统设计

一.硬件方案 本系统是以排队抽号顺序为核心&#xff0c;客户利用客户端抽号&#xff0c;工作人员利用叫号端叫号&#xff1b;通过显示器及时显示当前所叫号数&#xff0c;客户及时了解排队信息&#xff0c;通过合理的程序结构来执行排队抽号。电路主要由51单片机最小系统LCD12…

Vue-cli项目及Element UI 环境搭建 保姆级教程

一、Vue-cli介绍及其作用 什么是Vue-cli手脚架 vue-cli 官方提供的一个脚手架&#xff0c;用于快速生成一个 vue 的项目模板&#xff1b;预先定义 好的目录结构及基础代码&#xff0c;就好比咱们在创建 Maven 项目时可以选择创建一个 骨架项目&#xff0c;这个骨架项目就是脚…

手把手教你玩转AD9361数字调制解调系列(二) ----纯逻辑实现FSK信号的数字调制解调

因最近客户需求&#xff0c;用纯PL实现AD9361的数字信号调制解调&#xff0c;于是就把各种数字调制都在AD9361上都实现了一遍。优点就是&#xff1a;既可以在zynq系列上配置9361&#xff0c;也可以在纯FPGA系列配置9361。并且理解起来比较简单&#xff01;&#xff01;&#xf…

lidar3607.2 雷达点云数据处理软件功能介绍

LiDAR360 是北京数字绿土科技股份有限公司自主研发的点云后处理及行业应用软件。平台可处理 TB 级点云数据&#xff0c;并拥有 10 余种国际领先的点云处理及 AI 算法&#xff0c;推动激光雷达 的多行业应用。700 余项强大且灵活的功能&#xff0c;解决用户最后一公里的应用难题…

云仓是如何发展起来的?

1、电子商务的繁荣&#xff1a; 随着电商的兴起&#xff0c;对高效仓储和物流的需求越来越大。传统的仓储方式难以满足海量订单处理和快速配送的要求&#xff0c;因此需要一种更加灵活和高效的仓储解决方案。 ------------------------------------------------- 2、科技进步…

罗盘复杂网络教程—3步轻松构建社团检测任务

作为复杂网络领域中重要的课题之一&#xff0c;社团检测有助于揭示网络中存在的功能性模块或群集&#xff0c;旨在于仅利用网络中蕴含的来识别模块&#xff0c;并可能进而识别它们的层次组织。社团检测在各个领域具有重要的应用&#xff0c;可以帮助深入理解复杂系统潜在的模式…

一键进阶ComfyUI!懂AI的设计师现在都在用的节点式Stable Diffusion

前言 _ 万字教程&#xff01;奶奶看了都会的 ComfyUI 入门教程 推荐阅读 一、川言川语 大家好&#xff0c;我是言川。 阅读文章 > ](https://www.uisdc.com/comfyui-3) 目前使用 Stable Diffusion 进行创作的工具主要有两个&#xff1a;WebUI 和 ComfyUI。而更晚出现的…

SceneXplain 图片叙事升级:如何让图片听得到

SceneXplain 是一个由多模态 AI 驱动的产品服务&#xff0c;它不仅 提供一流的图像和视频标注解决方案&#xff0c;还具备卓越的多模态视觉问答能力&#xff0c;为用户解锁视觉内容的全新维度。 在[《图像描述算法排位赛》中&#xff0c;我们探讨了图像描述&#xff08;Image …

有兄弟对这类区域比较感兴趣,也引起我的好奇,我提取出来给大家看看

要说这类地区&#xff0c;亚洲泰国排第二估计没人敢说第一吧&#xff0c;所以我就提取泰国的数据给大家看看&#xff01; 如图&#xff1a;这些特殊服务地区主要集中在曼谷和芭提雅地区&#xff0c;芭提雅最多&#xff01;看来管理还是不错的&#xff0c;限制在一定范围&#x…

便携应急气象站设备—实时监测和记录气象数据

TH-BQX10便携应急气象站设备是一种高度集成、轻便易携的气象观测系统。它采用新型一体化结构设计&#xff0c;能够快速安装和拆卸&#xff0c;适用于各种复杂环境。通过集成多种气象传感器&#xff0c;该设备能够实时监测和记录温度、湿度、风向、风速、降雨量、气压等多种气象…

AMEYA360:广和通发布LTE Cat.1 bis模组MC610-GL,赋能全球漫游追踪器

广和通LTE Cat.1 bis模组MC610-GL搭载展锐8910平台&#xff0c;覆盖全球主流LTE频段&#xff0c;下行峰值速率达10.3Mbps&#xff0c;上行速率达5.1Mbps&#xff0c;满足全球终端对4G速率连接的需求;同时支持LTE和GSM双模通信&#xff0c;便于用户灵活切换网络。在尺寸封装上&a…

开放式耳机怎么选?五大2024年口碑销量爆棚机型力荐!

作为一名数码测评up主&#xff0c;今天来测评市面上的开放式耳机。开放式耳机它的设计非常的新颖&#xff0c;不管是舒适的佩戴&#xff0c;还是可以边听音乐&#xff0c;边听到周围的声音&#xff0c;给人更加安全的听感体验。长时间佩戴&#xff0c;不仅舒适度进一步的提升&a…

【机器学习】高斯混合模型(Gaussian Mixture Models, GMM)深度解析

&#x1f308;个人主页: 鑫宝Code &#x1f525;热门专栏: 闲话杂谈&#xff5c; 炫酷HTML | JavaScript基础 ​&#x1f4ab;个人格言: "如无必要&#xff0c;勿增实体" 文章目录 高斯混合模型&#xff08;Gaussian Mixture Models, GMM&#xff09;深度解析引…

【uml期末复习】统一建模语言大纲

前言&#xff1a; 关于uml的期末复习的常考知识点&#xff0c;可能对你们有帮助&#x1f609; 目录 第一部分 概念与基础 第一章 面向对象技术 第二章 统一软件过程 第三章 UML概述 第四章 用例图 第五章 类图 第六章 对象图 第七章 顺序图 第八章 协作图 第九章 状态…

Transformers 安装与基本使用

文章目录 Github文档推荐文章简介安装官方示例中文情感分析模型分词器 Tokenizer填充 Padding截断 Truncation google-t5/t5-small使用脚本进行训练Pytorch 机器翻译数据集下载数据集格式转换 Github https://github.com/huggingface/transformers 文档 https://huggingface…

Selenium时间控件的处理

我们经常在做web自动化测试过程中会遇到时间控件&#xff0c;那么对于时间控件如何处理&#xff0c;我们可以来分析下。 对于时间控件一般分为两种&#xff1a; 1、普通的时间控件 直接通过send_keys就可以解决 d.get("https://www.ctrip.com/?sid155952&alliancei…