在「Android Studio」中,導入自定義「Framework」的「Jar」包

Android:AOSP

RICK
Oct 7, 2020

概要

在開發「系統級」的應用程式時,開發者常會遇到需要使用「系統級別接口」或是「供應商客制接口」的情況。

像是「BluetoothDevice」的「removeBond()」就是「SystemApi」,如下:

事實上,這類屬於「@hide」的欄位或方法是不允許亦不建議一般開發者去使用的,因此在「Android Studio」中,我們是無法直接地呼叫,如下:

而「供應商客制接口」也是類似的情況,因為其不屬於「Google」所制定的標準接口,因此亦不存在於預設的「SDK」套件中。

針對該問題,常見的解決方式是透過反射機制,但「反射」解決存在著幾個嚴重的問題,如效能差、可讀性差,以及安全性的問題,像是內部暴露等;事實上,Google 強烈不建議我們使用這樣的方式,如下

但若為系統廠,我們有去串接其系統級別接口的必要性,因此,我們可以藉由導入系統「Framework」的方式來使用該類接口。

正文

取得系統的「framework.jar」

如果我們要取得「framework.jar」,我們就必須將「AOSP」項目編譯,其檔案路徑如下:

/out/target/common/obj/JAVA_LIBRARIES/framework_intermediates/classes.jar

複製一份「classes.jar」,將之更名為「framework.jar」並放到「Android App」的專案目錄下的「libs」資料夾中,如下:

設定「Project」級別的「build.gradle」

接著,我們必須在項目級別的「Gradle」文件中,「all projects」的項目底下,加入「framework.jar」的引用語法,如下:

代碼如下:

備註:「-Xbootclasspath/p」是一個跟「Jar」包引用相關的參數。

設定「Module」級別的「build.gradle」

接著,我們必在「Module」級別,也就是「App」級別的「Gradle」文件中的「dependencies」下加入依賴設定,如下:

代碼如下:

compileOnly files('libs/framework.jar')

備註:由於該類方法已經存在於系統「SDK」 中,「@hide」標籤的作用僅是為了不讓開發者呼叫而已,與執行時期無關,也就是說,我們僅在「編譯時」需要該「Jar」包的參與,因此,我們僅使用「compileOnly」。

而其它的第三方庫,如「Gson」、「OkHttp」等,由於它們本身並不存在於系統 「SDK」,因此我們必須藉由「implementation」將其打包進去,至此,我們已經完成「framework.jar」的引用。

但是,此時執行編譯依然會出錯,如下:

這是「Android」的一項限制,當方法數超過「65535」就會使得「APK」夠建失敗,而在此處,是因為預設的「dependencies」設定會將「libs」導入,因此,我們將它移除,如下:

修正「編譯器的錯誤提示」

雖然可以正常產出「APK」了,但是編譯器的錯誤提示仍會報錯,如下:

這是因為編譯器還是使用預設的「SDK」作為依據,因此我們要去修改編譯器的設定檔,在「Project Files」的模式下,找到「app.iml」,如下:

找到關於「jdk」的設定,如下:

將其移動到最後一行,如下:

按下「Ctrl」+「S」,儲存後,就搞定了,如下:

備註:「app.iml」會因為「Gradle Sync」或「Invalidate Caches」等原因而重置,此時重新設定「app.iml」即可。

--

--

RICK

當遇到重開機無法解決的 BUG 時,那就試試關機吧。