Android Studio无源码调试app
第一步
Android Studio安装smalidea-0.03.zip,点击File->Settings->Plugins->Instal plugins from disk,选择下载的zip包就行。安装完成后,AS提示重启生效。
Paste_Image.png第二步
Apktool A tool for reverse engineering Android apk files
用法很简单,java -jar apktool.jar d -f 源文件 -o 输出文件夹,其中-f代表如果输出文件夹存在则先删除
批处理文件如下:
@echo off
set apk=%1
set output=%apk:~0, -4%
java -jar apktool.jar d -f %apk% -o %output%
第三步
AS导入工程,选择上一步Apktool 的输出文件夹,一路next,最后结果如下图
Paste_Image.png第四步
配置AS调试配置,Run->Edit Configurations,点击+号,新建remote类型调试器,如果默认端口被占用则需要 修改端口号。
Paste_Image.png第五步
adb shell am start -D -n me.ele/.adr
以调试模式启动应用,进程挂起。me.ele是包名,.adr是将要启动的activity。
Paste_Image.pngadb shell ps | findstr "me.ele"
adb forward tcp:5005 jdwp:20058
设置端口转发,这条命令的含义可以认为是在本地5005端口与手机20058进程之间建立一条通道,当开始调试时,AS连接本地的5005端口,通过这条通道控制程序的运行
这三步有点麻烦,写了一个控制台程序来一步到位。
Paste_Image.png三个参数分别是 包名、activity、端口号。
using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Text.RegularExpressions;
class Program
{
static void Main(string[] args)
{
if (args.Length != 3)
{
Console.WriteLine("usage: package activity port");
return;
}
var package = args[0];
var activity = args[1];
var port = args[2];
const string adb = "adb";
StartProcess(adb, string.Format("shell am start -D -n {0}/{1}", package, activity));
bool first = true;
var standardOutput = StartProcess(adb, "shell ps", (item) =>
{
if(first)
{
first = false;
return true;
}
return item != null && item.Contains(package);
});
var input = standardOutput.Find((item) => item != null && item.Contains(package));
if(input != null)
{
var matches = Regex.Matches(input, @"\S+");
var arguments = string.Format("forward tcp:{0} jdwp:{1}", port, matches[1].Value);
Console.WriteLine(adb + " " + arguments);
StartProcess(adb, arguments);
}
}
public static List<string> StartProcess(string fileName, string arguments, Predicate<string> filterStandardOutput = null, Predicate<string> filterStandardError = null)
{
var processStartInfo = new ProcessStartInfo();
processStartInfo.FileName = fileName;
processStartInfo.Arguments = arguments;
processStartInfo.CreateNoWindow = true;
processStartInfo.RedirectStandardInput = false;
processStartInfo.RedirectStandardOutput = true;
processStartInfo.RedirectStandardError = true;
processStartInfo.UseShellExecute = false;
var process = new Process();
process.StartInfo = processStartInfo;
var standardOutput = new List<string>();
process.OutputDataReceived += (sender, e) => standardOutput.Add(e.Data);
var standardError = new List<string>();
process.ErrorDataReceived += (sender, e) => standardError.Add(e.Data);
process.Start();
process.BeginOutputReadLine();
process.BeginErrorReadLine();
process.WaitForExit();
if (filterStandardOutput != null)
standardOutput = standardOutput.FindAll(filterStandardOutput);
foreach (var item in standardOutput)
{
if (item == null)
continue;
Console.WriteLine(item);
}
if(filterStandardError != null)
standardError = standardError.FindAll(filterStandardError);
foreach (var item in standardError)
{
if (item == null)
continue;
Console.WriteLine(item);
}
return standardOutput;
}
}
第六步
在左侧栏鼠标右键选择显示行号,在行号旁边单击即可下断点,点击Debug开始调试。
Paste_Image.png Paste_Image.png
看到这个信息就说明成功了。
Paste_Image.png注意事项
如果以上步骤你都没做错,结果一直失败,那么请检查你的AndroidManifest.xml配置。
Paste_Image.png重新打包
修改代码之后重新打包,安装后再次调试。
java -jar apktool.jar b 第二步的输出文件夹 -o 输出文件
批处理文件如下:
@echo off
set output=%1
set apk_unsigned=%output%_unsigned.apk
java -jar apktool.jar b %output% -o %apk_unsigned%
adb install -r %apk_unsigned%