使用 ProGuard 调试已编译的 APK

Posted

技术标签:

【中文标题】使用 ProGuard 调试已编译的 APK【英文标题】:Debugging a compiled APK with ProGuard 【发布时间】:2015-12-22 14:47:57 【问题描述】:

将已编译的 APK 上传到 Google Developer Play Console 后,您可以在应用崩溃时看到日志消息。此外,在调试模式下测试应用时,如果应用崩溃,您可以看到日志消息。

在将应用程序作为已编译的 APK 进行测试时,是否可以查看日志消息?请注意,我使用的是 ProGuard。

我的意思是,当在设备上安装编译的 APK 时,能够以某种方式查看来自应用程序崩溃的日志消息。如果问题仍然不清楚,请在 cmets 中告诉我。

【问题讨论】:

【参考方案1】:

这里有一些代码示例,当您的应用使用 proguard 加密时,堆栈清晰:

    private static void trace(String txt) 
    if (ENABLE_TRACE) 
        Trace.trace(txt);
        Trace.trace("\n");
        System.out.println(txt);
    


public static String retrieveProguardStackInternal(String stack, File proguardFile,String sdkPath,String javaPath) 
    String ret = stack;
    trace("trying to uncrypt stack");
    trace("==== raw stack ====");
    trace(stack);
    if ((stack == null) || (stack.length() == 0) || (proguardFile == null) || (!proguardFile.exists()) || (sdkPath == null) || (javaPath == null)) 
        if ((stack == null) || (stack.length() == 0)) 
            trace("empty stack => abort");
        
        if (!proguardFile.exists()) 
            trace("proguard file does not exists "+proguardFile.getAbsolutePath());
        
        if (sdkPath == null) 
            trace("sdk path not defined");
        
        if (javaPath == null) 
            trace("java path not defined");
        
        return ret;
           
    trace("sdk : "+sdkPath);
    trace("jdk : "+javaPath);
    StringBuilder sb = new StringBuilder();
    sb.append(sdkPath);
    sb.append(File.separatorChar);
    sb.append("tools");
    sb.append(File.separatorChar);
    sb.append("proguard");
    sb.append(File.separatorChar);
    sb.append("lib");
    sb.append(File.separatorChar);
    sb.append("retrace.jar");
    String retraceJarPath = sb.toString();
    File retraceJar = new File(retraceJarPath);
    if (!retraceJar.exists()) 
        trace("proguard lib not found at "+retraceJarPath);
        return ret;
       
    sb = new StringBuilder();
    sb.append(javaPath);
    sb.append(File.separatorChar);
    sb.append("java");
    String javaexePath = sb.toString();
    sb = new StringBuilder();
    try 
        // using the Runtime exec method:
        Process p = Runtime.getRuntime().exec(new String[] javaexePath,"-jar",retraceJarPath,proguardFile.getAbsolutePath());
        OutputStream out = p.getOutputStream();
        out.write(stack.getBytes());
        out.close();
        BufferedReader stdInput = new BufferedReader(new InputStreamReader(p.getInputStream()));
        BufferedReader stdError = new BufferedReader(new InputStreamReader(p.getErrorStream()));
        // read the output from the command
        String line = null;
        String lineSeparator = System.getProperty("line.separator");
        while ((line = stdInput.readLine()) != null) 
            sb.append(line);
            sb.append(lineSeparator);
        
        // read any errors from the attempted command
        StringBuilder error = new StringBuilder();
        while ((line = stdError.readLine()) != null) 
            error.append(line);
        
        trace("error trace :"+error);
        p.waitFor(); 
     catch (Throwable e) 
        trace("exception happened - here's what I know: ");
        trace(e.toString());
    
    ret = sb.toString();
    trace("=== final stack ===");
    trace(ret);
    trace("===================");
    return ret;

需要提供原始栈+编译时proguard生成的map文件

【讨论】:

【参考方案2】:

只需将debuggable true 放在我的应用程序的build.gradle 中,当我的手机连接到android Studio 时,我就可以查看已编译的APK 应用程序的堆栈跟踪(但是没有行号)。

我的build.gradle 文件在添加这一行后看起来有点像这样:

...

buildTypes 
    release 
        debuggable true // This allows stack traces to appear in LogCat
        minifyEnabled true // This obfuscates the code
        proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'
    


...

另外,this answer 解释了如何使用 ProGuard 在堆栈跟踪中显示行号。

【讨论】:

以上是关于使用 ProGuard 调试已编译的 APK的主要内容,如果未能解决你的问题,请参考以下文章

ProGuard 警告不允许我的应用编译发布

使用 ProGuard 值得吗?

使用 ProGuard 混淆 clojure uberjars

Android debuggable=true with proguard 开启

Proguard minifyEnabled true 用于调试构建,不适用于预棒棒糖

启用 proguard 后调试应用程序构建失败