English | 简体中文 | 繁體中文 | Русский язык | Français | Español | Português | Deutsch | 日本語 | 한국어 | Italiano | بالعربية
Preface
In the previous section, we sorted out the communication between threads in Android <What is the relationship between Thread, Handler, and HandlerThread> , these are all within the same process. So how to achieve inter-process communication, or communication between different applications? At this point, you need to use AIDL (Android Interface Definition Language, Android interface definition language).
Usage (AndroidStudio)
I find that most of the AIDL tutorials are still based on Eclipse, but there are still some differences when using AIDL in AndroidStudio. Let's take a look at how to use it. First, create a new project as the server:
After creating it, right-click on any folder and select New-->AIDL-->AIDL File, after editing the filename, it will be automatically generated in src/Create a new aidl folder under the main directory of src, and the package directory structure is as follows:
main
aidl
com.example.tee.testapplication.aidl
java
com.example.tee.testapplication
res
AndroidManifest.xml
The automatically generated aidl file is as follows:
// AidlInterface.aidl package com.example.tee.testapplication.aidl; // Declare any non-default types here with import statements interface AidlInterface { /** * 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); }
We can see that the code format of the aidl file is very similar to Java, supporting Java's basic types as well as List, Map, etc. If it is a custom class, it needs to be manually imported; we will talk about it later. Let's start with the simplest: create a new IMyAidlInterface.aidl file and modify it as follows:
package com.example.tee.testapplication.aidl; interface IMyAidlInterface { String getValue(); }
Define a getValue method in the interface that returns a string. Now you can compile the project and find the app/build/generated/source/aidl/In the debug directory, under our application package name, you will find a generated Interface class with the same name as the aidl file we defined. This indicates that the aidl file will eventually be converted into an interface to implement it, and this file does not require our maintenance; it is automatically generated after compilation.
Then create a new class that inherits from Service:
public class MAIDLService extends Service{ public class MAIDLServiceImpl extends IMyAidlInterface.Stub{ @Override public String getValue() throws RemoteException { return "get value"; } } @Nullable @Override public IBinder onBind(Intent intent) { return new MAIDLServiceImpl(); } }
In the MAIDLService class, define an inner class that inherits from IMyAidlInterface.Stub and overrides the getValue method that we defined in aidl, which is in the interface, returning the string 'get value'.
Here, we have successfully created this service, which is used to return a string after the call, and finally declare it in the AndroidManifest file:
<service android:name=".MAIDLService" android:process=":remote"//If this line is added, the client call will create a new process android:exported="true"//It is set to true by default and can be omitted, indicating whether remote invocation is allowed > <intent-filter> <category android:name="android.intent.category.DEFAULT"> /> <action android:name="com.example.tee.testapplication.aidl.IMyAidlInterface"> /> </intent-filter> </service>
The line android:process=":remote" indicates whether a new process is created when called. Next, write the client code, create a new project, copy the just created aidl file to this project, note that it should also be placed in the aidl folder, and then write the following code in MainActivity:
public class MainActivity extends AppCompatActivity { private TextView mValueTV; private IMyAidlInterface mAidlInterface = null; private ServiceConnection mServiceConnection = new ServiceConnection() { @Override public void onServiceConnected(ComponentName name, IBinder service) { mAidlInterface = IMyAidlInterface.Stub.asInterface(service); } @Override public void onServiceDisconnected(ComponentName name) { } }; @Override protected void onCreate(Bundle savedInstanceState) { Intent intent = new Intent("com.example.tee.testapplication.aidl.IMyAidlInterface"); bindService(intent, mServiceConnection, BIND_AUTO_CREATE); mValueTV = (TextView) findViewById(R.id.tv_test_value); mValueTV.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View v) { try { mValueTV.setText(mAidlInterface.getValue()); } catch (RemoteException e) { e.printStackTrace(); } } }); } @Override protected void onDestroy() { if(mAidlInterface != null){ unbindService(mServiceConnection); } super.onDestroy(); } }
Note that the parameter string passed to the newly created Intent is a custom action tag in the manifest, and remember to unbind the service in onDestroy.
The execution result is that when we click on the TextView, it will display the 'get value' string returned by the server.
Custom object
We used the basic type String just now, and it is not feasible to use the above method when using ourself-defined classes. We need to manually import our custom class and modify the project created just now as the server-side project.
Firstly, create a new Student.java file under the aidl package generated at the beginning (all aidl-related files should be placed in this package).
public class Student implements Parcelable{ public String name; public int age; protected Student(Parcel in) { readFromParcel(in); } public Student() { } public static final Creator<Student> CREATOR = new Creator<Student>() { @Override public Student createFromParcel(Parcel in) { return new Student(in); } @Override public Student[] newArray(int size) { return new Student[size]; } }; @Override public int describeContents() { return 0; } @Override public void writeToParcel(Parcel dest, int flags) { dest.writeInt(age); dest.writeString(name); } public void readFromParcel(Parcel in){ age = in.readInt(); name = in.readString(); } @Override public String toString() { return String.format(Locale.ENGLISH, "STUDENT[%s:%d]", name, age); } }
Implement the Parcelable serialization interface, AndroidStudio will automatically generate the static inner class CREATOR and describeContents method, these parts we do not need to modify, just use the automatically generated ones. Then overwrite the writeToParcel method, and define the readFromParcel method, note that the property order in these two methods must be consistent, one is for writing, and the other is for reading. Call the readFromParcel(in) method in the constructor Student(Parcel in).
Next, create a new Student.aidl file (also in the aidl package):
// Student.aidl package com.example.tee.testapplication.aidl; // Declare any non-default types here with import statements parcelable Student;
Note that the keyword parcelable before Student is lowercase, and modify the IMyAidlInterface.aidl file as follows:
// IMyAidlInterface.aidl package com.example.tee.testapplication.aidl; // Declare any non-default types here with import statements import com.example.tee.testapplication.aidl.Student; interface IMyAidlInterface { Student getStudent(); void setStudent(in Student student); String getValue(); }
Defined two methods, one is to set Student, and the other is to get Student, pay attention to the in keyword before the parameter type in the setStudent method, in AIDL, parameters are divided into in input and out output
Now, in MAIDLService.java, override the two newly added methods:
private Student mStudent; public class MAIDLServiceImpl extends IMyAidlInterface.Stub{ @Override public Student getStudent() throws RemoteException { return mStudent; } @Override public void setStudent(Student student) throws RemoteException { mStudent = student; } @Override public String getValue() throws RemoteException { return "get value : " + Thread.currentThread().getName(); + Thread.currentThread().getId(); } }
After modifying the server-side code, come to the client project and copy over the file from the aidl package just now, keeping both sides consistent, and then modify the following in MainActivity.java:
mValueTV = (TextView) findViewById(R.id.tv_test_value); mStudentTV = (TextView) findViewById(R.id.tv_test_student); mValueTV.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View v) { try { mValueTV.setText(mAidlInterface.getValue()); } catch (RemoteException e) { e.printStackTrace(); } } }); mStudentTV.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View v) { try { Student student = new Student(); student.age = 10; student.name = "Tom"; mAidlInterface.setStudent(student); mStudentTV.setText(mAidlInterface.getStudent().toString()); } catch (RemoteException e) { e.printStackTrace(); } } });
Now, when compiling the project, you will find that the project will report an error, cannot find the class Student. We need to add the following code to the build.gradle file under the app directory:
android { sourceSets { main { manifest.srcFile 'src/main/AndroidManifest.xml' java.srcDirs = ['src/main/java/main/aidl resources.srcDirs = ['src/main/java/main/aidl aidl.srcDirs = ['src/main/aidl res.srcDirs = ['src/main/res assets.srcDirs = ['src/main/assets } } }
That is, specify the file directory, and there will be no problem when compiling again
Summary
The use of Android's IPC is quite simple, and the syntax of the AIDL file is very similar to the interface we use in our daily lives, but it only supports basic types, can only refer to AIDL files, and it is a bit麻烦 when using custom classes.
This is the summary of the materials on Android IPC process communication. We will continue to supplement relevant materials, and thank everyone for their support of this site!
Declaration: The content of this article is from the network, and the copyright belongs to the original author. The content is contributed and uploaded by Internet users spontaneously. This website does not own the copyright, has not been manually edited, and does not assume any relevant legal responsibility. If you find any content suspected of copyright infringement, please send an email to: notice#oldtoolbag.com (Please replace # with @ when sending an email for reporting violations, and provide relevant evidence. Once verified, this site will immediately delete the infringing content.)