zoukankan      html  css  js  c++  java
  • Android工程中共主线差异化打包方案说明

     转载请标注来源:http://www.cnblogs.com/charles04/p/9017501.html


    Android工程中共主线差异化打包方案说明

    0、目录

    1. 引言
    2. 需求分析
    3. 方案描述
    4. 参考文献

    1、引言

    随着项目的不断迭代,经常需要基于同一套基线代码,release部分差异的不同APK。例如,不同的应用市场,release不同的适配版本。原始的办法一般是,从最新的基线上拉去代码分支来支持不同版本的发布。但是,这样需要同时维护不同的分支代码,从而额外增加开发和维护成本,影响正常的开发进度。

    2、需求分析

    同一个工程,通过差异化的设计编码,构建出两套差异化的版本,实现在同一个工程下管理不同的版本的目的。

    其中,差异化版本之间,存在以下异同点:

    • 不同版本之间,大部分代码相同,公用一套公共组件,底层代码等;
    • 不同版本之间,需要差异化实现不同的功能,包括显示(xml)不同,逻辑(java)不同,配置(Manifest)不同等;
    • 不同版本之间,包名不同;

    3、方案描述

    在Android Studio中,通过配置不同的productFlavors实现同一个工程下的差异化版本构建。例如,通过同一套代码,实现两个不同的产品,分别为productA和productB,具体的操作如下。

    3.1. Build配置

    在build中分别为productA和productB配置不同的flavors,如下:

     1 android {
     2     compileSdkVersion 24
     3     buildToolsVersion "24.0.2"
     4     defaultConfig {
     5         applicationId "com.example.product"
     6         minSdkVersion 20
     7         targetSdkVersion 24
     8         versionCode 1
     9         versionName "1.0.0.0"
    10     }
    11 
    12     productFlavors {
    13         productA {
    14             applicationId "com.example.product.a"
    15             versionName "1.0.0.1"
    16         }
    17 
    18         productB {
    19             applicationId "com.example.product.b"
    20             versionName "1.0.0.2"
    21         }
    22     }
    23 
    24     buildTypes {
    25         release {
    26             minifyEnabled false
    27             proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'
    28         }
    29     }
    30 }

    其中,不同flavors下面设定的applicationId即为对应版本的进程名称,也即package name。

    Tips:Android工程中build中设定的applicationId和Manifest中设置的package(name)有什么区别?
    
    解释:application id与package name在Android工程中分工明确,其中:
    (1).application id 负责 App 的进程 ID
    (2).package name 负责 R 的包名以及 Manifest 中 Activity 等四大组件的相对包名

    如果 build.gradle 中没有指定 applicationId,那么 application id 的默认值就是 manifest 的 package 属性值。

    3.2. 工程结构

    在src/main目录下新建两个同级目录productA与productB,目录的名称要与productFlavors中设定的工程名保持一致。如下所示:

    productA/productB与main目录一样,也可以有自己的java包,res资源文件和AndroidManifest配置文件。其中,对于productA和productB来说,main目录下的文件和资源是共享的,而productA与productB下的文件和资源是对应的product特有的,在这里可以做一些差异化的编码,达到共主线,差异化逻辑的效果。

    值得注意的是,productA和productB中可以存在同名文件,在gradle编译的时候,会自动链接各自product的文件。这样就给编码带来了极大的便利。例如:

    • 想要做到差异化显示,只需要在对应的product目录给同一个Activity配置不同的同名xml;
    • 想要实现不同的页面逻辑,只需要在对应的product目录中实现各自的同名Activitry;
    • 想要获取差异化数据,只需要在对应的product目录中配置不同内容的同名的Config;
    • 想要对同一个Activity实现不同的配置(启动模式,过滤模式等),只需要在对应的product中配置不同的Manifest;
    • 想要在不同版本中依赖不同的Modulejar包,也可以通过差异化的依赖来实现,如下:
    1 dependencies {
    2     compile project(':common-lib')
    3     productACompile project(':common-entity')
    4     productBCompile project(':common-overseas-entity')
    5 } 
    • 想要在Manifest中配置不同的渠道值,只需要在productFlavors中配置不同的manifestPlaceholders,如下:
    1 productFlavors{
    2         productA{
    3             manifestPlaceholders = [CHANNEL:"productA"]
    4         }
    5         productB{
    6             manifestPlaceholders = [CHANNEL:"productB"]
    7         }
    8 } 

    对应的Manifest配置如下:

    1 <meta-data android:name="UMENG_CHANNEL" android:value="${CHANNEL}"/>

    类似这样的操作,可以在多渠道差异化打包过程中,减少了很多不必要的逻辑判断。这样一来,不仅代码更加健壮,而且代码可读性大大提升。

    3.3. 编译命令

    代码编写完成之后,就可以通过gradle编译出差异化的版本。与一般的编译情况一样,差异化编译版本也有两种编译途径:

    (1). 通过gradle视图,直接点击编译,如下:

    分别点击assembleProductA和assembleProductB就可以差异化的编译出productA和productB的包;

    (2). 通过命令行编译;

    以编译ProductB为例,

    1 gradlew assembleProductB:编译productB的release和debug包;
    2 gradlew assembleProductBDebug:编译productB的debug包;
    3 gradlew assembleProductBRelease:编译productB的release包;

    3.4. 运行

    编译之后,就可以生成可执行的二进制文件,如下:

    分别安装app-productA-debug.apk和app-productB-debug.apk,可以发现手机上生成了两个不一样的apk,如下:

    这是因为,二者的keystore虽然一致,但是不同的product的applicationId不一致,所以对应的签名信息是有区别的。所以,前后安装两个APK不会覆盖。

    分别点击进行两个APK,跳转的流程如下:

    可以发现,通过上述方法已经实现了共主线差异打包的能力。

    4、参考文献

     

  • 相关阅读:
    uoj 36 玛里苟斯
    readlink
    Endless Spin
    rm
    rmdir
    [学习笔记]min-max容斥
    cp
    [HAOI2015]按位或
    java实现第四届蓝桥杯公式求值
    java实现第四届蓝桥杯危险系数
  • 原文地址:https://www.cnblogs.com/charles04/p/9017501.html
Copyright © 2011-2022 走看看