高版本 Android Studio 集成 framework.jar

banner.jpg

前言

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

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

集成 framework.jar 方案

導(dǎo)入 framework.jar

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

# 項(xiàng)目結(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 文件復(fù)制到 Demo/app/libs 路徑下怕品;
  2. Demo/app/build.gradle.kts 文件中添加依賴:
dependencies {
    ...
    // 添加 framework.jar,僅編譯
    compileOnly(files("libs/framework.jar"))
}

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

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

這是由于默認(rèn)情況下,Android SDK 中的資源優(yōu)先級(jí)是高于手動(dòng)導(dǎo)入的資源的骑素,因此我們需要手動(dòng)修改這個(gè)優(yōu)先級(jí)炫乓,這部分定義在項(xiàng)目根目錄下 .idea/modules/app/xxxx.iml 中,所以接下來需要在對(duì)應(yīng)模塊的 build.gradle.kts 中添加配置献丑。

Demo 項(xiàng)目中末捣,我們要在 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 任務(wù)執(zhí)行完之后處理
    // 定義修改 .iml 文件中 Android SDK 優(yōu)先級(jí)方法
    fun changeSdkOrder(path: String) {
        runCatching {
            val imlFile = File(path)
            with(XmlParser().parse(imlFile)) {
                // 從 .iml 文件中讀取 NewModuleRootManager 節(jié)點(diǎn)
                val rootManagerComponent = getAt(QName.valueOf("component"))
                    .map { it as Node }
                    .first { it.attribute("name") == "NewModuleRootManager" }
                // 從 NewModuleRootManager 節(jié)點(diǎn)中獲取 Android SDK 配置節(jié)點(diǎn)
                val jdkEntry = rootManagerComponent.getAt(QName.valueOf("orderEntry"))
                    .map { it as Node }
                    .first { it.attribute("type") == "jdk" }
                // 保存節(jié)點(diǎn)參數(shù)
                val jdkName = jdkEntry.attribute("jdkName")
                val jdkType = jdkEntry.attribute("jdkType")
                println("> Task :${project.name}:preBuild:doLast:changedSdkOrder jdkEntry = $jdkEntry")
                // 從 NewModuleRootManager 節(jié)點(diǎn)中移除 Android SDK 配置節(jié)點(diǎn)
                rootManagerComponent.remove(jdkEntry)
                // 重新將 Android SDK 配置節(jié)點(diǎn)添加到 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ù)為模塊對(duì)應(yīng)的 .iml 配置文件路徑,可按照自己的項(xiàng)目配置创橄,按需修改箩做。

如此一來,在項(xiàng)目中就可以盡情的使用 framework.jar 中的方法了妥畏。

配置引導(dǎo)類路徑

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

Demo 項(xiàng)目中,我們要在 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 添加到引導(dǎo)類路徑中薪韩,無論是在本地還是在服務(wù)器構(gòu)建,就都不會(huì)出現(xiàn)問題了捌锭。

高版本 Android Studio 適配

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

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

經(jīng)過多次 Google讹躯、百度Bing 無果缠劝,能找到的都是已知的配置潮梯,最終找到了 Android Studio 中的一個(gè)配置項(xiàng),路徑在 File -> Settings -> Build, Execution, Deployment -> Build Tools -> Gradle 中惨恭,有一個(gè) Generate *.iml files for modules imported from Gradle秉馏,把這個(gè)選項(xiàng)勾選上,restart Android Studio脱羡,.iml 文件中的配置就恢復(fù)了沃饶。

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

文章作者: WangJie0822

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

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

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末噩茄,一起剝皮案震驚了整個(gè)濱河市,隨后出現(xiàn)的幾起案子复颈,更是在濱河造成了極大的恐慌绩聘,老刑警劉巖,帶你破解...
    沈念sama閱讀 216,372評(píng)論 6 498
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件耗啦,死亡現(xiàn)場(chǎng)離奇詭異凿菩,居然都是意外死亡,警方通過查閱死者的電腦和手機(jī)帜讲,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 92,368評(píng)論 3 392
  • 文/潘曉璐 我一進(jìn)店門衅谷,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人似将,你說我怎么就攤上這事获黔。” “怎么了在验?”我有些...
    開封第一講書人閱讀 162,415評(píng)論 0 353
  • 文/不壞的土叔 我叫張陵玷氏,是天一觀的道長。 經(jīng)常有香客問我译红,道長预茄,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 58,157評(píng)論 1 292
  • 正文 為了忘掉前任侦厚,我火速辦了婚禮耻陕,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘刨沦。我一直安慰自己诗宣,他們只是感情好,可當(dāng)我...
    茶點(diǎn)故事閱讀 67,171評(píng)論 6 388
  • 文/花漫 我一把揭開白布想诅。 她就那樣靜靜地躺著召庞,像睡著了一般。 火紅的嫁衣襯著肌膚如雪来破。 梳的紋絲不亂的頭發(fā)上篮灼,一...
    開封第一講書人閱讀 51,125評(píng)論 1 297
  • 那天,我揣著相機(jī)與錄音徘禁,去河邊找鬼诅诱。 笑死,一個(gè)胖子當(dāng)著我的面吹牛送朱,可吹牛的內(nèi)容都是我干的娘荡。 我是一名探鬼主播干旁,決...
    沈念sama閱讀 40,028評(píng)論 3 417
  • 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場(chǎng)噩夢(mèng)啊……” “哼炮沐!你這毒婦竟也來了争群?” 一聲冷哼從身側(cè)響起,我...
    開封第一講書人閱讀 38,887評(píng)論 0 274
  • 序言:老撾萬榮一對(duì)情侶失蹤大年,失蹤者是張志新(化名)和其女友劉穎换薄,沒想到半個(gè)月后,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體鲜戒,經(jīng)...
    沈念sama閱讀 45,310評(píng)論 1 310
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡专控,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 37,533評(píng)論 2 332
  • 正文 我和宋清朗相戀三年,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了遏餐。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片伦腐。...
    茶點(diǎn)故事閱讀 39,690評(píng)論 1 348
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡,死狀恐怖失都,靈堂內(nèi)的尸體忽然破棺而出柏蘑,到底是詐尸還是另有隱情,我是刑警寧澤粹庞,帶...
    沈念sama閱讀 35,411評(píng)論 5 343
  • 正文 年R本政府宣布咳焚,位于F島的核電站,受9級(jí)特大地震影響庞溜,放射性物質(zhì)發(fā)生泄漏革半。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 41,004評(píng)論 3 325
  • 文/蒙蒙 一流码、第九天 我趴在偏房一處隱蔽的房頂上張望又官。 院中可真熱鬧,春花似錦漫试、人聲如沸六敬。這莊子的主人今日做“春日...
    開封第一講書人閱讀 31,659評(píng)論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽外构。三九已至,卻和暖如春播掷,著一層夾襖步出監(jiān)牢的瞬間审编,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 32,812評(píng)論 1 268
  • 我被黑心中介騙來泰國打工歧匈, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留割笙,地道東北人。 一個(gè)月前我還...
    沈念sama閱讀 47,693評(píng)論 2 368
  • 正文 我出身青樓,卻偏偏與公主長得像伤溉,于是被迫代替她去往敵國和親。 傳聞我的和親對(duì)象是個(gè)殘疾皇子妻率,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 44,577評(píng)論 2 353

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