安卓项目中 gradle 文件使用技巧小结

官方说明

https://developer.android.google.cn/studio/build?hl=zh_cn#groovy

下载加速

Android studio 下载东西太慢了,可以试试阿里云的仓库,在项目的 gradle 文件中配置:

buildscript {
    repositories {
        //jcenter()
        maven{ url'https://maven.aliyun.com/repository/google/' }
        maven{ url'https://maven.aliyun.com/repository/public/' }//central仓和jcenter仓的聚合仓
        google()
    }
    dependencies {
        classpath 'com.android.tools.build:gradle:3.6.1'
        // NOTE: Do not place your application dependencies here; they belong
        // in the individual module build.gradle files
    }
}

allprojects {
    repositories {
        //jcenter()
        maven{ url'https://maven.aliyun.com/repository/google/' }
        maven{ url'https://maven.aliyun.com/repository/public/' }//central仓和jcenter仓的聚合仓
        google()
    }
}

ps. jcenter 停止维护了,不知道会不会有影响。

统一版本控制

有时候一个安卓项目中有多个 module,其中的版本一般需要一致,可以在项目的 gradle 文件中统一配置,使用如下:

ext {
    compileSdkVersion = 28
    buildToolsVersion = "28.0.3"
    minSdkVersion = 19
    targetSdkVersion = 28

    //数组,注意上面是等号,下面是冒号,其实是一个map
    var = [
    	supportLibraryVersion : '28.0.0'
    ]
}

使用(这里要注意变量都是 string 类型的,其他类型要转换一下):

android {
    ...
	defaultConfig {
        minSdkVersion rootProject.ext.minSdkVersion
        targetSdkVersion rootProject.ext.targetSdkVersion
    }
}

dependencies {
    ...
    api "com.android.support:appcompat-v7:$rootProject.supportLibraryVersion"
    api "com.android.support:appcompat-v7:${supportLibraryVersion}"
}

也可以将 ext 写到文件中,例如根目录下 config.gradle,最后在 build.gradle 中导入就可以了:

apply from:'config.gradle'

配置密钥,使用 gradle 打包

使用 Android studio 打包的时候都要点好多下,其实可以通过配置好密钥,使用 gradle 命令打包。

首先在根目录下的 local.properties 文件中定义变量

key.file=D\:\\SDK\\Android\\xxx.keystore
keyAlias=xxx
keyPassword=xxx
storePassword=xxx

这个 local.properties 文件注意在根目录下的 .gitignore 保证不会被引入,默认应该就可以了

# Local configuration file (sdk path, etc)
local.properties

读取密钥信息如下:

android {
	...
	signingConfigs {
        release {
            //加载资源
            Properties properties = new Properties()
            InputStream inputStream = project.rootProject.file('local.properties').newDataInputStream()
            properties.load(inputStream)

            //读取文件
            def keyDir = properties.getProperty('key.file')
            storeFile file( keyDir )

            //读取字段
            def key_keyAlias = properties.getProperty('keyAlias')
            def key_keyPassword = properties.getProperty('keyPassword')
            def key_storePassword = properties.getProperty('storePassword')

            storePassword key_storePassword
            keyAlias key_keyAlias
            keyPassword key_keyPassword
        }
    }

}

使用 gradle 打包,在你的 Android studio 侧边栏找到 gradle 打开,在 app 目录下的 Run Configurations 里面找到 assemble 双击就可以打包了。

修改打包输出文件名

每次 Android studio 打包输出的文件都是默认的 release.apk,我们可以修改默认文件名,改成带版本号等信息,省的给测试的时候还得手动改名字,方法如下:

android {
	android.applicationVariants.all { variant ->
        variant.outputs.all {
            outputFileName = "xxx_${variant.name}_${variant.versionName}.apk"
        }
    }
	...
}

这里的 variant 可以看下面差异化打包那节,用谷歌的文档来说叫产品变种,其实就是一个项目打包成多个产品的意思吧。这里对所有变种,修改了它们的 outputFileName 属性,改成了我们需要的输出 apk 名称,至于 applicationVariants 有关属性,可以参考下面这篇博客,或者官方文档(好像没什么用):

操作task之applicationVariants

http://www.manongjc.com/detail/16-tooggtpfetmzyry.html

官方文档

https://developer.android.google.cn/reference/tools/gradle-api/7.0/com/android/build/api/variant/ApplicationVariant

区分正式版、测试版

正式版和测试版的 app 装在我们的手机上,真的是分辨不出来,而且包名一样,混着安装就会安装失败,那么如何解决这个问题呢?看下面

修改测试版包名

在 gradle 中提供了 versionNameSuffix 和 applicationIdSuffix 来让我们修改版本名和包名

android {
	...
	buildTypes {
		...
		debug {
			versionNameSuffix '.2'
            applicationIdSuffix '.debug'
		}
	}
}
修改测试版图标、文字等

和上面类似,gradle 中还提供了 manifestPlaceholders 变量,可以让我们在 manifest 中引用这些变量,控制不同的图标等。

android {
	...
	buildTypes {
		...
		debug {
			...
            manifestPlaceholders = [app_name:"@string/app_name_debug", app_icon:"@mipmap/ic_launcher_debug"}
		}
	}
}

manifest 中使用:

<application
        android:name=".MyApplication"
        android:allowBackup="false"
        android:icon="${app_icon}"
        android:label="${app_name}"、
        ...
        />

差异化打包(多渠道打包)

有时候不同的客户会要求不同的展示效果,比如换换 logo 什么的啊,如果东西比较少,多弄一份工程肯定是不划算的,这时候就要用到 productFlavors 这个属性了,和多渠道打包一样,不过我们这不是为了发不同的应用市场,使用如下:

android {
 	...
    productFlavors {
        first {
            applicationId 'xxx.xxx.xxx'
            buildConfigField "String", "PRODUCT_SERVER", "\"xxx.xxx.xxx.com\""
            buildConfigField "boolean", "xxx", "true"
            manifestPlaceholders = [app_name : "@string/app_name",app_icon : "@mipmap/ic_launcher"]
        }
        second {
            applicationId 'xxx.xxx.xxx2'
            buildConfigField "String", "PRODUCT_SERVER", "\"x.x.xxx.com\""
            buildConfigField "boolean", "xxx", "false"
            manifestPlaceholders = [app_name : "@string/app_name",app_icon : "@mipmap/ic_launcher"]
        }
    }
}

配置好后,我们侧边栏的 Build Variant 中就有对应两套 app 的四个 variant (release 和 debug),侧边栏的 app 目录下的 Run Configurations 里面也会多几个打包命令,需要打包哪个应用选择对应命令就行。

applicationId 以及 manifestPlaceholders 应该不用介绍了,上面有提及,具体说下 buildConfigField 的使用,实际上它会保存到我们的 BuildConfig 文件中:

private final static String SERVER_ADDR_RELEASE = BuildConfig.PRODUCT_SERVER;

这里就可以判断我们的服务器地址了,这里还可以用不同的文件夹来展示不同的数据,可以参考网上多渠道打包的博客,下面给出两篇。


结语

分享了一些挺有意思的技巧,希望对大家有所帮助!

end