handleIntentChooser
Manage system intent chooser dialogs by specifying preferences ('always', 'just_once', or 'custom') to streamline app selection during automation. Supports custom app package selection for tailored workflows.
Instructions
Automatically handle system intent chooser dialog with specified preferences
Input Schema
TableJSON Schema
| Name | Required | Description | Default |
|---|---|---|---|
| customAppPackage | No | Specific app package to select when preference is 'custom' | |
| preference | No | Preference for handling intent chooser (default: 'just_once') |
Implementation Reference
- src/utils/deepLinkManager.ts:292-361 (handler)Core handler implementation: detects intent chooser in view hierarchy, locates appropriate button or app based on preference, computes tap coordinates, and executes ADB tap command.async handleIntentChooser( viewHierarchy: ViewHierarchyResult, preference: "always" | "just_once" | "custom" = "just_once", customAppPackage?: string ): Promise<IntentChooserResult> { try { const detected = this.detectIntentChooser(viewHierarchy); if (!detected) { return { success: true, detected: false }; } logger.info(`[DeepLinkManager] Intent chooser detected, preference: ${preference}`); // Parse the view hierarchy to find buttons const rootNodes = this.elementUtils.extractRootNodes(viewHierarchy); let targetElement = null; if (preference === "always") { // Look for "Always" button for (const rootNode of rootNodes) { targetElement = this.findButtonByText(rootNode, ["Always", "ALWAYS"]); if (targetElement) {break;} } } else if (preference === "just_once") { // Look for "Just once" button for (const rootNode of rootNodes) { targetElement = this.findButtonByText(rootNode, ["Just once", "JUST ONCE", "Once"]); if (targetElement) {break;} } } else if (preference === "custom" && customAppPackage) { // Look for specific app in the list for (const rootNode of rootNodes) { targetElement = this.findAppInChooser(rootNode, customAppPackage); if (targetElement) {break;} } } if (targetElement) { // Simulate tap on the target element const center = this.elementUtils.getElementCenter(targetElement); await this.adbUtils.executeCommand(`shell input tap ${center.x} ${center.y}`); logger.info(`[DeepLinkManager] Tapped on intent chooser option at (${center.x}, ${center.y})`); return { success: true, detected: true, action: preference, appSelected: customAppPackage }; } else { return { success: false, detected: true, error: `Could not find target element for preference: ${preference}` }; } } catch (error) { logger.error(`[DeepLinkManager] Failed to handle intent chooser: ${error}`); return { success: false, detected: true, error: error instanceof Error ? error.message : String(error) }; } }
- src/server/deepLinkTools.ts:124-130 (registration)Registers the 'handleIntentChooser' tool with ToolRegistry, including name, description, schema, and handler function.ToolRegistry.registerDeviceAware( "handleIntentChooser", "Automatically handle system intent chooser dialog with specified preferences", handleIntentChooserSchema, handleIntentChooserHandler, false // Does not support progress notifications );
- src/server/deepLinkTools.ts:18-21 (schema)Zod schema defining optional input parameters: preference (enum) and customAppPackage (string).export const handleIntentChooserSchema = z.object({ preference: z.enum(["always", "just_once", "custom"]).optional().describe("Preference for handling intent chooser (default: 'just_once')"), customAppPackage: z.string().optional().describe("Specific app package to select when preference is 'custom'"), });
- src/server/deepLinkTools.ts:82-105 (handler)Top-level tool handler: instantiates HandleIntentChooser class, calls execute with args, formats JSON response, handles errors.const handleIntentChooserHandler = async (device: BootedDevice, args: HandleIntentChooserArgs) => { try { const handleIntentChooser = new HandleIntentChooser(device); const result = await handleIntentChooser.execute( args.preference || "just_once", args.customAppPackage, ); return createJSONToolResponse({ message: result.detected ? `Intent chooser handled with preference: ${args.preference || "just_once"}` : "No intent chooser detected", success: result.success, detected: result.detected, action: result.action, appSelected: result.appSelected, error: result.error, observation: result.observation }); } catch (error) { logger.error(`[handleIntentChooser] Failed to handle intent chooser: ${error}`); throw new ActionableError(`Failed to handle intent chooser: ${error}`); } };
- Helper class extending BaseVisualChange: initializes DeepLinkManager, wraps core handler in observedInteraction for view hierarchy observation.export class HandleIntentChooser extends BaseVisualChange { private deepLinkManager: DeepLinkManager; /** * Create an TerminateApp instance * @param device - Optional device * @param adb - Optional AdbUtils instance for testing * @param idb - Optional IdbPython instance for testing */ constructor(device: BootedDevice, adb: AdbUtils | null = null, axe: Axe | null = null) { super(device, adb, axe); this.device = device; this.deepLinkManager = new DeepLinkManager(device); } /** * Execute intent chooser handling * @param preference - User preference for handling ("always", "just_once", or "custom") * @param customAppPackage - Optional specific app package to select for custom preference * @returns Promise with intent chooser handling results */ async execute( preference: "always" | "just_once" | "custom" = "just_once", customAppPackage?: string ): Promise<IntentChooserResult> { return this.observedInteraction( async (observeResult: ObserveResult) => { const viewHierarchy = observeResult.viewHierarchy; if (!viewHierarchy) { return { success: false, error: "View hierarchy not found" }; } return await this.deepLinkManager.handleIntentChooser( viewHierarchy, preference, customAppPackage ); }, { changeExpected: false, timeoutMs: 500, } ); } }