当前位置:网站首页>Cross process communication Aidl
Cross process communication Aidl
2022-07-05 09:47:00 【Black Mountain demon 2018】
AIDL What is it? , What is the role
The project involves two applications, that is, data communication between two processes , and Android Memory addresses between processes in are independent , One process cannot access the memory address of another process . Here is a brief introduction to the concept of process , A process is an entity of a program or application , Each process has its own independent memory address space . Official documents say , To communicate , The process needs to decompose its objects into primitives that can be understood by the operating system , And group them into objects that you can manipulate . Writing the code to perform the grouping operation is cumbersome , therefore Android Will use AIDL To complete cross process communication .
Android The cross process in is actually IPC(Inter-Process Communication) signal communication , and AIDL It is IPC The mechanism of communication .
AIDL The full name is Android Interface Definition Language, It means Android interface definition , Realize cross process communication by defining relevant interfaces .
AIDL Use
1.AIDl Supported data types
AIDL Use a simple syntax , Allows you to use one or more methods ( Acceptable parameters and return values ) To declare acceptance mouth . Parameters and return values can be of any type , Even AIDL Other interfaces generated .
You must use Java Programming language construction .aidl file . Every .aidl Each document must define a single interface , And you only need the interface declaration and method signature .
By default ,AIDL The following data types are supported :
Java All primitive types in programming languages ( Such as int、long、char、boolean etc. java Basic data type )
1.String
2.CharSequence
3.List
List All elements in the must be data types supported in the above list , Or what you declared by AIDL Other interfaces generated or Parcelable type . You can choose to List Used as a “ Generic ” class ( for example ,List). Although the generated method is intended to use List Interface , But the specific class actually received by the other party is always ArrayList.
4. Map
Map All elements in the must be data types supported in the above list , Or what you declared by AIDL Other interfaces generated or Parcelable type . Generics are not supported Map( Such as Map<String,Integer> Formal Map). Although the generated method is intended to use Map Interface , But the specific class actually received by the other party is always HashMap.
5. other AIDL Generated interfaces
6. Realization Parcelable Class data type
2. To write AIDL Related codes
Write server code
Create entity class Person class , Realization Parcelable Interface , Entity classes for cross process communication .
public class People implements Parcelable {
private String id;
private String name;
@Override
public void writeToParcel(Parcel dest, int flags) {
dest.writeString(id);
dest.writeString(name);
}
@Override
public int describeContents() {
return 0;
}
public static final Creator<People> CREATOR = new Creator<People>() {
@Override
public People createFromParcel(Parcel in) {
People people = new People();
people.setId(in.readString());
people.setName(in.readString());
return people;
}
@Override
public People[] newArray(int size) {
return new People[size];
}
};
public String getId() {
return id;
}
public void setId(String id) {
this.id = id;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
}
establish .aldl file , Here are two files , One is the entity class People The file of , One is the interface file
// People.aidl
package com.uniubi.aidlapplication;
parcelable People;
// People.aidl
package com.uniubi.aidlapplication;
import com.uniubi.aidlapplication.People;
interface IRemoteService {
void basicTypes(int a, long b, in People person, in String d);
}
Remember to import People class , otherwise .aidl The file will not be found .
Implementation interface
Click on android studio Of make project
Will be in build/generated//Users/chenxuming/generated/aidl_source_output_dir/debug/compileDebugAidl/out/ Generate under directory IRemoteService.java file .
Remember to be present moudle Of gradle The document specifies .aidl File path , Otherwise, the compiler will not find People This class ,
I suffered a big loss here .
sourceSets {
main {
manifest.srcFile 'src/main/AndroidManifest.xml'
java.srcDirs = ['src/main/java', 'src/main/aidl']
resources.srcDirs = ['src/main/java', 'src/main/aidl']
aidl.srcDirs = ['src/main/aidl']
res.srcDirs = ['src/main/res']
assets.srcDirs = ['src/main/assets']
}
}
View the generated java file , You can see the interface IRemoteService Class inheritance android.os.IInterface Interface , It contains an inheritance Binder Of Sub Subclass , And this Sub Subclass implementation IRemoteService Interface , Later, we will talk about the generated IRemoteService Class specific source code .
establish Service, And create binder object , adopt onBind Method returns this binder object , So far, the server code has been written .
public class RemoteService extends Service {
private static final String TAG = "RemoteService";
private IRemoteService.Stub binder = new IRemoteService.Stub() {
@Override
public void basicTypes(int a, long b, People person, String d) throws RemoteException {
Log.i(TAG, "basicTypes" + person.getName());
}
};
@Override
public IBinder onBind(Intent intent) {
return binder;
}
}
Expose the interface to the client
1. Will server end src/main The whole below aidl Copy the files in the directory to the same location of the client , Under the client project, don't forget the current module Under the gradle To configure sourceSets, Can let .aidl File found People class , then make project.
2. Binding remote services , Here, you must bind the remote service ,“com.uniubi.aidlapplication.RemoteService” It is a remote service actiob name, Bind implicitly .
Intent intent1 = new Intent();
intent1.setComponent(new ComponentName("com.uniubi.aidlapplication", "com.uniubi.aidlapplication.RemoteService"));
bindService(intent1, serviceConnection, BIND_AUTO_CREATE);
private IRemoteService iRemoteService;
private ServiceConnection serviceConnection = new ServiceConnection() {
@Override
public void onServiceConnected(ComponentName name, IBinder service) {
Log.i("MainActivity", "onServiceConnected");
iRemoteService = IRemoteService.Stub.asInterface(service);
}
@Override
public void onServiceDisconnected(ComponentName name) {
Log.i("MainActivity", "onServiceDisconnected");
}
};
From the code, we can see that after binding the remote service successfully , Can get it IBinder object , And then through IRemoteService.Stub.asInterface(service) Turn it into what we need iRemoteService object , And then through
iRemoteService object , You can make cross process requests .
try {
if(iRemoteService != null){
iRemoteService.basicTypes(1, 2, people, " ha-ha ");
}
} catch (RemoteException e) {
Log.i("MainActivity", e.getMessage());
e.printStackTrace();
}
AIDL Source code analysis
The generated code format is messy , It's best to format it first for easy reading .
/* * This file is auto-generated. DO NOT MODIFY. * Original file: /Users/chenxuming/AndroidStudioProjects/AIDLClient/app/src/main/aidl/com/uniubi/aidlapplication/IRemoteService.aidl */
package com.uniubi.aidlapplication;
public interface IRemoteService extends android.os.IInterface {
/** * Local-side IPC implementation stub class. */
public static abstract class Stub extends android.os.Binder implements com.uniubi.aidlapplication.IRemoteService {
private static final java.lang.String DESCRIPTOR = "com.uniubi.aidlapplication.IRemoteService";
/** * Construct the stub at attach it to the interface. */
public Stub() {
this.attachInterface(this, DESCRIPTOR);
}
/** * Cast an IBinder object into an com.uniubi.aidlapplication.IRemoteService interface, * generating a proxy if needed. */
public static com.uniubi.aidlapplication.IRemoteService asInterface(android.os.IBinder obj) {
if ((obj == null)) {
return null;
}
android.os.IInterface iin = obj.queryLocalInterface(DESCRIPTOR);
if (((iin != null) && (iin instanceof com.uniubi.aidlapplication.IRemoteService))) {
return ((com.uniubi.aidlapplication.IRemoteService) iin);
}
return new com.uniubi.aidlapplication.IRemoteService.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;
switch (code) {
case INTERFACE_TRANSACTION: {
reply.writeString(descriptor);
return true;
}
case TRANSACTION_basicTypes: {
data.enforceInterface(descriptor);
int _arg0;
_arg0 = data.readInt();
long _arg1;
_arg1 = data.readLong();
com.uniubi.aidlapplication.People _arg2;
if ((0 != data.readInt())) {
_arg2 = com.uniubi.aidlapplication.People.CREATOR.createFromParcel(data);
} else {
_arg2 = null;
}
java.lang.String _arg3;
_arg3 = data.readString();
this.basicTypes(_arg0, _arg1, _arg2, _arg3);
reply.writeNoException();
return true;
}
default: {
return super.onTransact(code, data, reply, flags);
}
}
}
private static class Proxy implements com.uniubi.aidlapplication.IRemoteService {
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;
}
@Override
public void basicTypes(int a, long b, com.uniubi.aidlapplication.People person, java.lang.String d) 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(a);
_data.writeLong(b);
if ((person != null)) {
_data.writeInt(1);
person.writeToParcel(_data, 0);
} else {
_data.writeInt(0);
}
_data.writeString(d);
mRemote.transact(Stub.TRANSACTION_basicTypes, _data, _reply, 0);
_reply.readException();
} finally {
_reply.recycle();
_data.recycle();
}
}
}
static final int TRANSACTION_basicTypes = (android.os.IBinder.FIRST_CALL_TRANSACTION + 0);
}
public void basicTypes(int a, long b, com.uniubi.aidlapplication.People person, java.lang.String d) throws android.os.RemoteException;
}
It's not hard to find out IRemoteService This class consists of two parts , Part is the declared interface , Part is inheritance Binder Class Sub Inner class , This Sub Inner classes have two main methods ,asInterface() and onTransact() Method , There is also an inner class Proxy, At the first glance, you can see that it is the agent mode , I won't elaborate on the proxy mode here .
Step by step , Take a look first iRemoteService = IRemoteService.Stub.asInterface(service) This line of code , Will serve the end of binder Object resolves to client iRemoteService object , This method returns IRemoteService.Stub.Proxy object , in other words iRemoteService Object is IRemoteService.Stub.Proxy, Then look at the call iRemoteService.basicTypes(1, 2, people, “ ha-ha ”) The place of , In fact, what you see is Proxy Object's basicTypes Method , See key code mRemote.transact(Stub.TRANSACTION_basicTypes, _data, _reply, 0); It's through mRemote Object's transact Methods to communicate ,mRemote The object is the remote server Sub object , Click in to check the source code , Main view onTransact Method , And the above also mentioned Sub Class implements Binder Class onTransact Methodical ( It has been posted , There is no repetition here ).
public final boolean transact(int code, @NonNull Parcel data, @Nullable Parcel reply,
int flags) throws RemoteException {
if (false) Log.v("Binder", "Transact: " + code + " to " + this);
if (data != null) {
data.setDataPosition(0);
}
boolean r = onTransact(code, data, reply, flags);
if (reply != null) {
reply.setDataPosition(0);
}
return r;
}
Find out onTransact It's through code To specify the specific invocation behavior , Key code this.basicTypes(_arg0, _arg1, _arg2, _arg3); And here it is this It's the remote server Sub object , Specifically basicTypes The implementation of the method has to go to the server , The client cannot see . Here, the whole process of cross process communication between client and server is explained .
summary
1.asInterface(android.os.IBinder obj)
For server Binder Object is converted to what the client needs AIDL Object of interface type , This conversion process is process specific ( If the client and server are in the same process , Then what this method returns is the... Of the server Stub Object itself , Otherwise, the returned is the system encapsulated Stub.proxy object )
2.onTransact(int code, android.os.Parcel data, android.os.Parcel reply, int flags)
Clients' cross process requests are mainly through remote services binder Object's onTransact Method to complete .
code : Determine the target method of the client request .
data : If the target method has parameters , From data Get the parameters required by the target method .
reply : When the target method is executed , If the target method has a return value , As to the reply Write the return value in .
flag : 0
3.DESCRIPTOR
Binder Unique identification of , Usually use the current AIDL The interface name indicates .
In short, everything is through binder Object to complete , The remote server holds binder Object entities , Local client Proxy Hold the server binder Object reference , And pass Sub.asInterface() Method into a local interface class object .
边栏推荐
- How to empty uploaded attachments with components encapsulated by El upload
- 【对象数组的排序】
- 百度评论中台的设计与探索
- LeetCode 31. Next spread
- OpenGL - Coordinate Systems
- Officially launched! Tdengine plug-in enters the official website of grafana
- 写入速度提升数十倍,TDengine 在拓斯达智能工厂解决方案上的应用
- [ctfhub] Title cookie:hello guest only admin can get flag. (cookie spoofing, authentication, forgery)
- Tongweb set gzip
- 百度交易中台之钱包系统架构浅析
猜你喜欢
Unity SKFramework框架(二十四)、Avatar Controller 第三人称控制
一次 Keepalived 高可用的事故,让我重学了一遍它
一篇文章带你走进cookie,session,Token的世界
LeetCode 31. 下一个排列
移动端异构运算技术-GPU OpenCL编程(进阶篇)
Understand the window query function of tdengine in one article
OpenGL - Lighting
Solve the problem of no all pattern found during Navicat activation and registration
How to implement complex SQL such as distributed database sub query and join?
为什么不建议你用 MongoDB 这类产品替代时序数据库?
随机推荐
TDengine 已经支持工业英特尔 边缘洞见软件包
Kotlin introductory notes (VI) interface and function visibility modifiers
H.265编码原理入门
[NTIRE 2022]Residual Local Feature Network for Efficient Super-Resolution
Unity skframework framework (XXII), runtime console runtime debugging tool
分布式数据库下子查询和 Join 等复杂 SQL 如何实现?
Three-level distribution is becoming more and more popular. How should businesses choose the appropriate three-level distribution system?
From "chemist" to developer, from Oracle to tdengine, two important choices in my life
Solve the problem of no all pattern found during Navicat activation and registration
A detailed explanation of the general process and the latest research trends of map comparative learning (gnn+cl)
How do enterprises choose the appropriate three-level distribution system?
[hungry dynamic table]
Lepton 无损压缩原理及性能分析
Android privacy sandbox developer preview 3: privacy, security and personalized experience
The popularity of B2B2C continues to rise. What are the benefits of enterprises doing multi-user mall system?
SMT32H7系列DMA和DMAMUX的一点理解
C language - input array two-dimensional array a from the keyboard, and put 3 in a × 5. The elements in the third column of the matrix are moved to the left to the 0 column, and the element rows in ea
百度交易中台之钱包系统架构浅析
How to empty uploaded attachments with components encapsulated by El upload
LeetCode 556. Next bigger element III