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

发布于 2024-11-29 19:31:48 字数 326 浏览 2 评论 0原文

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

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

我的想法:

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

As far as I know, in android "release build" is signed APK. How to check it from code or does Eclipse has some kinda of secret defines?

I need this to debug populating ListView items from web service data (no, logcat not an option).

My thoughts:

  • Application's android:debuggable, but for some reason that doesn't look reliable.
  • Hard-coding device ID isn't good idea, because I am using same device for testing signed APKs.
  • Using manual flag somewhere in code? Plausible, but gonna definitely forget to change at some time, plus all programmers are lazy.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(10

关于从前 2024-12-06 19:31:48

要检查可调试标志,您可以使用以下代码:

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

Kotlin:

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

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

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

To check the debuggable flag, you can use this code:

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

Kotlin:

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

For more information, please see Securing Android LVL Applications.

Alternatively, if you're using Gradle correctly, you can check if BuildConfig.DEBUG is true or false.

临走之时 2024-12-06 19:31:48

Mark Murphy 回答说

最简单、最好的长期解决方案是使用BuildConfig.DEBUG。这是一个 boolean 值,对于调试构建,该值将为 true,否则为 false

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

Answered by Mark Murphy

The simplest, and best long-term solution, is to use BuildConfig.DEBUG. This is a boolean value that will be true for a debug build, false otherwise:

if (BuildConfig.DEBUG) {
  // do something for a debug build
}
雾里花 2024-12-06 19:31:48

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

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

There are different way to check if the application is build using debug or release certificate, but the following way seems best to me.

According to the info in Android documentation Signing Your Application, debug key contain following subject distinguished name: "CN=Android Debug,O=Android,C=US". We can use this information to test if package is signed with debug key without hardcoding debug key signature into our code.

Given:

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

You can implement an isDebuggable method this way:

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;
}
随心而道 2024-12-06 19:31:48

如果您想静态检查 APK,如果 APK 不可调试,则可以使用

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

此输出 0,如果 APK 不可调试,则可以使用 1代码> 如果是的话。

If you want to check an APK statically, you could use

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

This outputs 0 if the APK isn't debuggable and 1 if it is.

彡翼 2024-12-06 19:31:48

也许晚了,但 iosched 使用 BuildConfig.DEBUG

Maybe late, but iosched uses BuildConfig.DEBUG

那小子欠揍 2024-12-06 19:31:48

首先将其添加到您的 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;
    }
}

First add this to your build.gradle file, this will also allow side by side running of debug and release builds:

buildTypes {
    debug {
        applicationIdSuffix ".debug"
    }
}

Add this method:

public static boolean isDebug(Context context) {
    String pName = context.getPackageName();
    if (pName != null && pName.endsWith(".debug")) {
        return true;
    } else {
        return false;
    }
}
怎会甘心 2024-12-06 19:31:48

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

A debug build is signed as well, just with a different key. It's generated automatically by Eclipse, and its certificate is valid for one year only. What's the problem with android:debuggable? You can get this value from code using PackageManager.

甜味超标? 2024-12-06 19:31:48

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

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

Another option, worth mentioning. If you need to execute some code only when debugger is attached, use this code:

if (Debug.isDebuggerConnected() || Debug.waitingForDebugger()) { 
    //code to be executed 
}
泪是无色的血 2024-12-06 19:31:48

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

Solved with android:debuggable. It was bug in reading item where in some cases debug flag on item was not being stored in record getting if (m.debug && !App.isDebuggable(getContext())) always evaluated to false. My bad.

听,心雨的声音 2024-12-06 19:31:48

我目前正在使用的 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 过程)

Solution in Kotlin that I'm using at the moment:

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

that way I can still SIGN in debug and those will be reported to Crashlytics (example, for the QA process)

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文