1.配置签名信息

场景:在应用中牵扯到第三方平台集成的话,因为很多第三方要求正式签名后生成的包才可以正常使用。所以,在debug模式下配置正式签名包,就可以解决问题。
配置示例:

android {...signingConfigs {    myConfig {        //storeFile file("你的storeFile")当签名文件在app目录下的时候不用写路径。也可以放在别的目录下,写出路径即可:storeFile file("D:/wh/wh-keystore.jks")        storeFile file("你的storeFile")        storePassword "你的storePassword"        keyAlias "你的keyAlias"        keyPassword "你的keyAlias"    }}buildTypes { debug {//android studio直接运行的时候是安装的这里生成的apk,不配置这里相当于运行时用的还是临时签名            signingConfig signingConfigs.myConfig//签名        }    release {        signingConfig signingConfigs.myConfig//签名        minifyEnabled false        proguardFiles getDefaultProguardFile('proguard-android-optimize.txt'), 'proguard-rules.pro'    }}...}

对于签名相关的信息,直接写在gradle当然不好,特别是一些开源项目,可以添加到local.properties,然后从中读取需要的信息:
示例:

key.file=D\:/wh/wh-keystore.jksstorePassword=xxxkeyAlias=xxxkeyPassword=xxx

然后在build.gradle中引用即可:

android {...    signingConfigs {        myConfig {            //加载资源            Properties properties = new Properties()            InputStream inputStream = project.rootProject.file('local.properties').newDataInputStream() ;            properties.load( inputStream )            //读取文件            def sdkDir = properties.getProperty('key.file')            storeFile file( sdkDir )            //读取字段            def key_storePassword = properties.getProperty( 'storePassword' )            def key_keyAlias = properties.getProperty( 'keyAlias' )            def key_keyPassword = properties.getProperty( 'keyPassword' )            storePassword key_storePassword            keyAlias key_keyAlias            keyPassword key_keyPassword        }    }    ...}

2.使用 gradle 在编译时动态设置 Android BuildConfig

在build.gradle中动态的替换掉java中的变量。
在你的 gradle 文件 buildTypes 或者 productFlavors 下面,debug、release等体内写buildConfigField 设置,示例如下:

android{...    buildTypes {        debug {            buildConfigField ("String", "APP_HOST ", "\"http://example.com1/\"")            buildConfigField ("boolean", "LOG_DEBUG", "false")        }        release {            minifyEnabled false            proguardFiles getDefaultProguardFile('proguard-android-optimize.txt'), 'proguard-rules.pro'            buildConfigField ("String", "APP_HOST ", "\"http://example.com2/\"")            buildConfigField ("boolean", "LOG_DEBUG", "false")        }    }    ...}

gradle sync 一下后,BuildConfig.APP_HOST 就会被赋值为 http://example.com 就可以供 Java 代码调用了。使用例子:
有时会不同步,重新build一下。

public static final String MY_URL= BuildConfig.APP_HOST + "xxx";//显示http://example.com/xxxif (BuildConfig.LOG_DEBUG) {    //不打日志}else{    //打日志}

3.使用 gradle 在编译时动态设置 Android Manifest

场景:例如:百度地图等服务 在多渠道打包的时候,不同的包得需要配置不同的API_KEY(包名不一样平台会生成不同的API_KEY)。
在AndroidManifest中定义一个变量,在build.gradle中动态的替换掉,十分方便,语法也十分简单。
例子:
在AndroidManifest中定义一个变量

<meta-data         android:name="UMENG_APPKEY"         android:value="${umeng_app_key}"/><meta-data         android:name="UMENG_SECRET"         android:value="${umeng_app_secret}"/>

接着,我们在build.gradle文件中根据不同的环境或者不同的包(多渠道打包,内容有差别,详看后文)中,生成不同appkey的apk。

buildTypes {        debug {            /*一博客里看到的可以这样用,记下备忘:            manifestPlaceholders = [app_label:"@string/app_name_debug"]*/            manifestPlaceholders = [                umeng_app_key: "你替代的内容",                umeng_app_secret:"你要替换的内容"]        }        release {       manifestPlaceholders = [                umeng_app_key: "你替代的内容",                umeng_app_secret:"你要替换的内容"]        }        develop {      manifestPlaceholders = [                umeng_app_key: "你替代的内容",                umeng_app_secret:"你要替换的内容"]        }    }

注意:这里的“你替代的内容”,不能为特殊关键词,比如:TRUE,否则在Java代码中获取不到meta-data中的值

不止在meta-data中,其他地方也可以配置,如
QQ的APP_ID,个推的APP_ID。

<activityandroid:name="com.mob.tools.MobUIShell"...>    <intent-filter>        <data android:scheme="tencent${QQ_APP_ID}" />...    intent-filter>activity>
<receiver...    >                <action android:name="com.igexin.sdk.action.${GETUI_APP_ID}" />    intent-filter>receiver>

在多渠道打包中使用示例:

android{...//多渠道打包    productFlavors {        one {...            //个推配置参数            manifestPlaceholders = [                    //个推                    GETUI_APP_ID    : "xxxxxxxx",                    //qq的APPID                    QQ_APP_ID       : "xxxxxxxx",            ]            return true        }        two {        ...            manifestPlaceholders = [                    GETUI_APP_ID    : "xxxxxxxxxx",                    QQ_APP_ID       : "xxx",            ]            return true        }...}

4多工程全局配置(一博客里复制的)

随着产品渠道的铺开,往往一套代码需要支持多个产品形态,这就需要抽象出主要代码到一个Library,然后基于Library扩展几个App Module。
相信每个module的build.gradle都会有这个代码:

android {    compileSdkVersion 22    buildToolsVersion "23.0.1"    defaultConfig {        minSdkVersion 10        targetSdkVersion 22        versionCode 34        versionName "v2.6.1"    }}

当升级sdk、build tool、target sdk等,几个module都要更改,非常的麻烦。最重要的是,很容易忘记,最终导致app module之间的差异不统一,也不可控。
强大的gradle插件在1.1.0支持全局变量设定,一举解决了这个问题。
先在project的根目录下的build.gradle定义ext全局变量:

ext {    compileSdkVersion = 22    buildToolsVersion = "23.0.1"    minSdkVersion = 10    targetSdkVersion = 22    versionCode = 34    versionName = "v2.6.1"}

然后在各module的build.gradle中引用如下:

android {    compileSdkVersion rootProject.ext.compileSdkVersion    buildToolsVersion rootProject.ext.buildToolsVersion    defaultConfig {        applicationId "com.xxx.xxx"        minSdkVersion rootProject.ext.minSdkVersion        targetSdkVersion rootProject.ext.targetSdkVersion        versionCode rootProject.ext.versionCode        versionName rootProject.ext.versionName    }}

然后每次修改project级别的build.gradle即可实现全局统一配置。

5.自定义导出的APK名称

static def releaseTime() {    return new Date().format("MMdd", TimeZone.getTimeZone("UTC"))}android{...    //不同的打包生成自定义的名称    applicationVariants.all { variant ->        variant.outputs.all { output ->            def outputFile = output.outputFile            if (outputFile != null && outputFile.name.endsWith('.apk')) {                def huanJing;                if (variant.buildType.name == 'release') {                    huanJing = "s";                } else if (variant.buildType.name == 'debug') {                    huanJing = "c";                } else {                    huanJing = "${variant.buildType.name}";                }                def apkName                // 如果有渠道,显示渠道名""                if (variant.flavorName != "") {                    apkName = huanJing + "${releaseTime()}${variant.productFlavors[0].name}${variant.versionName}.apk"/*名字示例:s0613one1.2.apk*/                } else {                    apkName = huanJing + "${releaseTime()}v${variant.versionName}.apk"                }                outputFileName = apkName            }        }    }...}

6.多渠道打包不同版本资源不同

根据业务的需求,有时我们需要打不同的包,发布不同的版本,可在gradle中进行配置。

android{...defaultConfig {...    flavorDimensions "default"...}//多渠道打包    productFlavors {        one {            applicationId "com.hjqjl.testdemo"            versionCode 2            versionName "1.2"            //配置参数            manifestPlaceholders = [                    PACKAGE_NAME : applicationId,                    //百度                    BAIDU_API_KEY: "0",            ]            //buildConfigField ("String", "APP_PRODUCTID", "\"my1\"")            //如果想在代码里面使用BAIDU_API_KEY,如下:            //buildConfigField "String", "BAIDU_API_KEY", "\"" + manifestPlaceholders.BAIDU_API_KEY + "\""            return true        }        two {            applicationId "com.hjqjl.two"            versionCode 3            versionName "1.3"            manifestPlaceholders = [                    PACKAGE_NAME : applicationId,                    BAIDU_API_KEY: "0",            ]            return true        }    }...}

多渠道打包的时候不同的版本可能有一部分代码不同或布局或资源文件,需要在src下创建与渠道名相同的文件夹,将资源文件放进去。运行时会自动获取相应文件下的资源文件。

下面是一个示意图,自己体会:

整体的gradle如下:

apply plugin: 'com.android.application'static def releaseTime() {    return new Date().format("MMdd", TimeZone.getTimeZone("UTC"))}android {    compileSdkVersion 29    defaultConfig {        minSdkVersion 21        targetSdkVersion 29        flavorDimensions "default"        testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner"    }    //多渠道打包    productFlavors {        one {            applicationId "com.hjqjl.testdemo"            versionCode 2            versionName "1.2"            //配置参数            manifestPlaceholders = [                    PACKAGE_NAME : applicationId,                    //百度                    BAIDU_API_KEY: "0",            ]            buildConfigField("String", "APP_PRODUCTID", "\"my1\"")            //如果想在代码里面使用BAIDU_API_KEY,如下:            //buildConfigField "String", "BAIDU_API_KEY", "\"" + manifestPlaceholders.BAIDU_API_KEY + "\""            return true        }        two {            applicationId "com.hjqjl.two"            versionCode 3            versionName "1.3"            manifestPlaceholders = [                    PACKAGE_NAME : applicationId,                    BAIDU_API_KEY: "0",            ]            buildConfigField("String", "APP_PRODUCTID", "\"my2\"")            return true        }    }    buildTypes {        debug {            buildConfigField("String", "APP_HOST ", "\"http://example.com/\"")            buildConfigField("boolean", "LOG_DEBUG", "false")        }        release {            minifyEnabled false            proguardFiles getDefaultProguardFile('proguard-android-optimize.txt'), 'proguard-rules.pro'            buildConfigField("String", "APP_HOST ", "\"http://example.com/\"")            buildConfigField("boolean", "LOG_DEBUG", "false")        }    }/*  //注释部分为配置签名信息(实现运行的时候用真实签名,不是临时签名),    //因为签名文件等 位于本地,不上传Gitee,clone下来要进行调试,所以这一部分进行注释了。    signingConfigs {        //从本地读取签名信息,配置签名信息        myConfig {            //加载资源            Properties properties = new Properties()            InputStream inputStream = project.rootProject.file('local.properties').newDataInputStream()            properties.load(inputStream)            //读取文件            def sdkDir = properties.getProperty('key.file')            storeFile file( sdkDir )            //读取字段            def key_storePassword = properties.getProperty( 'storePassword' )            def key_keyAlias = properties.getProperty( 'keyAlias' )            def key_keyPassword = properties.getProperty( 'keyPassword' )            storePassword key_storePassword            keyAlias key_keyAlias            keyPassword key_keyPassword        }    }    buildTypes {        debug {            //android studio直接运行的时候是安装的这里签名生成的apk,不配置这里相当于运行时用的还是临时签名            // (myConfig的名字如果是debug的话,因为默认名字的关系,不配置这里也会用你的签名)            signingConfig signingConfigs.myConfig//签名        }        release {            signingConfig signingConfigs.myConfig//签名            minifyEnabled false            proguardFiles getDefaultProguardFile('proguard-android-optimize.txt'), 'proguard-rules.pro'        }    }    */    //不同的打包生成自定义的名称    applicationVariants.all { variant ->        variant.outputs.all { output ->            def outputFile = output.outputFile            if (outputFile != null && outputFile.name.endsWith('.apk')) {                def huanJing;                if (variant.buildType.name == 'release') {                    huanJing = "s";                } else if (variant.buildType.name == 'debug') {                    huanJing = "c";                } else {                    huanJing = "${variant.buildType.name}";                }                def apkName                // 如果有渠道,显示渠道名""                if (variant.flavorName != "") {                    apkName = huanJing + "${releaseTime()}${variant.productFlavors[0].name}${variant.versionName}.apk"/*名字示例:s0613one1.2.apk*/                } else {                    apkName = huanJing + "${releaseTime()}v${variant.versionName}.apk"                }                outputFileName = apkName            }        }    }    buildFeatures {        viewBinding = true    }}dependencies {    implementation fileTree(dir: "libs", include: ["*.jar"])    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.1'    androidTestImplementation 'androidx.test.espresso:espresso-core:3.2.0'    implementation 'com.gitee.hjqjl:AndroidUtils:1.0.2-beta'}

源码:https://gitee.com/hjqjl/WhDemo

更多相关文章

  1. android项目R文件丢失怎么办
  2. Android应用开发之XML文件解析之一
  3. 【转】Android(安卓)性能优化之内存检测、卡顿优化、耗电优化、A
  4. 《第一行代码》-第一次学习笔记(第一章).md
  5. 基础知识:android 数据存储--->文件存储
  6. Android中把文件存放在SDCard
  7. NDK简单实例
  8. android 定制个性按钮 控件
  9. 【Android】Android(安卓)Studio中新创建的app目录结构

随机推荐

  1. Android真机测试 连接本地服务器 手机测
  2. 2020年Android开发的未来发展方向该如何
  3. 简述android线程间消息处理机制(Looper、H
  4. Android(安卓)Studio 一些方便使用的设置
  5. Andriod内嵌HTML5项目构建以及整包更新配
  6. [置顶] android 多媒体和相机详解六
  7. Android(安卓)XML shape 标签使用详解(ap
  8. Android车轮之图片加载框架Android-Unive
  9. Android(安卓)即时音视频解决方案2——腾
  10. [Android]自定义View(一):坐标系