如何检查 APK 是否已签名或“调试构建”?

问题描述 投票:0回答:10

据我所知,在android中“发布版本”是签名的APK。如何从代码中检查它或者 Eclipse 是否有某种秘密定义?

我需要它来调试从 Web 服务数据填充 ListView 项目(不,logcat 不是一个选项)。

我的想法:

    应用程序的
  • android:debuggable
    ,但由于某种原因看起来不可靠。 
  • 硬编码设备 ID 不是一个好主意,因为我使用同一设备来测试签名的 APK。
  • 在代码中的某处使用手动标志?貌似有道理,但有时肯定会忘记更改,而且所有程序员都很懒。
android debugging certificate
10个回答
146
投票
要检查可调试标志,可以使用以下代码:

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

科特林:

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

有关更多信息,请参阅

保护 Android LVL 应用程序

或者,如果您正确使用 Gradle,您可以检查

BuildConfig.DEBUG

 是 true 还是 false。


134
投票
马克·墨菲回答

最简单、最好的长期解决方案,就是使用BuildConfig.DEBUG

。这是一个 
boolean
 值,对于调试版本将为 
true
,否则为 
false

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

81
投票
有不同的方法来检查应用程序是否是使用调试或发布证书构建的,但以下方法对我来说似乎最好。

根据 Android 文档

签署您的应用程序中的信息,调试密钥包含以下主题专有名称:“CN=Android Debug,O=Android,C=US”。我们可以使用此信息来测试包是否使用调试密钥进行签名,而无需将调试密钥签名硬编码到我们的代码中。

鉴于:

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

您可以这样实现 isDebuggable 方法:

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; }
    

37
投票
如果你想静态检查

APK

,你可以使用

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

0

 不可调试,则输出 
APK
;如果可调试,则输出 
1


22
投票
也许晚了,但 iosched 使用

BuildConfig.DEBUG


    


10
投票
首先将其添加到您的 build.gradle 文件中,这也将允许并行运行调试和发布版本:

buildTypes { debug { applicationIdSuffix ".debug" } }

添加这个方法:

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

5
投票
调试版本也已签名,只是使用不同的密钥。它由Eclipse自动生成,其证书的有效期仅为一年。

android:debuggable

有什么问题吗?您可以使用 
PackageManager
 从代码中获取该值。


4
投票
另一个选择,值得一提。如果您需要仅在附加调试器时执行某些代码,请使用以下代码:

if (Debug.isDebuggerConnected() || Debug.waitingForDebugger()) { //code to be executed }
    

0
投票

android:debuggable

解决。这是读取项目时的错误,在某些情况下,项目上的调试标志未存储在记录中,而 
if (m.debug && !App.isDebuggable(getContext()))
 始终评估为 
false
。我的错。


0
投票
我目前正在使用的 Kotlin 解决方案:

@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 }

这样我仍然可以在调试中签名,并且这些内容将报告给 Crashlytics(例如,对于 QA 过程)

© www.soinside.com 2019 - 2024. All rights reserved.