当前位置:网站首页>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 .
边栏推荐
- Tongweb set gzip
- Why don't you recommend using products like mongodb to replace time series databases?
- TDengine 连接器上线 Google Data Studio 应用商店
- Develop and implement movie recommendation applet based on wechat cloud
- Figure neural network + comparative learning, where to go next?
- 测试老鸟浅谈unittest和pytest的区别
- Tdengine can read and write through dataX, a data synchronization tool
- C语言-从键盘输入数组二维数组a,将a中3×5矩阵中第3列的元素左移到第0列,第3列以后的每列元素行依次左移,原来左边的各列依次绕到右边
- Vs code problem: the length of long lines can be configured through "editor.maxtokenizationlinelength"
- 为什么不建议你用 MongoDB 这类产品替代时序数据库?
猜你喜欢

百度评论中台的设计与探索
![[sourcetree configure SSH and use]](/img/9a/1cd4ca29e5b7a3016ed6d5dc1abbef.png)
[sourcetree configure SSH and use]

From "chemist" to developer, from Oracle to tdengine, two important choices in my life

LeetCode 503. 下一个更大元素 II

SQL learning - case when then else

TDengine 连接器上线 Google Data Studio 应用商店

How to correctly evaluate video image quality

Tdengine connector goes online Google Data Studio app store

Officially launched! Tdengine plug-in enters the official website of grafana

OpenGL - Lighting
随机推荐
About getfragmentmanager () and getchildfragmentmanager ()
OpenGL - Coordinate Systems
【两个对象合并成一个对象】
Unity SKFramework框架(二十三)、MiniMap 小地图工具
oracle 多行数据合并成一行数据
Unity SKFramework框架(二十二)、Runtime Console 运行时调试工具
OpenGL - Model Loading
Kotlin introductory notes (VII) data class and singleton class
90%的人都不懂的泛型,泛型的缺陷和应用场景
LeetCode 503. Next bigger Element II
How to choose the right chain management software?
[JS sort according to the attributes in the object array]
Unity skframework framework (XXIII), minimap small map tool
【技术直播】如何用 VSCode 从 0 到 1 改写 TDengine 代码
一次 Keepalived 高可用的事故,让我重学了一遍它
Android privacy sandbox developer preview 3: privacy, security and personalized experience
Analysis on the wallet system architecture of Baidu trading platform
LeetCode 31. 下一个排列
阿里十年测试带你走进APP测试的世界
MySQL does not take effect in sorting string types