Android Studio的gradle配置

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.jks
storePassword=xxx
keyAlias=xxx
keyPassword=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/xxx
if (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。

<!-- 分享 ==== -->
<activity
	android:name="com.mob.tools.MobUIShell"
	...>
    <intent-filter>
        <data android:scheme="tencent${QQ_APP_ID}" />
		...
    </intent-filter>
</activity>
<!-- 个推配置第三方Receiver -->
<receiver
	...
    <intent-filter>
        <!-- 替换为action android:name="com.igexin.sdk.action.第三方应用APPID" -->
        <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/wh-demo

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值