Android 定制化apk生成

日常开发过程中,经常会遇到定制化的app,但所谓的定制化,往往只是更改其中的一部分数据,或者更改不一样的功能,那么一般的做法也就是所谓的多渠道打包。

但是多渠道打包的缺点就是首先需要知道有多少渠道。如果增加了渠道,还需要手动编辑build.gradle配置,然后再次生成。

 

其实我们所说的渠道一般指的是应用商店的渠道,大的应用商店屈指可数,所以直接配置多渠道打包,也未尝不可,新增加一个应用商店那就手动添加一次。应用商店这种基础服务,不会一天出现好多,基本在市场初期就已经奠定基础了。

 

但是并不是所有app都会上架到应用商店的,有一些apk只能去固定的地方下载,特别是toB的app。

 

比如,我们原来是做web端的服务,一开始做的是PC端的,然后又做了移动端H5。由于服务是sass服务,对于每个租户来说都有其固定域名,租户访问服务都去访问自己的域名。由于移动端H5体验并不是很好,一次开发应用就显示十分必要,那么怎么区分租户app呢?

 

最简单的形式是给每个租户定制化app[比如更改生成app的名字等],假如我们现有100个租户,每天新增十个,那么我如何动态更改呢?

 

手动更改太累了

 

那么有没有什么办法,可以避免手动操作呢?

 

使用gradle,我们可以在build.gradle中编辑

 

android {
    compileSdkVersion 28
    buildToolsVersion "29.0.0"
    defaultConfig {
        applicationId "cn.kanyun.tenant"
        minSdkVersion 24
        targetSdkVersion 28
        versionCode 1
        versionName "1.0"
        testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner"
        flavorDimensions "default"

    }
    buildTypes {
        release {
            minifyEnabled false
            proguardFiles getDefaultProguardFile('proguard-android-optimize.txt'), 'proguard-rules.pro'
            buildConfigField "String", "BASE_URL", APP_DYM_URL
        }
        debug {
            minifyEnabled false
            proguardFiles getDefaultProguardFile('proguard-android-optimize.txt'), 'proguard-rules.pro'
//            buildConfigField可以增加自动生成的BuildConfig类的变量
            buildConfigField "String", "BASE_URL", APP_DYM_URL
        }
    }

    productFlavors {
//        WUMEI{
//            applicationId "wumei.kanyun.cn"
//            manifestPlaceholders=[app_name:"物美"]
//        }
//        SUNING{
//            applicationId "suning.kanyun.cn"
//            manifestPlaceholders=[app_name:"苏宁"]
//        }

        dym {
            applicationId APP_DYM_ID
            manifestPlaceholders = [app_name: APP_DYM_NAME]
        }
    }
}

我们通过编辑其中的 productFlavors 和 buildTypes 就可以了

 

上述就是所谓的多渠道打包

 

我们所要做的就是在多渠道打包中添加点别的东西

注意 标黄 的部分,那个部分定义的是变量

那么这个变量定义在哪里呢?

其定义在 gradle.properties 文件中

 

 

配置了这些变量,就可以在build.gradle中就可以读取到了。

那么当有新租户来的时候,只需要后台修改gradle.properties文件,然后运行构建脚本就可以生成apk了。

但是这算是全部了吗?

并不是这样的。

这样其实也就定制了app的名字而已。

前面说过由于我们的服务是sass服务,每个租户都有其固定域名,因此每个app发出的请求都有其固定前缀。

我使用的是 Retrofit 框架

        Retrofit retrofit = new Retrofit.Builder()
                .baseUrl(Constant.BASE_URL)
                .addConverterFactory(GsonConverterFactory.create()) //设置使用Gson解析(记得加入依赖)
                .build();

可以看到 baseUrl() 方法,里面就是固定的前缀。

那么问题就是如果让读取到gradle.properties中配置的 固定前缀呢(其实也就是租户域名) ,打包好的apk是没有gradle.properties的。

那么只有一个可能,那就是在打包时,就将 固定前缀 赋值到  Constant.BASE_URL  

 

来看Constant类

 

public class Constant {

    public static final String BASE_URL = BuildConfig.BASE_URL;
}

这个类只有一行代码,可以看到 有一个 BuildConfig 类,

这个类是哪里来的呢?我自己并没有定义过这个类

 

来看看这个类的定义

 

 

可以看到这类中的部分字段的值,就是之前在gradle.properties中定义的。

那么这个BuildConfig这个类是哪里来的呢?

 

实际上这个BuildConfig 类是自动生成的类,类似于R.class

这个类是根据build.gradle配置文件自动生成的。生成后不能修改,只能修改配置文件。

其中最重要的就是 需要修改 buildTypes 下的 buildConfigField 配置。

关于这个类,可以查看  https://www.jianshu.com/p/274c9d95cf76

 

总之,通过修改,我们终于可以实现定制化打包了。

现在我们的服务更加完善了,用户填写了一些基础信息并注册完成后,后台通过CI/CD 下载app源码 -> 根据用户信息修改gradle.properties文件 -> 构建生成 等一系列操作 。之后我们就会直接给用户生成定制化的app下载链接,是不是更方便了。

 

posted @ 2020-05-14 11:29  陈无问  阅读(502)  评论(0编辑  收藏  举报