Skip to content

feat(android): cross-activity show, lifecycle, and webview retention#121

Open
jboileau99 wants to merge 20 commits into
mainfrom
justin/feat/cross-activity-lifecycle
Open

feat(android): cross-activity show, lifecycle, and webview retention#121
jboileau99 wants to merge 20 commits into
mainfrom
justin/feat/cross-activity-lifecycle

Conversation

@jboileau99

@jboileau99 jboileau99 commented Jun 17, 2026

Copy link
Copy Markdown
Contributor

Description of this change

Track foreground Activity for show-from-any-activity, auto-dismiss on real navigation, and retain the WebView on hideExperience for faster re-shows and post-hide JS events.

  • KetchLifecycleTracker.kt / KetchSdk.kt: foreground Activity tracking; SDK create without FragmentManager.
  • Ketch.kt: lazy host resolution, auto-dismiss, loadedSignature warm/cold paths, retain-on-hide vs kill on other teardown, preference-tab JSON for imperative show.
  • KetchWebView.kt / KetchDialogFragment.kt / Index.kt: detach/kill ownership, showConsentExperience/showPreferenceExperience, remove tap-outside bridge.
  • integration-tests/: cross-activity, auto-dismiss, benign lifecycle, WebView retention, preference-tab DOM tests; reflection probes in IntegrationTestApp.kt.
  • sample-app-* / Makefile / scripts/run-sample.sh: cross-activity demo, shared-preferences debug, local run targets.

Why is this change being made?

  • Chore (non-functional changes)
  • Bug fix (non-breaking change that fixes an issue)
  • New feature (non-breaking change that adds functionality)
  • Breaking change (fix or feature that would cause existing functionality to not work as expected)

How was this tested? How can the reviewer verify your testing?

  • ./gradlew ktlintCheck — pass
  • ./gradlew :integration-tests:connectedDebugAndroidTest — pass on Pixel 9a (API 16) emulator, including ZCrossActivityShowTest, ZWebViewRetentionTest, and ZPreferenceTabArgsTest

Related issues

N/A

Checklist

  • I have added tests to cover my changes.
  • All new and existing tests passed.
  • I have evaluated the security impact of this change, and OWASP Secure Coding Practices have been observed.
  • I have informed stakeholders of my changes.

Note

High Risk
Large behavioral changes to Activity/WebView/dialog lifecycle and public init patterns affect every integrator; mistaken auto-dismiss or WebView retention could strand UI or leak context, though new instrumented coverage targets the main paths.

Overview
The SDK no longer requires a FragmentManager at create time: KetchLifecycleTracker tracks the foreground FragmentActivity, and KetchSdk.create(context, …) is the primary factory (the FragmentManager overload is deprecated). Experiences can be shown from any activity; navigating to another activity while a dialog is open auto-dismisses with onDismiss(HideExperienceStatus.ActivityChanged), while rotation and backgrounding keep the experience alive.

WebView lifecycle is reworked around a loadedSignature cache: matching config reuses a warm WebView via imperative ketch('showConsent') / showPreferences JS instead of reloading. hideExperience retains the WebView for fast re-show and trailing bridge events; other dismiss paths (dismissDialog, renderer gone, config invalidation) tear it down. Tap-outside dismissal and the tapOutside JS bridge are removed.

Supporting changes include setWebResourceUrlOverrides (HTML + WebResourceOverrideHandler), IntegrationTestApp-based harness with Z* instrumented tests (cross-activity, auto-dismiss, benign lifecycle, retention, preference tabs), sample apps on Application-scoped Ketch, Makefile / run-sample tooling, Cursor rules/skills, and README integration docs.

Reviewed by Cursor Bugbot for commit 8c8d6ec. Configure here.

jboileau99 and others added 4 commits June 17, 2026 11:21
Co-authored-by: Cursor <cursoragent@cursor.com>
Co-authored-by: Cursor <cursoragent@cursor.com>
Co-authored-by: Cursor <cursoragent@cursor.com>
Co-authored-by: Cursor <cursoragent@cursor.com>
jboileau99 and others added 5 commits June 18, 2026 15:19
Add run-sample.sh with UID-based logcat, Makefile targets for sample apps
and integration tests, trim READMEs to make-only commands, remove legacy
run-integration-tests.sh, and add shared preferences logging to the
standard sample app (merged with cross-activity SecondActivity flow).

Co-authored-by: Cursor <cursoragent@cursor.com>
Co-authored-by: Cursor <cursoragent@cursor.com>
Co-authored-by: Cursor <cursoragent@cursor.com>
Co-authored-by: Cursor <cursoragent@cursor.com>
Co-authored-by: Cursor <cursoragent@cursor.com>
@jboileau99 jboileau99 changed the title feat(android): cross-activity show and lifecycle auto-dismiss feat(android): cross-activity show, lifecycle, and webview retention Jun 19, 2026
@ethanpschoen
ethanpschoen force-pushed the justin/feat/cross-activity-lifecycle branch from 8c8d6ec to e9a46ec Compare July 7, 2026 17:25
@ethanpschoen
ethanpschoen force-pushed the justin/feat/cross-activity-lifecycle branch from 08a18f2 to 48815f0 Compare July 21, 2026 17:49
When jurisdiction/environment aren't fully set, getFullConfiguration()
falls back to the short config.json path, which previously carried no
language hint. Native HTTP stacks (OkHttp) don't send Accept-Language,
so the server silently defaulted to "en" on non-English devices.

Now the short path always sends a language query param: the explicit
languageCode if set, otherwise the device locale (formatted to match
ketch-tag's formatLanguage convention). jurisdiction/region are
forwarded when explicitly set. The full static path is unchanged.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants