Какой API хранилища для автоматического сохранения и извлечения снимков экрана?

Я автоматизирую создание снимков экрана с помощью инструментальных тестов (androidTest) в отладочной версии моего приложения с помощью UiAutomator и сценария оболочки, использующего adb pull.

После того, как каждый снимок экрана будет сделан, мне нужно предоставить доступ к каталогу на устройстве Android для записи каждого изображения, а именно:

  • может быть записан без ввода данных пользователем (например, запрос разрешений, сборщик файлов)
  • к ADB можно получить доступ без каких-либо специальных уловок - они могут сломаться в будущем (например, запуск от имени).
  • не требует действий по настройке на каждом устройстве, которые могут сломаться, если кто-то в будущем добавит новые устройства (например, рутирование устройства, установка специальных сертификатов).
  • не требует каких-либо сторонних инструментов (например, лучшая синхронизация с adb)
  • должен работать только на устройствах Android с API 26 и более поздних версий (8.0+).
  • желательно не требует каких-либо разрешений манифеста (но это не является препятствием).

Документы Android для выбора API хранилища ориентированы на обычное использование пользователем рабочего приложения и не указывают, может ли adb получить к ним доступ.

Существует так много устаревших советов (благодаря множеству критических изменений в API-интерфейсах хранилища Android за последние 10 лет), что соотношение сигнал/шум для существующих советов очень низкое, и проверка того, работает ли каждое найденное решение, является задачей нетривиальный.

Какой API хранилища я должен/могу использовать, чтобы он удовлетворял вышеуказанным требованиям?

0
0
53
3
Перейти к ответу Данный вопрос помечен как решенный

Ответы 3

В конце концов, единственным современным 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/

Другие вопросы по теме