Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to check if APK is signed or "debug build"?

To check the debuggable flag, you can use this code:

boolean isDebuggable =  ( 0 != ( getApplicationInfo().flags & ApplicationInfo.FLAG_DEBUGGABLE ) );

Kotlin:

val isDebuggable = 0 != applicationInfo.flags and ApplicationInfo.FLAG_DEBUGGABLE

For more information, please see Securing Android LVL Applications.

Alternatively, if you're using Gradle correctly, you can check if BuildConfig.DEBUG is true or false.


Answered by Mark Murphy

The simplest, and best long-term solution, is to use BuildConfig.DEBUG. This is a boolean value that will be true for a debug build, false otherwise:

if (BuildConfig.DEBUG) {
  // do something for a debug build
}

There are different way to check if the application is build using debug or release certificate, but the following way seems best to me.

According to the info in Android documentation Signing Your Application, debug key contain following subject distinguished name: "CN=Android Debug,O=Android,C=US". We can use this information to test if package is signed with debug key without hardcoding debug key signature into our code.

Given:

import android.content.pm.Signature;
import java.security.cert.CertificateException;
import java.security.cert.X509Certificate;

You can implement an isDebuggable method this way:

private static final X500Principal DEBUG_DN = new X500Principal("CN=Android Debug,O=Android,C=US");
private boolean isDebuggable(Context ctx)
{
    boolean debuggable = false;

    try
    {
        PackageInfo pinfo = ctx.getPackageManager().getPackageInfo(ctx.getPackageName(),PackageManager.GET_SIGNATURES);
        Signature signatures[] = pinfo.signatures;

        CertificateFactory cf = CertificateFactory.getInstance("X.509");

        for ( int i = 0; i < signatures.length;i++)
        {   
            ByteArrayInputStream stream = new ByteArrayInputStream(signatures[i].toByteArray());
            X509Certificate cert = (X509Certificate) cf.generateCertificate(stream);       
            debuggable = cert.getSubjectX500Principal().equals(DEBUG_DN);
            if (debuggable)
                break;
        }
    }
    catch (NameNotFoundException e)
    {
        //debuggable variable will remain false
    }
    catch (CertificateException e)
    {
        //debuggable variable will remain false
    }
    return debuggable;
}

If you want to check an APK statically, you could use

aapt dump badging /path/to/apk | grep -c application-debuggable

This outputs 0 if the APK isn't debuggable and 1 if it is.


Maybe late, but iosched uses BuildConfig.DEBUG


First add this to your build.gradle file, this will also allow side by side running of debug and release builds:

buildTypes {
    debug {
        applicationIdSuffix ".debug"
    }
}

Add this method:

public static boolean isDebug(Context context) {
    String pName = context.getPackageName();
    if (pName != null && pName.endsWith(".debug")) {
        return true;
    } else {
        return false;
    }
}