Android Studio 导入classes.jar包

Android SDK 中有很多带有 @hide 注解的 api,这些API为系统隐藏的 api,上层应用无法直接调用。我们开发时如果必须使用有两种方式,一是利用java反射机制。二则是在我们项目中导入 Android 系统源码编译出的classes.jar 包,该 jar 包生成在out/target/common/obj/JAVA_LIBRARIES/framework_intermediates/classes.jar。这里我重点介绍Android Studio如何导入classes.jar.

1.考虑到 libs 目录下可能会有其他 jar 包,我们在app目录下建立 syslibs 文件夹,并将 classes.jar 包放入该路径,因为这里的 classes.jar 包只用于编译,无须打包进 apk 中。

2.右键工程–>【Open Module Settings】,点击左侧【Dependencies】,选择app,点击【+】选择【2 Jar Dependency】,添加jar包,如下图。

3.经过步骤2之后,Module的build.gradle中,dependencies自动增加依赖配置 如下:

implementation files('syslibs\\classes.jar')

修改为:

1
compileOnly files('syslibs\\classes.jar')

这么做是因为我们使用该jar包只用于编译,不打包进apk中,该包里包含的是Android SDK,当apk运行到手机里时,手机里有运行所需的sdk环境。

4.project 的 build.gradle添加如下代码:

1
2
3
4
5
gradle.projectsEvaluated {
tasks.withType(JavaCompile) {
options.compilerArgs.add('-Xbootclasspath/p:app\\syslibs\\classes.jar')
}
}

添加位置如下:

5.修改jar包优先级,在Moduels的app.iml文件中找到我们的classes.jar包所在行

1
<orderEntry type="library" name="Gradle: __local_aars__:D.\AndroidStudioProjects\Blue\app\syslibs\classes.jar:unspecified@jar" level="project" />

将其移动到

1
<orderEntry type="jdk" jdkName="Android API 28 Platform" jdkType="Android SDK" />

之上。

这么做是为了让项目编译时优先用我们提供的jar包里的SDK,而不是原有Android SDK。

6.经过第5步之后,就能正常使用我们jar里的SDK了,但是,每次编译之后,app.iml 中的

1
<orderEntry type="jdk" jdkName="Android API 28 Platform" jdkType="Android SDK" />

又会被移动到最上面。下次编译时我们又得将他移动到

1
<orderEntry type="library" name="Gradle: __local_aars__:D.\AndroidStudioProjects\Blue\app\syslibs\classes.jar:unspecified@jar" level="project" />

的后面,这样比较麻烦。网上提供了一种一劳永逸的方法,将下面的代码加入到Moudle的build.gradle里:

preBuild {
    doLast {

    def imlFile = file(project.name + ".iml")

    println 'Change ' + project.name + '.iml order'

    try {

        def parsedXml = (new XmlParser()).parse(imlFile)

        def jdkNode = parsedXml.component[1].orderEntry.find { it.'@type' == 'jdk' }

        parsedXml.component[1].remove(jdkNode)

        def sdkString = "Android API " + android.compileSdkVersion.substring("android-".length()) + " Platform"

        new Node(parsedXml.component[1], 'orderEntry', ['type': 'jdk', 'jdkName': sdkString, 'jdkType': 'Android SDK'])

        groovy.xml.XmlUtil.serialize(parsedXml, new FileOutputStream(imlFile))

    } catch (FileNotFoundException e) {

        // nop, iml not found

    }

   }
}

加入位置如下:

至此,classes.jar导入完成,我们可以在Android Studio里可以直接调用系统隐藏的api里,如果遇到某些系统隐藏的api在使用时报红,一般为ide为bug,可以尝试clean project,然后rebuild project恢复正常了

文章目录
|