terminateApp
Stop a mobile application by specifying its package ID to close running processes and free device resources.
Instructions
Terminate an app by package name
Input Schema
TableJSON Schema
| Name | Required | Description | Default |
|---|---|---|---|
| appId | Yes | App package ID of the app |
Implementation Reference
- src/server/appTools.ts:102-107 (registration)Registration of the "terminateApp" tool using ToolRegistry.registerDeviceAware, linking the name, description, input schema, and handler function.ToolRegistry.registerDeviceAware( "terminateApp", "Terminate an app by package name", packageNameSchema, terminateAppHandler );
- src/server/appTools.ts:64-77 (handler)The registered handler function for the terminateApp tool. It creates a TerminateApp instance, executes it with the appId, and formats the response.const terminateAppHandler = async (device: BootedDevice, args: AppActionArgs) => { try { const terminateApp = new TerminateApp(device); const result = await terminateApp.execute(args.appId); // observe = true return createJSONToolResponse({ message: `Terminated app ${args.appId}`, observation: result.observation, ...result }); } catch (error) { throw new ActionableError(`Failed to terminate app: ${error}`); } };
- src/server/appTools.ts:10-12 (schema)Zod input schema for the terminateApp tool, defining the required 'appId' parameter.export const packageNameSchema = z.object({ appId: z.string().describe("App package ID of the app"), });
- Core execution logic of terminating the app: checks if installed/running/foreground, then force-stops via adb, returns detailed result.async execute( packageName: string, progress?: ProgressCallback ): Promise<TerminateAppResult> { return this.observedInteraction( async () => { // Check if app is installed const isInstalledCmd = `shell pm list packages -f ${packageName} | grep -c ${packageName}`; const isInstalledOutput = await this.adb.executeCommand(isInstalledCmd, undefined, undefined, true); const isInstalled = parseInt(isInstalledOutput.trim(), 10) > 0; if (!isInstalled) { return { success: true, packageName, wasInstalled: false, wasRunning: false, wasForeground: false }; } // Check if app is running const isRunning = true; if (!isRunning) { return { success: true, packageName, wasInstalled: true, wasRunning: false, wasForeground: false }; } // Check if app is in foreground const currentAppCmd = `shell "dumpsys window windows | grep '${packageName}'"`; const currentAppOutput = await this.adb.executeCommand(currentAppCmd); // App is in foreground if it's either the top app or an IME target const isTopApp = currentAppOutput.includes(`topApp=ActivityRecord{`) && currentAppOutput.includes(`${packageName}`); const isImeTarget = currentAppOutput.includes(`imeLayeringTarget`) && currentAppOutput.includes(`${packageName}`); const isForeground = isTopApp || isImeTarget; await this.adb.executeCommand(`shell am force-stop ${packageName}`); return { success: true, packageName, wasInstalled: true, wasRunning: true, wasForeground: isForeground, }; }, { changeExpected: false, // TODO: Can make this true if we progress } ); }
- TypeScript interface defining the output/result structure of the terminateApp operation.export interface TerminateAppResult { success: boolean; packageName: string; wasInstalled: boolean; wasRunning: boolean; wasForeground: boolean; observation?: ObserveResult; error?: string; }