How to Automate the Caching Checksum Value?
Now that we know how to implement the build integrity verification one question remains: how and when should we store the checksum in strings.xml? Once we are ready for an application release, we could use this simplistic algorithm:
- Build apk like we normally would.
- Retrieve classes.dex file from apk file and calculate the checksum for that.
- Store calculated checksum in strings.xml file and then build application once again.
This process would be cumbersome if we had to perform these steps every time we want to release a new update to Google Play Store. Also, it’s common these days to use a continuous integration system to automate application builds. To address these issues, we will create two gradle tasks:
static def getChecksum() {
def command = "crc32 PATH_TO_CLASSES_DEX"
return command.execute().text
}
def getCachedChecksum() {
//retrieve cached checksum in strings.xml and return it
}
task verifyChecksum() {
doLast {
if(getChecksum() != getCachedChecksum()) {
throw new GradleException()
}
}
}
task updateChecksum() {
doLast {
//store currentChecksum in strings.xml
}
}
We left out certain implementation details as an exercise for you.
Now that we have those gradle tasks, we can utilize them in the bash script that will be executed by the CI system:
set -e
./gradlew clean
./gradlew app:assembleRelease
set +e
if ./gradlew verifyChecksum ; then
echo "Checksum valid"
else
set -e
./gradlew updateChecksum
./gradlew clean
./gradlew app:assembleRelease
./gradlew verifyChecksum
fi
Here we simply build an application and then verify the checksum. If the checksum is incorrect, then we update it and then build apk once again. Now the checksum should be correct, and we can safely distribute the build to our users.
It’s important to notice that we execute a “clean” task before each build. Otherwise the calculated checksums would differ and our algorithm wouldn’t work correctly.