3.3 KiB
name, description, metadata
| name | description | metadata | ||||||
|---|---|---|---|---|---|---|---|---|
| dict-lookup-browser-hijack-4559 | Android system-dictionary lookup landing in the OEM browser instead of Eudic/欧路 — package-visibility + PROCESS_TEXT browser hijack |
|
#4559 (PR #4568): on VIVO/iQOO (OriginOS) the system-dictionary lookup opened com.vivo.browser/.BrowserActivity instead of an installed dictionary. TWO root causes, both in the Android half of show_lookup_popover (tauri-plugin-native-bridge/.../NativeBridgePlugin.kt):
- Package-visibility filtering (primary). App is
targetSdk 36, but the native-bridge manifest had NO<queries>forACTION_PROCESS_TEXT. Under Android 11+ filtering,queryIntentActivities(PROCESS_TEXT)then returns only auto-visible apps — web browsers are auto-visible (web-intent exception), arbitrary dictionary apps (Eudic/欧路/GoldenDict) are NOT. So the query returned just the browser. Fix = add<queries><intent><action PROCESS_TEXT/><data text/plain/></intent></queries>to the plugin manifest (mirrors the native-ttsTTS_SERVICEpattern). This alone is likely the whole user-visible fix. - Browser hijack. Even when visible, an OEM browser registering
ACTION_PROCESS_TEXTcan be the system default and swallow a plainstartActivity. Fix = filter browsers out of the handler set in a puredecideLookupDispatch(handlers, browserPackages, remembered)(newLookupDispatch.kt, JUnit-tested): no-browser → implicit (unchanged, keeps native "Always"); browser+1 dict → explicitsetClassNamedirect launch; browser+≥2 →createChooser+EXTRA_EXCLUDE_COMPONENTS; browser-only →unavailable:true. Browsers detected viaqueryIntentActivities(ACTION_VIEW https + BROWSABLE)(auto-visible, no<queries>needed).
Remember-the-choice (the maintainer wanted "smooth once chosen"): ACTION_CHOOSER has NO native "Always" button (mutually exclusive with EXTRA_EXCLUDE_COMPONENTS — the resolver that has Always can't exclude and obeys the browser default). Re-implemented Always: pass an IntentSender to createChooser; system returns EXTRA_CHOSEN_COMPONENT to a manifest LookupChoiceReceiver (exported=false; explicit intra-app PendingIntent so non-exported is fine; FLAG_MUTABLE on S+) which persists pkg/class to a plain SharedPreferences (readest_lookup_dictionary_v1). Next lookup fast-paths it. Reset UI: get_lookup_dictionary/clear_lookup_dictionary commands (build.rs COMMANDS + default.toml + autogenerated TOMLs/schema/reference regenerate on cargo build -p tauri-plugin-native-bridge) → Android-only conditional reset row in CustomDictionaries.tsx, only shown when something is actually remembered (getRememberedLookupApp returns null otherwise, so no clutter).
Maintainer DECLINED a settings picker to pre-pick a specific app ("we won't call the app directly"); browser-exclusion respects that (dynamic, not a user-set hardcode). Verified: gradle JUnit (7 cases) + vitest (12). test:rust/clippy were blocked by UNRELATED stale shared-target/ cache (deleted sibling worktree readest-feat-android-rangefile-protocol path in fs plugin permission scan) — not my change; validated Rust via targeted plugin build. Related: android-open-with-intent-flow, android-nativefile-remotefile-io.