起因
fork了一个项目,准备用kotlin完全重写,但是又想提交在同一个项目上,而且不污染原作者的代码。于是研究了一下可行方案:
- git 新开一个分支,pass(其实是对git不熟……)
- 新开一个productFlavor
最后决定使用方案2。话不多说,方案详细是这样的:
新开一个productFlavor,使用不同的SourceSet装载自己的一份完整代码,包括核心(src)、资源(res,assets)、清单(manifest.xml)。使用姿势大概是这样的:
在app的build.gradle文件中:
android {
...
sourceSets {
main {
manifest.srcFile 'AndroidManifest.xml'
java.srcDirs = ['src']
resources.srcDirs = ['src']
aild.srcDirs = ['src']
renderscript.srcDirs = ['src']
res.srcDirs = ['res']
assets.srcDirs = ['assets']
}
kotlin {
java.srcDirs = ['src-dev']
}
}
}
其中的定义见代码,这里略过。
我的踩坑记录
一开始我的配置是这样的
sourceSets {
kotlin {
manifest.srcFile 'src/main/KotlinAndroidManifest.xml'
java.srcDirs = 'src/main/kotlin'
res.srcDirs = 'src/main/res-kotlin'
}
}
productFlavors {
kotlin {}
}
目录结构:
看上去很完美。
运行,报错:
Error:Cannot cast object 'src/main/kotlin' with class 'java.lang.String' to class 'java.lang.Iterable'
稍微想了一下,哦,原来是java.srcDirs
和res.srcDirs
不能直接用一个引号,需要使用数组(Iterable)。改成
java.srcDirs = ['src/main/kotlin']
res.srcDirs = ['src/main/res-kotlin']
依旧报错。又查了一下,发现有souceset是有一个默认集main的,如果使用默认的souceset需要加上。
sourceSets {
main {
manifest.srcFile 'src/main/AndroidManifest.xml'
java.srcDirs = ['src/main/java']
res.srcDirs = ['src/main/res']
}
kotlin {
manifest.srcFile 'src/main/KotlinAndroidManifest.xml'
java.srcDirs = ['src/main/kotlin']
res.srcDirs = ['src/main/res-kotlin']
}
}
嗯,编译不报错了,运行又报错。又发现一个问题:左下角的切换productflavor里面只有一个kotlin的,默认那个哪去了?百思不得其解,查了好多,后面发现直接简单粗暴的给一个默认flavor命名为normal:
productFlavors {
normal {}
kotlin {}
}
sourceSets {
main {
manifest.srcFile 'src/main/AndroidManifest.xml'
java.srcDirs = ['src/main/java']
res.srcDirs = ['src/main/res']
}
normal {
manifest.srcFile 'src/main/AndroidManifest.xml'
java.srcDirs = ['src/main/java']
res.srcDirs = ['src/main/res']
}
kotlin {
manifest.srcFile 'src/main/KotlinAndroidManifest.xml'
java.srcDirs = ['src/main/kotlin']
res.srcDirs = ['src/main/res-kotlin']
}
}
normal的sourceset就和main一致。果然出现了
已经规避但是也需要注意的坑
- 在gradle文件里需要先写flavors ,再写sourceSets。参考这里
- 如果出现类或者资源文件重复的情况,猜测可能是打包的时候把别的sourceset也检测了一遍。我的做法是自己的souceset里面文件命名全部带一个
kotlin
的前缀 - manifest合并失败,报错
Execution failed for task ':app:processDebugManifest'. > Manifest merger failed : Attribute application@theme value=(@style/AppTheme) from AndroidManifest.xml:35:9-40 is also present at [TC_Hospital_Patient:zybwenzhen:unspecified] AndroidManifest.xml:17:9-47 value=(@style/AppWenzhenTheme). Suggestion: add 'tools:replace="android:theme"' to <application> element at AndroidManifest.xml:29:5-44:19 to override.
根据建议需要在application
节点添加
tools:replace="android:theme"
添加以后build发现还有一条类似的错误是关于
tools:replace="android:name"
解决办法是使用
tools:replace="android:name,android:theme"
如果还有更多就用逗号隔开。