We use a build server to create all our builds by running Unity using build scripts from the command line. This presented a bit of a problem when it comes to android as there doesn’t seem to be any way to enter the keystore password if you are running unity on the command line.
I couldn’t find any help for this on the forums, so I thought I’d share my solution:
In player settings leave all the keystore entries blank so unity signs the package with the debug keys.
Use BuildPipeline.BuildPlayer() to build the game package.
Run this command to remove the signing information from the package: zip -d MyAndroidPackage.apk "META-INF/*"
Now sign the package with your keystore: jarsigner -verbose -sigalg MD5withRSA -digestalg SHA1 -keystore MyKeystore.keystore -storepass <password> MyAndroidPackage.apk <keystore alias>
Finally run zipalign to ensure the package has proper alignment: zipalign -v 4 MyAndroidPackage.apk FinalAlignedPackage.apk
This approach obviously has the disadvantage that you have the password for your keystore included in your build scripts. My current plan is to use one keystore for development, and a different keystore when we actually submit to the app store. I’ll have to enter the passwords for the final submission build manually which is a bit of a pain, but at least we have fully automatic builds during development.
I’d love to know if anyone has a better solution to this problem?
The problem here is to actually pass those passwords from the command line in a secure way. Unity logs every command-line argument it receives, excluding its own “-password” one, which is unfortunate. The log files are usually saved in CI, so having those in them is totally insecure.
I’ve just implemented this on our CI pipeline. For anyone still interested, the gist is to use Environment.ExpandEnvironmentVariables() to evaluate and expand environment variables set in the terminal that is executing the Unity.exe process. This lets you read the keystore password value, without having the value leak into the console output because you pass it as a command line parameter.
Here is the C# code that should go in your C# buildscript that is executed via command line:
string query = "%AndroidKeystorePassword%"; // TODO: Account for OSX and Linux syntax for environment variables
string keystorePassword = Environment.ExpandEnvironmentVariables(query);
And here is a sample Windows batch script to set the environment variable and execute the Unity.exe for building via command line:
@echo off
SET Unity=C:\Program Files\Unity\2018.4.5f1\Editor\Unity.exe
SET Project=C:\Users\kgc\Documents\Projects\AwesomeUnityProject
SET BuildPath=%Project%\Builds
SET AndroidKeystorePassword=12345678
"%Unity%" -quit -batchmode -nographics -projectPath "%Project%" -logFile "%BuildPath%\build.android.log" -executeMethod "BuildScript.BuildAndroid"
Hope this helps someone out there with the same problem!