前言
最近工作需要在項(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
- 將 framework.jar 文件復(fù)制到
Demo/app/libs
路徑下怕品; - 在
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态罪!