Android 详解Gradle(3.1.4)实现多渠道打包

环境

文章的运行环境为:
AndroidStudio版本:3.1.4
Gradle版本:3.1.4

前言

在日常开发中,不同平台,不同客户,我们需要打包不同的版本,有可能还要进行一些显示上的改动。
如果多达几十个版本,我们一个个替换更改,是很让人抓狂的。
因此我们可以通过build.gradle配置,实现多渠道打包,一劳永逸。

问题

仅通过build.gradle配置,不能在代码中用if-else、swith等实现如下四个问题:
1、在同一台手机上能够同时安装debug版本和release版本;
2、在同一台手机上的debug版本和release版本能够在首页上显示自己是debug版本还是release版本;
3、在同一台手机上能够同时安装公司debug版本、公司release版本、医院debug版本、医院release版本;
4、在同一台手机上的公司debug版本、公司release版本、医院debug版本、医院release版本能够在首页上显示自己是什么版本;

由于不能使用if-else,所以就无法使用BuildConfig.DEBUG来判断debug还是release。

代码及目录

GitHub: https://github.com/MyAndroidDemo/MultiChannelPackaging
这里写图片描述

效果图

这里写图片描述

实现

MainActivity

如上效果图,主界面只有两个TextView。
第一个显示当前版本,通过资源文件的string值来控制不同版本显示。
第二个显示当前包名,使用getPackageName()获取。

public class MainActivity extends AppCompatActivity {
    TextView tvPackage;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        tvPackage = findViewById(R.id.tv_package);
        tvPackage.setText("当前包名:" + getPackageName());

    }
}

<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:gravity="center"
    android:orientation="vertical"
    tools:context=".MainActivity">

    <TextView
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:text="@string/home_text"
        android:textColor="#000000"
        android:textSize="18sp" />

    <TextView
        android:id="@+id/tv_package"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_marginTop="20dp"
        android:textColor="#000000"
        android:textSize="18sp" />
LinearLayout>

资源文件的适配

为了达到不同版本显示不同的内容,我们可以对资源文件进行适配。
配置资源文件路径,可动态指定不同版本资源文件。
如上目录所示,我们可以创建格式如:res-版本 来控制不同版本使用不同的资源文件。
版本问题解决了,那么怎么来判断debug还是release?
在build.gradle定义资源文件值,可以在程序中像其他string值一样被引用。
如果不明白的可以查看这两篇文章:
Gradle实现多渠道打包(不同资源文件打不同的包)
Android 同时安装debug release版, 并且显示不同名字

公司版本©的strings.xml
<resources>
    <string name="app_name">Demo(C)string>
    <string name="text_release">Company_releasestring>
    <string name="text_debug">Company_debugstring>
resources>
医院版本(H)的strings.xml
<resources>
    <string name="app_name">Demo(H)string>
    <string name="text_release">Hospital_releasestring>
    <string name="text_debug">Hospital_debugstring>
resources>

配置build.gradle
android {
	...
   //配置资源文件路径,可动态指定不同版本资源文件
    sourceSets {
        //用各自对应的资源文件路径
        company.res.srcDirs = ['src/main/res-company']
        hospital.res.srcDirs = ['src/main/res-hospital']
        ...
    }

    buildTypes {
       //在build.gradle定义资源文件值,可以在程序中像其他string值一样被引用
       //格式resValue 类型, key(不能与strings.xml文件中的相同), value(可以直接使用strings.xml文件中的值)
        debug {
            ...
            resValue "string", "home_text", "@string/text_debug"
            ...
        }
        release {
            ...
            resValue "string", "home_text", "@string/text_release"
            ...
        }
    }
   ....
}

多渠道配置

flavor维度,3.0以上,必须每个渠道版本必须增加,此处以版本号作为维度值
详情见:https://blog.csdn.net/syif88/article/details/75009663/

android {
	...
 //多渠道配置,可以配置多个,此处只配置两个
    productFlavors {
        company {
            //修改包名,能够同时安装多个渠道版本
            applicationId "com.demon.multichannelpackaging.company"
            versionCode 1
            versionName "0.1"
            //flavor维度,3.0以上,必须每个渠道版本必须增加,此处以版本号作为维度值
            //详情见:https://blog.csdn.net/syif88/article/details/75009663/
            flavorDimensions "versionCode"
        }
        hospital {
            //修改包名,能够同时安装多个渠道版本
            applicationId "com.demon.multichannelpackaging.hospital"
            versionCode 1
            versionName "0.1"

            flavorDimensions "versionCode"
        }
    }
    ...
   }

多渠道打包配置

android {
	...
//版本比较多时,自定义导出的APK名称,不同的渠道编出的APK的文件名应该是不一样的
    //Android插件3.0迁移指南所示:
    //用all()而不是each()
    //如果您只更改文件名(这是您的情况),请使用outputFileName而不是output.outputFile
    applicationVariants.all { variant ->
        variant.outputs.all() { output ->
            def flavor = variant.productFlavors[0]
            def fileName = "${variant.flavorName}_${flavor.versionCode}.${variant.versionName}.apk"
            /*//默认打包方式,打包到app的子目录下
            outputFileName = fileName*/
            //修改打包路径,工程apkpackage文件夹下
            //也可以在打包时手动选择对应目录
            def des = output.packageApplication.outputDirectory.toPath().relativize(rootDir.toPath()).toFile()
            outputFileName = new File("$des/apkpackage", fileName)
        }
    }
    ...
 }

build.gradle完整代码

代码注释些的很多,请自行查看。

apply plugin: 'com.android.application'

android {
    compileSdkVersion 28

    dexOptions {
        javaMaxHeapSize "2g"
        preDexLibraries = false
    }

    defaultConfig {
        applicationId "com.demon.multichannelpackaging"
        minSdkVersion 16
        targetSdkVersion 28
        versionCode 1
        versionName "1.0"
        multiDexEnabled true
    }
    //配置资源文件路径,可动态指定不同版本资源文件
    sourceSets {
        //用各自对应的资源文件路径
        company.res.srcDirs = ['src/main/res-company']
        hospital.res.srcDirs = ['src/main/res-hospital']
        //多渠道打包目录配置
        debug.setRoot('build-types/debug')
        release.setRoot('build-types/release')
    }

    //版本比较多时,自定义导出的APK名称,不同的渠道编出的APK的文件名应该是不一样的
    //Android插件3.0迁移指南所示:
    //用all()而不是each()
    //如果您只更改文件名(这是您的情况),请使用outputFileName而不是output.outputFile
    applicationVariants.all { variant ->
        variant.outputs.all() { output ->
            def flavor = variant.productFlavors[0]
            def fileName = "${variant.flavorName}_${flavor.versionCode}.${variant.versionName}.apk"
            /*//默认打包方式,打包到app的子目录下
            outputFileName = fileName*/
            //修改打包路径,工程apkpackage文件夹下
            //也可以在打包时手动选择对应目录
            def des = output.packageApplication.outputDirectory.toPath().relativize(rootDir.toPath()).toFile()
            outputFileName = new File("$des/apkpackage", fileName)
        }
    }
    //debug和release版本的签名配置
    signingConfigs {
        debug {
            storeFile file("DeMon.jks")
            keyAlias = 'key'
            keyPassword = '123456'
            storePassword = '123456'
        }

        release {
            storeFile file("DeMon.jks")
            keyAlias = 'key'
            keyPassword = '123456'
            storePassword = '123456'
        }

    }
    buildTypes {
        //指定打包时的签名,如果有不同的签名可放在productFlavors不同项目下执行,不过一般都会相同
        debug {
            //显示Log
            buildConfigField "boolean", "LOG_DEBUG", "true"
            //apk包名称后缀,用来区分release和debug
            versionNameSuffix "-debug"
            //修改包名,能够同时安装debug和release
            applicationIdSuffix ".debug"
            //在build.gradle定义资源文件值,可以在程序中像其他string值一样被引用
            //格式resValue 类型, key(不能与strings.xml文件中的相同), value(可以直接使用strings.xml文件中的值)
            resValue "string", "home_text", "@string/text_debug"
            minifyEnabled false
            signingConfig signingConfigs.debug
        }
        release {
            //不显示Log
            buildConfigField "boolean", "LOG_DEBUG", "false"
            versionNameSuffix "-release"
            //修改包名,能够同时安装debug和release
            applicationIdSuffix ".release"
            resValue "string", "home_text", "@string/text_release"
            minifyEnabled false
            proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'
            signingConfig signingConfigs.release

        }
    }
    //多渠道配置,可以配置多个,此处只配置两个
    productFlavors {
        company {
            //修改包名,能够同时安装多个渠道版本
            applicationId "com.demon.multichannelpackaging.company"
            versionCode 1
            versionName "0.1"
            //flavor维度,3.0以上,必须每个渠道版本必须增加,此处以版本号作为维度值
            //详情见:https://blog.csdn.net/syif88/article/details/75009663/
            flavorDimensions "versionCode"
        }
        hospital {
            //修改包名,能够同时安装多个渠道版本
            applicationId "com.demon.multichannelpackaging.hospital"
            versionCode 1
            versionName "0.1"

            flavorDimensions "versionCode"
        }
    }
}

dependencies {
    implementation fileTree(dir: 'libs', include: ['*.jar'])
    implementation 'com.android.support:appcompat-v7:28.0.0-rc02'
    implementation 'com.android.support.constraint:constraint-layout:1.1.2'
}

参考

Gradle实现多渠道打包(不同资源文件打不同的包)
Android 同时安装debug release版, 并且显示不同名字
https://blog.csdn.net/syif88/article/details/75009663/

你可能感兴趣的:(#,Android笔记)