1. 背景:
方便开发人员确认某个App安装包中是否包含对应的代码
2. 解决方案
比较传统的方法是反编译app,直接用jadx或jd-gui等工具看代码是否包含。
然而比较麻烦,app加固之后也不能方便的反编译。
最后决定在app中增加一个后门对话框,参考google android开发者模式,2秒内点击5次就可以弹出对话框。
对话框中记录最后一次Git commit信息,版本号,编译时间等等信息。
2秒内点击5次的判断逻辑:
private void something() {
getmTitleBar()
.setOnClickListener(
new View.OnClickListener() {
final int COUNTS = 5;
final long DURATION = 2 * 1000;
long[] mHits = new long[COUNTS];
@Override
public void onClick(View v) {
// 实现左移
System.arraycopy(mHits, 1, mHits, 0, mHits.length - 1);
mHits[mHits.length - 1] = SystemClock.uptimeMillis();
if (mHits[0] >= (SystemClock.uptimeMillis() - DURATION)) {
// show dialog
}
}
});
}
编译时获取最后一次git commit信息:
这里需要注意由于Android无法解析windows对汉字的GBK编码,会出现乱码,因此需要直接对字节流utf-8处理,而不能直接拿文字信息;
如果团队都是mac和linux系统,
可以直接使用def gitCommit = cmd.execute().text.trim()获取命令的执行结果,在Android上展示无乱码问题,考虑兼容性,还是需要转换一次
def inputStream = cmd.execute().getIn()
def gitLog = IOGroovyMethods.getText(new BufferedReader(new InputStreamReader(inputStream, "utf-8")))
完整代码如下:
import org.codehaus.groovy.runtime.IOGroovyMethods
def getGitCommit() {
def gitDir = new File("${rootDir}/.git")
println("gitdir is ${gitDir}")
if (!gitDir.isDirectory()) {
return 'non-git-build'
}
def cmd = "git log --pretty=format:%cn_%s_%h_%cd --date=format:'%Y-%m-%d_%H:%M' -1"
def inputStream = cmd.execute().getIn()
def gitLog = IOGroovyMethods.getText(new BufferedReader(new InputStreamReader(inputStream, "utf-8")))
if (gitLog != null && gitLog.length() > 0) {
return gitLog
} else {
return "unknown"
}
}
在Gradle编译时插入相关字段:
variant.buildConfigField 'String', 'LAST_CI', "\"${getGitCommit()}\""
variant.buildConfigField 'String', 'BUILD_TIME', "\"${releaseTime()}\""
在Java中引用:
String message = BuildConfig.LAST_CI
得到的结果类似:
Tony_MOBILE-2722 优化环境配置_abea5547_2019-07-31_09:46
格式为:git 提交者+ git commit message + git hash + 时间
Git log的格式自定义:
git log --pretty=format:%cn_%s_%h_%cd --date=format:'%Y-%m-%d_%H:%M' -1
具体自定义可参考Git log