当前位置:网站首页>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 .
边栏推荐
- [ctfhub] Title cookie:hello guest only admin can get flag. (cookie spoofing, authentication, forgery)
- Charm of code language
- Unity SKFramework框架(二十二)、Runtime Console 运行时调试工具
- Viewpager pageradapter notifydatasetchanged invalid problem
- Project practice | excel export function
- An article takes you into the world of cookies, sessions, and tokens
- 基于宽表的数据建模应用
- oracle 多行数据合并成一行数据
- Resolve the horizontal (vertical) sliding conflict between viewpager and WebView
- MySQL installation configuration and creation of databases and tables
猜你喜欢

The writing speed is increased by dozens of times, and the application of tdengine in tostar intelligent factory solution

百度APP 基于Pipeline as Code的持续集成实践

idea用debug调试出现com.intellij.rt.debugger.agent.CaptureAgent,导致无法进行调试

Online chain offline integrated chain store e-commerce solution

E-commerce apps are becoming more and more popular. What are the advantages of being an app?

Community group buying has triggered heated discussion. How does this model work?

Kotlin introductory notes (VIII) collection and traversal

Nips2021 | new SOTA for node classification beyond graphcl, gnn+ comparative learning

一次 Keepalived 高可用的事故,让我重学了一遍它

Principle and performance analysis of lepton lossless compression
随机推荐
MYSQL 对字符串类型排序不生效问题
Project practice | excel export function
About getfragmentmanager () and getchildfragmentmanager ()
使用el-upload封装得组件怎么清空已上传附件
Android privacy sandbox developer preview 3: privacy, security and personalized experience
【对象数组a与对象数组b取出id不同元素赋值给新的数组】
Oracle combines multiple rows of data into one row of data
22-07-04 Xi'an Shanghao housing project experience summary (01)
What are the advantages of the live teaching system to improve learning quickly?
Unity skframework framework (24), avatar controller third person control
[sourcetree configure SSH and use]
【js 根据对象数组中的属性进行排序】
Viewpager pageradapter notifydatasetchanged invalid problem
Gradientdrawable get a single color
Solve the problem of no all pattern found during Navicat activation and registration
分布式数据库下子查询和 Join 等复杂 SQL 如何实现?
Unity SKFramework框架(二十四)、Avatar Controller 第三人称控制
What should we pay attention to when entering the community e-commerce business?
Analysis on the wallet system architecture of Baidu trading platform
LeetCode 556. Next bigger element III