如果开发一些依赖framework中隐藏方法的应用的话, 如果一直用反射比较繁琐, 所以如果导入framework.jar, 编译的时候依赖framework, 打包的时候不打包, 这样开发就简单了许多, 而且效率也搞。
这个功能之前在eclipse中的实现网上有很多教程都介绍了, 现在都转到AS了, AS的优点太多了, 我转过来是因为要使用aar。
第一步把framework.jar当做一个普通的lib包导入AS, 教程太多了(记得选的Providered方式, 不打包到APK)
关键第二部: 至今网上没介绍:
原理是理解AS的编译依赖环境的配置, 这个文件保存在 app 下的 iml 文件(Project一个iml, 每个Model有自己的iml, 你需要修改具体app下的 iml)
<orderEntry type="library" exported="" scope="PROVIDED" name="framework" level="project" /> <orderEntry type="sourceFolder" forTests="false" /> <orderEntry type="jdk" jdkName="Android API 22 Platform (1)" jdkType="Android SDK" /> <orderEntry type="library" exported="" name="appcompat-v7-21.0.3" level="project" />
把 framework的order提高到比SDK的等级高就可以了
更新:
上面其实解决的只是AS上编译器的依赖问题, 当真正使用Gradle打包的时候又会出现问题, Gradle使用的不是之前iml配置的依赖顺序 (PS: 之前成功是由于AS编译缓存给我造成的假象)。
最近研究了Ant打包的流程, 引入自定义 framework.jar
<target name="-pre-compile" >
<echo message="JARPATH=${toString:project.target.class.path}"></echo>
<property name="framework.dir" value="${jar.libs.dir}/framework"></property>
<path id="framework.lib">
<pathelement location="${framework.dir}/framework.jar"></pathelement>
<path path="${toString:project.target.class.path}"></path>
</path>
<path id="project.target.class.path">
<path refid="framework.lib"></path>
</path>
<echo message="JARPATH=${toString:project.target.class.path}"></echo>
</target>
分析: project.target.class.path 其实指向的是android.jar的位置, 只要把自定义的framework.jar 引入这里, 编译的时候会先查找自定义的framework.jar, 打包的时候也不会打包的 classes.dex 里面。
Android Studio 的方式:
通过艰难努力, 终于搞定了这个问题, 而且是十分优美的方式搞定的。
1: AndroidStudio IDE 的编译无错误提示
这里推荐在 Iml 文件中自定义:
<orderEntry type="jdk" jdkName="Android API 22 Platform-aosp" jdkType="Android SDK" />
如何自定义
Android API 22 Platform-aosp, 首先把这个名字改错, 然后编译, 根据提示进入到SDK的编辑界面:
这里先删除 android.jar 然后再加入 framework.jar 和 android.jar
这样就确保IDE编译无错误。
2: Gradle的编译出APK
这里就是重头戏了, Gradle的编译脚本是定义在 build.gradle 中的。
对于三方普通的 jar 包的处理, 比较简单:
dependencies { compile fileTree(dir: 'libs', include: ['*.jar']) compile 'com.android.support:support-v4:22.1.1' compile 'com.github.lecho:hellocharts-library:1.5.5@aar' compile 'com.avast:android-styled-dialogs:2.2.0' }
但是这里无法配置我们需要的jar包(优先级比android.jar高, 而且不要打包到 dex 文件中)
我们可以配置:
allprojects {
repositories {
jcenter()
}
gradle.projectsEvaluated {
tasks.withType(JavaCompile) {
options.compilerArgs.add('-Xbootclasspath/p:libs\\framework.jar')
}
}
}
解释一下, 这是在最外层的 build.gradle 里面配置的, 目的是应用到所有的模块。
在进行 javac 编译的时候, 添加一个参数。 其实和上面Ant编译的命令是一样的, 都是在 bootclasspath 中引入自己的 jar 包。
测试真实有效(PS 清除了缓存, 没有再次被欺骗)
3: 引入framework-res.apk 中自定义的属性
如果看到这里, 我就告诉你跟build tools的版本有关, 高版本的会过滤掉你自定义的attr, 你需要使用低版本(推荐 19.1.0)
这个是折磨了很久的编译问题, 至今未看到网上有相关的介绍, 如果还有疑问可以发邮件: eva_59421@163.com