欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页

Android 使用Gradle进行多渠道打包详解

程序员文章站 2024-01-11 15:49:22
...

一、为什么需要多渠道打包?

现在App会上架很多应用商店如:应用宝、小米、华为等,我们需要统计应用商店注册量、下载量等就需要在App中写一个标识然后传给后台进行统计这样的操作就需要用到多渠道打包。

二、为什么不用传统打包方式?

假如现在我们要上架11个应用市场那么我们就要手动打包11次修改标识11次这样重复的操作很容易出错并且也不方便。

三、解决方案

经过我多方调研决定用Gradle进行多渠道打包。

1、在AndroidMainfest中Application标签下配置meta-data标签
 <meta-data
            android:name="CHANNEL"
            android:value="${CHANNEL_VALUE}" />
2、在Gradle中Android标签下配置
  /*配置渠道*/
    productFlavors {
        华为 {
            manifestPlaceholders = [CHANNEL_VALUE: "huawei"]
        }
        小米 {
            manifestPlaceholders = [CHANNEL_VALUE: "xiaomi"]
        }
//
        应用宝 {
            manifestPlaceholders = [CHANNEL_VALUE: "yingyongbao"]
        }
        '360' {
            manifestPlaceholders = [CHANNEL_VALUE: "360"]
        }
        oppo {
            manifestPlaceholders = [CHANNEL_VALUE: "btwj1018oppo"]
        }
        vivo {
            manifestPlaceholders = [CHANNEL_VALUE: "vivo"]
        }
        魅族 {
            manifestPlaceholders = [CHANNEL_VALUE: "meizhu"]
        }
        三星 {
            manifestPlaceholders = [CHANNEL_VALUE: "sanxing"]
        }
        豌豆荚 {
            manifestPlaceholders = [CHANNEL_VALUE: "wandoujia"]
        }
    }
3、如需配置输出路径和apk名称可在Android标签下配置
buildTypes {
        release {
            minifyEnabled true
            shrinkResources true
            zipAlignEnabled true
            proguardFiles getDefaultProguardFile('proguard-android-optimize.txt'), 'proguard-rules.pro'
            // 自定义输出配置
            applicationVariants.all { variant ->
                variant.outputs.all { output ->
                    outputFileName = "app_name_${variant.productFlavors[0].name}_${releaseTime()}.apk"
                }
            }
        }
        }

在gradle中配置releaseTime()

//获取编译时间
static def releaseTime() {
    return new Date().format("yyyy-MM-dd", TimeZone.getTimeZone("UTC"))
}
5、如果配置成功遇到如下错误

Android 使用Gradle进行多渠道打包详解
如果在配置成功后遇到如下错误则在defaultConfig标签中配置flavorDimensions "versionCode"

6、配置示例

AndroidManifest

<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
   >
  <application>
        <meta-data
            android:name="CHANNEL"
            android:value="${CHANNEL_VALUE}" />
    </application>

</manifest>

Gradle

apply plugin: 'com.android.application'

android {
    compileSdkVersion 29
    buildToolsVersion "29.0.3"
    defaultConfig {
        applicationId "com.xxxxxxx.xxxxx"
        minSdkVersion 21
        targetSdkVersion 29
        versionCode 1
        versionName "1.0"
        multiDexEnabled true
        testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner"
        flavorDimensions "versionCode"
    }
    buildTypes {
        release {
            minifyEnabled true
            shrinkResources true
            zipAlignEnabled true
            proguardFiles getDefaultProguardFile('proguard-android-optimize.txt'), 'proguard-rules.pro'
            // 自定义输出配置
            applicationVariants.all { variant ->
                variant.outputs.all { output ->
                    outputFileName = "app_name_${variant.productFlavors[0].name}_${releaseTime()}.apk"
                }
            }
        }
        debug {
            minifyEnabled false
//            shrinkResources true
//            zipAlignEnabled true
            proguardFiles getDefaultProguardFile('proguard-android-optimize.txt'), 'proguard-rules.pro'
        }

    }
    compileOptions {
        sourceCompatibility = 1.8
        targetCompatibility = 1.8
    }
    /*配置渠道*/
    productFlavors {
        华为 {
            manifestPlaceholders = [CHANNEL_VALUE: "huawei"]
        }
        小米 {
            manifestPlaceholders = [CHANNEL_VALUE: "xiaomi"]
        }
        '360' {
            manifestPlaceholders = [CHANNEL_VALUE: "360"]
        }
        oppo {
            manifestPlaceholders = [CHANNEL_VALUE: "oppo"]
        }
        vivo {
            manifestPlaceholders = [CHANNEL_VALUE: "vivo"]
        }
    }
}
//获取编译时间
static def releaseTime() {
    return new Date().format("yyyy-MM-dd", TimeZone.getTimeZone("UTC"))
}

dependencies {
    implementation fileTree(include: ['*.jar'], dir: 'libs')
    implementation 'androidx.appcompat:appcompat:1.1.0'
    implementation 'androidx.constraintlayout:constraintlayout:1.1.3'
    testImplementation 'junit:junit:4.12'
    androidTestImplementation 'androidx.test.ext:junit:1.1.0'
    androidTestImplementation 'androidx.test.espresso:espresso-core:3.2.0'
}

7、获取标识
 public static String getChannel(Context context) {
        try {
            PackageManager manager = context.getPackageManager();
            ApplicationInfo appInfo = manager.getApplicationInfo(context.getPackageName(), PackageManager.GET_META_DATA);
            return appInfo.metaData.getString("CHANNEL");
        } catch (PackageManager.NameNotFoundException e) {
            e.printStackTrace();
            return "";
        }
    }
8、打包

Android 使用Gradle进行多渠道打包详解
每次打包的时候直接选择包就可以了也可以使用gradlew assembleRelease进行批量打包。