据我所知,在安卓系统中“发布版本”是签名 APK。如何检查它 来自代码或 Eclipse 是否有某种秘密定义?
我需要它来调试从 Web 服务数据中填充 ListView 项(不,logcat 不是一个选项)。
我的想法是:
android:debuggable
调试版本也是签名的,只是使用了不同的键。它是由 Eclipse 自动生成的,其证书仅有效一年。android:debuggable有什么问题?可以使用 PackageManager从代码中获取此值。
PackageManager
要检查可调试标志,可以使用以下代码:
boolean isDebuggable = ( 0 != ( getApplicationInfo().flags & ApplicationInfo.FLAG_DEBUGGABLE ) );
科特林:
val isDebuggable = 0 != applicationInfo.flags and ApplicationInfo.FLAG_DEBUGGABLE
有关详细信息,请参阅 保护 Android LVL 应用程序的安全。
或者,如果您正确地使用 Gradle,您可以检查 BuildConfig.DEBUG是真还是假。
BuildConfig.DEBUG
用 android:debuggable解决。在读取条目时出现错误,在某些情况下,条目上的调试标志没有存储在记录中,因此 if (m.debug && !App.isDebuggable(getContext()))总是计算为 false。我的错。
if (m.debug && !App.isDebuggable(getContext()))
false
有不同的方法来检查应用程序是否使用调试或发布证书构建,但下面的方法对我来说似乎是最好的。
根据 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; }
也许晚了,但是 iosching 使用 BuildConfig.DEBUG
如果要静态检查 APK,可以使用
APK
aapt dump badging /path/to/apk | grep -c application-debuggable
如果 APK不可调试,则输出 0; 如果可调试,则输出 1。
0
1
另一个选项,值得一提。如果您只需要在附加调试器时执行某些代码,请使用以下代码:
if (Debug.isDebuggerConnected() || Debug.waitingForDebugger()) { //code to be executed }
马克 · 墨菲回答
最简单、也是最好的长期解决方案 是使用 BuildConfig.DEBUG。这是一个 boolean值,对于一个调试构建,它将是 true,否则是 false:
boolean
true
if (BuildConfig.DEBUG) { // do something for a debug build }
首先将它添加到 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; } }
我目前在 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 过程)