如何解决Jenkins 模拟器插件 - 手动分配端口
最终更新 - 解决方案 - 连接到正确端口后安装失败,因为安装leaked file descriptors。按照 here 中的建议更新环境变量可解决问题
更新2 似乎环境变量会更改 gradle 命令的目标端口,但不会更改模拟器插件本身的等待循环。我决定手动启动模拟器
/var/lib/jenkins/android-sdk/emulator/emulator -avd testing24xlarge2 -wipe-data -no-window -no-audio -partition-size 4096 -ports 5558,5559&
EMULATOR_PID=$!
在这里我意识到,我没有指定 adb 超时,所以我决定使用之前插件使用的 tcp 端口,然后再试一次,但这没有丝毫帮助。
/var/lib/jenkins/android-sdk/emulator/emulator -report-console tcp:5829,max=96000 -avd testing24xlarge2 -wipe-data -no-window -no-audio -partition-size 4096 -ports 5558,5559&
EMULATOR_PID=$!
。我能想到的一个可能但不太可能的原因是调试 apk 太大(我尝试的应用程序从 200 Mb 到 700 mb)可能会导致这种情况,但错误消息似乎并未表明这一点。尝试使用 adb 命令而不是 gradle 任务安装应用程序也无济于事
android {
adbOptions {
timeOutInMs 6000000 // set timeout to 100 minutes
}
}
./gradlew assembleStagingDebug --no-daemon -Dkotlin.compiler.execution.strategy="in-process"
./gradlew assembleStagingDebugAndroidTest --no-daemon -Dkotlin.compiler.execution.strategy="in-process"
/var/lib/jenkins/android-sdk/platform-tools/adb -s emulator-5558 shell input keyevent 82
/var/lib/jenkins/android-sdk/platform-tools/adb -s emulator-5558 install -r -t myapp/build/outputs/apk/staging/debug/myapp-staging-debug.apk
/var/lib/jenkins/android-sdk/platform-tools/adb -s emulator-5558 install -r -t myapp/build/outputs/apk/androidTest/staging/debug/myapp-staging-debug-androidTest.apk
#/var/lib/jenkins/android-sdk/platform-tools/adb -e shell am instrument -w mypackage.testcases.tests/androidx.test.runner.AndroidJUnitRunner
在我尝试使用“可接受的 apk 大小”后,我将再次更新此帖子
更新:我想我已经正确地识别了问题,但我仍然无法让它工作。
Ddmlib 查找 5555,5586 之间的端口,当模拟器位于不同的端口时,应用程序安装自然会失败。
In official docs 建议我们可以利用环境变量让模拟器插件在我们想要的端口中搜索设备。但是与端口相关的环境变量(ANDROID_SERIAL,ANDROID_AVD_DEVICE
等)(我在我的主要 Jenkins 配置中设置它们)都没有改变 adb -s
的目标。因此,使用 ports 5558,5559
手动更改端口模拟器运行失败,因为模拟器在端口 5558 中启动,但是
/var/lib/jenkins/android-sdk/platform-tools/adb -s emulator-5776 wait-for-device shell getprop dev.bootcomplete
在模拟器插件的随机分配端口中运行,当模拟器在我选择的端口中启动时它会卡住。
_______________________________________________________________________________________
在解决了数十个不同的问题以在模拟器中打开和运行 UI 测试后,我希望能解决最后一个问题,我尝试了所有我能想到的方法,但没有奏效。
环境:我在最小 SDK = 24 的应用程序中使用 API 级别为 24 的模拟器以避免 INCOMPATIBLE_DEVICE_ERROR。 Jenkins 在 Ubuntu 20.04 中运行,但我认为这无关紧要。我的目标 sdk 和编译 sdk 是 28(我也会尝试降级它们,但由于我已经解决了 INCOMPATIBLE 错误,我怀疑这会解决问题)。 Adb timeout
是 96000 秒,而 startup delay
是 20 秒,这是很好的衡量标准。
正如下面的脚本将演示的那样,我很确定,我可以通过 adb 命令找到连接的模拟器,但是在安装和运行测试时,我尝试了两种不同的解决方案,但我都被卡住了。
>第一次尝试解决
while [ "`/var/lib/jenkins/android-sdk/platform-tools/adb shell getprop service.bootanim.exit | tr -d '\r' `" != "1" ] ; do sleep 1; done
/var/lib/jenkins/android-sdk/platform-tools/adb devices -l
/var/lib/jenkins/android-sdk/platform-tools/adb shell input keyevent 82
./gradlew myapp:connectedStagingDebugAndroidTest --no-daemon -Dkotlin.compiler.execution.strategy="in-process"
它正确等待设备启动(android 模拟器插件在此之前也会检查 sys.boot_completed)并列出连接的设备 /passes the input key event 82
这会导致以下错误
om.android.build.gradle.internal.testing.ConnectedDevice > runTests[testing24xlarge2(AVD) - 7.0] [31mFAILED [0m
com.android.builder.testing.api.DeviceException: com.android.ddmlib.InstallException
at com.android.build.gradle.internal.testing.ConnectedDevice.installPackage(ConnectedDevice.java:132)
[no message defined]
java.util.concurrent.ExecutionException: java.lang.RuntimeException: com.android.builder.testing.api.DeviceException: com.android.ddmlib.InstallException
at java.util.concurrent.ForkJoinTask.get(ForkJoinTask.java:1006)
at com.android.ide.common.workers.ExecutorServiceAdapter.await(ExecutorServiceAdapter.kt:102)
at com.android.build.gradle.internal.testing.BaseTestRunner.runTests(BaseTestRunner.java:201)
at com.android.build.gradle.internal.tasks.DeviceProviderInstrumentTestTask.lambda$doTaskAction$2(DeviceProviderInstrumentTestTask.java:201)
at com.android.builder.testing.api.DeviceProvider.use(DeviceProvider.java:53)
at com.android.build.gradle.internal.tasks.DeviceProviderInstrumentTestTask.doTaskAction(DeviceProviderInstrumentTestTask.java:191)
at
Caused by: java.lang.RuntimeException: com.android.builder.testing.api.DeviceException: com.android.ddmlib.InstallException
at com.android.build.gradle.internal.testing.SimpleTestRunnable.run(SimpleTestRunnable.java:231)
Caused by: com.android.builder.testing.api.DeviceException: com.android.ddmlib.InstallException
at com.android.build.gradle.internal.testing.ConnectedDevice.installPackage(ConnectedDevice.java:132)
at com.android.build.gradle.internal.testing.SimpleTestRunnable.run(SimpleTestRunnable.java:134)
... 116 more
Caused by: com.android.ddmlib.InstallException
at com.android.ddmlib.Device.installRemotePackage(Device.java:1174)
at com.android.ddmlib.Device.installPackage(Device.java:998)
at com.android.ddmlib.Device.installPackage(Device.java:974)
at com.android.ddmlib.Device.installPackage(Device.java:963)
at com.android.build.gradle.internal.testing.ConnectedDevice.installPackage(ConnectedDevice.java:126)
... 117 more
Caused by: com.android.ddmlib.ShellCommandUnresponsiveException
at com.android.ddmlib.AdbHelper.executeRemoteCommand(AdbHelper.java:553)
at com.android.ddmlib.AdbHelper.executeRemoteCommand(AdbHelper.java:378)
at com.android.ddmlib.Device.executeShellCommand(Device.java:675)
at com.android.ddmlib.Device.installRemotePackage(Device.java:1165)
... 121 more
(我尝试在不限制重要信息的情况下尽可能地减少异常链)
在这里你可以看到附加了模拟器
+ /var/lib/jenkins/android-sdk/platform-tools/adb devices -l
List of devices attached
emulator-5802 device product:sdk_google_phone_armv7 model:sdk_google_phone_armv7 device:generic transport_id:1
第二次尝试,建议here 这里也行不通
./gradlew clean
./gradlew assembleDebug
./gradlew assembleDebugAndroidTest
/var/lib/jenkins/android-sdk/platform-tools/adb install app/build/outputs/apk/app-debug.apk
/var/lib/jenkins/android-sdk/platform-tools/adb install app/build/outputs/apk/app-debug-androidTest-unaligned.apk
/var/lib/jenkins/android-sdk/platform-tools/adbshell am instrument -w com.google.samples.apps.topeka.test/android.support.test.runner.AndroidJUnitRunner
这里的问题是之后
/var/lib/jenkins/android-sdk/platform-tools/adb shell input keyevent 82
/var/lib/jenkins/android-sdk/platform-tools/adb install -r -t -g myapp/build/outputs/apk/staging/debug/myapp-staging-debug.apk //I have also tried adb -e to target the emulator as it is the only running device
控制台输出只在安装命令(带有标志和不带标志 -r -t -g)时冻结,并且您可能猜到下一个命令不会被执行。等了很长时间后,我收到以下错误,说 adb 可能无法工作,因为端口模拟器在。
adb: failed to install myapp/build/outputs/apk/staging/debug/myapp-staging-debug.apk: Performing Streamed Install
Build step 'Execute shell' marked build as failure
[android] Stopping Android emulator
emulator: WARNING: encryption is off
emulator: feeding guest with passive gps data,in headless mode
emulator: WARNING: Requested adb port (5775) is outside the recommended range [5555,5586]. ADB may not function properly for the emulator. See -help-port for details.
saving arm snapshot.... !!!
这是否因为端口错误而失败?如何在 Emulator Plugin 中指定我想要的端口号?它只让我
分配唯一的 TCP 端口以避免冲突。如果我在模拟器选项中指定它,它仍然会尝试使用没有分配的随机端口执行 adb 命令,所以这不起作用。接下来我尝试复制我在控制台中看到的脚本来自己启动模拟器,但它似乎也不起作用(当我手动添加命令时,模拟器没有启动
/var/lib/jenkins/android-sdk/platform-tools/adb start-server
/var/lib/jenkins/android-sdk/emulator/emulator -report-console tcp:5845,max=96000 -avd testing24xlarge2 -wipe-data -no-window -partition-size 4096 -ports 5558,5559
while [ "`/var/lib/jenkins/android-sdk/platform-tools/adb shell getprop service.bootanim.exit | tr -d '\r' `" != "1" ] ; do sleep 1; done //Doesn't pass here
我完全被困在这里,可能掉了大部分头发,可以接受第一个解决方案尝试或第二个解决方案尝试的修复。
解决方法
可以用环境变量来控制行为,例如:
export ANDROID_SERIAL=emulator-5802
还有一些,其中 ADB_LOCAL_TRANSPORT_MAX_PORT
可能有用:
$ADB_TRACE
comma-separated list of debug info to log:
all,adb,sockets,packets,rwx,usb,sync,sysdeps,transport,jdwp
$ADB_VENDOR_KEYS colon-separated list of keys (files or directories)
$ANDROID_SERIAL serial number to connect to (see -s)
$ANDROID_LOG_TAGS tags to be used by logcat (see logcat --help)
$ADB_LOCAL_TRANSPORT_MAX_PORT max emulator scan port (default 5585,16 emus)
$ADB_MDNS_AUTO_CONNECT comma-separated list of mdns services to allow auto-connect (default adb-tls-connect)
通常也可以告诉使用哪个端口:
usb restart adbd listening on USB
tcpip PORT restart adbd listening on TCP on PORT
,
您遇到了允许 ddmlib 与 ADB 服务器通信的底层 TCP 套接字失败。为了最终调查此问题,我建议您做两件事:
- 当失败发生时,检查套接字状态'lsof -i 5037'
- 为了调查哪个请求实际上失败了,请运行 tcpdump/Wireshark。请记住,所使用的接口很可能是环回。这样,您将看到执行的最后一个请求。从堆栈跟踪来看,它是 apk 推送到设备后的“pm install”
版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。