使用 ProGuard 调试已编译的 APK
Debugging a compiled APK with ProGuard
将已编译的 APK 上传到 Google 开发者 Play 控制台后,您可以在应用崩溃时看到日志消息。此外,在调试模式下测试应用程序时,如果应用程序崩溃,您可以看到日志消息。
在将应用程序作为已编译的 APK 进行测试时,是否可以查看日志消息?请注意,我正在使用 ProGuard。
我的意思是,在设备上安装已编译的 APK 时,能够以某种方式查看应用程序崩溃的日志消息。如果还有不明白的地方,请在评论中告诉我。
这里有一些代码示例,当您的应用程序使用混淆器加密时,堆栈清晰可见:
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文件
通过简单地将 debuggable true
放入我的应用程序的 build.gradle
中,当我的 phone 连接到Android工作室。
我的 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 在堆栈跟踪中显示行号。
将已编译的 APK 上传到 Google 开发者 Play 控制台后,您可以在应用崩溃时看到日志消息。此外,在调试模式下测试应用程序时,如果应用程序崩溃,您可以看到日志消息。
在将应用程序作为已编译的 APK 进行测试时,是否可以查看日志消息?请注意,我正在使用 ProGuard。
我的意思是,在设备上安装已编译的 APK 时,能够以某种方式查看应用程序崩溃的日志消息。如果还有不明白的地方,请在评论中告诉我。
这里有一些代码示例,当您的应用程序使用混淆器加密时,堆栈清晰可见:
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文件
通过简单地将 debuggable true
放入我的应用程序的 build.gradle
中,当我的 phone 连接到Android工作室。
我的 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 在堆栈跟踪中显示行号。