Home > android, tools > Signing Andorid packages for production builds

Signing Andorid packages for production builds

I keep thinking about switching my production build system to be Ant-based, but keep exporting from Eclipse instead. Maybe one day… Meanwhile, here is how I get an exported (unsigned, unaligned) .apk ready for Market.

In my source tree, I have a special directory, release, which is the release (duh!) staging area. The production key files are located here, which, besides being convenient, makes sure they get backed up.

Making a production build for me takes three steps:

  1. Cleaning the project in Eclipse (I won’t want my production build to get a weird crash because of an outdated R.java).
  2. Generating an obfuscated, unsigned, unaligned .apk by selecting Android Tools – Export Unsigned Application Package in Eclipse.
  3. Running a script to sign and align the .apk, which gets it ready for a Market or a web site upload, or for installation to a test device.

The filename I use for the second step always follows a special pattern: it’s some base name, with the version number and the suffix “-raw” appended. So for Bluetooth Widget version 1.8.1, I export to “kmanBluetoothWidget-1.8.1-raw.apk“, and for WiFi Manager version 2.1.1pre3 I export to “kmanWifiManager-2.1.1pre3-raw.apk“.

( a side note: the “kman” thing goes back quite a few years… my co-workers used to call me that, because “Kostya” was too complicated for some people )

Similarly, there is a pattern to my production keystores: they are named the same as the application’s base file name (without the version, obviously), and the key alias inside the store also has a certain name.

Now, the script.

I’ve been using PowerShell as my command line window for about a month now, and just today rewrote my script from being a .cmd batch file into a PowerShell script.

The script takes two arguments, the first is the abbreviated application name, and the second is the version number.

So, after exporting, let’s say, kmanWifiManager-2.1.1-raw.apk, I run the script as “.\sign_and_pack.ps1 wfm 2.1.1” – where “wfm” is the application, “WiFi Manager” and “2.1.1” is the verison number. Or I could sign Bluetooth Widget version 1.8.1 by running “.\sign_and_pack.ps1 btw 1.8.1“.

The script determines the application’s exported .apk name based on the arguments, signs it with that particular application’s key, and aligns it for faster runtime resource access as recommended by Google.

Here is the source:

if ($Args.length -lt 2) {
	Write-Output "Usage: sign_and_pack.ps1 program version"

$argProgram = $Args[0]
$argVersion = $Args[1]

switch ($argProgram) {
	"wfm" {
		$procName = "WiFi Manager"
		$procBaseName = "kmanWifiManager"
		$procKeyName = "WifiManagerKey"
	"btw" {
		$procName = "Bluetooth Widget"
		$procBaseName = "kmanBluetoothWidget"
		$procKeyName = "BluetoothWidgetKey"

	default {
		Write-Output "Unknown application: $argProgram"

Write-Output "***" "***" "*** Program: $procName, version: $argVersion" "***" "***" ""

$keypass = "*** my keystore password goes here ***"
$fileKeystore = "$procBaseName.keystore"

$fileRaw = "$procBaseName-$argVersion-raw.apk"
$fileTemp = "$procBaseName-$argVersion-temp.apk"
$fileDest = "$procBaseName-$argVersion.apk"

$fileRawExists = Test-Path "$fileRaw"

if (-not $fileRawExists) {
	Write-Output "Error: $fileRaw does not exist"

Write-Output "Copying $fileRaw to $fileTemp"
Copy-Item $fileRaw $fileTemp

Write-Output "Signing $fileTemp with $fileKeystore"
jarsigner -storepass $keypass -keystore $fileKeystore $fileTemp $procKeyName

Write-Output "Aligning $fileTemp to $fileDest"
zipalign -f 4 $fileTemp $fileDest

Remove-Item $fileTemp

Write-Output "" "***" "***" "*** Ready: $fileDest" "***" "***"

#$key = Read-Host "Install? (Y/N)"

#if ($key -eq "Y" -or $key -eq "y") {
#	Write-Output "Installing $fileDest"
#	adb install -r $fileDest

Here is example output, assuming I just exported WiFi Manager 2.1.1 as “kmanWifiManager-2.1.1-raw.apk”:

PS D:\Android\proj-indigo\release> .\sign_and_pack.ps1 wfm 2.1.1
*** Program: WiFi Manager, version: 2.1.1

Copying kmanWifiManager-2.1.1-raw.apk to kmanWifiManager-2.1.1-temp.apk
Signing kmanWifiManager-2.1.1-temp.apk with kmanWifiManager.keystore
Aligning kmanWifiManager-2.1.1-temp.apk to kmanWifiManager-2.1.1.apk

*** Ready: kmanWifiManager-2.1.1.apk
PS D:\Android\proj-indigo\release> _

The commented-out stuff at the end of the script can install the just generated release .apk to a device (I’m not sure yet which is more convenient: doing it from the script, or typing “adb install -r” myself…)

So here it is….

Categories: android, tools
  1. No comments yet.
  1. No trackbacks yet.

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s