背景
最近在封装一个分享功能库,因为没有自己的腾讯\微信\微博开放平台账号,所以使用了公司项目的api_key和keystore,于是带来了一个问题,这些信息是绝对不能提交到github上去的,所以每次提交代码时,都需要把相关的代码删除。某次,提交代码时忘了这一步操作,误将这些敏感的信息push到了github上,急忙使用git命令来挽救这次失误:
git reset --hard <commit_id>
git push origin HEAD --force
在挽救回这次操作之后,我开始反思、寻找更好的解决方法,最终目标是让 代码脱敏 ,即无论怎么迭代代码,push时都不用再担心会把敏感信息误提交了。
配置文件
首先,我们先来回顾一下Android Studio里的Project板块,当展示模式切换成Android之后,我们会看到有一个Gradle Scripts的集合,今天的主角都在这里面,让我们暂时先忘记日常写代码的module,把全部的注意力放在Gradle Scripts部分。
在图中,我们可以看到gradle.properties(Global Properties)、gradle.prooperties(Project Properties)、local.properties(SDK Location)等三个配置文件,而它们就是我们的武器。
gradle.properties(Global Properties)
从文件名后的注释我们可以知道,它是Gradle全局性的配置文件,在Linux、Mac中,它位于/Users/{YOUR_NAME}/.gradle/,windows用户请自行google确定它的位置。也有部分用户可能会没有这个文件,此时应该自己创建一个,它会在我们日常工作中提供非常大的帮助。
打开这个文件,我们可以看到,里面默认配置了gradle的JVM最大可用内存、持久代可用大小、以及一些gradle的优化参数,这些配置是所有项目共享的。
跟随这一思路,当我们有某些配置是所有项目都会用到的,那么就可以把它配置在这个文件中,这样就不必每次新建、clone一个项目之后,还要去一一配置。比如bintray、nexus的账号信息。
由于这个文件并不在项目下,所以我们可以大胆的把敏感信息配置在里面,而不用担心会push到git上。
gradle.properties(Project Properties)
顾名思义,这个文件是项目级的配置文件,由于它会被提交到git上,所以不适合配置敏感信息,此处就不多做介绍。一般这个配置文件中会配置项目级的功能开关,比如android.useAndroidX、android.enableJetifier等。
在现在比较流行的组件化开发中,module是application还是library的开关通常也会配置在这里。
local.properties(SDK Location)
这个文件中默认配置了本地的sdk、ndk路径。该文件的header中写到:
This file must NOT be checked into Version Control Systems
然而,这个文件很多时候并不会被VCS忽略,所以需要手动将它排除。因此,在把敏感信息配置在这个文件中时,我们要确保它没有被VCS收录。
系统环境变量
除了上述3种配置文件之外,某些情况下,我们还可以使用系统环境变量来配置敏感信息。但是由于它是系统级的,某些情况下可能会无法正常读取,甚至极端情况下会因为配置错误,导致系统宕机。所以,除非不得不配置在系统环境变量中,否则建议不要配置成系统环境变量。
读取上述配置文件
在上一部分,我们了解了在一个 Android 项目中可以使用到的配置文件类型,现在来看一下,当配置完成之后,我们怎么读取使用这些配置。
gradle.properties(Global AND Project)
- 在任意.gradle文件中,我们可以通过getProperties().get("KEY_NAME")方式来读取参数值
def getRepositoryUsername() {
return getProperties().get('bintray.user')
}
def getRepositoryPassphrase() {
return getProperties().get('bintray.gpg.password')
}
def getApiKey() {
return getProperties().get("bintray.apikey")
}
- 在Android项目的build.gradle中,可以直接用KEY来获取参数值
signingConfigs {
sign {
storeFile file(ANDROID_STORE_FILE)
storePassword ANDROID_STORE_PASSWORD
keyAlias ANDROID_KEY_ALIAS
keyPassword ANDROID_KEY_PASSWORD
}
}
local.properties
由于这个配置文件只供gradle程序使用,所以无法像gradle.properties那样直接读取。我们需要通过JDK的Properties类去手动加载它,然后读取其中的参数
Properties properties = new Properties()
properties.load project.rootProject.file('local.properties').newDataInputStream()
def APP_ID = properties.getProperty("APP_ID")
def WB_ID = properties.getProperty("WB_ID")
def WX_ID = properties.getProperty("WX_ID")
def QQ_ID = properties.getProperty("QQ_ID")
系统环境变量
虽然不建议这种配置方式,但是还是简单地介绍下读取方法,由于它是系统级参数,所以在gradle文件中,我们可以通过System.getenv来读取
def env = { System.getenv it }
signingConfigs {
sign {
storeFile file(env("ANDROID_STORE_FILE"))
storePassword env("ANDROID_STORE_PASSWORD")
keyAlias env("ANDROID_KEY_ALIAS")
keyPassword env("ANDROID_KEY_PASSWORD")
}
}
最佳实践
在上文中介绍了不同的配置文件以及它的读取方法。最后,我想介绍一下在这次封装分享库时的一些最佳实践
- 不同项目间通用的配置建议放在Global Properties中,如Bintray、Nexus账号信息
- 项目专有的敏感信息,如微信\腾讯\微博开放平台的KEY建议放在local.properties中
- Project Properties中只存放不敏感的参数
- 除非必须,否则不要使用系统环境变量
末尾
安利一下使用kotlin语言封装的分享库RxShare,使用RxJava实现一行代码完成分享。