iOS 测试 iOS 远程真机实现讨论帖!!

烟消云散 · 2017年08月11日 · 最后由 mosign 回复于 2018年04月13日 · 6336 次阅读
本帖已被设为精华帖!

如题,最近公司看见 MTC 实现的远程真机,需要我去攻坚,但是由于技术储备以及对测试的不了解,没能攻克,希望在这里和大家一起讨论,一起解决这个问题。。。好东西一起分享嘛~~~
嘛,我先来说下我的大概思路吧:

页面显示

先前不是有ios-minicap可以通过不断的自动截图来显示 iOS 页面的实时显示嘛,基于这个框架可以实现页面的回显。具体安装步骤可以看一下我在 CSDN 里面写的ios-minicap 安装使用指南

真机连接

连接协议主要是用的 usbmuxd Proxy,这个主要还是通过libimobiledevice协议库来实现安装啊截图啊日志啊什么的

然后是 Facebook 提供的绝大多数都在使用的 WebdriverAgent,可以直接用 WebSocket 通讯发送命令 (ps:我的 WDA 特别傲娇各种找我麻烦,特别爱报 operation never finished bootstrapping 的错,https://testerhome.com/topics/9666,这里特别讲了一下我遇到的两个大麻烦)

操纵实现

有两个方案
一、是@codeskyblue 大神写的wdaproxy,看了下好像是用 go 语言写的,哇,萌新瑟瑟发抖 ing

大概是这样的:

 tap: function(x, y) {
          var self = this;
          return $.ajax({
            url: "/session/" + self.sessionId + "/wda/tap/0",
            method: "POST",
            data: JSON.stringify({
              x: x,
              y: y
            }),
          }).then(function(ret) {
            if (ret.status !== 0) {
              console.log(ret.value);
            } else {
              return "Success";
            }
          })
        },

initScreenSize: function() {
          $.\
          ({
              url: "/status",
            })
            .then(function(ret) {
              this.sessionId = ret.sessionId;
              return $.ajax({
                url: "/session/" + ret.sessionId + "/window/size",
              })
            }.bind(this))
            .then(function(ret) {
              this.display.width = ret.value.width;
              this.display.height = ret.value.height;
            }.bind(this))
        },

这个其实是@weamylady 给我说的,so,有什么其他的想法也来讨论一下吧。

二、百度 MTC 项光特大佬提的,用 iOS 的私有 API XCEventGenerator 来实现不同类型的屏幕触控事件

关于这个要多谢@zhangzhao_lenovo 大神提供了两个地址:
swift:
https://github.com/zalando/SwiftMonkey/blob/master/SwiftMonkey/MonkeyXCTestPrivate.swift

oc 的 wda:
https://github.com/facebook/WebDriverAgent/blob/master/PrivateHeaders/XCTest/XCEventGenerator.h

或者通过iOS-Runtime-Headers来获取 iOS 的私有 API

还有个说法是:
通过 iproxy 工具把接口映射到宿主机
宿主机通过 curl 命令的方式实现对设备的控制

希望这篇文章对大家实现 iOS 远程真机有帮助,也希望得到其他大神朋友们的帮助,跪谢!
同时也很感谢 TesterHome 这个平台,让我学习了很多有用的东西,希望 TesterHome 越做越好!

照例,在最后 @ 几个大神防止帖子沉下去。。。。

@seveniruby @xdf @junhe (最近看着几位大神的文章比较多~~~~)

2017-8-14

上周我开了这个讨论话题,多谢@seveniruby思寒的加精让我觉得这个话题还是有实现的必要性的~
现在我讲一下我现在觉得可行性较高的一套实现思路,希望社区里面大神们也帮我参考参考,也希望能帮助更多人得到 iOS 远程真机实现的思路。

思路

首先,通过 ios-minicap,我们可以获取一个 Web 端的页面,这个页面通过不断的对真机进行截图实现实时显示真机页面的功能;

然后,我们可以通过 js 对获取到的 Web 页面进行事件控制(包括鼠标的拖拽,点击,长按等);

其次,我们可以使用 WDA 作为 PC 端与真机进行连接的工具,调用苹果的私有 API XCEventGenerator 来实现 PC 端对真机的触控事件;

再其次,通过 js 的事件控制来调用 WDA,实现 Web 端对 PC 端的操纵,最后达到 Web 端控制真机的触控;

最后,通过 ios-minicap 再实时回显真机上被 WDA 触控导致的操作,完成 iOS 远程真机的实现。

难点:

1.如何调用苹果的私有 API XCEventGenerator 来实现 PC 端对真机的触控事件

2.如何通过 js 实现鼠标的拖拽,点击,长按等事件,达到调用 WDA 的目的

2017-10-16

时隔两个月,现在基本有了 iOS 远程真机的解决方案——iOS-remote,感谢 weamylady2 的分享,安装使用详情可见https://testerhome.com/topics/10466

如果觉得我的文章对您有用,请随意打赏。您的支持将鼓励我继续创作!
共收到 37 条回复 时间 点赞

我只是打酱油的,要搞这个还得恶补 JS😖

water 回复

大佬请不要这么说~~~~

我也只是随便写写

给个思路,xcode9 出来之后,可以远程 debug,是不是能借助这条通道?

思寒_seveniruby 将本帖设为了精华贴 08月13日 15:08

说一个不太沾边的想法,假如有一种硬件"屏幕”,替换掉现有手机的屏幕,这个新 “屏幕” 可以把视频信息转换到 web 上并模拟触控,那就可以实现所有类型手机的远程控制了,不过实现这个需要拆解手机,可能比较麻烦,估计目前市面上也没有这种东西。

blueshark 回复

这个如果能做到,屏幕本身就是信息处理中心了,估计那个时候手机就只有个屏幕了吧,也就更薄了,不过对我们还是有点远~~现在我们还是讨论通过软件方面来实现远程控制吧

很赞哟

一起讨论实现嘛~

匿名 #10 · 2017年08月15日

问楼主个问题 就是 ios-minicap 的截图速度跟 facebook 的 WDA 里面的截图速度比怎么样@yxys01

前者快得多耶~

匿名 #12 · 2017年08月15日

@yxys01 我看了下 ios-minicap 源码都是处理图片的 具体的截取动作是不是在 cmake 做的还是其他原理呀

这个我也在研究~但是还没找到是怎么实现截取的~~~你如果找到了我们可以一起分享嘛

匿名 #14 · 2017年08月15日

我现在有两套方案都是跟这个有关 一个是在执行自动化的时候 去实时获取页面截图 因为调用 IOS 原生的 ReplayKit 没有提供接口 所以就把图片合成视频 第二个就是我做的一个实时操控 iphone 的也需要获取图片 都是使用的 wda 的 screenshot 差不多 100-200ms 一张

萌新提供个思路,不知道是否正确。iosApp 端作为服务器接收 iosminicap 的点击请求,调用私有 api

1.如何调用苹果的私有 API XCEventGenerator 来实现 PC 端对真机的触控事件

楼上说的思路应该是正确的,这个应该通过 app 来实现,类似 stf services

31楼 已删除
匿名 #18 · 2017年08月17日

@lancelot_mn 可以参考下 facebook 的 webdriveragent 和阿里的 XCTestWD

29楼 已删除
28楼 已删除

能给个联系方式私聊下吗?qq 微信皆可。。。

22楼 已删除

楼主是在将 ios_minicap 弄到 atx 里?

MTC 的远程真机,是我们家技术支持的,在真机页面的右下角可以看到,由苏州跬步支持。有疑问,可以直接私聊完😇

你要的打包命令

go generate ./web
go build -tags vfs
无缺 回复

怎么没在你们平台上看到 iOS 的真机远程呢

krisdy 回复

网站:http://www.bugzero.cn/index,你打开这个网站试试

无缺 回复

做的还不错,不过没有苹果手机呀,Android 也没有远程终端

codeskyblue 回复

iOS 正在沟通更好的方案,Android 是有的哟~

无缺 回复

你们这界面做的真不错,方便透露下做成这样花了多少时间和人力吗?

blueshark 回复

布局方面是后来改的,css 部分花了 1 天。从 0 开始估计一个月

看了百度的远程真机方案,感觉还是 ios-minicap 回显 +wda 远程操控做起来比较简单,这个月想要把这个搞出来,大家一起讨论下咯

给位大佬好,我这边已经用 ios-minicap+Jfinal+Tomacat 把屏幕回显做出来了,屏幕监听事件借用了 wdaproxy 项目中的 js。
今天在调 tap 事件,遇到一个大问题卡住了:
1,先启动 WebDriverAgent,再启动 ios-minicap,那么在 WDA 的进程会多出一条日志,然后卡死了。感觉是 iOS-minicap 也在某个地方调用了 WDA,后续的 tap 操作就没办法执行。
2,如果在 ios-minicap 启动之后,再启动 WDA,那么在向 ios-minicap 发起 socket 获取截图,WDA 同样会出现一样的日志,然后卡死。

WDA 日志如下:

99-6-88-54:WebDriverAgent waterhuang$ xcodebuild -project WebDriverAgent.xcodeproj -scheme WebDriverAgentRunner -destination 'id=bb7787b7ba9d57bb6f9c84273d22fe3204d1e547' test
2017-09-14 16:44:46.386 xcodebuild[20603:567818]  IDETestOperationsObserverDebug: Writing diagnostic log for test session to:
/Users/waterhuang/Library/Developer/Xcode/DerivedData/WebDriverAgent-dikkwtrisltbeobjmfvpthwwekvs/Logs/Test/86F41E4A-F9BF-4585-B2A9-C25DF7D17CCC/Session-WebDriverAgentRunner-2017-09-14_164446-6Y1V40.log
2017-09-14 16:44:46.387 xcodebuild[20603:567817] [MT] IDETestOperationsObserverDebug: (727C4322-FEB3-4E83-8C45-35F618841E8D) Beginning test session WebDriverAgentRunner-727C4322-FEB3-4E83-8C45-35F618841E8D at 2017-09-14 16:44:46.387 with Xcode 8E3004b on target <DVTiOSDevice: 0x7fe2fcfdb1c0> {
        deviceSerialNumber:         C8QP5BQHG5MP
        identifier:                 bb7787b7ba9d57bb6f9c84273d22fe3204d1e547
        deviceClass:                iPhone
        deviceName:                 iPhone
        deviceIdentifier:           bb7787b7ba9d57bb6f9c84273d22fe3204d1e547
        productVersion:             10.3.3
        buildVersion:               14G60
        deviceSoftwareVersion:      10.3.3 (14G60)
        deviceArchitecture:         arm64
        deviceTotalCapacity:        12241596416
        deviceAvailableCapacity:    8145756160
        deviceIsTransient:          NO
        ignored:                    NO
        deviceIsBusy:               NO
        deviceIsActivated:          YES
        deviceActivationState:      Activated
        isPasscodeLocked:           NO
        deviceType:                 <DVTDeviceType:0x7fe2fcca88c0 Xcode.DeviceType.iPhone>
        supportedDeviceFamilies:    (
    1
)
        applications:              (null)
        provisioningProfiles:      (null)
        activityProgress:          -2
        activityTitle:             
        hasInternalSupport:        NO
        isSupportedOS:             YES
        developerDiskMountError:   (null)
(null)
    bootArgs:                  <unavailable>
        } (10.3.3 (14G60))
=== BUILD TARGET WebDriverAgentLib OF PROJECT WebDriverAgent WITH CONFIGURATION Debug ===

Check dependencies

=== BUILD TARGET WebDriverAgentRunner OF PROJECT WebDriverAgent WITH CONFIGURATION Debug ===

Check dependencies

MDMCreateDeltaDirectory:1920 calling MDMDirectoryDiff with:
state->old_bundle: /var/folders/lq/q_5j5j1d2d5_v7w4bxmhgv5r0000gn/C/com.apple.DeveloperTools/All/Xcode/EmbeddedAppDeltas/33d6e04dc03b69e6e6e6fd8dea37958a/bb7787b7ba9d57bb6f9c84273d22fe3204d1e547/WebDriverAgentRunner-Runner.app
state->new_bundle: /Users/waterhuang/Library/Developer/Xcode/DerivedData/WebDriverAgent-dikkwtrisltbeobjmfvpthwwekvs/Build/Products/Debug-iphoneos/WebDriverAgentRunner-Runner.app
state->dst_bundle: /var/folders/lq/q_5j5j1d2d5_v7w4bxmhgv5r0000gn/C/com.apple.DeveloperTools/All/Xcode/EmbeddedAppDeltas/WebDriverAgentRunner-Runner.app.NXYEQh/WebDriverAgentRunner-Runner.app_sparse.ipa/Payload//WebDriverAgentRunner-Runner.app, binaryDiff flag: FALSE
    dst_ipa: /var/folders/lq/q_5j5j1d2d5_v7w4bxmhgv5r0000gn/C/com.apple.DeveloperTools/All/Xcode/EmbeddedAppDeltas/WebDriverAgentRunner-Runner.app.NXYEQh/WebDriverAgentRunner-Runner.app_sparse.ipa
MDMDirectoryDiff_block_invoke:1473 calling writeDictToFile with: /var/folders/lq/q_5j5j1d2d5_v7w4bxmhgv5r0000gn/C/com.apple.DeveloperTools/All/Xcode/EmbeddedAppDeltas/WebDriverAgentRunner-Runner.app.NXYEQh/WebDriverAgentRunner-Runner.app_sparse.ipa/ManifestCache.plist
writeDictToFile:1278 ==== Successfully wrote Manifest cache to /var/folders/lq/q_5j5j1d2d5_v7w4bxmhgv5r0000gn/C/com.apple.DeveloperTools/All/Xcode/EmbeddedAppDeltas/WebDriverAgentRunner-Runner.app.NXYEQh/WebDriverAgentRunner-Runner.app_sparse.ipa/ManifestCache.plist
2017-09-14 16:45:13.717753+0800 XCTRunner[2688:701460] Running tests...
2017-09-14 16:45:14.727374+0800 XCTRunner[2688:701460] Continuing to run tests in the background with task ID 1
Test Suite 'All tests' started at 2017-09-14 16:45:14.890
Test Suite 'WebDriverAgentRunner.xctest' started at 2017-09-14 16:45:14.894
Test Suite 'UITestingUITests' started at 2017-09-14 16:45:14.895
Test Case '-[UITestingUITests testRunner]' started.
    t =     0.00s     Start Test at 2017-09-14 16:45:14.899
    t =     0.01s     Set Up
2017-09-14 16:45:14.936272+0800 XCTRunner[2688:701560] [User Defaults] Failed to write value for key AutomationDisableFauxCollectionCells in CFPrefsPlistSource<0x1701056a0> (Domain: com.apple.Accessibility, User: kCFPreferencesCurrentUser, ByHost: No, Container: (null)): setting preferences outside an application's container requires user-preference-write or file-write-data sandbox access, switching to read-only
2017-09-14 16:45:15.031058+0800 XCTRunner[2688:701460] Built at Sep 14 2017 09:19:49
2017-09-14 16:45:15.224069+0800 XCTRunner[2688:701460] ServerURLHere->http://99.6.91.22:8100<-ServerURLHere
    t =     3.20s     Find the Application "local.pid.53" 0x1740b6c20
    t =     3.20s         Snapshot accessibility hierarchy for local.pid.53
    t =     3.46s     Find the Application "local.pid.53" 0x1740b6c20
    t =     3.46s         Use cached accessibility hierarchy for local.pid.53
    t =     3.46s     Use cached accessibility hierarchy for local.pid.53
    t =     3.49s     Find the Application "local.pid.53" 0x1740b6c20
    t =     3.50s         Snapshot accessibility hierarchy for local.pid.53
    t =     3.64s     Find the Application "local.pid.53" 0x1740b6c20
    t =     3.64s         Use cached accessibility hierarchy for local.pid.53
2017-09-14 16:45:25.314 xcodebuild[20603:567915]  IDETestOperationsObserverDebug: Writing diagnostic log for test session to:
/Users/waterhuang/Library/Developer/Xcode/DerivedData/WebDriverAgent-dikkwtrisltbeobjmfvpthwwekvs/Logs/Test/86F41E4A-F9BF-4585-B2A9-C25DF7D17CCC/Session-WebDriverAgentRunner-2017-09-14_164525-Nq4VNG.log
2017-09-14 16:45:25.315 xcodebuild[20603:567817] [MT] IDETestOperationsObserverDebug: (5246C677-3941-41EA-98A8-853990396271) Beginning test session WebDriverAgentRunner-5246C677-3941-41EA-98A8-853990396271 at 2017-09-14 16:45:25.314 with Xcode 8E3004b on target <DVTiOSDevice: 0x7fe2fcfdb1c0> {
        deviceSerialNumber:         C8QP5BQHG5MP
        identifier:                 bb7787b7ba9d57bb6f9c84273d22fe3204d1e547
        deviceClass:                iPhone
        deviceName:                 iPhone
        deviceIdentifier:           bb7787b7ba9d57bb6f9c84273d22fe3204d1e547
        productVersion:             10.3.3
        buildVersion:               14G60
        deviceSoftwareVersion:      (null)
        deviceArchitecture:         arm64
        deviceTotalCapacity:        12241596416
        deviceAvailableCapacity:    8145756160
        deviceIsTransient:          NO
        ignored:                    YES
        deviceIsBusy:               NO
        deviceIsActivated:          NO
        deviceActivationState:      Activated
        isPasscodeLocked:           NO
        deviceType:                 <DVTDeviceType:0x7fe2fcca88c0 Xcode.DeviceType.iPhone>
        supportedDeviceFamilies:    (null)
        applications:              (null)
        provisioningProfiles:      (null)
        activityProgress:          -2
        activityTitle:             
        hasInternalSupport:        NO
        isSupportedOS:             NO
        developerDiskMountError:   (null)
(null)
    bootArgs:                  <unavailable>
        } ((null))


water 回复

给你说下顺序,启动 minicap 然后启动 socket 获取图像,然后启动 wda

codeskyblue 回复

多谢,这个顺序是可以。有没有解决的方法?这个顺序启动的话,还是挺慢的。

@yxys01 有空加我微信聊聊吧,xiaotao4495,目前已经把 Demo 写出来了,但还是存在很多的问题,尤其是运行的顺序这个有待优化。

water 回复

https://github.com/openstf/ios-minicap/issues/14

This is because the active USB configuration changes. Normally, it's "PTP + Apple Mobile Device". When minicap (or QuickTime) runs, it changes to "PTP + Apple Mobile Device + Valeria". This causes a reconnection. When minicap ends, the configuration changes back, again triggering a brief disconnection. For that reason you must start minicap before anything else and keep it running the whole time.

Kai Zhang 回复

minicap 要这个机制就没办法了,目前我已经把顺序启动写好了,就是时间有点长,刷新网页之后需要 20 秒钟才能用起来。

https://github.com/weamylady2/iOS_remote

Demo 已上传,欢迎大家指点意见。

@weamylady @yxys01 一台 mac 服务器部署多台设备这个能实现不,一台服务器连接一台手机这个成本有点大啊

heygrl 回复

截图部分用 idevicescreenshot 替代,是可以的,不过会变得很卡很延时,看你能不能接受了。

如何实现真机轨迹操作?类似手势密码解锁,备忘录画图?

simple 专栏文章:[精华帖] 社区历年精华帖分类归总 中提及了此贴 12月13日 20:49
simple [精彩盘点] TesterHome 社区 2018 年 度精华帖 中提及了此贴 01月07日 12:08
codeskyblue iOS 远程真机方案整理 中提及了此贴 03月08日 23:45
需要 登录 后方可回复, 如果你还没有账号请点击这里 注册