Automate taking screenshots of Android app with Jetpack Compose By TMarcelin Tutorials - March 25, 2022 Comments: 0 Views: 729 In the article I'll show how to automate taking screenshots of the Android application written in Jetpack Compose. 1. Create test Start with setting up instrumented test. This test will not check anything, it will only perform actions such clicking button and take screenshots of the application. First, set up testing in app/build.gradle: android { // other properties defaultConfig { // other properties testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner" // Add this line } } // ... dependencies { // other dependencies androidTestImplementation "androidx.compose.ui:ui-test-junit4:$compose_version" // Add this line } Now, let's suppose this is the Activity we want to take screenshots of: package com.example import android.os.Bundle import androidx.activity.ComponentActivity import androidx.activity.compose.setContent import androidx.compose.foundation.layout.Arrangement import androidx.compose.foundation.layout.Column import androidx.compose.foundation.layout.padding import androidx.compose.material.Button import androidx.compose.material.Scaffold import androidx.compose.material.Text import androidx.compose.runtime.getValue import androidx.compose.runtime.mutableStateOf import androidx.compose.runtime.remember import androidx.compose.runtime.setValue import androidx.compose.ui.Modifier import androidx.compose.ui.unit.dp class MainActivity : ComponentActivity() { override fun onCreate(savedInstanceState: Bundle?) { super.onCreate(savedInstanceState) setContent { Scaffold { Column( verticalArrangement = Arrangement.spacedBy(16.dp), modifier = Modifier.padding(16.dp), ) { var greetingVisible by remember { mutableStateOf(false) } if (greetingVisible) { Text("Hello!") } Button(onclick = { greetingVisible = true }) { Text("Show greeting") } } } } } } Create the test in androidTest directory: package com.example import androidx.compose.ui.test.junit4.createAndroidComposeRule import androidx.compose.ui.test.onNodeWithText import androidx.compose.ui.test.performClick import androidx.test.ext.junit.runners.AndroidJUnit4 import org.junit.Rule import org.junit.Test import org.junit.runner.RunWith @RunWith(AndroidJUnit4::class) class ScreenshotTest { @get:Rule val rule = createAndroidComposeRule<MainActivity>() @Test fun makeScreenshot() { // TODO: Take screenshot before clicking button rule .onNodeWithText("Show greeting") .performClick() // TODO: Take screenshot after clicking button } } 2. Take the screenshot In order to take screenshot and save it as an image, use the following functions: private fun ComposeContentTestRule.takeScreenshot(file: String) { onRoot() .captureToImage() .asAndroidBitmap() .save(file) } private fun Bitmap.save(file: String) { val path = InstrumentationRegistry.getInstrumentation().targetContext.filesDir.canonicalPath FileOutputStream("$path/$file").use { out -> compress(Bitmap.CompressFormat.PNG, 100, out) } } Here is the full test which takes screenshots of the app: package com.example import android.graphics.Bitmap import androidx.compose.ui.graphics.asAndroidBitmap import androidx.compose.ui.test.captureToImage import androidx.compose.ui.test.junit4.ComposeContentTestRule import androidx.compose.ui.test.junit4.createAndroidComposeRule import androidx.compose.ui.test.onNodeWithText import androidx.compose.ui.test.onRoot import androidx.compose.ui.test.performClick import androidx.test.ext.junit.runners.AndroidJUnit4 import androidx.test.platform.app.InstrumentationRegistry import org.junit.Rule import org.junit.Test import org.junit.runner.RunWith import java.io.FileOutputStream @RunWith(AndroidJUnit4::class) class ScreenshotTest { @get:Rule val rule = createAndroidComposeRule<MainActivity>() @Test fun makeScreenshot() { rule.takeScreenshot("before-click.png") rule .onNodeWithText("Show greeting") .performClick() rule.takeScreenshot("after-click.png") } } private fun ComposeContentTestRule.takeScreenshot(file: String) { onRoot() .captureToImage() .asAndroidBitmap() .save(file) } private fun Bitmap.save(file: String) { val path = InstrumentationRegistry.getInstrumentation().targetContext.filesDir.canonicalPath FileOutputStream("$path/$file").use { out -> compress(Bitmap.CompressFormat.PNG, 100, out) } } 3. Save screenshots on the host PC All screenshots taken by the code are stored in the emulator or phone. To fetch them manually you can use Device File Explorer, which is build in Android Studio. Screenshots can be found in the following directory:/data/data/$applicationId/files/ This process can be automated by ADB command: adb root adb pull /data/data/com.example/files/ screenshots Extra information Turn off animations In some cases turning off animations is needed to run tests. To do it, use these commands: adb shell settings put global window_animation_scale 0 adb shell settings put global animator_duration_scale 0 adb shell settings put global transition_animation_scale 0 Some users have reported that their devices need to be reboot to apply these settings. If that's your case, you can use the following command: adb shell "su 0 am start -a android.intent.action.REBOOT" Turn off keyboard Soft keyboard can affect screenshots by cropping them. To disable it use the following commands: # Show all keyboards (-a for all, -s for short summary). adb shell ime list -s -a # Disable keyboards: adb shell ime disable <<keyboard id>> # Example: adb shell ime disable com.android.inputmethod.latin
The evolution of the Android security system or how the system is protected today How it all started The road to protecting Android has been thorny. At the end of 2021, Android March 16, 2022 Blog
Jetpack Compose - how to easily build a UI on Android In July of last year, along with Android Studio Arctic Fox, one of the long-awaited libraries, March 4, 2022 Tutorials
Online radio for Android: step by step guide In this tutorial, I'll walk you through building your own Android radio app. I'll start right away February 22, 2022 Tutorials