赞
踩
开发某个应用,基本功能是一样的,在打包的时候,区分渠道、配置不同的包名、签名。
很简单,新建一个默认的 Hello World 工程就可以了。
在 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>
修改 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
栏出现多选,说明成功了。
通过 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
}
// ...
}
新建的工程,图标不是直接用的 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 ,需要修改哪个渠道的东西,还是要先切到该渠道。
在代码中如果需要判断渠道,用 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";
}
切换到需要的渠道,然后 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 、图标也不一样。
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。