android 一套代码多用 以及 多套代码用于一个项目
文章关键字 productFlavors
目前在项目中遇到了这样一种情况,公司的产品需要在不同的机子(自己产品)上进行运行,有的是正常手机 有的是没有显示屏的手机,需要另外做处理。那么现在问题来了,总不可能一个产品一个项目把,那么我们就可以通过productflavors进行代码多用
项目使用mvp架构 demo也是以此为前提
第一种情况,代码不变,素材变化
举一个极端的例子,你家的app卖不出,别人来代理你家的app,说图标要换成他家的,那么你怎么办?总不可能直接拿项目改把,万一又说不要你家app了呢?(开个玩笑)
步骤:
先将android studio的目录结构改成project
image.png
在与main同级下新建一个目录
我这里叫seller
image.png
并且根据main目录的目录结构(一定要一样),新建res 新建values 新建strings.xml
image.png
并将原来的appname 在后面加上111
tips1:这里说明一下,在res目录下的替换都是批量替换,在main目录的strings.xml里面肯定不止一个strings,我们在seller的strings.xml下新建一个appname 并更改了值 那么只有这个appname会被替换 其他的还是原封不动的使用main的东西
tips2:其他同理,只要是在res目录下,都是批量替换(名字一定要一样 无论是string 还是图片)
在替换之前 我们还需要做一些事情,就是声明
在gradle文件里面
image.png
新增一个productFlavors 里面声明一个seller
productFlavors {
seller {
}
}
gradle sync之后
在build Variants里面就可以看到不同的项目了
image.png image.png
你可能会说 现在不就只剩一个了么,想用原来的代码不想用seller怎么办?
笑哭.jpg 新增一个就好
image.png
新增一个空的origin
image.png声明一下
image.png
打包的时候你可以同时打两个包
image.png image.png
在build Variants里面的选项的作用:你选择哪个,运行的时候(debug run)就运行哪个版本
以上就是素材的替换
第二种情况代码的替换
可能某一个部分的机器需要另外的新增的代码 而且与原来的代码区别还是蛮大的
那么我们可以进行代码的替换
tips1:代码的替换并不是部分替换 而是文件的替换(例如一个mainActivity的替换,而不是mainActivity的某个代码片段的替换)
tips2:要替换的代码的那个文件不能存在于main文件夹内
现在 我们在seller下新建一样的代码结构
image.png并把MainActivity文件复制过来
image.png并将Build Variant设置成sellerdebug
image.png你会发现报错 所以说替换代码的时候main 文件夹内不能存在那个文件
现在将origin也复制一遍代码结构 并且将main文件夹内的删除
image.png不再报错
Tips:目前Build Variant是sellerdebug 所以seller下面的文件夹和main文件夹是有颜色的 但是origin没有,侧面说明android studio还是挺智能的
以上就是代码的替换 只要你你运行那个分支你就会运行哪里的代码(没有替换的代码会用main文件夹的)
一些使用心得:如果只是小部分代码需要替换 最后还是在main里面if else修改 比较方便 不然你就要维护两套代码 使用mvp分层的话 可以尽量减少文件的替换 维护更少的代码!!!
第一二种情况可以混用
字符串的替换
如果你在seller中使用一个ip origin使用一个ip 怎么办
productFlavors {
seller {
buildConfigField("String", "URL", '"www.baidu.com"')
}
origin{
buildConfigField("String", "URL", '"www.google.com"')
}
}
使用buildConfig字段
String ip = BuildConfig.URL;
这样这个ip在seller下是baidu 在origin下是google 是自动的
此外 也可以在debug和release下使用
buildTypes {
debug{
minifyEnabled false
proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'
buildConfigField("String", "URL", '"www.baidu.com"')
}
release {
minifyEnabled false
proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'
buildConfigField("String", "URL", '"www.google.com"')
}
}
项目的判断
if (BuildConfig.FLAVOR.equals("seller")) {
//// TODO: 2017/12/7
}
使用flavor字段可以判断运行的是哪个分支 然后进行小范围的代码的if else
项目的compile
例如 seller下使用腾讯的sdk
但是origin的使用百度的sdk
难道打包就需要打包两个sdk???
举个例子
使用分支的名字加上Compile就可以只在seller项目中compile这个东东
但是这样有个问题 如果你在同一套代码里面做了if else判断 如果在某个分支里面没有compile这个包 那么可能会报错
//举个例子:demo例子
//如果在seller项目中没有compile tx的sdk 那么编译的时候会报错 说没有找到tx sdk这个类
if(flag){
TXSdk.init(this)
}else{
BaiduSdk,init(this)
}
ui一样的情况下 新增代码逻辑
在我的项目中 有一台手机是没有屏幕的 但是有一个lcd屏 所以我需要新增逻辑 进行处理
假设这个没有屏幕的手机是seller项目
seller项目需要compile一个jar包这个jar包很大
因为我是sellerCompile的 在origin中是没有的 所以我不能在main的代码中写入关于这个jar的代码 不然origin就编译不起来
那么我是怎么办的呢?
image.png我新增一个receiver 和一个service
通过发intent的方式 如果是seller项目自然可以收到intent 并且使用jar包的类进行处理(使用jar包的代码在seller分支里面 而不是在main里面) 就没有问题,如果是origin项目 不会有receiver会收到这个intent 然后就不会处理
所以我是通过receiver进行中转处理的
以上就是我在项目中遇到的一些问题 以及productFlavor的一些使用 当然 productFlavor还有其他的一些用法 大家可以自己去了解一下
项目的demo(只有结构哈):https://github.com/Lemniscate317/ProductFlavorsDemo