9

As refer by Getting "debuggable" value of androidManifest from code?, there are two options of checking if the build is debuggable:

1.) BuildConfig.DEBUG flag

 if (BuildConfig.DEBUG)`

2.) ApplicationInfo.FLAG_DEBUGGABLE

 if (0 != (getContext().getApplicationInfo().flags & 
     ApplicationInfo.FLAG_DEBUGGABLE))

Are they two identical, or they are different? When to use what?

Elye
  • 30,821
  • 26
  • 115
  • 272

4 Answers4

11

They are not identical.

There may be many buildTypes, but debug and release are mandatory. BuildConfig.DEBUG will be true if currently selected build type is debug, otherwise it will be false (see exclusion case below).

ApplicationInfo.FLAG_DEBUGGABLE corresponds to following:


    buildTypes {
        debug {
            debuggable true
        }

        ...
    }

Now, ApplicationInfo.FLAG_DEBUGGABLE will be true.

Thus, you may conclude, that you may perform following:


    buildTypes {
        debug {
            debuggable false
        }

        ...
    }

Interestingly, although you are in debug build type, BuildConfig.DEBUG will become false.

azizbekian
  • 53,978
  • 11
  • 145
  • 225
3

Found a good article here: http://tekeye.biz/2013/android-debug-vs-release-build.

Also tested it out. If we force android:debuggable="false" or android:debuggable="true" on Manifest Application, it will warn :

 Avoid hardcoding the debug mode; leaving it out allows debug and release builds to automatically assign one less...

 It's best to leave out the android:debuggable attribute from the manifest. If you do, then the tools will automatically insert android:debuggable=true when building an APK to debug on an emulator or device. And when you perform a release build, such as Exporting APK, it will automatically set it to false.  
 If on the other hand you specify a specific value in the manifest file, then the tools will always use it. This can lead to accidentally publishing your app with debug information.

I would conclude, in default situation ApplicationInfo.FLAG_DEBUGGABLE behave the same as BuildConfig.DEBUG, unless override by changing android:debuggable, which is not something advisable.

Compare to BuildConfig.DEBUG, ApplicationInfo.FLAG_DEBUGGABLE is a more reliable way to check for debug build, as at a lower dependent module, it can't access the BuildConfig.DEBUG of the parent module, and could have a different value.

e.g. App use MyLib module. App's BuildConfig.DEBUG could be false, but MyLib BuildConfig.DEBUG could be true. Hence it's better to check using ApplicationInfo.FLAG_DEBUGGABLE

Elye
  • 30,821
  • 26
  • 115
  • 272
2

One area that did highlight the differences in the usages of these flags was following a pen test of our app. The pen test report pointed out to us that attackers can employ a technique called "hooking" where the app is recompiled with the android:debuggable flag changed to true (how this is done I'm not totally sure).

Their recommendation to detect this happening was to add some code as follows:

if (!BuildConfig.DEBUG) {
        try {
            ApplicationInfo appInfo = getPackageManager().getApplicationInfo("uk.co.myapp", 0);
            if ((appInfo.flags & appInfo.FLAG_DEBUGGABLE) != 0) {
                // App has been compromised 
                finish();
                return;
            }
        } catch (Exception ex) {
            ex.printStackTrace();
        }
    }

What you do when you detect this circumstance is down to you. I added it to my startup activity, and if triggered, I display a message followed by the finish() statement.

Nick Wright
  • 1,103
  • 8
  • 18
0

My experience is that BuildConfig.DEBUG is always linked to the debuggable build attribute in the gradle file.

buildTypes {
    debug {
        debuggable true
    }
    debug {
        debuggable false
    }

    ...
}

The documentation also supports this:

  • boolean DEBUG – if the build is debuggable.

getContext().getApplicationInfo().flags & ApplicationInfo.FLAG_DEBUGGABLE was likely the only way to determine if a build was debuggable before the gradle build system and Android Studio replaced eclipse around 2015.

Use BuildConfig.DEBUG because it resolves to a constant which can be used during compilation to optimize code.

Jon
  • 7,185
  • 6
  • 45
  • 66