多渠道打包:一套代码打包多个应用,配置不一样的应用名、包名、签名、图标

开发某个应用,基本功能是一样的,在打包的时候,区分渠道、配置不同的包名、签名。

1.新建一个工程

很简单,新建一个默认的 Hello World 工程就可以了。

2.新建对应渠道的文件夹

在 src 目录新建一个文件夹 qudao1 ,然后照着 main 文件的样子生成一样的目录,只需要目录,各目录下的文件先不要。
(要也不影响,本篇主要讲配置,不改代码)

在 src 目录新建一个文件夹 qudao2 ,操作同新建 qudao1 。

为了区分,我们简单修改下 string.xml ,

main 下的,

<resources>
    <string name="app_name">OneAppMutilBale</string>
</resources>

qudao1 的,

<resources>
    <string name="app_name">OneAppMutilBaleQudao1</string>
</resources>

qudao2 的,

<resources>
    <string name="app_name">OneAppMutilBaleQudao2</string>
</resources>

3.配置渠道

修改 app 的 build.gradle

添加 sourceSets { } ,指明各个模块用的文件夹 。添加这个需要配置 flavorDimensions "app" ,要不然报错,app 可以替换成其他名称。

添加 productFlavors { } ,指明渠道,按渠道配置包名、版本号等。
applicationId 是最终生成的 apk 的包名。
其中的 base 、qudao1、qudao2 自己取名就行。
dimension 对应 flavorDimensions 。

plugins {
    id 'com.android.application'
}

android {
    compileSdkVersion 30

    defaultConfig {
        applicationId "com.cosmos.oneappmutilbale"
        minSdkVersion 23
        targetSdkVersion 30
        versionCode 1
        versionName "1.0"
        flavorDimensions "app"
        testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner"
    }

    buildTypes {
        release {
            minifyEnabled false
            proguardFiles getDefaultProguardFile('proguard-android-optimize.txt'), 'proguard-rules.pro'
        }
    }
    compileOptions {
        sourceCompatibility JavaVersion.VERSION_1_8
        targetCompatibility JavaVersion.VERSION_1_8
    }

    sourceSets {
        base {
            java.srcDir('src/main/java')
            res.srcDir('src/main/res')
            // assets.srcDir('src/main/assets')
            // manifest.srcFile('src/main/AndroidManifest.xml')
        }

        qudao1 {
            java.srcDir('src/qudao1/java')
            res.srcDir('src/qudao1/res')
            // assets.srcDir('src/qudao1/assets')
            // manifest.srcFile('src/qudao1/AndroidManifest.xml')
        }
    }
    }

    productFlavors {
        base {
            applicationId "com.cosmos.oneappmutilbale"
            dimension "app"
            versionCode 1
            versionName "1.0"
        }
        qudao1 {
            applicationId "com.cosmos.oneappmutilbale.q1"
            dimension "app"
            versionCode 1
            versionName "1.1"
        }
    }

    applicationVariants.all {
        variant ->
            variant.outputs.all {
                outputFileName = "OneAppMutilBale_${variant.productFlavors[0].name}_v${variant.productFlavors[0].versionName}.apk"
            }
    }
}

dependencies {
    implementation 'androidx.appcompat:appcompat:1.2.0'
    implementation 'com.google.android.material:material:1.2.1'
    implementation 'androidx.constraintlayout:constraintlayout:2.0.1'
    testImplementation 'junit:junit:4.+'
    androidTestImplementation 'androidx.test.ext:junit:1.1.2'
    androidTestImplementation 'androidx.test.espresso:espresso-core:3.3.0'
}

applicationVariants.all { } 部分是指定生成的 apk 的名字。

同步一下,如果在 Build Variants 栏出现多选,说明成功了。
在这里插入图片描述

4.配置不同的渠道签名

通过 AS 生成多个 jks 签名。(具体过程省略)

我新建了一个 jks 目录(路径 src/jks)用来存放 jks 签名文件。

修改 app 的 build.gradle ,

添加 signingConfigs { } ,指明 jks 路径和密码。其中的 signbase 、signqudao1 、signqudao2 自己取名就行。

plugins {
    id 'com.android.application'
}

android {
    compileSdkVersion 30

    defaultConfig {
        applicationId "com.cosmos.oneappmutilbale"
        minSdkVersion 23
        targetSdkVersion 30
        versionCode 1
        versionName "1.0"
        flavorDimensions "app"
        testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner"
    }

    buildTypes {
        release {
            minifyEnabled false
            proguardFiles getDefaultProguardFile('proguard-android-optimize.txt'), 'proguard-rules.pro'
        }
    }
    compileOptions {
        sourceCompatibility JavaVersion.VERSION_1_8
        targetCompatibility JavaVersion.VERSION_1_8
    }

    sourceSets {
        base {
            java.srcDir('src/main/java')
            res.srcDir('src/main/res')
            // assets.srcDir('src/main/assets')
            // manifest.srcFile('src/main/AndroidManifest.xml')
        }

        qudao1 {
            java.srcDir('src/qudao1/java')
            res.srcDir('src/qudao1/res')
            // assets.srcDir('src/qudao1/assets')
            // manifest.srcFile('src/qudao1/AndroidManifest.xml')
        }

        qudao2 {
            java.srcDir('src/qudao2/java')
            res.srcDir('src/qudao2/res')
            // assets.srcDir('src/qudao2/assets')
            // manifest.srcFile('src/qudao2/AndroidManifest.xml')
        }
    }

    signingConfigs {
        signbase {
            storeFile file("src/jks/main.jks")
            storePassword "123456"
            keyAlias "keymain"
            keyPassword "123456"
            // 开启 V2 签名
            v2SigningEnabled true
        }
        signqudao1 {
            storeFile file("src/jks/qudao1.jks")
            storePassword "789456"
            keyAlias "keyqudao1"
            keyPassword "789456"
            v2SigningEnabled true
        }
        signqudao2 {
            storeFile file("src/jks/qudao2.jks")
            storePassword "456123"
            keyAlias "keyqudao2"
            keyPassword "456123"
            v2SigningEnabled true
        }
    }

    productFlavors {
        base {
            applicationId "com.cosmos.oneappmutilbale"
            dimension "app"
            versionCode 1
            versionName "1.0"
            signingConfig signingConfigs.signbase
        }
        qudao1 {
            applicationId "com.cosmos.oneappmutilbale.q1"
            dimension "app"
            versionCode 1
            versionName "1.1"
            signingConfig signingConfigs.signqudao1
        }
        qudao2 {
            applicationId "com.cosmos.oneappmutilbale.q2"
            dimension "app"
            versionCode 2
            versionName "2.0"
            signingConfig signingConfigs.signqudao2
        }
    }

    applicationVariants.all {
        variant ->
            variant.outputs.all {
                outputFileName = "OneAppMutilBale_${variant.productFlavors[0].name}_v${variant.productFlavors[0].versionName}.apk"
            }
    }
}

dependencies {
    implementation 'androidx.appcompat:appcompat:1.2.0'
    implementation 'com.google.android.material:material:1.2.1'
    implementation 'androidx.constraintlayout:constraintlayout:2.0.1'
    testImplementation 'junit:junit:4.+'
    androidTestImplementation 'androidx.test.ext:junit:1.1.2'
    androidTestImplementation 'androidx.test.espresso:espresso-core:3.3.0'
}

为了密码的安全的,可以把实际的信息写到 gradle.properties 文件中, build.gradle 引用即可。

gradle.properties 添加如下,

JKSFILE=/src/jks/main.jks
JKSPASSWORD=123456
KEYALIAS=keymain
KEYPASSWORD=123456

build.gradle 引用,

	signingConfigs {
        signbase {
            storeFile file(JKSFILE)
            storePassword JKSPASSWORD
            keyAlias KEYALIAS
            keyPassword KEYPASSWORD
            // 开启 V2 签名
            v2SigningEnabled true
        }
        // ...
    }

5.修改图标

新建的工程,图标不是直接用的 drawable 下的图片,是这样用的,

android:roundIcon="@mipmap/ic_launcher_round"

ic_launcher_round.xml 内容如下,

<?xml version="1.0" encoding="utf-8"?>
<adaptive-icon xmlns:android="http://schemas.android.com/apk/res/android">
    <background android:drawable="@drawable/ic_launcher_background" />
    <foreground android:drawable="@drawable/ic_launcher_foreground" />
</adaptive-icon>

ic_launcher_background.xml 内容如下,

<?xml version="1.0" encoding="utf-8"?>
<vector xmlns:android="http://schemas.android.com/apk/res/android"
    android:width="108dp"
    android:height="108dp"
    android:viewportWidth="108"
    android:viewportHeight="108">
    <path
        android:fillColor="#4DDC84"
        android:pathData="M0,0h108v108h-108z" />
	// ...
>

为了改出差异,将 main 目录下的 ic_launcher_background.xml 文件 拷贝到 qudao1 、qudao2 目录下,并放在对应的目录下(目录要一致,这很重要),
然后修改 android:fillColor 属性,换成不同的颜色就可以了。

引申,要用不同的资源文件,需要在对应渠道的对应目录下放入main文件夹下的同名文件,保证目录结构一样,然后修改渠道下的文件就可以了。

icon 、lable 、roundIcon 属性都是这样改。

android:icon="@mipmap/ic_launcher"
android:label="@string/app_name"
android:roundIcon="@mipmap/ic_launcher_round"

有个点 mark 一样。Build Variants 切到 qudao1 时,修改 qudao1 下的 xml 才会有代码提示、并且不爆红。
so ,需要修改哪个渠道的东西,还是要先切到该渠道。

6.代码中判断渠道

在代码中如果需要判断渠道,用 BuildConfig ,它是编译生成的。和 productFlavors { } 里的信息一一对应 。

我的 demo 生成的,示例,

package com.cosmos.oneappmutilbale;

public final class BuildConfig {
  public static final boolean DEBUG = false;
  public static final String APPLICATION_ID = "com.cosmos.oneappmutilbale.q2";
  public static final String BUILD_TYPE = "release";
  public static final String FLAVOR = "qudao2";
  public static final int VERSION_CODE = 2;
  public static final String VERSION_NAME = "2.0";
}

7.安装验证

切换到需要的渠道,然后 build apk 就可以生成该渠道的 apk 了。

使用 Gradle 编译,可以一次生成多个渠道的 apk 了。
在这里插入图片描述
这里我用了不一样的签名,生成的 apk 签名肯定是不一样的。如何验证呢?

build 之后,会在 app/build/outputs/apk/ 目录生成多个渠道的 apk ,在 Terminal 栏使用如下命令查看 apk 的签名,

keytool -printcert -jarfile apk_path

apk_path 是 apk 的路径。
在这里插入图片描述
3 个渠道的 apk ,用的 jks 不一样,对应的结果是不一样的,说明已配置了不一样的签名。

3 个渠道的应用,包名不一样,可以安装到同一台机器上。对应的 app_name 、图标也不一样。
在这里插入图片描述

评论 3
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值