Я пытаюсь получить видео неудачных тестов на моем CI-сервере.
Цель состоит в том, чтобы начать снимок экрана при каждом тесте, а затем, когда он не удается, сохранить видео где-нибудь и когда оно пройдет, удалите видео.CI-сервер будет подбирать файлы, используя adb.
Я рассматриваю возможность использования screenrecord
для этой цели.Я подумал, что это было легко, потому что этот двоичный файл уже присутствует на устройстве и действительно хорошо работает при использовании через ADB.
Вот как я использую его программно: откройте поток, который запустится и будет следовать процессу, изапустите его до начала теста:
@Before
fun baseBefore() {
startScreenRecording()
}
private fun startScreenRecording() {
Timber.d("screenrecord: start record thread")
screenRecordThread = Thread(screenRecordRunnable)
screenRecordThread.start()
Timber.d("screenrecord: wait a bit")
Thread.sleep(5000)
Timber.d("screenrecord: go")
}
Я жду 5 секунд, потому что screenrecord
может потребоваться некоторое время для запуска.
Вот фактический screenrecord
вызов:
private class ScreenRecordRunnable : Runnable {
private lateinit var process: Process
override fun run() {
try {
Timber.d("screenrecord-record: start")
// tried also with the following: no luck
// process = ProcessBuilder(
// "/system/bin/screenrecord",
// "--time-limit", "60",
// "--verbose",
// "--bit-rate", "4M",
// "--bugreport",
// "/sdcard/test.mp4",
// "&"
// )
// .redirectErrorStream(true)
// .start()
process = Runtime.getRuntime().exec("/system/bin/screenrecord --time-limit 60 --verbose --bit-rate 4M --bugreport /sdcard/test.mp4")
val reader = BufferedReader(InputStreamReader(process.inputStream))
while (true) {
val line = reader.readLine() ?: break
Timber.d("screenrecord-record: log: $line")
}
Timber.d("screenrecord-record: wait for (isAlive: ${process.isAlive})")
process.waitFor()
Timber.d("screenrecord-record: wait stopped; exit value: ${process.exitValue()}")
reader.close()
} catch (e: IOException) {
throw Exception(e)
} catch (e: InterruptedException) {
throw Exception(e)
}
}
}
В методе @After
я извлекаю PID процесса screenrecord
(через pgrep
, он работает) и отправляю его kill -2 $pid
, чтобы имитировать Ctrl-C на этомпроцесс, чтобы остановить запись экрана.
Код для этого не включен, потому что он не выглядит актуальным.
Вот что происходит:
12-16 21:11:31.527 5487 5543 D InstrumentedTestBase: screenrecord: start record thread
12-16 21:11:31.528 5487 5543 D InstrumentedTestBase: screenrecord: wait a bit
12-16 21:11:31.528 5487 5573 D InstrumentedTestBase$ScreenRecordRunnable: screenrecord-record: start
12-16 21:11:31.633 5487 5573 D InstrumentedTestBase$ScreenRecordRunnable: screenrecord-record: log: Main display is 1440x2960 @60.00fps (orientation=0)
12-16 21:11:31.633 5487 5573 D InstrumentedTestBase$ScreenRecordRunnable: screenrecord-record: log: Configuring recorder for 1440x2960 video/avc at 4.00Mbps
12-16 21:11:32.362 5574 5574 W screenrecord: type=1400 audit(0.0:22906): avc: denied { read } for name="u:object_r:vendor_default_prop:s0" dev="tmpfs" ino=19753 scontext=u:r:untrusted_app:s0:c242,c256,c512,c768 tcontext=u:object_r:vendor_default_prop:s0 tclass=file permissive=0
12-16 21:11:32.492 5574 5574 W screenrecord: type=1400 audit(0.0:22907): avc: denied { read } for name="u:object_r:vendor_default_prop:s0" dev="tmpfs" ino=19753 scontext=u:r:untrusted_app:s0:c242,c256,c512,c768 tcontext=u:object_r:vendor_default_prop:s0 tclass=file permissive=0
12-16 21:11:32.543 5487 5573 D InstrumentedTestBase$ScreenRecordRunnable: screenrecord-record: log: Bugreport overlay created
12-16 21:11:32.544 5487 5573 D InstrumentedTestBase$ScreenRecordRunnable: screenrecord-record: log: Content area is 1440x2960 at offset x=0 y=0
12-16 21:11:39.780 5487 5543 D InstrumentedTestBase: screenrecord: go
12-16 21:11:43.546 5487 5543 D InstrumentedTestBase: screenrecord: wait for record thread to stop
12-16 21:11:43.546 5487 5543 D InstrumentedTestBase$ScreenRecordStopperRunnable: screenrecord-stopper: get pid
12-16 21:11:43.578 5487 5543 D InstrumentedTestBase$ScreenRecordStopperRunnable: screenrecord-stopper: getpid log: 5574
12-16 21:11:43.579 5487 5543 D InstrumentedTestBase$ScreenRecordStopperRunnable: screenrecord-stopper: kill -2 5574
12-16 21:11:43.679 5487 5573 D InstrumentedTestBase$ScreenRecordRunnable: screenrecord-record: log: Encoder stopping; recorded 1 frames in 7 seconds
12-16 21:11:43.680 5487 5573 D InstrumentedTestBase$ScreenRecordRunnable: screenrecord-record: log: Stopping encoder and muxer
12-16 21:11:43.784 5487 5573 D InstrumentedTestBase$ScreenRecordRunnable: screenrecord-record: log: Executing: /system/bin/am broadcast -a android.intent.action.MEDIA_SCANNER_SCAN_FILE -d file:///sdcard/test.mp4
12-16 21:11:43.860 5487 5573 D InstrumentedTestBase$ScreenRecordRunnable: screenrecord-record: log: Broadcasting: Intent { act=android.intent.action.MEDIA_SCANNER_SCAN_FILE dat=file:///sdcard/test.mp4 flg=0x400000 }
12-16 21:11:43.919 5487 5573 D InstrumentedTestBase$ScreenRecordRunnable: screenrecord-record: wait for (isAlive: true)
12-16 21:11:43.919 5487 5573 D InstrumentedTestBase$ScreenRecordRunnable: screenrecord-record: wait stopped; exit value: 0
12-16 21:11:44.013 5487 5543 D InstrumentedTestBase: screenrecord: rename video file to /sdcard/failed_test_emptyDeclarationState.mp4
Как вы можете видеть всевыглядит хорошо, за исключением того, что сохраняется только один кадр:
Остановка кодера;записал 1 кадр за 7 секунд
, этот кадр является --bugreport
результатом, с информацией об устройстве (производитель, модель и т.видео этого теста?