http://www.31mins.com/android-studio-build-system-application/
之前,我们都使用Eclipse IDE去开发Android的系统应用,不过现在,我们有了Android Studio,
如何使用它去编译系统应用呢?
我正在做一个AOSP的项目,在这个项目中,有一些应用需要客制化,如Settings,Laucher等。
当开发Settings应用时,它使用了隐藏的API,在SDK里是非public的,如EthernetManager。
因此,它需要包含了系统应用需要的隐藏API的framework.jar,以下是编译此应用的方法:
1.找到未压缩过的framework.jar ,在
/android/out/target/common/obj/JAVA_LIBRARIES/framework_intermediates/classes.jar
请小心,不是这个文件:/android/out/target/product/your_target/system/framework/framework.jar
第一个是未压缩过的java library,第二个是用于官方SDK的library。
2.把它拷贝到工程路径:/project_path/system_libraries,然后重命名为framework.jar。
3.增加“providerd”到依赖,这一步和eclipse一样设置扩展库。
dependencies {
compile fileTree(dir: 'libs', include: ['*.jar'])
testCompile 'junit:junit:4.12'
compile 'com.android.support:appcompat-v7:23.4.0'
provided fileTree(dir: 'system_libraries', include: ['*.jar'])
}
然后现在应用应该可以识别 EthernetManager了。
不过我还遇到个问题,API似乎没有效果,当使用framework.jar替换Android SDK的framework.jar时,我遇到的问题。
例如当使用WifiManager时,Android SDK有一些公共的API,而framework.jar中,有一些隐藏的API,如果你直接编译,还是会有问题的。按照以前的方式,Eclipse可以设置依赖标志知道哪一个优先被导入。但是在Android Studio中,它总是会把Andorid SDK放到第一个,因此我们需要找到一个方法把framework.jar放到Android SDK之前。
有一个文件叫app.iml,对于不同的library,有<orderEntry>,我们把<orderEntry type="jdk" jdkName="Android API 23 Platform" jdkType="Android SDK" />放到最后,然后Android Studio就可以使用我们自己的framework.jar了。
上面提到的app.iml 会由Android Studio自动改变,因此当Gradle同步时,我们创建新任务去改变它。
task pushDownJdkDependency {
def imlFile = file("app.iml")
println 'Change app.iml order'
try {
def parsedXml = (new XmlParser()).parse(imlFile)
def jdkNode = parsedXml.component[1].orderEntry.find { it.'@type' == 'jdk' }
parsedXml.component[1].remove(jdkNode)
new Node(parsedXml.component[1], 'orderEntry', ['type': 'jdk', 'jdkName': "Android API 23 Platform", 'jdkType': 'Android SDK'])
def writer = new StringWriter()
new XmlNodePrinter(new PrintWriter(writer)).print(parsedXml)
imlFile.text = writer.toString()
} catch (FileNotFoundException e) {
// nop, iml not found
}
}
}
改好之后,预编译没有问题,但是在生成package时,仍然会报一些编译错误,我们加一个hook到Android Studio Gradle插件中,-Xbooclasspath/p:是把classpath加在 bootstrap classpath之前,如下:
gradle.projectsEvaluated {
preBuild.dependsOn(brandCopy)
tasks.withType(JavaCompile) {
options.compilerArgs.add('-Xbootclasspath/p:app/system_libraries/framework.jar')
}
}
这2个代码片段应该放到Android关闭之前,确保编译过程是有效的。
经历过这些步骤后,现在我们可以使用Android Studio编译系统应用了。祝你coding愉快!