系统应用开发之_Android studio使用定制framework.jar 调用@hide api

702 阅读2分钟

详细步骤如下所示:

1. 在工程添加库

将所需要的framework.jar放到工程的libs的目录下

2. 添加app模块对framework.jar的依赖

依次打开 File –> Project Structure –> Modules 中找到 app ,在右边选择 Dependencies 选项卡,点击左下角的 + 按钮,选择 File dependency ,在弹出的 Select Path 窗口中选择 libs 中的 framework.jar

3. 修改依赖库作用优先级

在新增的 Dependencies 记录的右边,将 Compile 修改为 Provided ,点 击 OK 保存修改,Provided 的作用是只参与编译,但不打包到apk中

这时可以看到app模块build.grade文件中已经变成了想要的形式了

app build.gradle 中添加 (和dependencies 同级)

preBuild {
    doLast {
        //***需要使用你项目中的App.iml的路径 (不同的项目结构路径不一样,请在自己的项目中找,路径不对就会达不到效果)***
        def imlFile = file("../app/app.iml")
        println 'Change ' + imlFile.getAbsoluteFile()
        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
        }
    }
} 

4. 修改project的build.grade

allprojects {
    //framework.jar可以放在任何地方,这里写的必须是正确的路径,否则无法识别
    String path = getRootDir().getAbsolutePath() + '\\app\\libs\\framework.jar'

    gradle.projectsEvaluated {
        tasks.withType(JavaCompile) {
            // 如果是单模块app, 可以使用相对路径
//            options.compilerArgs << '-Xbootclasspath/p:libs/framework.jar'

            //  如果是单模块app, 多模块(我的项目里有两个app模块)需要使用绝对路径,否则会出现assembleDebug assembleRelease能成功
            // 但是直接使用android studio run 会保错,找不到相关的类 (原因是编译时脚本所在的位置不一样)

            options.compilerArgs << '-Xbootclasspath/p:' + path
            println(path)
        }
    }
gradle.projectsEvaluated {
        tasks.withType(JavaCompile) {
            Set<File> fileSet = options.bootstrapClasspath.getFiles()
            List<File> newFileList = new ArrayList<>();
            //JAVA语法,可连续调用,输入参数建议为相对路径
            newFileList.add(new File("libs/framework.jar"))
            //最后将原始参数添加
            newFileList.addAll(fileSet)
            options.bootstrapClasspath = files(
                    newFileList.toArray()
            )
        }
    }
}

Xbootclasspath/p:是java编译的寻址优先设置,先找缺省路径还是全路径

5. 调用framework.jar中的相关方法

完成以上的步骤可以进行相关的代码编写,但是会存在一个问题就是无法调用到隐藏的api,如果调用到了也会提示method not find,如遇到此问题的童鞋请参照第七条

6. 修改app.iml

问题5出现的原因还是在编译的时候android.jar调用的优先级要高于自己添加的framework.jar,那么是否只需要将framework.jar的编译优先级高于android.jar就可以了呢?答案是肯定的!

这时只需要将app.iml中framework.jar的调用顺序提到调用android api之前;

7. 保存,重启studio