每个客户都会提出对产品的定制化需求,为了解决这个问题,我们此前都是采用svn/git开分支的解决方法,但是如果产品出现了一个共性的bug我们就需要对所有的分支进行修改,毫无疑问,这个非常麻烦。
采用多渠道打包的方法可以部分解决这个问题,我们可以基于已经做好的产品进行特异性的打包。这样一来,如果出现共性BUG,我们每次可以通过只修改公共部分更新到所有产品。
1.生成不同渠道
每次我们需要对项目进行修改的时候就需要生成一个渠道,这点类似于在svn/git上创建分支。用户提出的需求我们都需要在这个渠道中进行修改。
Android Studio本身提供可视化界面来创建不同的渠道,这种方式很简单,在此不做过多介绍。
或者你也可以直接在build.gradle中进行配置,我的build.gradle如下
apply plugin: 'com.android.application'
android {
compileSdkVersion 25
buildToolsVersion "26.0.1"
defaultConfig {
applicationId "com.esensoft.mutilpackage"
minSdkVersion 15
targetSdkVersion 25
versionCode 1
versionName "1.0"
testInstrumentationRunner "android.support.test.runner.AndroidJUnitRunner"
}
buildTypes {
release {
minifyEnabled false
proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'
}
}
productFlavors {
product1{
}
product2{
}
}
}
dependencies {
compile fileTree(include: ['*.jar'], dir: 'libs')
androidTestCompile('com.android.support.test.espresso:espresso-core:2.2.2', {
exclude group: 'com.android.support', module: 'support-annotations'
})
compile 'com.android.support:appcompat-v7:25.3.1'
compile 'com.android.support.constraint:constraint-layout:1.0.2'
testCompile 'junit:junit:4.12'
}
其中
productFlavors {
product1{
}
product2{
}
}
就是配置多渠道,product1是我的渠道名。
配置完成以后通过如下界面切换当前激活的渠道(用于调试)
2.替换文件
在渠道创建好之后,我们就需要对项目进行修改,实现用户的需求,通过替换文件,或者增加逻辑开关我们就可以实现这些需求。
我们要在mian的同级路径下创建和渠道同名的文件夹,把需要替换的文件放到这些文件夹里面(驱动),并且需要保持和主渠道一样的路径。
此处需要特别注意res下的资源文件会自动替换,Androidmainfest.xml自动合并,如果渠道中没有Androidmainfest.xml则会使用主渠道的。如果需要替换Java文件,则需要将主渠道中同名Java文件删除(否则会抛出类重名异常)。
由于需要删除同名Java文件可能造成不便,此处还有第二种解决方案,在代码中动态获取渠道名,并由此获取到当前的产品信息,然后通过 if 或者 swtich 逻辑开关对需要修改的位置添加只有当前产品才能进入的逻辑块,资源替换方法不变。
在配置好渠道之后渠道添加渠道名,具体就是在build.gradle修改配置好的渠道信息。
productFlavors {
product1 {
}
product2 {
}
productFlavors.all { flavor ->
flavor.manifestPlaceholders = [UMENG_CHANNEL_VALUE: name]
}
}
同时,需要在AndroidManifest的<application>标签中添加如下代码,完成渠道名的自动配置
<meta-data
android:name="UMENG_CHANNEL"
android:value="${UMENG_CHANNEL_VALUE}"/>
在代码逻辑中通过如下方法取得渠道名,然后根据渠道名进行逻辑判断。按照上述操作得到的渠道名就是在build.gradle中product1,product2
/**
* 获取application中指定的meta-data。本例中,调用方法时key就是UMENG_CHANNEL
*
* @return 如果没有获取成功(没有对应值,或者异常),则返回值为空
*/
public static String getAppMetaData(Context ctx, String key) {
if (ctx == null || key.equals("") || key == null) {
return null;
}
String resultData = null;
try {
PackageManager packageManager = ctx.getPackageManager();
if (packageManager != null) {
ApplicationInfo applicationInfo = packageManager.getApplicationInfo(ctx.getPackageName(), PackageManager.GET_META_DATA);
if (applicationInfo != null) {
if (applicationInfo.metaData != null) {
resultData = applicationInfo.metaData.getString(key);
}
}
}
} catch (PackageManager.NameNotFoundException e) {
e.printStackTrace();
}
return resultData;
}
3.生成不同渠道的apk
到此,我们已经完成对不同渠道版本的定制操作,点击android studio右侧的gradle即可开始打包工作。