android productFlavors多马甲打包

productFlavors多马甲打包

先上官方文档,写的很不错了,地址:https://developer.android.com/studio/build/build-variants?utm_source=android-studio#product-flavors
这里只是总结下用法和一些注意点。

背景

有时候公司需要我们打很多马甲包(改包名和名字,其他一样的)、或者对不同应用市场的渠道包(应用图标不同、启动图或者厂商的推送分开集成)等需求,就可能需要创建很多项目去单独修改,很是麻烦。但是google提供了这种多变种配置来处理这种清空

配置构建变体

debug和release变体

可以在模块级 build.gradle 文件中的 android 代码块内创建和配置构建类型。当您创建新模块时,Android Studio 会自动为您创建“debug”构建类型和“release”构建类型。虽然“debug”构建类型没有出现在构建配置文件中,但 Android Studio 会使用 debuggable true 配置它。这样,您就可以在安全的 Android 设备上调试应用,并使用常规调试密钥库配置 APK 签名。——官方解释
就是我们可以在模块级中给debug和release配置不同的参数和配置项,比如签名信息、是否开启zip、区分包命名、manifestPlaceholders等参数等,方便你测试不同情景。我觉得其实这是一个更好的约束,是对release包防护吧。

注意

注意:官方文档里定义了如下属性

 debug {
            applicationIdSuffix ".debug"
            debuggable true
        }

applicationIdSuffi意思就是针对目标版本替换了新包名。其实我们对于debug和release区别只是要求配置参数不同,而不是要求不同包名,对于大部分需求其实不需要包名的对照,而是需要配置参数的对照。当然你需要同时安装debug包或者release包还是可以配置的。

常规配置
 buildTypes {
        //定义2个
        def buildrelease
        def builddebug

        buildrelease = {
            minifyEnabled true
            zipAlignEnabled true
            shrinkResources true
            proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard.cfg'
            buildConfigField "boolean", "LOGENABLE", log
            buildConfigField "String", "APIENV", '"' + environment + '"'
            manifestPlaceholders = [AMAP_KEY          : "release"
                                    , CC_EXPORTED     : 'false'
                                    , LICENSE_KEYBOARD: '654321']
        }

        builddebug = {
            minifyEnabled false
            zipAlignEnabled false
            shrinkResources false
            //设置签名
            signingConfig signingConfigs.testConfig
            proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard.cfg'
            buildConfigField "boolean", "LOGENABLE", log
            buildConfigField "String", "APIENV", '"' + environment + '"'
            manifestPlaceholders = [AMAP_KEY          : "debug"
                                    , CC_EXPORTED     : 'true'
                                    , LICENSE_KEYBOARD: '123456']
        }

        release buildrelease

        debug builddebug

    }

反正你觉得要隔离debug和release都可以这里区分。

配置风味版本

如果需要多条产品线配置不同内容,并且在一个编译版本上,就需要配置productFlavors代码块。在新的3.0版本上,需要配置flavorDimensions增加多个纬度。

flavorDimensions "app"
    //设置渠道
    productFlavors {
        teacher {
            dimension "app"
            manifestPlaceholders = [
                    package          : "com.hujin.student",
                    WAN_CHANNEL_VALUE: "teacher",
                    name             : "老师端"]
            signingConfig signingConfigs.debug
            applicationId "com.hujin.wan"
        }
        student {
            dimension "app"
            manifestPlaceholders = [
                    package          : "com.hujin.student",
                    WAN_CHANNEL_VALUE: "studnet",
                    name             : "学生端"]
            signingConfig signingConfigs.debug
            applicationId "com.hujin.student"

        }

    }
更多配置

这样就会生成debug-release * teacher-student 四个包。
还可以配置多个纬度的包,设置不同的dimension。还可以设置过滤规则variantFilter


    flavorDimensions "app","size"
    //设置渠道
    productFlavors {
        teacher {
            dimension "app"
            manifestPlaceholders = [
                    package          : "com.hujin.student",
                    WAN_CHANNEL_VALUE: "teacher",
                    name             : "老师端"]
            signingConfig signingConfigs.debug
            applicationId "com.hujin.wan"
        }
        student {
            dimension "app"
            manifestPlaceholders = [
                    package          : "com.hujin.student",
                    WAN_CHANNEL_VALUE: "studnet",
                    name             : "学生端"]
            signingConfig signingConfigs.debug
            applicationId "com.hujin.student"

        }

        normal{
            dimension "size"
        }

        big{
            dimension "size"
        }
    }


    //过滤某个 不能过滤debug 和 release 标示
    variantFilter { variant ->
        def names = variant.flavors*.name
        if (names.contains("normal") && names.contains("student")) {
            System.out.println("过滤成功")
            setIgnore(true)
        }
    }

这样就会生成debug-release * teacher-student * big-normal - studentNormalDebug包 - studentNormalRelease包 共 六个包。具体在student左边侧边栏下部可以查看:
在这里插入图片描述

可以点击选择切换不同的包后自动同步,完成切换。
除此之外,还可以设置sourceSets

  sourceSets {
        teacher {
            java.srcDirs = ['src/main/java']
            manifest.srcFile 'AndroidManifest.xml'
            res.srcDirs = ['src/main/res']
        }

        student {
            java.srcDirs = ['src/student/java']
            res.srcDirs = ['src/student/res']
            manifest.srcFile 'src/student/AndroidManifest.xml'
        }
    }

还可以配置不同的dependencies

dependencies {
    implementation fileTree(dir: 'libs', include: ['*.jar'])
    implementation 'androidx.appcompat:appcompat:1.2.0'
    implementation 'androidx.constraintlayout:constraintlayout:2.0.1'
    studentImplementation 'org.greenrobot:eventbus:3.1.1'
    debugImplementation  'com.readystatesoftware.chuck:library:1.1.0'

}

例外还可以设置BuildConfig,这个可以有很多操作空间了,比如设置不同host。

flavorDimensions "app"
    //设置渠道
    String hostStudent = "www.baidu.com";
    String hostMain = "www.qq.com";
    productFlavors {
        teacher {
            dimension "app"
            manifestPlaceholders = [
                    package          : "com.hujin.student",
                    WAN_CHANNEL_VALUE: "teacher",
                    name             : "老师端"]
            signingConfig signingConfigs.debug
            buildConfigField ("String", "HOST", '"'+ hostMain + '"')
            applicationId "com.hujin.wan"
        }
        student {
            dimension "app"
            manifestPlaceholders = [
                    package          : "com.hujin.student",
                    WAN_CHANNEL_VALUE: "studnet",
                    name             : "学生端"]
            signingConfig signingConfigs.debug
            buildConfigField ("String", "HOST", '"'+ hostStudent + '"')
            applicationId "com.hujin.student"

        }

    }

设置了HOST,build后会在BuildConfig下生成HOST字段了,然后再设置网络请求就可以用BuildConfig.HOST设置达到不同的host效果。

public final class BuildConfig {
  public static final boolean DEBUG = Boolean.parseBoolean("true");
  public static final String APPLICATION_ID = "com.hujin.wan";
  public static final String BUILD_TYPE = "debug";
  public static final String FLAVOR = "teacher";
  public static final int VERSION_CODE = 1;
  public static final String VERSION_NAME = "1.0";
  // Fields from product flavor: teacher
  public static final String HOST = "www.qq.com";
}

public final class BuildConfig {
  public static final boolean DEBUG = Boolean.parseBoolean("true");
  public static final String APPLICATION_ID = "com.hujin.student";
  public static final String BUILD_TYPE = "debug";
  public static final String FLAVOR = "student";
  public static final int VERSION_CODE = 1;
  public static final String VERSION_NAME = "1.0";
  // Fields from product flavor: student
  public static final String HOST = "www.baidu.com";
}
举个例子

比如这里配置了studeng风格的包,我需要分别设置不同资源和代码。
在这里插入图片描述
对于studeng风格的,资源方面会自动优先寻找studeng包下的资源,如果没有找到则会找默认包下面的资源。

对于代码不同需要设置sourceSets如上面所说,最重要的是对于不同的包下的

 sourceSets {
        teacher {
            java.srcDirs = ['src/main/java']
            manifest.srcFile 'AndroidManifest.xml'
            res.srcDirs = ['src/main/res']
        }

        student {
            java.srcDirs = ['src/student/java']
            res.srcDirs = ['src/student/res']
            manifest.srcFile 'src/student/AndroidManifest.xml'
        }
    }

AndroidManifest.xml的合并需要特别注意:具体查看
https://my.oschina.net/wolfcs/blog/550127?fromerr=bHHJWN7F文章。
这里特意设置了不同的风格有自己的AndroidManifest.xml文件。
主:

<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools"
    package="com.hujin.wan">

    <application
        android:allowBackup="true"
        android:name="MyApplication"
        android:icon="@mipmap/ic_launcher"
        android:label="${name}"
        android:roundIcon="@mipmap/ic_launcher_round"
        android:supportsRtl="true"
        android:theme="@style/AppTheme"
        tools:ignore="GoogleAppIndexingWarning">
        <activity android:name=".TestActivity"/>


        <activity android:name=".MainActivity"
            android:label="${name}">
            <intent-filter>
                <action android:name="android.intent.action.MAIN" />

                <category android:name="android.intent.category.LAUNCHER" />
            </intent-filter>
        </activity>



        <meta-data
            android:name="WAN"
            android:value="${WAN_CHANNEL_VALUE}" />
    </application>

</manifest>

student:

<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools">

    <application
        tools:replace="android:icon, android:theme"
        android:allowBackup="true"
        android:icon="@mipmap/ic_launcher"
        android:label="${name}"
        android:roundIcon="@mipmap/ic_launcher_round"
        android:supportsRtl="true"
        android:theme="@style/AppTheme"
        tools:ignore="GoogleAppIndexingWarning">


        <activity android:name="com.hujin.student.MainActivity"
            android:label="${name}">
            <intent-filter>
                <action android:name="android.intent.action.MAIN" />

                <category android:name="android.intent.category.LAUNCHER" />
            </intent-filter>
        </activity>



        <meta-data
            android:name="WAN"
            android:value="${WAN_CHANNEL_VALUE}" />

    </application>

</manifest>

注意点:

  • 风格包下的不需要再设置包名了,要不然会冲突。
  • 不同icon和风格可适用如下配置tools:replace="android:icon, android:theme"
  • 最好风格包下的类,最好全路径来设置(我的项目上出现类找不到)
  • 运行不起来的,可以看下Project Structure-Bulid-Variants下不同变体的各属性是否缺失
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值