Signing Release Mode APKs
Following all of your hard work on UseUtils, you decide to release this app to your friends. However, you cannot distribute an APK file built in debug mode (and signed by a debug key). Instead, you must create this APK in release mode, and sign it with a release key based on a purchased or self-signed certificate. Then, you need to align the APK, to reduce the amount of consumed RAM when running the app.
Execute the following command to build a release mode version of UseUtils:
ant release
You should discover a UseUtils-release-unsigned.apk file in the bin directory. If you attempt to install this APK file on the emulated or actual device (via adb install bin\UseUtils-release-unsigned.apk), you will observe the following error message (because the APK must be signed):
Failure [INSTALL_PARSE_FAILED_NO_CERTIFICATES]
Before signing the APK, you need a private key that is backed by a certificate. Create this key with the JDK's keytool command (spread across two lines for readability), as follows:
keytool -genkey -v -keystore useutils-release-key.keystore -alias useutils_key -keyalg RSA -keysize 2048 -validity 10000
keytool is invoked to generate a public and private key pair, to be stored in the keystore named useutils-release-key.keystore, which is created in the current directory. Furthermore, an alias named useutils_key for the keystore entry containing this key pair is specified, and will be used during the signing operation.
The RSA encryption algorithm is used when generating the key, whose size is set to 2048 bits (the default size is 1024, but Google recommends 2048 for increased security). Finally, the key is to remain valid for 10000 days following the day on which it was created. (Google recommends a minimum validity period of 10000 days, or 25 years.)
After responding to keytool's prompts, you should observe a keystore file. Sign the APK with the JDK's jarsigner command (spread across two lines for readability), as follows:
jarsigner -verbose -keystore useutils-release-key.keystore bin\UseUtils-release-unsigned.apk useutils_key
jarsigner is invoked with the name of the previously created keystore file (useutils-release-key.keystore), the location and name of the APK file being signed (bin\UseUtils-release-unsigned.apk), and the alias of the previously created keystore entry (useutils_key). It outputs messages identifying files added to the APK and files that were signed.
Finally, you need to align the APK, and you can do that with the SDK's zipalign tool, as follows:
zipalign -f -v 4 bin\UseUtils-release-unsigned.apk bin\UseUtils.apk
At this point, bin should contain a UseUtils.apk file. Attempt to install this APK on the device via the following command:
adb install bin\UseUtils.apk
You should observe the following error message:
Failure [INSTALL_PARSE_FAILED_NO_CERTIFICATES]
Although the APK has been signed, you are still receiving the same error message as when attempting to install an unsigned release mode APK. Issue 19567 in Google's Android issues database discusses this problem and offers a workaround that consists of specifying -digestalg SHA1 -sigalg MD5withRSA with jarsigner, as follows:
jarsigner -verbose -keystore useutils-release-key.keystore bin\UseUtils-release-unsigned.apk -digestalg SHA1 -sigalg MD5withRSA useutils_key
Rebuild the project, sign UseUtils-release-unsigned.apk with jarsigner including -digestalg SHA1 -sigalg MD5withRSA as additional arguments, and realign the APK. You should be able to successfully install the UseUtils.apk app package on the device and launch UseUtils (see Figure 3).
Conclusion
You can develop Android apps with JDK 7, but three problems can catch you off guard. This article focused on the problems of dx not including the Dalvik equivalent of JDK 7-compiled classfiles in classes.dex, and signed release mode APKs not being installable without including certain jarsigner options. You learned why these problems occur and how to overcome them.
The second part of this two-part series presents the third problem and its solution.