据我所知,在android“发布版”中签名为APK。如何检查从代码或Eclipse是否有一些秘密定义?
我需要这个来调试从Web服务数据中填充ListView项目(不,logcat不是一个选项)。
我的想法:
android:debuggable
,但由于某种原因看起来不可靠。 答案 0 :(得分:135)
要检查可调试标志,可以使用以下代码:
boolean isDebuggable = ( 0 != ( getApplicationInfo().flags & ApplicationInfo.FLAG_DEBUGGABLE ) );
科特林:
val isDebuggable = 0 != applicationInfo.flags and ApplicationInfo.FLAG_DEBUGGABLE
有关详细信息,请参阅Securing Android LVL Applications。
或者,如果您正确使用Gradle,则可以检查BuildConfig.DEBUG
是真还是假。
答案 1 :(得分:130)
Mark Murphy回答
最简单,最好的长期解决方案,就是使用BuildConfig.DEBUG
。对于调试版本,这是boolean
值true
,否则为false
:
if (BuildConfig.DEBUG) {
// do something for a debug build
}
答案 2 :(得分:76)
有不同的方法来检查应用程序是否使用调试版或发布证书构建,但以下方式对我来说似乎最好。
根据Android文档Signing Your Application中的信息,调试密钥包含以下主题专有名称:“ 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;
}
答案 3 :(得分:21)
也许迟到了,但iosched使用BuildConfig.DEBUG
答案 4 :(得分:18)
如果要静态检查APK
,可以使用
aapt dump badging /path/to/apk | grep -c application-debuggable
如果0
不可调试,则输出APK
,如果是1
,则输出{。}}。
答案 5 :(得分: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;
}
}
答案 6 :(得分:5)
也会使用不同的密钥对调试版本进行签名。它由Eclipse自动生成,其证书有效期仅为一年。 android:debuggable
有什么问题?您可以使用PackageManager
从代码中获取此值。
答案 7 :(得分:3)
另一种选择,值得一提。如果只在附加调试器时需要执行某些代码,请使用以下代码:
if (Debug.isDebuggerConnected() || Debug.waitingForDebugger()) {
//code to be executed
}
答案 8 :(得分:0)
解决android:debuggable
。读取项目时出现错误,在某些情况下,项目上的调试标记未存储在记录中,if (m.debug && !App.isDebuggable(getContext()))
始终评估为false
。我的坏。
答案 9 :(得分: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(例如,用于质量检查流程)