当前位置:网站首页>Aidl basic use
Aidl basic use
2022-07-01 21:46:00 【Liu Yichu】
One 、 Approximate process
1. Server creation .aidl file
2. Defining interfaces
3.build Generate corresponding java file
4. Expose the interface to the client ( Write a service, rewrite onBind(), return Stub The realization of the class )
5. Copy aidl Documents and corresponding bean class ( If any ) To client
6. client binderService Get binder Instance calls server method .
Example :
1. The service side in src/main Create aidl file IPersonManager.aidl
// IPersonManager.aidl
package com.lmy.androidutilcode;
import com.lmy.androidutilcode.bean.Person;
interface IPersonManager {
List<Person> getPersonList();
boolean addPerson(inout Person person);
}
2. Define the object to be transferred Person
class Person(var name: String? = "") : Parcelable {
constructor(parcel: Parcel) : this(parcel.readString())
override fun toString(): String {
return "Person(name=$name) hashcode = ${hashCode()}"
}
override fun writeToParcel(parcel: Parcel, flags: Int) {
parcel.writeString(name)
}
fun readFromParcel(parcel: Parcel) {
this.name = parcel.readString()
}
override fun describeContents(): Int {
return 0
}
companion object CREATOR : Parcelable.Creator<Person> {
override fun createFromParcel(parcel: Parcel): Person {
return Person(parcel)
}
override fun newArray(size: Int): Array<Person?> {
return arrayOfNulls(size)
}
}
3. Then you have to aidl Of Same directory I also need to declare this Person object . Create a new one Person.aidl
package com.xfhy.allinone.ipc.aidl;
parcelable Person;
Pictured :
4.rebuild once ,AS The following code will be generated automatically IPersonManager.java.
Be careful :aidl It is better not to use Chinese Notes in the document
5. The server exposes the interface like the client
Define a Service, And then take it. process Set up a new process , Separate from the main process ( Or like I use here 2 individual module, namely 2 individual application). Simulate cross process access , It needs to realize .aidl Generated interfaces
class RemoteService : Service() {
private val mPersonList = mutableListOf<Person?>()
private val mBinder: Binder = object : IPersonManager.Stub() {
override fun getPersonList(): MutableList<Person?> = mPersonList
override fun addPerson(person: Person?): Boolean {
return mPersonList.add(person)
}
}
override fun onBind(intent: Intent?): IBinder? {
return mBinder
}
override fun onCreate() {
super.onCreate()
mPersonList.add(Person("Garen"))
mPersonList.add(Person("Darius"))
}
}
Realized IPersonManager.Stub It's a Binder, Need to pass through onBind() return , The client needs to pass this Binder To call... Across processes Service The service here .
6. Copy aidl Documents and corresponding bean Object to client
Be careful : The directory structure should be exactly the same
7. Client calls
class AidlActivity : TitleBarActivity() {
companion object {
const val TAG = "lmy"
}
private var remoteServer: IPersonManager? = null
private val serviceConnection = object : ServiceConnection {
override fun onServiceConnected(name: ComponentName?, service: IBinder?) {
log(TAG, "onServiceConnected")
// stay onServiceConnected call IPersonManager.Stub.asInterface Get an instance of the interface type
// Call the service of the server through this instance
remoteServer = IPersonManager.Stub.asInterface(service)
}
override fun onServiceDisconnected(name: ComponentName?) {
log(TAG, "onServiceDisconnected")
}
}
override fun getThisTitle(): CharSequence {
return "AIDL"
}
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_aidl)
btnConnect.setOnClickListener {
connectService()
}
btnGetPerson.setOnClickListener {
getPerson()
}
btnAddPerson.setOnClickListener {
addPerson()
}
}
private fun connectService() {
val intent = Intent()
//action and package(app The package name )
intent.action = " You can give it to the server service Define a action"
intent.setPackage(" Server package name ")
val bindServiceResult = bindService(intent, serviceConnection, Context.BIND_AUTO_CREATE)
}
private fun addPerson() {
// When the client calls the server method , You need to catch the following exceptions :
//RemoteException abnormal :
//DeadObjectException abnormal : An exception will be thrown when the connection is interrupted ;
//SecurityException abnormal : Defined in client and server AIDL An exception is thrown when a conflict occurs ;
try {
val addPersonResult = remoteServer?.addPerson(Person(" galen "))
log(TAG, "addPerson result = $addPersonResult")
} catch (e: RemoteException) {
e.printStackTrace()
} catch (e: DeadObjectException) {
e.printStackTrace()
} catch (e: SecurityException) {
e.printStackTrace()
}
}
private fun getPerson() {
val personList = remoteServer?.personList
log(TAG, "person list $personList")
}
override fun onDestroy() {
super.onDestroy()
// Finally remember unbindService
unbindService(serviceConnection)
}
}
Be careful :
If targetSdk yes 30, Then it needs to be dealt with Android 11 Package visibility in Specific see : https://developer.android.com/about/versions/11/privacy/package-visibility
Two 、in,out,inout keyword
Define... Above AIDL At the interface , I used a keyword in, The key is actually orientation tag, It is used to point out the way of data flow . also 2 individual tag yes out and inout, All non basic parameters need an orientation tag To point out the flow of data , Orientation of basic parameters tag Default and can only be in.
in The method is to transfer data from the client to the server ,out No way.
out The method is to transfer data from the server to the client ,in No way.
No matter whether the server has modified the object data passed in the past , The object reference of the client will not change , What changes is only the data of the client , be perfectly logical and reasonable , Cross process is the way to serialize and deserialize data .
3、 ... and 、oneway keyword
take aidl Add... Before the method of the interface oneway Keyword, this method is called asynchronously , Does not block the calling thread , When the client side calls the method of the server side , If you don't need to know the return result , At this time, using asynchronous call can improve the execution efficiency of the client .
verification : I will aidl Interface methods are defined as oneway Of , On the server AIDL Method implementation Thread.sleep(2000) Block the method call , Then the client calls this method , Check the time before and after the method call
private fun addPersonOneway() {
log(TAG, “oneway Starting time : ${System.currentTimeMillis()}”)
remoteServer?.addPersonOneway(Person(“oneway”))
log(TAG, “oneway End time : ${System.currentTimeMillis()}”)
}
// Log output
//oneway Starting time : 1608858291371
//oneway End time : 1608858291372
You can see , When the client calls this method, it is true that it is not blocked .
Four 、 Thread safety
AIDL The method is on the server side Binder Executed in thread pool , Therefore, when multiple clients connect and operate data at the same time, multiple threads may access at the same time . In this case , We need to be on the server side AIDL Method to deal with multi-threaded synchronization .
边栏推荐
猜你喜欢
随机推荐
JS how to get a list of elements in a collection object
pytest合集(2)— pytest運行方式
Using closures to switch toggle by clicking a button
个人炒股怎样开户?安全吗。
Fundamentals - IO intensive computing and CPU intensive computing
图片拼图微信小程序源码_支持多模板制作和流量主
[NOIP2013]积木大赛 [NOIP2018]道路铺设 贪心/差分
选择在同花顺上炒股开户可以吗?安全吗?
Spark面试题
分离字符串中的字母和数字并使得字母在前数组在后
【直播回顾】战码先锋首期8节直播完美落幕,下期敬请期待!
PCB plug hole technology~
EMC-电路保护器件-防浪涌及冲击电流用
UVM教程
PCB线路板塞孔工艺的那些事儿~
测试撤销1
旁路由设置的正确方式
从MLPerf谈起:如何引领AI加速器的下一波浪潮
latex如何打空格
最近公共祖先离线做法(tarjan)