据我所知,在android中“发布版本”是签名的APK。如何从代码中检查它或者 Eclipse 是否有某种秘密定义?
我需要它来调试从 Web 服务数据填充 ListView 项目(不,logcat 不是一个选项)。我的想法:
android:debuggable
,但由于某种原因看起来不可靠。
boolean isDebuggable = ( 0 != ( getApplicationInfo().flags & ApplicationInfo.FLAG_DEBUGGABLE ) );
科特林:
val isDebuggable = 0 != applicationInfo.flags and ApplicationInfo.FLAG_DEBUGGABLE
有关更多信息,请参阅
保护 Android LVL 应用程序。
或者,如果您正确使用 Gradle,您可以检查BuildConfig.DEBUG
是 true 还是 false。
最简单、最好的长期解决方案,就是使用BuildConfig.DEBUG
。这是一个
boolean
值,对于调试版本将为
true
,否则为
false
:
if (BuildConfig.DEBUG) {
// do something for a debug build
}
根据 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;
}
APK
,你可以使用
aapt dump badging /path/to/apk | grep -c application-debuggable
如果 0
不可调试,则输出
APK
;如果可调试,则输出
1
。
BuildConfig.DEBUG
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;
}
}
android:debuggable
有什么问题吗?您可以使用
PackageManager
从代码中获取该值。
if (Debug.isDebuggerConnected() || Debug.waitingForDebugger()) {
//code to be executed
}
android:debuggable
解决。这是读取项目时的错误,在某些情况下,项目上的调试标志未存储在记录中,而
if (m.debug && !App.isDebuggable(getContext()))
始终评估为
false
。我的错。
@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 过程)