標籤:通訊 aidl bec vat otv 檔案中 使用 linu linux核心
Android-Binder(一)學習自
《Android開發藝術探索》
https://www.jianshu.com/p/bdef9e3178c9
72765136
Binder漫談
Binder是IBinder介面的一個實作類別,inder是串連系統的各種Manager和其對應的Service的橋樑,Binder主要用於Service中。
Android系統的分層
對Android系統的分層瞭解了之後,我們會對IPC有一個更清晰的認知,所以我們來看一看系統的分層
我們來依次看一下各層的職責:
- Linux Kernel(Linux核心層), 這一層中主要是各種硬體的驅動,Binder IPC的驅動也是在此層的
- HAL(硬體抽象層),對核心層的封裝,為系統服務層提提供可調用的介面,以JNI的方式。
- Android System Service(Android 系統服務層), Android系統的核心服務,為應用程式層提供調用的介面
- Binder IPC Proxys(Binder IPC的代理層),是應用程式層和系統服務層之間的橋樑,實現跨進程通訊
- Application Freamwork(應用程式架構層), 這一程就是我們的SDK,提供我們日常開發所用到的類庫
其中Linux核心層好硬體抽象層,都是以C/C++來實現,硬體抽象層會編譯為so檔案,已JNI的方式提供給系統服務層調用,系統服務層通過Java實現,該層中的服務隨著手機的開機而啟動(不關機就會一直運行),這些服務負責Activity的管理,Window的管理等等。因為系統服務層是通過Java實現的所以,他們肯定是運行與一個獨立的 Dalvik
中。
因為我們程式員自己開發的程式和系統的服務都分別運行在不同的虛擬機器中,之間的通訊就只能靠 IPC技術來完成了,為了方便Coder調用系統服務介面Google提供了一系統服務相對應的Manager。其調用關係如下:
從AIDL開始
AIDL(Android Interface Definition Language) Androd 介面定義語言,通過AIDL可以實現IPC,通過AIDL定義的介面我們可以完成用戶端和服務的跨進程通訊,使用了AIDL的話在編譯的時候系統會自動幫我們產生 Binder
.
建立AIDL相關的檔案
建立需要的實體類 Book 實現Parcelable介面
package top.littledavid.studyipc.beansimport android.os.Parcelimport android.os.Parcelable/** * Created by IT on 7/30/2018. */class Book(val bookId: Int, val bookName: String, val author: String) : Parcelable { constructor(parcel: Parcel) : this( parcel.readInt(), parcel.readString(), parcel.readString()) { } override fun writeToParcel(parcel: Parcel, flags: Int) { parcel.writeInt(bookId) parcel.writeString(bookName) parcel.writeString(author) } override fun describeContents(): Int { return 0 } override fun toString(): String { return "Book(bookId=$bookId, bookName='$bookName', author='$author')" } companion object CREATOR : Parcelable.Creator<Book> { override fun createFromParcel(parcel: Parcel): Book { return Book(parcel) } override fun newArray(size: Int): Array<Book?> { return arrayOfNulls(size) } }}
建立AIDL目錄,隨便輸入一名稱,建立起目錄解構即可,然後把檔案刪掉,我們自家定義我們自己的檔案
建立實體類對應檔 Book.aidl
要在aidl 下與Book 實體類相同的包下才行,否則會報錯,無法通過編譯,實體類的包介面是 top.littledavid.studyipc.beans->beans
所以aidl下的 Book.aidl包也要一樣才行
//實體映射包名一定要和實體定義的包名相同package top.littledavid.studyipc.beans;//定義映射parcelable Book;
定義 IBookManager.aidl
其中定義了IPC操作的方法
// IBookManager.aidlpackage top.littledavid.studyipc;// Declare any non-default types here with import statementsimport top.littledavid.studyipc.beans.Book;interface IBookManager { List<top.littledavid.studyipc.beans.Book> getBookList(); //這是如果不是使用的基礎資料類型,一定要使用方向類型標識 : in ,out ,inout void addBook(in Book book);}
整體目錄解構如下
編譯成功後會在 項目路徑\app\build\generated\source\aidl\debug\top\littledavid\studyipc
(包名可能不同)下產生一個 IBookManager.java
,其中實現了IPC相關的代碼。
建立Service
class BookService : Service() { private lateinit var mBookList: MutableList<Book> override fun onBind(intent: Intent?): IBinder { mBookList = mutableListOf() Log.e("TAG", "OnBind") return mIBinder } //實現AIDL定義的介面 private val mIBinder = object : IBookManager.Stub() { override fun getBookList(): List<Book> { return [email protected]() } override fun addBook(book: Book) { [email protected](book) } }}
在Minefast檔案中佈建服務
<service android:name=".BookService" android:enabled="true" android:exported="true" android:process=":remote" />
進行IPC
在Activity中進行IPC
class MainActivity : AppCompatActivity() { private var mIBookManager: IBookManager? = null private val mConn = object : ServiceConnection { override fun onServiceDisconnected(name: ComponentName?) { mIBookManager = null } override fun onServiceConnected(name: ComponentName?, service: IBinder?) { //將IBinder轉換為AIDL介面 mIBookManager = IBookManager.Stub.asInterface(service) } } override fun onCreate(savedInstanceState: Bundle?) { super.onCreate(savedInstanceState) setContentView(R.layout.activity_main) //開啟服務 val serviceBindIntent = android.content.Intent(this, BookService::class.java) this.bindService(serviceBindIntent, mConn, Context.BIND_AUTO_CREATE) } //添加書籍資訊 fun addBook(view: View) { val book = Book(1, "Android開發藝術探索", "任玉剛老師") this.mIBookManager!!.addBook(book) loadBookInfo() } private fun loadBookInfo() { val bookList = mIBookManager!!.bookList val stringBuilder = StringBuilder() bookList.forEach { stringBuilder.append(it.toString() + "\r\n") } this.bookInfoTV.text = stringBuilder.toString() } override fun onDestroy() { super.onDestroy() this.unbindService(mConn) }}
總結
磕磕絆絆的總算完成了AIDL的IPC,非常感謝參考文檔中國的博主的無私奉獻。下一章我們來看一看Binder的原理。
Android-Binder(一)