NewLLDebugTool里面实现了一个智能 monkey,现在已经支持快速遍历算法和随机遍历算法,因为 monkey 是集成在 app 里面,如果 app 发生 crash(如果开启 fuzzy 功能,很容易发生 crash),那么如何重新拉起 app,继续运行呢?
app 自己本身肯定无法拉起自己,肯定需要外力进行拉起,我自己调研有两种可行的方案:
1、通过私有 api 进行拉起,使用的私有 api LSApplicationWorkspace
,大体代码如下所示:
+(BOOL)isOpenApp:(NSString*)appIdentifierName
{
Class LSApplicationWorkspace_class = objc_getClass("LSApplicationWorkspace");
NSObject* workspace = [LSApplicationWorkspace_class performSelector:@selector(defaultWorkspace)];
BOOL isOpenApp = [workspace performSelector:@selector(openApplicationWithBundleID:) withObject:appIdentifierName];
return isOpenApp;
}
这种方案最终我放弃了,主要考虑以下几点:1、私有 api,顾名思义是苹果不允许使用的 api,很可能在苹果的后续版本更新中就无法使用了,从而导致这种保活方式的可兼容性很差; 2、可扩展能力不强,如果后续我们想接入持续集成 (未来的趋势),那必定需要定时或者 ci 的时候拉去最新的安装包跑 monkey,很明显自动拉取最新包并安装到手机上,是通过私有 api 完成不了的,如果能完成,ios 全家桶了解一下。
2、方案二也是现在我采用的方式,通过 ios 自带的 ui 自动化框架 xctest 进行保活。xctest 里面的XCUIApplication
可以检查当前 app 的状态是否激活,如果未激活可以拉起 app,大体代码如下所示:
public func addXCTestCheckCurrentApp(interval:Int, application:XCUIApplication) {
addCheck(interval:interval){ [weak self] in
let work = DispatchWorkItem(qos:.userInteractive){
if (application.state != XCUIApplication.State.runningForeground){
application.activate()
self?.sleep(5)
}
}
DispatchQueue.main.async(execute:work)
}
}
工程也已经开源,开源地址:MonkeyRunner,和 monkey 配合使用,效果更好。效果如下所示:
中间触发了一次预先写好的 crash,app 闪退,但是被 xctest 重新拉起,monkey 继续运行,如果我们想要停止 monkey,只需要摇一摇手机停止 monkey 即可。