detectIntentChooser
Identify intent chooser dialogs in mobile app views to automate user interaction testing and validation processes.
Instructions
Detect system intent chooser dialog in the current view hierarchy
Input Schema
| Name | Required | Description | Default |
|---|---|---|---|
No arguments | |||
Implementation Reference
- src/server/deepLinkTools.ts:116-122 (registration)Registers the MCP tool 'detectIntentChooser' with ToolRegistry, providing name, description, schema, and handler function.
ToolRegistry.registerDeviceAware( "detectIntentChooser", "Detect system intent chooser dialog in the current view hierarchy", detectIntentChooserSchema, detectIntentChooserHandler, false // Does not support progress notifications ); - src/server/deepLinkTools.ts:63-79 (handler)The main handler function for the 'detectIntentChooser' tool. Instantiates DetectIntentChooser class, calls execute(), and formats the response.
const detectIntentChooserHandler = async (device: BootedDevice, args: DetectIntentChooserArgs) => { try { const detectIntentChooser = new DetectIntentChooser(device); const result = await detectIntentChooser.execute(); return createJSONToolResponse({ message: `Intent chooser detection completed. Detected: ${result.detected}`, success: result.success, detected: result.detected, error: result.error, observation: result.observation }); } catch (error) { logger.error(`[detectIntentChooser] Failed to detect intent chooser: ${error}`); throw new ActionableError(`Failed to detect intent chooser: ${error}`); } }; - src/server/deepLinkTools.ts:15-16 (schema)Zod schema definition for the tool arguments (no parameters required).
export const detectIntentChooserSchema = z.object({ }); - DetectIntentChooser class that performs screen observation and delegates detection to DeepLinkManager.
export class DetectIntentChooser extends BaseVisualChange { private deepLinkManager: DeepLinkManager; constructor(device: BootedDevice, adb: AdbUtils | null = null) { super(device, adb); this.deepLinkManager = new DeepLinkManager(device); } /** * Execute intent chooser detection * @returns Promise with intent chooser detection results */ async execute(): Promise<IntentChooserResult> { return this.observedInteraction( async (observeResult: ObserveResult) => { try { const viewHierarchy = observeResult.viewHierarchy; if (!viewHierarchy) { return { success: false, error: "View hierarchy not found" }; } logger.info("[DetectIntentChooser] Starting intent chooser detection"); const detected = this.deepLinkManager.detectIntentChooser(viewHierarchy); logger.info(`[DetectIntentChooser] Intent chooser detection completed. Detected: ${detected}`); return { success: true, detected }; } catch (error) { logger.error(`[DetectIntentChooser] Failed to detect intent chooser: ${error}`); return { success: false, detected: false, error: error instanceof Error ? error.message : String(error) }; } }, { changeExpected: false } ); } } - src/utils/deepLinkManager.ts:204-282 (helper)Core detection logic that traverses the view hierarchy and checks for text, class, and resource ID indicators of the intent chooser dialog.
detectIntentChooser(viewHierarchy: ViewHierarchyResult): boolean { try { // If the hierarchy is empty, return false if (!viewHierarchy || !viewHierarchy.hierarchy || !viewHierarchy.hierarchy.node) { return false; } // Look for common intent chooser indicators const textIndicators = [ "Choose an app", "Open with", "Complete action using", "Always", "Just once" ]; const classIndicators = [ "com.android.internal.app.ChooserActivity", "com.android.internal.app.ResolverActivity" ]; const resourceIdIndicators = [ "android:id/button_always", "android:id/button_once", "resolver_list", "chooser_list" ]; // Get root nodes from the view hierarchy const rootNodes = this.elementUtils.extractRootNodes(viewHierarchy); // Check all nodes in the hierarchy for (const rootNode of rootNodes) { let foundIndicator = false; this.elementUtils.traverseNode(rootNode, (node: any) => { if (foundIndicator) {return;} const nodeProperties = this.elementUtils.extractNodeProperties(node); const nodeClass = nodeProperties.class || ""; const nodeText = nodeProperties.text || nodeProperties["content-desc"] || ""; const nodeResourceId = nodeProperties["resource-id"] || ""; // Check for class indicators for (const className of classIndicators) { if (nodeClass.includes(className)) { foundIndicator = true; return; } } // Check for text indicators (exact match) for (const text of textIndicators) { if (nodeText === text) { foundIndicator = true; return; } } // Check for resource ID indicators for (const resourceId of resourceIdIndicators) { if (nodeResourceId.includes(resourceId)) { foundIndicator = true; return; } } }); if (foundIndicator) { return true; } } return false; } catch (error) { logger.warn(`[DeepLinkManager] Error detecting intent chooser: ${error}`); return false; } }