56

I'm building an Android application and would like to maintain a few environment variables that I can tweak depending on whether I'm in development mode or release mode. For example, I need to invoke a web service and the URL will be slightly different in either mode. I'd like to externalize this and other settings so I can change them easily based on my target deployment.

Are there any best practices or anything in the SDK to assist with this need?

Janusz
  • 187,060
  • 113
  • 301
  • 369
Joe Holloway
  • 28,320
  • 15
  • 82
  • 92

8 Answers8

44

The following solution assumes that in manifest file you always set android:debuggable=true while developing and android:debuggable=false for application release.

Now you can check this attribute's value from your code by checking the ApplicationInfo.FLAG_DEBUGGABLE flag in the ApplicationInfo obtained from PackageManager.

The following code snippet could help:

PackageInfo packageInfo = ... // get package info for your context
int flags = packageInfo.applicationInfo.flags; 
if ((flags & ApplicationInfo.FLAG_DEBUGGABLE) != 0) {
    // development mode
} else {
    // release mode
}
Viktor Brešan
  • 5,293
  • 5
  • 33
  • 36
  • 5
    As of the more recent SDK versions this would seem the best approach, as both Eclipse and Ant set this automatically depending on build type. – Zulaxia Apr 28 '11 at 11:40
32

According to this stackoverflow post, in SDK Tools version 17 (we're on 19 as of this writing) adds a BuildConfig.DEBUG constant that is true when building a dev build.

Community
  • 1
  • 1
yincrash
  • 6,394
  • 1
  • 39
  • 41
9

Android build.gradle has Handles Debug and Release Environment well.

Append the following code snippet in build.gradle file

buildTypes {
    debug {
        buildConfigField "Boolean", "IS_DEBUG_MODE", 'true'
    }

    release {
        buildConfigField "Boolean", "IS_DEBUG_MODE", 'false'
    }
}

Now you can access the variable like below

    if (BuildConfig.IS_DEBUG_MODE) { {
        //Debug mode.
    } else {
        //Release mode
    }
Community
  • 1
  • 1
Zumry Mohamed
  • 9,318
  • 5
  • 46
  • 51
9

@viktor-bresan Thanks for a useful solution. It'd be more helpful if you just included a general way to retrieve the current application's context to make it a fully working example. Something along the lines of the below:

PackageInfo packageInfo = getPackageManager().getPackageInfo(getPackageName(), 0);
Eron Villarreal
  • 995
  • 10
  • 15
4

I would check out isDebuggerConnected

Joseph
  • 25,330
  • 8
  • 76
  • 125
  • 1
    Thanks, that may come in handy one day, but I can technically be running the emulator in development mode w/o a debugger attached. – Joe Holloway Nov 16 '09 at 17:49
3

How about something like the code below ...

public void onCreate Bundle b ) {
   super.onCreate(savedInstanceState);
   if ( signedWithDebugKey(this,this.getClass()) ) {
     blah blah blah
   }

  blah 
    blah 
      blah

}

static final String DEBUGKEY = 
      "get the debug key from logcat after calling the function below once from the emulator";    


public static boolean signedWithDebugKey(Context context, Class<?> cls) 
{
    boolean result = false;
    try {
        ComponentName comp = new ComponentName(context, cls);
        PackageInfo pinfo = context.getPackageManager().getPackageInfo(comp.getPackageName(),PackageManager.GET_SIGNATURES);
        Signature sigs[] = pinfo.signatures;
        for ( int i = 0; i < sigs.length;i++)
        Log.d(TAG,sigs[i].toCharsString());
        if (DEBUGKEY.equals(sigs[0].toCharsString())) {
            result = true;
            Log.d(TAG,"package has been signed with the debug key");
        } else {
            Log.d(TAG,"package signed with a key other than the debug key");
        }

    } catch (android.content.pm.PackageManager.NameNotFoundException e) {
        return false;
    }

    return result;

} 
prayagupa
  • 30,204
  • 14
  • 155
  • 192
Jeff S
  • 3,256
  • 1
  • 18
  • 7
  • 1
    The DEBUGKEY in this case is actually the entire certificate. I recommend using the method in http://stackoverflow.com/questions/6122401/android-compare-signature-of-current-package-with-debug-keystore instead. This way, you're not limited to the debug key from a single machine. – Ralf Feb 10 '12 at 12:49
1

I came across another approach today by accident that seems really straight forward.. Look at Build.TAGS, when the app is created for development this evaluates to the String "test-keys".

Doesn't get much easier than a string compare.

Also Build.MODEL and Build.PRODUCT evaluate to the String "google_sdk" on the emulator!

Jeff S
  • 3,256
  • 1
  • 18
  • 7
  • Is this reliable? It seems like test-keys could be set for rooted devices: http://stackoverflow.com/questions/1101380/determine-if-running-on-a-rooted-device That makes me think there may be other instances where this approach could fail. – christoff Apr 14 '11 at 00:40
0

Here's the method I use:

http://whereblogger.klaki.net/2009/10/choosing-android-maps-api-key-at-run.html

I use it to toggle debug logging and the maps API key.

wirbly
  • 2,183
  • 1
  • 24
  • 24