Я автоматизирую создание снимков экрана с помощью инструментальных тестов (androidTest) в отладочной версии моего приложения с помощью UiAutomator и сценария оболочки, использующего adb pull.
После того, как каждый снимок экрана будет сделан, мне нужно предоставить доступ к каталогу на устройстве Android для записи каждого изображения, а именно:
Документы Android для выбора API хранилища ориентированы на обычное использование пользователем рабочего приложения и не указывают, может ли adb получить к ним доступ.
Существует так много устаревших советов (благодаря множеству критических изменений в API-интерфейсах хранилища Android за последние 10 лет), что соотношение сигнал/шум для существующих советов очень низкое, и проверка того, работает ли каждое найденное решение, является задачей нетривиальный.
Какой API хранилища я должен/могу использовать, чтобы он удовлетворял вышеуказанным требованиям?
В конце концов, единственным современным API, который можно было прочитать извне, был MediaStore.
Используя код , адаптированный из документации Android :
private fun saveWithMediaStore(context: Context, bm: Bitmap, fileName: String) {
// Add a media item that other apps don't see until the item is
// fully written to the media store.
val resolver = context.contentResolver
// Find all audio files on the primary external storage device.
val imageCollection = if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.Q) {
MediaStore.Images.Media.getContentUri(
MediaStore.VOLUME_EXTERNAL_PRIMARY
)
} else {
MediaStore.Images.Media.EXTERNAL_CONTENT_URI
}
val imageDetails = ContentValues().apply {
put(MediaStore.Images.Media.DISPLAY_NAME, fileName)
put(MediaStore.Images.Media.IS_PENDING, 1)
}
val songContentUri = resolver.insert(imageCollection, imageDetails)
// "w" for write.
resolver.openFileDescriptor(songContentUri!!, "w", null).use { pfd: ParcelFileDescriptor? ->
// Write data into the pending image file.
if (pfd !=null) {
try {
val fOut = FileOutputStream(pfd.fileDescriptor)
bm.compress(Bitmap.CompressFormat.PNG, 85, fOut)
fOut.flush()
fOut.close()
} catch (e: Exception) {
e.printStackTrace()
}
}
}
// Now we're finished, release the "pending" status and let other apps view the image.
imageDetails.clear()
imageDetails.put(MediaStore.Images.Media.IS_PENDING, 0)
resolver.update(songContentUri, imageDetails, null, null)
}
На моем эмулируемом устройстве скриншот был записан на
/storage/emulated/0/Pictures/<filename_you_specify>
так что ты можешь просто сделать
adb pull /storage/emulated/0/Pictures/<filename_you_specify>
чтобы получить файл с устройства.
Вы можете посмотреть пример того, как снимки экрана делаются во временном файле, по адресу https://github.com/dtmilano/CulebraTester2-public/blob/master/app/src/main/java/com/dtmilano/android/culebratester2. /location/UiDevice.kt#L242.
Опубликовав свой первоначальный ответ, я нашел новую библиотеку AndroidX под названием TestStorage , которая, похоже, специально создана Google для этого сценария ( исходный код).
Обратите внимание, что он доступен только во время запуска androidTest (не в производственных или локальных модульных тестах).
Использование:
private fun saveScreenshot(bm: Bitmap, fileName: String) {
val testStorage: PlatformTestStorage = PlatformTestStorageRegistry.getInstance()
try {
val fOut = testStorage.openOutputFile(fileName)
bm.compress(Bitmap.CompressFormat.PNG, 85, fOut)
fOut.flush()
fOut.close()
} catch (e: Exception) {
e.printStackTrace()
}
}
Файл(ы), созданные таким образом во время тестового запуска, автоматически копируются обратно с устройства Android на ваш компьютер разработки и сохраняются в
<project root>/<module, eg app>/build/outputs/connected_android_test_additional_output/