从代码中检测App是否为生产/发布版本

时间:2011-11-27 21:00:07

标签: android

我的应用程序中有一个自制日志系统。它所做的事情是在开发过程中预先形成很多日志(到文件和logcat),并且可以通过一个可变的变化完全关闭。有关功能示例:

static public  final boolean DEVELOPMENT_VERBOSE = true;

public static void developmentLogMessage(String message) {
    if (DEVELOPMENT_VERBOSE)
        Log.i("com.xxx.app",  message);
}

我遇到的问题(可能更令人烦恼)是我必须记得将DEVELOPMENT_VERBOSE = false设置为释放。在代码中是否有一种方法可以检测应用程序何时完成发布(例如检查已签名的apk),以便我可以通过编程方式将DEVELOPMENT_VERBOSE设置为false

我看了Detect if app was downloaded from Android Market,但看来我的应用程序甚至在签名之前都有签名。

try {
    PackageManager manager = context.getPackageManager(); 
    PackageInfo appInfo = manager.getPackageInfo(
                    "com.xxx.app", PackageManager.GET_SIGNATURES
        );

    System.out.println(appInfo.signatures[0].toCharsString());
} catch (NameNotFoundException e) {
}

我希望签名数组是空的,我可以关键。但不行。

3 个答案:

答案 0 :(得分:4)

您可以使用ProGuard在构建版本时完全关闭相应的日志。 ProGuard可以做很多有趣的事情。除此之外,它还可以在构建过程中收缩不需要的代码。例如,如果您在开发期间使用调试日志(Log.d()),但想要在发布中禁用它,那么您可以将这些行添加到proguard.cfg中:

-assumenosideeffects class android.util.Log {
  public static int d(...);
}

要启用ProGuard,请设置属性

proguard.config=proguard.cfg

project.properties(如果您使用默认位置)。请注意,默认情况下ProGuard还会执行其他操作,因此您在发布项目时可能需要采取一些额外步骤。至少你当然想要保存生成的mapping.txt文件。有关详细信息,请参阅the ProGuard guide

答案 1 :(得分:0)

您可以查看用于签署应用的证书,并采取相应措施。

例如:

  for (Signature sig : getPackageManager().getPackageInfo(getPackageName(), PackageManager.GET_SIGNATURES).signatures) {
    // Get some (pseudo)uniqe value:
    long sigHash = Arrays.hashCode(sig.toByteArray());
    if (sigHash == releaseSigHash) DEVELOPMENT_VERBOSE = false;
  }

以下是我为Google MapView所做的事情,决定使用哪个API密钥,这是一个类似的问题

  for (Signature sig : getPackageManager().getPackageInfo(getPackageName(), PackageManager.GET_SIGNATURES).signatures) {
    MessageDigest m = MessageDigest.getInstance("MD5");
    m.update(sig.toByteArray());
    md5 = new BigInteger(1, m.digest()).toString(16);

    Log.d("findApiNøgle", "md5fingerprint: "+md5);

    // Jacobs debug-nøgle
    if (md5.equals("5fb3a9c4a1ebb853254fa1aebc37a89b")) return "0osb1BfVdrk1u8XJFAcAD0tA5hvcMFVbzInEgNQ";
    // Jacobs officielle nøgle
    if (md5.equals("d9a7385fd19107698149b7576fcb8b29")) return "0osb1BfVdrk3etct3WjSX-gUUayztcGvB51EMwg";

    // indsæt din egen nøgle her:
  }

答案 2 :(得分:-3)

经过一些研究/工作后,我们可以使用一种解决方案来检查被证明的证书。

        static public boolean DEVELOPMENT_VERBOSE = false;
        static private final  X500Principal RELEASE_DN = new X500Principal(
            "CN=aaa,OU=bbb,O=ccc,L=ddd,ST=eee,C=fff"
            );

        // auto disable the development logs if the apk is signed with a cert
        try {
            PackageManager manager = context.getPackageManager();
            PackageInfo appInfo = manager.getPackageInfo("com.xxx.app",
                    PackageManager.GET_SIGNATURES);
            Signature raw = appInfo.signatures[0];

            try {
                CertificateFactory cf = CertificateFactory.getInstance("X.509");
                X509Certificate cert = (X509Certificate) cf.generateCertificate(new ByteArrayInputStream(raw.toByteArray()));

                //DEVELOPMENT_VERBOSE = cert.getSubjectX500Principal().equals(DEBUG_DN);
                if (!cert.getSubjectX500Principal().equals(RELEASE_DN))
                    DEVELOPMENT_VERBOSE = true;

            } catch (CertificateException e) {  

            }           
        } catch (NameNotFoundException e) {

        }

只要您从应用程序的版本到版本使用相同的证书,这将始终有效。