关于Android打包

      最近在做厂商定制版的预装APP,考虑到不同厂商的需求的差异化,和共性,所以就和组里的人一起研究如何做到一份代码,保持共性,但是通过开关和配置文件的方式,控制打包的时候,打出相应的APK包给对应的厂商,同时每个包的功能既有共性也有差异化的定制版部分,从而避免通过拉很多代码分支的方式,去做差异化实现,减少维护的人力成本。

      举个例子:目前有OPPO,中兴两个厂商,他们都要我们的APP,但是有部分需要修改,如APP的图标,名字,APP的包名,以及升级需要接入他们自己的后台,单独做数据上报等差异化需求。如果是之前,我们会基于一个稳定版本,分别为OPPO和中兴拉两个分支,然后去两个分支上单独开发,替换图标,改包名,引入他们的升级sdk等。问题来了,这样的维护成本太高了,尤其是每个厂商都要拉一个分支,10个厂商就10个分支,一个厂商上面发现的bug,需要改10个分支的代码,简直是恐怖。我们需要做的就是,只有一个分支,但是可以做资源替换,比如icon打包的时候动态去替换成不同的厂商的icon;升级的接入,通过开关去控制升级的方式,OPPO就走OPPO升级,中兴就走中兴升级,这样打包的时候就做到了差异化,而且维护比较简单。

      接下来一点一点说具体是怎么实现的。

1.开关控制打包。

      一次打多个包,之前的文章里面也提过,不过只是说了一点点。可以参看文章:了解build.gradle。这里重点说下怎么做开关控制,从而实现差异化打包。

       build.gradle里面的buildTypesproductFlavors组合使用,可以打出多个包,比如:

buildTypes {

        debug {
            signingConfig signingConfigs.release
            debuggable true
        }

        release {
            signingConfig signingConfigs.release
            debuggable false
            minifyEnabled true
            shrinkResources false
            proguardFile 'proguard.cfg'
        }
    }
        buildTypes 说明的是生成的包的类型都会有 debug release 两种。
productFlavors {
        _default {}

        google {
            applicationId 'com.sun.google'
        }

        oppo {
            applicationId 'com.sun.oppo'
            buildConfigField "boolean", "KEEP_SHARE", "false"
        }
    }

       productFlavors说明的是会生成三个版本的包,默认的是_default,然后是googleoppo的。和buildTypes组合使用就是会生成2*3=6个包。这里需要重点关注一个点,就是生成googleoppo包的时候,包的名字是会被替换掉的,这里就是动态修改包名。

      那再考虑升级的策略,希望不同的厂商,都接入自己的sdk去做升级逻辑。我们想到的是利用模版设计模式,升级的主流程不变,同时有一个工厂类,根据打包的确定的是生成那个厂商的包,去创建具体的升级子类,然后走对应厂商的sdk升级。那么这个开关是怎么做到的呢?其实代码里面我们可以通过编译成功之后的BuildConfig去获取生成的是那个厂商的包的Flavor

if (BuildConfig.FLAVOR.equals("oppo")) {
    sOEMBaseReport = new OppoReport();
    sUpdateMethod = new OppoUpdate();
    sAppLaunchDialogHelper = new OPPOLaunchDialogHelper();
} else if (BuildConfig.FLAVOR.equals("google")) {
    sUpdateMethod = null; //google don't need to check update
    sAppLaunchDialogHelper = new AppLaunchDialogHelper();
} else {
    sUpdateMethod = new TrunkUpdate();
    sAppLaunchDialogHelper = new AppLaunchDialogHelper();
}

      这里就是我们通过开关去做升级和数据上报等定制化模块逻辑的差异化部分。

      当然开关还不仅这些,考虑场景,OPPO提需求说我们不想要APP支持分享逻辑,而google说我们需要支持分享,默认版本是需要支持分享逻辑的。那么我们做差异化呢?也是BuildConfig

      我们build.gradle默认有个defaultConfig,我们可以在其中定义一个buildConfigField,类似于定义一个变量,我们可以选择不同的包里面,修改这个变量的值,然后在分享模块入口的地方,加上if判断,决定是否需要屏蔽分享入口。

defaultConfig {
        minSdkVersion 17
        targetSdkVersion 24
        applicationId "com.sun.innocentsun"
        signingConfig signingConfigs.release
        versionCode getBuildVersionCode()
        versionName getBuildVersionName()

        buildConfigField "boolean", "KEEP_SHARE", "true"
    }
    
    productFlavors {
        _default {}

        google {
            applicationId 'com.sun.google'
        }

        oppo {
            applicationId 'com.sun.oppo'
            buildConfigField "boolean", "KEEP_SHARE", "false"
        }
    }

     google的不去设置这个变量,就会和defaultConfig里面一致。这样就可以保证,oppo打出来的包,获取BuildConfig.KEEP_SHARE = false。那么我们代码里面就可以在入口加上一个if判断下就搞定了。

2.资源替换。

      资源替换主要是icon和一些位置的图标替换,以及字符串的替换,比如APP的名字等。其实还可以包括AndroidManifest清单文件的部分内容替换。

      资源替换具体的做法就是在src目录下,新建一个文件夹,要和Flavors里面的名字保持一致,然后新建一个子目录res,再把需要替换的资源放进去,当然,因为是替换资源,所以名字必须一致,也就是说,工程的res里面的APP的图标名字是icon.png,那么你OPPO包需要更换APP图标的话,更换的图片名字必须也命名为icon.png才能被替换掉。可以参看我的工程目录,这里只列了一个oppo的替换,google的也是一样的。

      名字都一样才能替换,不一样的是不能被替换的。而且这个文件夹名字一定要和productFlavors里面一致,比如这里都是“oppo”。

      另外,APP的名字,这个需要在string.xml中也写一个相同的名字的变量,但是赋值不同。对比图:


      AndroidManifest 清单文件里面的内容也是可以替换的,比如把一个 activity 移除,然后用另外一个同名但是包名路径不同的 activity 替代。

      第一段是把本来在工程主路径下的清单文件里面的HelloWorldActivity给取消注册,然后引入自己路径下的同名Activity,这样就实现了替换。

      注意:上面说的都是替换,不是新增,如果想实现,主程序里面没有的资源文件,然后OPPO版本才有的这样新增,是不行的,只能实现替换。



  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值