device is a runtime proxy over the Android emulator API. Use it for emulator-level operations — such as setting location, placing images in the virtual camera scene, configuring network proxies, passing audio to the microphone, or running raw adb commands — that sit outside app UI interactions. Use driver for interacting with the app itself.
device is only available while a flow is running.
import { device, flow } from "@qawolf/flows/android";
setGeoLocation
Sets the emulator’s GPS location.
function setGeoLocation(options: GeoLocationOptions): Promise<string>;
type GeoLocationOptions = {
latitude: number;
longitude: number;
altitude?: number;
satellites?: number;
velocity?: number;
};
Example:
import { device, flow } from "@qawolf/flows/android";
export default flow("Set device location", "Android - Pixel", async () => {
await device.setGeoLocation({
latitude: 37.7749,
longitude: -122.4194,
});
});
Use this to test location-aware features without physically moving a device. See Mock device location for a full walkthrough.
setVirtualSceneImage
Places an image into the Android emulator’s virtual camera scene. Use this to test features that require the camera to see a specific image — such as barcode or QR code scanning.
function setVirtualSceneImage(options: VirtualSceneImageOptions): Promise<string>;
type VirtualSceneImageOptions = {
/** Path to the image file to place in the virtual scene. Defaults to the default virtual scene image when omitted. */
image?: string;
/** Where to place the image in the virtual scene. */
location: "table" | "wall";
};
Example:
import { device, flow } from "@qawolf/flows/android";
export default flow(
"Scan barcode",
{ target: "Android - Pixel", launch: true },
async ({ driver, test }) => {
await test("place barcode image", async () => {
await device.setVirtualSceneImage({
image: "/path/to/barcode.jpg",
location: "table",
});
});
},
);
Virtual scene is scoped to barcode/QR code scanning and augmented reality (AR) use cases. It is not a general photo or video injection mechanism. See Android barcode and QR scanning for a full walkthrough.
playAutomation
Triggers an automation macro on the Android emulator. Use this in combination with setVirtualSceneImage to animate the virtual camera toward a placed image.
function playAutomation(options: PlayAutomationOptions): Promise<string>;
type PlayAutomationOptions =
| {
/** Name of a built-in emulator macro. */
macro: "Reset_position" | "Track_horizontal_plane" | "Track_vertical_plane" | "Walk_to_image_room";
/** Optional path to override the macro file. */
overrideMacroPath?: string;
}
| {
/** Path to a custom macro file. */
file: string;
};
Example:
import { device, flow } from "@qawolf/flows/android";
export default flow(
"Scan barcode",
{ target: "Android - Pixel", launch: true },
async ({ driver, test }) => {
await test("place barcode and animate camera", async () => {
await device.setVirtualSceneImage({
image: "/path/to/barcode.jpg",
location: "table",
});
await device.playAutomation({
macro: "Walk_to_image_room",
});
});
},
);
Available built-in macros are determined by the Android emulator. Walk_to_image_room is the macro used to animate the virtual camera toward a placed image. See Android Emulator camera support for more detail on virtual scene automation.
setProxy
Configures a proxy for the Android emulator’s network traffic.
function setProxy(options: ProxyOptions): Promise<string>;
type ProxyOptions = {
/** Proxy URL. Include credentials in the URL if authentication is required (e.g. `http://username:password@proxy.example.com:8080`). */
url: string;
};
Example:
import { device, flow } from "@qawolf/flows/android";
export default flow("Set proxy", "Android - Pixel", async () => {
await device.setProxy({
url: "http://proxy.example.com:8080",
});
});
clearProxy
Removes any proxy configuration from the Android emulator.
function clearProxy(): Promise<string>;
Example:
import { device, flow } from "@qawolf/flows/android";
export default flow("Clear proxy", "Android - Pixel", async () => {
await device.clearProxy();
});
Call clearProxy() at the end of any flow that sets a proxy to avoid affecting subsequent flows.
Plays an audio file on the runner host so the emulator receives it as microphone input. Use this to test recording, voice, or speech-recognition features with known audio.
function passAudioAsMicrophoneInput(options: PassAudioAsMicrophoneInputOptions): Promise<string>;
type PassAudioAsMicrophoneInputOptions = {
/** File path on the runner host, or URL, for the audio to play. */
data: string;
/** Delay in seconds before playback starts. */
delaySeconds?: number;
/** Maximum playback duration in seconds. Omit to play the whole file. */
durationSeconds?: number;
};
Example:
import { device, flow } from "@qawolf/flows/android";
export default flow(
"Inject microphone audio",
{ target: "Android - Pixel", launch: true },
async ({ driver, test }) => {
await test("play audio into the microphone", async () => {
await device.passAudioAsMicrophoneInput({
data: `${process.env.TEAM_STORAGE_DIR}/audio.mp3`,
durationSeconds: 10,
});
});
},
);
Playback is bounded by the command timeout (1 minute by default). For audio longer than a minute, pass durationSeconds. See Microphone injection for a full walkthrough.
adb
Runs an adb command against the emulator and returns its combined stdout/stderr. Use this as an escape hatch for emulator or device operations not covered by a dedicated device method — such as dumpsys, emu sensor set, or pull.
Pass the arguments either as a single string (split on whitespace; quote a single value that contains spaces) or as an array (preferred when building arguments programmatically). The command does not go through a host shell, so it does not expand variables or run pipes.
function adb(command: string | string[]): Promise<string>;
Example:
import { device, flow } from "@qawolf/flows/android";
export default flow(
"Run adb commands",
{ target: "Android - Pixel", launch: true },
async ({ driver, test }) => {
await test("send a keyevent and pull a file", async () => {
await device.adb("shell input keyevent 26");
// quote a value that contains spaces, or pass an array to avoid quoting
await device.adb([
"pull",
"/sdcard/Recordings/My recording 1.m4a",
`${process.env.TEAM_STORAGE_DIR}/recorded.m4a`,
]);
});
},
);
Real-world example — jump the device clock to test time-gated features (disable auto time, move the clock, then restore):
import { device, flow } from "@qawolf/flows/android";
export default flow(
"Verify a time-gated feature can't be gamed",
{ target: "Android - Pixel", launch: true },
async ({ driver, test }) => {
await test("jump the device clock forward", async () => {
// Disable automatic time so the manual clock sticks
await device.adb("shell settings put global auto_time 0");
// Move the device clock forward 2 days
const targetMillis = Date.now() + 2 * 24 * 60 * 60 * 1000;
await device.adb(`shell cmd alarm set-time ${targetMillis}`);
// ... assert the time-gated feature (rewards/streaks) behaves correctly ...
// Restore automatic time
await device.adb("shell settings put global auto_time 1");
});
},
);