Pour autant que je sache, dans Android "release build" est signé APK. Comment le vérifier à partir du code ou Eclipse a-t-il une sorte de définition secrète?
J'ai besoin de cela pour déboguer les éléments ListView remplis à partir des données de service Web (non, logcat pas une option).
Mes pensées:
Android:debuggable
, mais pour une raison quelconque, cela ne semble pas fiable.Il existe différentes manières de vérifier si l'application est construite à l'aide du certificat de débogage ou de version, mais la méthode suivante me semble la meilleure.
Selon les informations contenues dans Android documentation signature de votre application , la clé de débogage contient le nom distinctif suivant: " CN = Débogage Android, O = Android, C = US ". Nous pouvons utiliser ces informations pour vérifier si le paquet est signé avec la clé de débogage sans coder en dur la signature de la clé de débogage dans notre code.
Donné:
import Android.content.pm.Signature;
import Java.security.cert.CertificateException;
import Java.security.cert.X509Certificate;
Vous pouvez implémenter une méthode isDebuggable de cette façon:
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;
}
Pour vérifier l'indicateur de débogage, vous pouvez utiliser ce code:
boolean isDebuggable = ( 0 != ( getApplicationInfo().flags & ApplicationInfo.FLAG_DEBUGGABLE ) );
Kotlin:
val isDebuggable = 0 != applicationInfo.flags and ApplicationInfo.FLAG_DEBUGGABLE
Pour plus d'informations, veuillez consulter Sécurisation Android Applications LVL .
Sinon, si vous utilisez correctement Gradle, vous pouvez vérifier si BuildConfig.DEBUG
est vrai ou faux.
Répondu par Mark Murphy
La solution la plus simple et la meilleure à long terme, consiste à utiliser BuildConfig.DEBUG
. Ceci est une valeur boolean
qui sera true
pour une construction de débogage, false
sinon:
if (BuildConfig.DEBUG) {
// do something for a debug build
}
Peut-être tard, mais iosched utilise BuildConfig.DEBUG
Si vous voulez vérifier un APK
de manière statique, vous pouvez utiliser
aapt dump badging /path/to/apk | grep -c application-debuggable
Cette sortie 0
si le APK
n’est pas debuggable et 1
Si c'est.
Ajoutez d'abord ceci à votre fichier build.gradle, cela permettra également l'exécution côte à côte des générations de débogage et de version:
buildTypes {
debug {
applicationIdSuffix ".debug"
}
}
Ajoutez cette méthode:
public static boolean isDebug(Context context) {
String pName = context.getPackageName();
if (pName != null && pName.endsWith(".debug")) {
return true;
} else {
return false;
}
}
Une version de débogage est également signée, avec une clé différente. Il est généré automatiquement par Eclipse et son certificat est valide pour un an seulement. Quel est le problème avec Android:debuggable
? Vous pouvez obtenir cette valeur à partir de code en utilisant PackageManager
.
Une autre option mérite d'être mentionnée. Si vous devez exécuter du code uniquement lorsque le débogueur est connecté, utilisez ce code:
if (Debug.isDebuggerConnected() || Debug.waitingForDebugger()) {
//code to be executed
}
Solution dans Kotlin que j'utilise en ce moment:
@SuppressLint("PackageManagerGetSignatures")
@Suppress("DEPRECATION")
fun isSigned(context: Context?): Boolean {
return (context?.packageManager?.getPackageInfo(context.packageName, PackageManager.GET_SIGNATURES)?.signatures?.firstOrNull()?.toByteArray()
?.let {
return@let CertificateFactory.getInstance("X.509").generateCertificate(ByteArrayInputStream(it))
} as? X509Certificate)
?.issuerDN
?.name
?.contains("O=Android", ignoreCase = false) ?: true
}
de cette façon, je peux toujours me connecter au débogage et ceux-ci seront signalés à Crashlytics (par exemple, pour le processus d'assurance qualité)
Résolu avec Android:debuggable
. Il y avait un bogue dans la lecture d’élément où, dans certains cas, le drapeau de débogage n’était pas stocké dans l’enregistrement, obtenant if (m.debug && !App.isDebuggable(getContext()))
toujours évaluée à false
. Ma faute.