@bryce3310687963/android-toolkit 0.0.0-stage → 1.0.51

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.md CHANGED
@@ -1,3 +1,101 @@
1
- # Temporary Holding Version
1
+ # Android Toolkit
2
2
 
3
- This version is a temporary placeholder for this package. An operational version to replace this has been submitted for review and is awaiting a staged release.
3
+ `@bryce3310687963/android-toolkit` is the native Android counterpart to
4
+ `@skrillex1224/playwright-toolkit`.
5
+
6
+ Actor code should import only `useAndroidToolKit()` and then use the returned modules.
7
+ The public API is intentionally small and destructive from v1 onward.
8
+
9
+ ```js
10
+ import { useAndroidToolKit } from '@bryce3310687963/android-toolkit';
11
+
12
+ const { Launch } = useAndroidToolKit();
13
+
14
+ await Launch.run(async ({ ctx, kit }) => {
15
+ const { ApifyKit, DeviceInput, Mutation, Share } = kit;
16
+ await ApifyKit.runStep('输入并发送', ctx, async () => {
17
+ await DeviceInput.click(ctx, { id: 'input_text' });
18
+ await DeviceInput.fill(ctx, { id: 'input_text' }, ctx.query);
19
+ await DeviceInput.click(ctx, { id: 'action_send' });
20
+ });
21
+ await Mutation.waitForStable(ctx, { id: 'message_list' });
22
+ const screenshotBase64 = await Share.captureScreen(ctx);
23
+ await ApifyKit.pushArtifact({ screenshotBase64 });
24
+ });
25
+ ```
26
+
27
+ ## Public Modules
28
+
29
+ | Module | Responsibility |
30
+ | --- | --- |
31
+ | `Launch` | Native actor entrypoint with fixed `/apify_storage/input.json` and `/apify_storage/output.json` paths plus lifecycle hooks. |
32
+ | `ApifyKit` | `runStep`, `runStepLoose`, `pushSuccess`, `pushFailed`, `pushArtifact`. |
33
+ | `Device` | Low-level ADB primitives only. |
34
+ | `DeviceView` | Native View-tree snapshot and selector lookup over `uiautomator dump`. |
35
+ | `DeviceInput` | View-tree-backed click/fill/press/scroll APIs using ADB input. |
36
+ | `Mutation` | Playwright-like stable wait semantics over matched ViewNode subtrees. |
37
+ | `Share` | Sprite screenshot and clipboard share-link polling. |
38
+ | `DeviceSQLite` | Root ADB-backed private SQLite snapshot queries. |
39
+ | `Constants` | Native-useful actor metadata and codes. |
40
+ | `Errors` | `CrawlerError` and error serialization. |
41
+
42
+ ## Runtime Contract
43
+
44
+ The toolkit does not install or discover runtime tools.
45
+
46
+ Required environment:
47
+
48
+ - `ANDROID_TOOLKIT_ADB_PATH`
49
+
50
+ Device initialization, Appium Settings, UnicodeIME, and root ADB access belong
51
+ to manager/cluster runtime. Runtime checks fail clearly when prerequisites are missing.
52
+
53
+ ## Boundaries
54
+
55
+ Included:
56
+
57
+ - ADB command execution, app launch, key input, screenshot, activity checks.
58
+ - View-tree parsing with a real XML parser.
59
+ - View selector operations: `id`, `text`, `textContains`, `contentDesc`, `className`.
60
+ - Root ADB-backed SQLite queries through `DeviceSQLite.query()` only.
61
+
62
+ Excluded:
63
+
64
+ - Public generic process injection or app hook execution.
65
+ - App hook clipboard helpers.
66
+ - WebView event recorder.
67
+ - App hook UI traversal/click helpers.
68
+ - Package name and activity truth. Backend/runtime input owns those values.
69
+ - Actor-specific DB schemas, message parsing, product parsing, and success criteria.
70
+
71
+ ## Android Actor Rules
72
+
73
+ - Do not use hardcoded absolute coordinates, screen-ratio coordinates, or naked point taps in actor code.
74
+ - Do not add fallback clicks. If the expected selector, DOM element, activity, or key-driven flow is unavailable, fail with a typed error and useful context.
75
+ - UI actions must be driven by one of: native `DeviceView` selectors, WebView DOM actions, Android activity/intents, or deterministic key events with activity/state verification.
76
+ - If an app renders custom UI that is invisible to `uiautomator`, use a stable app/runtime capability instead of guessing screen positions.
77
+ - Bounds-based taps are allowed only when the bounds come from a located native view; WebView clicks must stay in `WebView.click`/`WebView.evaluate`.
78
+
79
+ ## Browser Entry
80
+
81
+ `@bryce3310687963/android-toolkit/browser` exports only `Constants` and `Errors`.
82
+
83
+ ## Clear App Cache
84
+
85
+ `Device.clearAppCache(ctx, packageName = ctx.packageName)` requires root ADB access.
86
+ Stop the app before clearing its cache, then launch it again:
87
+
88
+ ```js
89
+ await Device.forceStopApp(ctx);
90
+ await Device.clearAppCache(ctx);
91
+ await Device.startLauncher(ctx);
92
+ ```
93
+
94
+ This clears the contents of `/data/data/<package>/cache`,
95
+ `/data/data/<package>/code_cache`, and `/sdcard/Android/data/<package>/cache`.
96
+ It preserves the cache directories themselves and toolkit runtime directories
97
+ `apify-webview-bridge` and `network-capture`. Databases, preferences, files,
98
+ WebView cookies, and login data are outside the cleanup scope. Missing cache
99
+ directories are skipped; invalid package names and cleanup errors fail the call.
100
+ Each actor chooses whether to call this method; `Launch.run` does not clear caches
101
+ automatically.
package/browser.d.ts ADDED
@@ -0,0 +1,158 @@
1
+ export interface WebViewHookConfig {
2
+ name: string | string[];
3
+ value: string[];
4
+ }
5
+
6
+ export namespace Constants {
7
+ export const Code: Record<string, number>;
8
+ export const Status: Record<string, string>;
9
+ export const StoragePath: {
10
+ Input: '/apify_storage/input.json';
11
+ Output: '/apify_storage/output.json';
12
+ };
13
+ export const ActorKey: {
14
+ DoubaoAndroid: 'doubao.android';
15
+ ErineAndroid: 'erine.android';
16
+ WechatAndroid: 'wechat.android';
17
+ QwenAndroid: 'qwen.android';
18
+ YuanbaoAndroid: 'yuanbao.android';
19
+ XhsAndroid: 'xhs.android';
20
+ };
21
+ export const WebViewBridge: {
22
+ packageName: string;
23
+ actionCommand: string;
24
+ cacheDir: string;
25
+ hookConfigFile: string;
26
+ commandDir: string;
27
+ resultDir: string;
28
+ };
29
+ export const ActorInfo: Record<string, {
30
+ key: string;
31
+ name: string;
32
+ icon: string;
33
+ webviews: WebViewHookConfig[];
34
+ share: {
35
+ mode: 'clipboard';
36
+ prefix: string;
37
+ xurl: unknown[];
38
+ };
39
+ }>;
40
+ }
41
+
42
+ export namespace Errors {
43
+ export class CrawlerError extends Error {
44
+ code: number;
45
+ context: Record<string, unknown>;
46
+ constructor(input?: string | {
47
+ message?: string;
48
+ code?: number;
49
+ context?: Record<string, unknown>;
50
+ });
51
+ static isCrawlerError(error: unknown): boolean;
52
+ static from(error: unknown, fallback?: {
53
+ code?: number;
54
+ context?: Record<string, unknown>;
55
+ }): CrawlerError;
56
+ }
57
+ }
58
+
59
+ export interface LoggerAdapter {
60
+ info(message: string): void;
61
+ warning?(message: string): void;
62
+ warn?(message: string): void;
63
+ error?(message: string): void;
64
+ debug?(message: string): void;
65
+ }
66
+
67
+ export interface LoggerTemplate {
68
+ step(step: string, status?: string, details?: unknown, level?: 'info' | 'warn' | 'warning' | 'error' | 'success' | 'start' | 'debug'): void;
69
+ taskStart(detail?: unknown): void;
70
+ taskSuccess(detail?: unknown): void;
71
+ taskFail(detail?: unknown, error?: unknown): void;
72
+ launchStart(detail?: unknown): void;
73
+ launchSuccess(detail?: unknown): void;
74
+ launchFail(detail?: unknown, error?: unknown): void;
75
+ inputMethodSnapshotFail(error?: unknown): void;
76
+ inputMethodRestoreFail(error?: unknown): void;
77
+ stepStart(step?: string, detail?: unknown): void;
78
+ stepSuccess(step?: string, detail?: unknown): void;
79
+ stepFail(step?: string, error?: unknown): void;
80
+ stepRetry(step?: string, attempt?: unknown): void;
81
+ adbExec(detail?: unknown): void;
82
+ adbRetry(detail?: unknown): void;
83
+ mutationWaitStart(detail?: unknown): void;
84
+ mutationWaitSuccess(detail?: unknown): void;
85
+ mutationWaitWarn(detail?: unknown): void;
86
+ webViewCommand(detail?: unknown): void;
87
+ webViewSuccess(detail?: unknown): void;
88
+ webViewWarn(detail?: unknown): void;
89
+ webViewFail(error?: unknown): void;
90
+ screenshotStart(detail?: unknown): void;
91
+ screenshotDone(detail?: unknown): void;
92
+ shareStart(detail?: unknown): void;
93
+ shareSuccess(detail?: unknown): void;
94
+ shareFail(error?: unknown): void;
95
+ dataPush(detail?: unknown): void;
96
+ dataPushFail(error?: unknown): void;
97
+ info(message: string, detail?: unknown): void;
98
+ success(message: string, detail?: unknown): void;
99
+ warning(message: string, detail?: unknown): void;
100
+ warn(message: string, detail?: unknown): void;
101
+ error(message: string, detail?: unknown): void;
102
+ debug(message: string, detail?: unknown): void;
103
+ start(message: string, detail?: unknown): void;
104
+ }
105
+
106
+ export interface LoggerModule {
107
+ setLogger(logger: LoggerAdapter | null): void;
108
+ createLogger(scope?: string): ScopedLoggerModule;
109
+ useTemplate(logger?: LoggerAdapter | null): LoggerTemplate;
110
+ start(message: string, detail?: unknown): void;
111
+ success(message: string, detail?: unknown): void;
112
+ fail(message: string, error?: unknown): void;
113
+ warn(message: string, detail?: unknown): void;
114
+ warning(message: string, detail?: unknown): void;
115
+ error(message: string, detail?: unknown): void;
116
+ info(message: string, detail?: unknown): void;
117
+ debug(message: string, detail?: unknown): void;
118
+ duration(startedAt: number): string;
119
+ }
120
+
121
+ export interface ScopedLoggerModule {
122
+ start(message: string, detail?: unknown): void;
123
+ success(message: string, detail?: unknown): void;
124
+ fail(message: string, error?: unknown): void;
125
+ warn(message: string, detail?: unknown): void;
126
+ warning(message: string, detail?: unknown): void;
127
+ error(message: string, detail?: unknown): void;
128
+ info(message: string, detail?: unknown): void;
129
+ debug(message: string, detail?: unknown): void;
130
+ useTemplate(): LoggerTemplate;
131
+ }
132
+
133
+ export interface LogTemplate {
134
+ key: string;
135
+ label: string;
136
+ group: string;
137
+ attention: 'low' | 'medium' | 'high' | 'critical';
138
+ patterns: RegExp[];
139
+ defaultSelected?: boolean;
140
+ }
141
+
142
+ export interface BrowserAndroidToolkit {
143
+ Constants: typeof Constants;
144
+ Errors: typeof Errors;
145
+ Logger: LoggerModule;
146
+ LOG_TEMPLATES: LogTemplate[];
147
+ $Internals: {
148
+ LOG_TEMPLATES: LogTemplate[];
149
+ stripAnsi(input: unknown): string;
150
+ };
151
+ }
152
+
153
+ export function useAndroidToolKit(): BrowserAndroidToolkit;
154
+ export namespace useAndroidToolKit {
155
+ const Mode: {
156
+ default: 'default';
157
+ };
158
+ }