如何检查APK是否已签名或"调试版本"?

Im0*_*ity 115 debugging android certificate

据我所知,在android"发布版"中签名APK.如何从代码中检查它还是Eclipse有一些秘密定义?

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

我的想法:

  • 应用程序android:debuggable,但由于某些原因看起来不可靠.
  • 硬编码设备ID不是一个好主意,因为我使用相同的设备来测试签名的APK.
  • 在代码中的某处使用手动标志?合理,但肯定会在某个时候忘记改变,加上所有程序员都很懒惰.

Blu*_*ell 136

要检查debuggable标志,可以使用以下代码:

boolean isDebuggable =  ( 0 != ( getApplicationInfo().flags & ApplicationInfo.FLAG_DEBUGGABLE ) );
Run Code Online (Sandbox Code Playgroud)

科特林:

val isDebuggable = 0 != applicationInfo.flags and ApplicationInfo.FLAG_DEBUGGABLE
Run Code Online (Sandbox Code Playgroud)

有关更多信息,请参阅保护Android LVL应用程序.

或者,如果您正确使用Gradle,则可以检查是否BuildConfig.DEBUG为true.

  • 第一个测试Manifest debuggable,这是不推荐使用的.第二个是库不可能的,lib将拥有它自己的BuildConfig - 无法导入使用Lib的App的BuildConfig.因此,明确的答案是"好的" (2认同)

Xar*_*mer 130

Mark Murphy回答

最简单,最好的长期解决方案是使用BuildConfig.DEBUG.这是一个boolean,这将是价值true的调试版本,false否则:

if (BuildConfig.DEBUG) {
  // do something for a debug build
}
Run Code Online (Sandbox Code Playgroud)

  • 这种方法的唯一缺点是它不适用于图书馆项目(aar's).构建库时,这将导致错误,因此即使使用该库的应用程序处于调试模式,此检查也会在库代码中导致错误. (7认同)

Oma*_*man 77

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

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

鉴于:

import android.content.pm.Signature;
import java.security.cert.CertificateException;
import java.security.cert.X509Certificate;
Run Code Online (Sandbox Code Playgroud)

您可以通过以下方式实现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;
}
Run Code Online (Sandbox Code Playgroud)

  • 为了帮助解决多个导入匹配问题,这里使用的类是`java.security.cert.X509Certificate`,`java.security.cert.CertificateException`和`android.content.pm.Signature`.所有其他课程都不会为我提供多个匹配项 (6认同)

urS*_*Sus 21

也许迟到了,但是iosched用途 BuildConfig.DEBUG


Hea*_*ers 21

如果你想APK静态检查,你可以使用

aapt dump badging /path/to/apk | grep -c application-debuggable
Run Code Online (Sandbox Code Playgroud)

0如果APK不可调试1则输出,如果是,则输出.

  • `aapt` 位于 `/Users/USER_NAME/library/Android/sdk/build-tools/28.0.3/aapt` (4认同)
  • 这是验证最终apk的唯一解决方案。其他响应假定您有来源。 (2认同)

Mea*_*man 10

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

buildTypes {
    debug {
        applicationIdSuffix ".debug"
    }
}
Run Code Online (Sandbox Code Playgroud)

添加此方法:

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


Nik*_*kov 5

调试版本也会被签名,只需使用不同的密钥.它由Eclipse自动生成,其证书有效期仅为一年.有什么问题 android:debuggable?您可以使用代码从代码中获取此值PackageManager.