通过Gradle 配置应用
问题引入
很多时候,我们的应用会在开发的时候使用一个测试的服务器,在发布正式应用的时候改为正式的服务器。
问题解决方案
- 把服务器信息写入一个静态类里面,然后统一引用,改的时候统一修改
- 把服务器信息写入到一个assets 文件中,然后再修改
- 把测试服务器和正式服务器都写到代码里面,通过BuildConfig.DEBUG 这个字段来判断使用哪一个
解决方案评价
1和2其实操作是一样的,2只是加快了编译速度而已。但是还是避免不了要人工修改的这个问题,很容易遗忘或者误操作,改完之后还要测试一下是否改对了
3操作做到了自动化,但是有个问题,就是把无用的信息带到了发布版里面去,这里的无用信息就是测试服务器的地址,既然是发布版,是断然不会用到测试服务器的,每次启动还要做一个判断是在是逼死我这个强迫症
新的方案
新的方案就是第二个方案的第三个方案的结合。第三个方案不好的地方在于把编译期间就可以做的事情放到了运行时候来做,第二个方案的坏处就是每次都要手动修改,很容易出错和遗忘。
第四个方案具体流程是,编译器就把不同的文件放到对应的的assets 目录中,程序运行时再从目录中读取对应的配置文件。
具体实现
我们先让我们的程序可以读取配置文件先
* 创建一个Model ,用来存放ServiceInfomation
public class MServiceConfig {
@SerializedName("host")
private String mHost;
@SerializedName("port")
private String mPort;
public String getHost() {
return mHost;
}
public void setHost(String host) {
mHost = host;
}
public String getPort() {
return mPort;
}
public void setPort(String port) {
mPort = port;
}
}
-
在Application 创建一个解析代码(这样做并不是很好,建议具体实现不要在Application添加代码,只是在Application 解析就好)
public class MyApplication extends Application { private MServiceConfig mMServiceConfig;
@Override
public void onCreate() {
super.onCreate();
mMServiceConfig = new Gson().fromJson(readConfig(),MServiceConfig.class);
}
public MServiceConfig getMServiceConfig() {
return mMServiceConfig;
}
private String readConfig(){
String config = "";
try {
InputStream inputStream = getResources().getAssets().open("config_service.json");
byte[] buffer = new byte[2048];
ByteArrayOutputStream byteArrayOutputStream = new ByteArrayOutputStream();
int length = 0 ;
while ((length = inputStream.read(buffer)) != -1){
byteArrayOutputStream.write(buffer,0,length);
}
config = byteArrayOutputStream.toString();
inputStream.close();
byteArrayOutputStream.close();
} catch (IOException e) {
e.printStackTrace();
}
return config;
}
}
下面我们可以进入正题了
怎么在编译期间就把不同的配置文件打包进入到assets呢。答案就是通过使用gradle这个编译系统。
在build.gradle 贴入以下代码就好了
//为每一类型都添加task
android.applicationVariants.all { variant ->
//获取当前变种名字
String variantName = variant.name;
//装换第一个字母为大写
variantName = "${variantName.substring(0, 1).toUpperCase()}" +
"${variantName.substring(1, variantName.length())}"
//获取assets目录的位置
def intoPath
android.sourceSets.main.assets.each{ value ->
intoPath = value.source.get(0)
}
//获取mergeAssets任务
project.getTasksByName("merge${variantName}Assets", false).each {
//创建拷贝任务,把configDebug or configRelease 中的文件拷贝到assets中
Task myTask = project.tasks.create(
name: "configApp${variantName}", type: Copy, overwrite: true) {
group = 'build'//分配在build 分组中
from("src/config${variantName}") {
include '*.json'//只是拷贝json文件,不需要可以去掉
}
into intoPath
}
//使mergeAssets 依赖于这个拷贝任务,这样当megeAssets 执行的时候就会先调用myTask
it.dependsOn myTask
}
}
这样就会把src目录下的configDebug或者configRelease导入到相应的Assets 里面了