Permissions
Configure app permissions on launch or mid-flow for iOS and Android testing.
Managing system permissions is a common challenge in mobile test automation. Since OS prompts (like "Allow Camera Access") typically only appear once, your test journey can become inconsistent if the app state isn't reset.
Flows solve this by allowing you to explicitly configure permissions either at launch or during the Flow, ensuring a predictable environment every time.
Configure permissions on launch
The easiest way to manage permissions is during the launchApp command. By default, Astra Scout grants all permissions, but you can override this behavior to test specific scenarios.
To customize launch permissions, you need to specify them when calling launchApp. The following example denies all permissions but explicitly allows the camera and location:
- launchApp:
permissions:
all: deny
camera: allow
location: allowChanging permissions mid-flow
Sometimes you need to change permissions while the app is running, for example, to test how your app handles a permission denial or to prepare for a specific feature flow like scanning a QR code. Use the setPermissions command for this purpose.
- setPermissions:
permissions:
notifications: allowAvailable permissions
Astra Scout uses standardized names to make your Flows cross-platform. For example, using bluetooth on Android targets both BLUETOOTH_CONNECT and BLUETOOTH_SCAN automatically.
The following table list all permissions available in iOS and Android.
| Permission | iOS | Android |
|---|---|---|
bluetooth | ❌ | ✅ |
calendar | ✅ | ✅ |
camera | ✅ | ✅ |
contacts | ✅ | ✅ |
health | ❌ | ❌ |
homekit | ✅ | ❌ |
location | ✅ | ✅ |
medialibrary | ✅ | ✅ |
microphone | ✅ | ✅ |
motion | ✅ | ❌ |
notifications | ✅ | ✅ |
phone | ❌ | ✅ |
photos | ✅ | ❌ |
reminders | ✅ | ❌ |
siri | ✅ | ❌ |
sms | ❌ | ✅ |
speech | ✅ | ❌ |
storage | ❌ | ✅ |
usertracking | ✅ | ❌ |
TIP
To grant all available permissions, use all: allow to represent all the permissions that the app can request.
Android custom permissions
If a specific Android permission isn't listed above, you can use the full Android Permission ID. The following example adds the ADD_VOICEMAIL permission:
- setPermissions:
permissions:
com.android.voicemail.permission.ADD_VOICEMAIL: allowINFO
Note that all: allow also covers custom permissions, so you don't need to specify them individually unless you want to deny everything else.
Android special permissions
Not all permissions are prompted for in the app, like location is. Some require the user to leave the app and grant the permission within the Settings app.
android.permission.MANAGE_EXTERNAL_STORAGE permission has been required since Android 12 if an app wished to access files that weren't its own (e.g. file browsers, virus scanners).
Astra Scout can manage this like other permissions without additional user interaction, acting like an app's "second use" rather than first use. If it's declared in the app's AndroidManifest.xml then it'll be set automatically. If you want fine grained control, do as with custom permissions:
- launchApp:
clearState: true
permissions:
android.permission.MANAGE_EXTERNAL_STORAGE: denyPermission values
You can set permissions to one of the following states:
| Value | Description |
|---|---|
allow | Grants the permission. On iOS, this also automatically dismisses the system prompt. |
deny | Denies the permission. Android will request permission during the Flow execution if the app requires access to a specific feature. |
unset | Resets the permission state, causing the system to prompt permission requests when running the Flow. |
Permission values can come from a variable or a JavaScript expression instead of being hard-coded:
appId: com.example.app
env:
CAMERA_PERMISSION_STATE: deny
---
- launchApp:
permissions:
camera: ${CAMERA_PERMISSION_STATE}This lets one Flow cover both the granted and the denied journey, driven by an Astra Scout environment variable or by the env block of the calling Flow.
Push notifications on iOS
Unlike other permissions, iOS does not grant notification permissions silently. When the app requests permissions, the system prompt appears, and Astra Scout automatically taps Allow.
On Android, the permission is granted silently without a prompt.
iOS-specific values
iOS supports additional granular values for certain permissions.
| Permission | Value | Description |
|---|---|---|
location | always | Grants Always Allow location access. |
inuse | Grants While Using the App location access. | |
never | Same as deny. | |
photos | limited | Grants Limited Access to the photo library. |
Answering iOS prompts in the Flow
Some prompts are not covered by permissions: Local Network access, or App Tracking Transparency when the Flow must decline it while allowing others. Launch with all: unset so nothing answers them for you, then answer each one by its text. While a system alert is in front of the app, visible, assertVisible, extendedWaitUntil and when conditions match its title, message and button labels, and tapOn presses the button with that label. Only plain text selectors reach the alert: id, index, relative and state selectors look at the app alone.
- launchApp:
permissions: { all: unset }
- extendedWaitUntil:
visible: ".*Would Like to Send You Notifications"
timeout: 15000
- tapOn: "Don’t Allow"When two prompts can come in either order, answer them in a loop:
- repeat:
times: 3
while:
visible: ".*to find devices on local networks\\?|.*to track your activity.*"
timeout: 5000
commands:
- runFlow:
when: { visible: ".*to find devices on local networks\\?" }
commands:
- tapOn: "Allow"
- runFlow:
when: { visible: ".*to track your activity.*" }
commands:
- tapOn: "Ask App Not to Track"Button labels use the typographic apostrophe of iOS (Don’t Allow). Only tapOn presses an alert's button: a long press, a double tap or a tap on a point acts on the app alone. A launchApp whose permissions answer prompts another way than the previous launch (all: allow allows them, all: deny denies them, anything else leaves them to the Flow) starts a new automation session, so the previous Flow's way does not carry over.
Usage examples
Deny all permissions
To ensure your app handles permission denied states, start your Flow by denying everything. This forces you to handle the edge cases where a user declines a system permission prompt.
- launchApp:
permissions:
all: denyDeny all but allow specific ones
This is a common pattern for testing specific features in isolation.
- launchApp:
permissions:
all: deny
medialibrary: allowRelated resources
launchApp: See the full reference for launching apps.setPermissions: Command for altering permissions configuration mid-flow.
