Android 多渠道多环境打包Apk

往往有时候会有打包多套App的需求,而这多个App的logo,启动页,引导页,applicationId,第三方分享key都不一样。放在以往我们的的做法往往使用多套代码进行修改之后再打包,费时费力,后来通过gradle可以轻松完成这个过程,打包也变得很简单。

gradle是一个基于Apache Ant和Apache Maven概念的项目自动化建构工具。他可以帮助我们轻松实现多渠道打包的功能,在这里我用多环境打包演示一下,因为多环境其实和多渠道一样的道理。
项目目录如下:

Android 多渠道多环境打包Apk_第1张图片
58BA6F93-08A8-4AF9-B1CA-7A0DA9723964.png

项目的gradle文件如下:

// Top-level build file where you can add configuration options common to all sub-projects/modules.

buildscript {
    repositories {
        jcenter()
    }
    dependencies {
        classpath 'com.android.tools.build:gradle:2.2.0'

        // NOTE: Do not place your application dependencies here; they belong
        // in the individual module build.gradle files
    }
}

allprojects {
    repositories {
        jcenter()
    }
}

task clean(type: Delete) {
    delete rootProject.buildDir
}

ext {
    // Sdk and tools
    minSdkVersion = 15
    targetSdkVersion = 24
    compileSdkVersion = 24
    buildToolsVersion = '24.0.1'
    versionCode=350
    versionName='3.5.0'

    //package
    applicationId='com.test'

    // App dependencies

}

App下的gradle文件

apply plugin: 'com.android.application'

//获取打包时间
def releaseTime() {
    return new Date().format("yyyyMMdd", TimeZone.getTimeZone("UTC"))
}
//获取local.properties的内容
Properties properties = new Properties()
properties.load(project.rootProject.file('local.properties').newDataInputStream())

android {
    compileSdkVersion rootProject.ext.compileSdkVersion
    buildToolsVersion rootProject.ext.buildToolsVersion

    defaultConfig {
        multiDexEnabled true
        applicationId rootProject.ext.applicationId
        minSdkVersion rootProject.ext.minSdkVersion
        targetSdkVersion rootProject.ext.targetSdkVersion
        versionCode rootProject.ext.versionCode
        versionName rootProject.ext.versionName
    }

    //添加签名文件
    signingConfigs{
        debug{}
        release{
            //为了保护签名文件,把它放在local.properties中并在版本库中排除
            //不把这些信息写入到版本库中(注意,此种方式签名文件中不能有中文)
            storeFile file(properties.getProperty("keystroe_storeFile"))
            storePassword properties.getProperty("keystroe_storePassword")
            keyAlias properties.getProperty("keystroe_keyAlias")
            keyPassword properties.getProperty("keystroe_keyPassword")
           注:这种方案并不是唯一方案,也可以采用直接在这里写死  但推荐以上方式。
        }
    }

    buildTypes {
        release {
            //允许混淆代码
            minifyEnabled true
            //打包过滤掉未引用资源文件
            shrinkResources true
            //引用混淆文件
            proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'
            //设置打包签名
            signingConfig signingConfigs.release
           //批量修改打包之后的命名规则
            applicationVariants.all{  variants ->
                variants.outputs.each{ output ->
                    def outFile=output.outputFile
                    if (outFile!=null && outFile.name.endsWith(".apk"))
                    {
                        def fileName="diankeyuan_"+"${variants.productFlavors[0].name}"+"_V"+"${defaultConfig.versionName}"+"_${releaseTime()}"+".apk"
                        output.outputFile=new File(outFile.parent,fileName);
                    }
                }
            }
        }
    }


    sourceSets {
        main {
            aidl.srcDirs = ['src/main/java']
            jniLibs.srcDirs = ['libs']
            java.srcDirs = ['src/main/java']
            res.srcDirs = ['src/main/res']
            assets.srcDirs = ['assets']
            manifest.srcFile 'src/main/AndroidManifest.xml'
        }
    }
    allprojects {
        repositories {
            mavenCentral()
        }
    }
   //测试环境  预生产环境  生产环境
    productFlavors{
         mtesting{
             manifestPlaceholders = [app_name: "@string/app_name"]
         }
         preing{
             manifestPlaceholders = [app_name: "@string/app_name"]
         }
        normal{
            manifestPlaceholders = [app_name: "@string/app_name"]
        }
    }
  //在项目src目录下,建了mtesting,preing,normal目录,注意都在java目录下并且包名要一样,在项目代码
  //里   可以如下引用:
   **
     * 参数拼接,没有.do
     *
     * @param action
     * @return
     */
     // private String getUrlString(String action) {
     //   if (!action.equals("")) {
     //     return Api.baseurl + action;
     //   }
     //   return Api.baseurl + "/";
     //  }

}

dependencies {
    compile fileTree(include: ['*.jar'], dir: 'libs')
}

local.properties文件

## This file is automatically generated by Android Studio.
# Do not modify this file -- YOUR CHANGES WILL BE ERASED!
#
# This file must *NOT* be checked into Version Control Systems,
# as it contains information specific to your local configuration.
#
# Location of the SDK. This is only used by Gradle.
# For customization when using a Version Control System, please read the
# header note.
#Mon Oct 17 09:15:05 CST 2016
sdk.dir=/Users/luo_mac/Library/Android/sdk
#对应自己实际的证书路径和名字,在这里由于签名文件是放在app目录下,因为没有写绝对路径。
keystroe_storeFile=chuangke.key
keystroe_storePassword=123456
keystroe_keyAlias=chuangke
keystroe_keyPassword=123456

看完build.gradle和local.properties的具体内容之后,我们再来挑选几个地方来具体说一下。

一. signingConfigs

在signingConfigs中主要是为打包配置签名文件具体信息的,第一种方式把签名文件的位置,storePassword ,keyAlias,keyPassword 等具体内容都直接写在其中,然后使用gradle进行打包,第二种是通过通过使用local.properties文件来间接加载签名文件的具体信息。一般我们更倾向于第二种方法,这样有助于保护我们的签名文件(在local.properties中不能有中文)。

二. productFlavors

不同渠道的设置基本都是在 productFlavors 里设置的,在里面想要添加多少个渠道都可以。

不同渠道app名称

manifestPlaceholders = [app_name: "@string/app_name"]

也可以修改app名称,通过resValue 我们可以在在 string.xml 里面添加了一个新的字段app_name,由于是添加,所以原来的string.xml 文件中不能存在app_name字段,否则会报错。
当然我们还可以添加布尔类型,还可以为color.xml、dimen.xml添加一些我们需要的字段。

修改app图标
当我们在productFlavors 中添加了不同渠道环境名称之后,我们还可以mian文件夹同层级中建立渠道对应的文件夹,并放入特定的图标文件,当然我们还可以放入其他资源文件,甚至AndroidManifest.xml都可以放入,Gradle在构建应用时,会优先使用flavor所属dataSet中的同名资源。所以,在flavor的dataSet中添加同名的资源文件,会覆盖默认的资源文件,这样就能达到不同环境不同软件图标的功能。

另外我们在添加签名之后,便可以直接使用命令打出不同渠道的apk包 ,命令是:

 ./gradlew assembleRelease

在使用这个命令时候,第一次也许会报一个-bash: ./gradlew: Permission denied的错误,可先使用如下命令

chmod +x gradlew

就可以编译出你想要的Apk包了,希望能帮到此时的你!!!

你可能感兴趣的:(Android 多渠道多环境打包Apk)