高版本 Android Studio 集成 framework.jar

banner.jpg

前言

最近工作需要在項目中集成系統(tǒng)的 framework.jar,以此來調(diào)用系統(tǒng)的定制功能,但是按照之前方案配置之后發(fā)現(xiàn)無法調(diào)用 framework.jar 中的方法,默認使用的還是 Android SDK 里面的方法。

經(jīng)過一系列的排查之后終于找到解決方案,做此分享。

集成 framework.jar 方案

導入 framework.jar

首先將 framework.jar 導入項目中,以一個簡單 Demo 項目舉例,項目中有一個 app 模塊,項目結(jié)構(gòu)如下(只列出了關(guān)鍵文件)

# 項目結(jié)構(gòu)
Demo
  |---- .idea
  |      |---- modules
  |      |      |---- app
  |      |      |      |---- Demo.app.main.iml
  |---- app
  |      |---- libs
  |      |---- src
  |      |---- build.gradle.kts
  |---- build.gradle.kts
  |---- settings.gradle.kts
  1. framework.jar 文件復制到 Demo/app/libs 路徑下;
  2. Demo/app/build.gradle.kts 文件中添加依賴:
dependencies {
    ...
    // 添加 framework.jar,僅編譯
    compileOnly(files("libs/framework.jar"))
}

配置依賴優(yōu)先級

僅僅在項目中導入 framework.jar 是沒有效果的,你會發(fā)現(xiàn)之前被標記為 @hide 的接口現(xiàn)在還是不能使用,導入的 framework.jar 中的定制方法還是不能調(diào)用,與之前不同的是此時你可以調(diào)用 framework.jar 中系統(tǒng)原生不存在的類,這樣的效果當然不能讓我們滿意。

這是由于默認情況下,Android SDK 中的資源優(yōu)先級是高于手動導入的資源的,因此我們需要手動修改這個優(yōu)先級,這部分定義在項目根目錄下 .idea/modules/app/xxxx.iml 中,所以接下來需要在對應模塊的 build.gradle.kts 中添加配置。

Demo 項目中,我們要在 Demo/app/build.gradle.kts 中修改:

import groovy.namespace.QName
import groovy.util.Node
import groovy.xml.XmlParser
import groovy.xml.XmlUtil
import java.io.FileOutputStream
...
project.tasks.preBuild.get().doLast {
    // 在 preBuild 任務執(zhí)行完之后處理
    // 定義修改 .iml 文件中 Android SDK 優(yōu)先級方法
    fun changeSdkOrder(path: String) {
        runCatching {
            val imlFile = File(path)
            with(XmlParser().parse(imlFile)) {
                // 從 .iml 文件中讀取 NewModuleRootManager 節(jié)點
                val rootManagerComponent = getAt(QName.valueOf("component"))
                    .map { it as Node }
                    .first { it.attribute("name") == "NewModuleRootManager" }
                // 從 NewModuleRootManager 節(jié)點中獲取 Android SDK 配置節(jié)點
                val jdkEntry = rootManagerComponent.getAt(QName.valueOf("orderEntry"))
                    .map { it as Node }
                    .first { it.attribute("type") == "jdk" }
                // 保存節(jié)點參數(shù)
                val jdkName = jdkEntry.attribute("jdkName")
                val jdkType = jdkEntry.attribute("jdkType")
                println("> Task :${project.name}:preBuild:doLast:changedSdkOrder jdkEntry = $jdkEntry")
                // 從 NewModuleRootManager 節(jié)點中移除 Android SDK 配置節(jié)點
                rootManagerComponent.remove(jdkEntry)
                // 重新將 Android SDK 配置節(jié)點添加到 NewModuleRootManager 的最后
                rootManagerComponent.appendNode(
                    "orderEntry", mapOf(
                        "type" to "jdk",
                        "jdkName" to jdkName,
                        "jdkType" to jdkType
                    )
                )
                // 將新生成的 .iml 寫入文件
                XmlUtil.serialize(this, FileOutputStream(imlFile))
            }
        }
    }
    
    // 修改 .iml 文件
    println("> Task :${project.name}:preBuild:doLast:changedSdkOrder")
    changeSdkOrder(rootDir.absolutePath + "/.idea/modules/app/Demo.app.main.iml")
}

方法 changeSdkOrder 的參數(shù)為模塊對應的 .iml 配置文件路徑,可按照自己的項目配置,按需修改。

如此一來,在項目中就可以盡情的使用 framework.jar 中的方法了。

配置引導類路徑

經(jīng)歷了上面兩個步驟的配置,在開發(fā)過程中已經(jīng)可以正常使用 framework.jar 中的內(nèi)容的,在本地 Android Studio 中也能正常編譯運行,但是如果你們公司配置在服務器編譯構(gòu)建就還是會報錯,那就需要在項目根目錄的 build.gradle.kts 中添加相關(guān)配置。

Demo 項目中,我們要在 Demo/build.gradle.kts 中修改:

...
allprojects {
    beforeEvaluate {
        // framework.jar 路徑
        val path = rootDir.absolutePath + "/app/libs/framework.jar"
        tasks.withType<JavaCompile> {
            // 低版本 gradle 的方案
            options.compilerArgs.add("-Xbootclasspath/p:$path")
            // 高版本 gradle 的方案
            val newFileList = mutableListOf<File>()
            newFileList.add(File(path))
            options.bootstrapClasspath?.files?.let { oldFileList ->
                newFileList.addAll(oldFileList)
            }
            options.bootstrapClasspath = files(*newFileList.toTypedArray())
        }
    }
}

通過上面的配置,我們將 framework.jar 添加到引導類路徑中,無論是在本地還是在服務器構(gòu)建,就都不會出現(xiàn)問題了。

高版本 Android Studio 適配

講了這么多,終于到了我們這篇文章的重點,就是高版本 Android Stuido (這里特指 3.6.3之后的版本)的適配。

作者這邊使用的 Android Studio 版本是 Iguana,按照上面的步驟配置完之后發(fā)現(xiàn)并沒有起作用,具體現(xiàn)象就是導入的 framework.jar 中的定制方法不能調(diào)用,只可以調(diào)用 framework.jar 中系統(tǒng)原生不存在的類,那不就是 依賴優(yōu)先級 的配置失效了嗎,打開 Demo/.idea/modules/app/Demo.app.main.iml 文件,發(fā)現(xiàn)里面只剩簡單的幾行配置,依賴優(yōu)先級 相關(guān)的幾個節(jié)點都沒有了,那該怎么配置?

經(jīng)過多次 Google百度Bing 無果,能找到的都是已知的配置,最終找到了 Android Studio 中的一個配置項,路徑在 File -> Settings -> Build, Execution, Deployment -> Build Tools -> Gradle 中,有一個 Generate *.iml files for modules imported from Gradle,把這個選項勾選上,restart Android Studio.iml 文件中的配置就恢復了。

經(jīng)過多個版本的多次嘗試,最終發(fā)現(xiàn):在 Android Studio 3.6.3 版本及以前,Generate *.iml files for modules imported from Gradle 選項默認是勾選上的,而在 3.6.3 之后的版本,該選項默認是沒有勾選的。經(jīng)歷了九九八十一難,終于解決了這個奇葩的問題,感謝各位的觀看!

文章作者: WangJie0822

文章鏈接: http://www.wangjie0822.top/posts/d0b7d4e2

版權(quán)聲明: 本博客所有文章除特別聲明外,均采用 CC BY-NC-SA 4.0 許可協(xié)議。轉(zhuǎn)載請注明來自 WangJie0822

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點,簡書系信息發(fā)布平臺,僅提供信息存儲服務。
  • 序言:七十年代末,一起剝皮案震驚了整個濱河市,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌,老刑警劉巖,帶你破解...
    沈念sama閱讀 228,702評論 6 534
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場離奇詭異,居然都是意外死亡,警方通過查閱死者的電腦和手機,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 98,615評論 3 419
  • 文/潘曉璐 我一進店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人,你說我怎么就攤上這事。” “怎么了?”我有些...
    開封第一講書人閱讀 176,606評論 0 376
  • 文/不壞的土叔 我叫張陵,是天一觀的道長。 經(jīng)常有香客問我,道長,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 63,044評論 1 314
  • 正文 為了忘掉前任,我火速辦了婚禮,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘。我一直安慰自己,他們只是感情好,可當我...
    茶點故事閱讀 71,826評論 6 410
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著,像睡著了一般。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上,一...
    開封第一講書人閱讀 55,227評論 1 324
  • 那天,我揣著相機與錄音,去河邊找鬼。 笑死,一個胖子當著我的面吹牛,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播,決...
    沈念sama閱讀 43,307評論 3 442
  • 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場噩夢啊……” “哼!你這毒婦竟也來了?” 一聲冷哼從身側(cè)響起,我...
    開封第一講書人閱讀 42,447評論 0 289
  • 序言:老撾萬榮一對情侶失蹤,失蹤者是張志新(化名)和其女友劉穎,沒想到半個月后,有當?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 48,992評論 1 335
  • 正文 獨居荒郊野嶺守林人離奇死亡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 40,807評論 3 355
  • 正文 我和宋清朗相戀三年,在試婚紗的時候發(fā)現(xiàn)自己被綠了。 大學時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點故事閱讀 43,001評論 1 370
  • 序言:一個原本活蹦亂跳的男人離奇死亡,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情,我是刑警寧澤,帶...
    沈念sama閱讀 38,550評論 5 361
  • 正文 年R本政府宣布,位于F島的核電站,受9級特大地震影響,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點故事閱讀 44,243評論 3 347
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧,春花似錦、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 34,667評論 0 26
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 35,930評論 1 287
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留,地道東北人。 一個月前我還...
    沈念sama閱讀 51,709評論 3 393
  • 正文 我出身青樓,卻偏偏與公主長得像,于是被迫代替她去往敵國和親。 傳聞我的和親對象是個殘疾皇子,可洞房花燭夜當晚...
    茶點故事閱讀 47,996評論 2 374

推薦閱讀更多精彩內(nèi)容