Detecting the Keystore Signature in Code

Here's a problem I'm sure many of us have faced: you've got code that runs one way when you're developing and another way when you're releasing. A few examples I've run into:

  • Logging during development, but disabled for release.
  • Targeting development vs. production servers.
  • MapView requires an API key tied to the signing key.

Before, I just setup static parameters in code that I'd have to remember to change before making a release build. It's a pain and error prone.

I've just determined a much better (and more automatic) way - detecting the signing keystore in code. Through use of the PackageManager you can actually determine the Signature of the app that's currently running.

First, you need to get the Signature of your release keystore. Put this code into your application temporarily, then sign it with your release keystore and run it:

PackageInfo pi = getPackageManager().getPackageInfo(getPackageName(), PackageManager.GET_SIGNATURES);
Log.i("test", pi.signatures[0].toCharsString());

Take the output from logcat and put it into this method:

private static final Signature SIG_RELEASE = new Signature("<YOUR SIGNATURE HERE>");

public static boolean isRelease(Context context) {
 try {
  PackageManager pm = context.getPackageManager();
  PackageInfo pi = pm.getPackageInfo(context.getPackageName(), PackageManager.GET_SIGNATURES);
  for (Signature sig : pi.signatures) {
   if (sig.equals(SIG_RELEASE)) {
    return true;
   }
  }
 }
 catch (Exception e) {
  Log.w("Exception thrown when detecting if app is signed by a release keystore.", e);

  // Return true if we can't figure it out, just to play it safe
  return true;
 }

 return false;
}

Now you can always call isRelease() and check whether your app was signed by your release keystore. No more having to edit files to create a release version of your app - just sign it with the correct keystore and you're ready to go!

comments powered by Disqus