@capgo/capacitor-webview-version-checker
v8.2.0
Published
Capacitor plugin for checking outdated Android WebView engines, emitting status events, and presenting native update prompts.
Maintainers
Readme
@capgo/capacitor-webview-version-checker
Capacitor plugin for checking whether the app WebView engine is up to date, emitting realtime status events, and optionally showing a native update prompt that redirects users to the proper update destination.
Install
bun add @capgo/capacitor-webview-version-checker
bunx cap syncUsage
Main use case: Browserslist-style compatibility checks by default.
The plugin uses this strategy out of the box, even if you do not add any plugin options:
minimumDeviceSharePercentdefaults to3- version-share data comes from a built-in dataset generated at build time from caniuse
- no runtime version-share URL call is required for the default flow
Default setup (no plugin settings):
import type { CapacitorConfig } from '@capacitor/cli';
const config: CapacitorConfig = {
plugins: {
WebviewVersionChecker: {},
},
};
export default config;Simple config-only setup with native prompt:
import type { CapacitorConfig } from '@capacitor/cli';
const config: CapacitorConfig = {
plugins: {
WebviewVersionChecker: {
autoPromptOnOutdated: true,
autoPromptDismissible: false,
},
},
};
export default config;Advanced mode with custom threshold and custom dataset:
import type { CapacitorConfig } from '@capacitor/cli';
const config: CapacitorConfig = {
plugins: {
WebviewVersionChecker: {
autoCheckOnLoad: true,
autoPromptOnOutdated: true,
minimumDeviceSharePercent: 3,
versionShareByMajor: {
'137': 58.2,
'136': 21.3,
'135': 4.6,
'134': 2.1,
},
},
},
};
export default config;What this means:
minimumDeviceSharePercent: 3means "consider a version compatible only if that major version still represents at least 3% of devices in my dataset".versionShareByMajoris your own dataset map where:- key = major version (for example
137) - value = share percent (
0..100)
- key = major version (for example
- If you do not provide
versionShareByMajor, the plugin uses its built-in generated dataset.
You can provide share data in two ways:
- Inline with
versionShareByMajor(as shown above) - Remote with
versionShareApiUrlreturning one of these shapes:{ "versionShareByMajor": { "137": 54.2, "136": 23.8 } }{ "shareByMajor": { "137": 54.2, "136": 23.8 } }{ "versions": [{ "major": 137, "share": 54.2 }, { "version": "136.0.0.0", "percent": 23.8 }] }
If you set versionShareApiUrl, the plugin fetches that URL at runtime and uses it as override.
Evaluation order:
- Browserslist-style threshold mode (
minimumDeviceSharePercent+ share dataset) is used first. By default this is3%with the built-in generated dataset. - Else the plugin compares against
latestVersion/latestVersionApiUrl. - Else it falls back to
minimumMajorVersion.
Advanced usage with JavaScript (manual check, listeners, custom prompt):
import { WebviewVersionChecker } from '@capgo/capacitor-webview-version-checker';
const listener = await WebviewVersionChecker.addListener('webViewOutdated', (status) => {
console.log('Outdated WebView detected', status);
});
const status = await WebviewVersionChecker.check({
latestVersionApiUrl:
'https://versionhistory.googleapis.com/v1/chrome/platforms/android/channels/stable/versions?page_size=1',
minimumMajorVersion: 124,
showPromptOnOutdated: true,
autoPromptDismissible: false,
promptTitle: 'Update WebView',
promptMessage: 'Your WebView is outdated. Please update to continue safely.',
promptUpdateButtonText: 'Update now',
promptCancelButtonText: 'Later',
});
console.log('WebView status', status);
// later
listener.remove();Why WebView Version Checker?
Capacitor already provides a built-in WebView minimum check through config:
import type { CapacitorConfig } from '@capacitor/cli';
const config: CapacitorConfig = {
android: {
minWebViewVersion: 124,
},
server: {
errorPath: 'unsupported-webview.html',
},
};
export default config;Why we're doing this instead
android.minWebViewVersionis static config; it does not give runtime plugin events likewebViewOutdated.- With
server.errorPath, users are redirected to a static error page (hard block UX) instead of seeing a native modal in your normal app flow. - Without
server.errorPath, Capacitor only logs the issue, but does not provide a native update prompt + store deep link UX. - This plugin gives soft enforcement: users can still open/use the app, get a native update modal, and you decide whether to require update later.
- Main use case: this plugin brings Browserslist-style compatibility logic to Android WebView (for example, "support versions still used by at least 3% of devices"), while keeping your app usable.
Android Provider Handling
The plugin resolves the active WebView provider package and version, then routes update links to the correct package:
- Android 5-6 and 10+: Android System WebView (
com.google.android.webview) - Android 7-9: Google Chrome (
com.android.chrome)
When provider detection is unavailable, fallback routing follows the same API-range rule above.
API
check(...)startMonitoring(...)stopMonitoring()getLastStatus()showUpdatePrompt(...)openUpdatePage(...)addListener('statusChanged', ...)addListener('webViewLatest', ...)addListener('webViewOutdated', ...)- Interfaces
- Type Aliases
Public API for checking WebView freshness and guiding users to updates.
check(...)
check(options?: CheckWebViewOptions | undefined) => Promise<WebViewVersionStatus>Runs a version check and returns the latest known status.
| Param | Type |
| ------------- | ------------------------------------------------------------------- |
| options | CheckWebViewOptions |
Returns: Promise<WebViewVersionStatus>
startMonitoring(...)
startMonitoring(options?: StartMonitoringOptions | undefined) => Promise<MonitoringStateResult>Enables background monitoring (typically on app resume).
| Param | Type |
| ------------- | ------------------------------------------------------------------------- |
| options | StartMonitoringOptions |
Returns: Promise<MonitoringStateResult>
stopMonitoring()
stopMonitoring() => Promise<MonitoringStateResult>Disables monitoring.
Returns: Promise<MonitoringStateResult>
getLastStatus()
getLastStatus() => Promise<LastStatusResult>Returns the last resolved status, or null if no check was run yet.
Returns: Promise<LastStatusResult>
showUpdatePrompt(...)
showUpdatePrompt(options?: ShowUpdatePromptOptions | undefined) => Promise<ShowUpdatePromptResult>Shows a native prompt asking the user to update the WebView.
| Param | Type |
| ------------- | --------------------------------------------------------------------------- |
| options | ShowUpdatePromptOptions |
Returns: Promise<ShowUpdatePromptResult>
openUpdatePage(...)
openUpdatePage(options?: OpenUpdatePageOptions | undefined) => Promise<OpenUpdatePageResult>Opens the configured update page directly.
| Param | Type |
| ------------- | ----------------------------------------------------------------------- |
| options | OpenUpdatePageOptions |
Returns: Promise<OpenUpdatePageResult>
addListener('statusChanged', ...)
addListener(eventName: 'statusChanged', listenerFunc: (status: WebViewVersionStatus) => void) => Promise<PluginListenerHandle>Fired for every successful status evaluation.
| Param | Type |
| ------------------ | ------------------------------------------------------------------------------------------ |
| eventName | 'statusChanged' |
| listenerFunc | (status: WebViewVersionStatus) => void |
Returns: Promise<PluginListenerHandle>
addListener('webViewLatest', ...)
addListener(eventName: 'webViewLatest', listenerFunc: (status: WebViewVersionStatus) => void) => Promise<PluginListenerHandle>Fired when the state resolves to latest.
| Param | Type |
| ------------------ | ------------------------------------------------------------------------------------------ |
| eventName | 'webViewLatest' |
| listenerFunc | (status: WebViewVersionStatus) => void |
Returns: Promise<PluginListenerHandle>
addListener('webViewOutdated', ...)
addListener(eventName: 'webViewOutdated', listenerFunc: (status: WebViewVersionStatus) => void) => Promise<PluginListenerHandle>Fired when the state resolves to outdated.
| Param | Type |
| ------------------ | ------------------------------------------------------------------------------------------ |
| eventName | 'webViewOutdated' |
| listenerFunc | (status: WebViewVersionStatus) => void |
Returns: Promise<PluginListenerHandle>
Interfaces
WebViewVersionStatus
Snapshot of the currently detected WebView status.
| Prop | Type | Description |
| -------------------------------- | ------------------------------------------------------------------- | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| platform | WebViewPlatform | Native platform that generated the status. |
| state | WebViewVersionState | Resolved version state. |
| isLatest | boolean | Convenience boolean equivalent to state === 'latest'. |
| checkedAt | string | ISO-8601 timestamp of the check. |
| reason | string | Human-readable explanation for the reported state. |
| currentVersion | string | Current WebView (or iOS system WebKit) version string. |
| currentMajorVersion | number | Current detected major version (if parseable). |
| latestVersion | string | Resolved latest version used for comparison. |
| latestMajorVersion | number | Resolved latest major version (if parseable). |
| currentVersionSharePercent | number | Device-share percentage for the installed WebView major version. Present only when a version-share dataset is available and includes the current major version. |
| minimumDeviceSharePercent | number | Configured threshold used by compatibility-threshold mode. Present only when minimumDeviceSharePercent was requested for that check. |
| versionShareSource | string | Source used for version-share data. Values: - versionShareByMajor (inline dataset) - versionShareApiUrl (remote dataset) - generatedVersionShareByMajor (built-in dataset generated at build time) |
| deviceShareError | string | Diagnostic message for compatibility-threshold mode. Present when minimumDeviceSharePercent was requested but the threshold check could not be fully evaluated. |
| providerPackage | string | Android package name of the active WebView provider. |
| updateUrl | string | URL that should be opened to update when outdated. |
| source | string | Internal source identifier for the check implementation. |
CheckWebViewOptions
Options for running a WebView version check.
| Prop | Type | Description | Default |
| -------------------------- | -------------------- | --------------------------------------------------------------------------------- | --------------------- |
| showPromptOnOutdated | boolean | Force showing a native prompt if an outdated WebView is detected. | false |
| source | string | Optional tag included in the status payload so you can identify the check origin. | "manual" |
MonitoringStateResult
Result payload for monitor controls.
| Prop | Type | Description |
| -------------------------- | -------------------- | ------------------------------------------------------------ |
| monitoring | boolean | Whether monitoring is currently active. |
| checkOnResume | boolean | Whether checks run on app resume while monitoring is active. |
| autoPromptOnOutdated | boolean | Whether outdated checks auto-trigger the native prompt. |
StartMonitoringOptions
Options for starting monitor mode.
| Prop | Type | Description | Default |
| ------------------- | -------------------- | ----------------------------------------------------------------- | ----------------- |
| checkOnStart | boolean | Run a check immediately when monitoring starts. | true |
| checkOnResume | boolean | Whether foreground checks should run while monitoring is enabled. | true |
LastStatusResult
Last known check snapshot.
| Prop | Type | Description |
| ------------ | ----------------------------------------------------------------------------- | ------------------------------------- |
| status | WebViewVersionStatus | null | Null until the first check completes. |
ShowUpdatePromptResult
Result payload for showUpdatePrompt().
| Prop | Type | Description |
| ---------------------- | -------------------- | ---------------------------------------------------------- |
| shown | boolean | Whether a native prompt was actually shown. |
| openedUpdatePage | boolean | Whether the update page was opened from the prompt action. |
ShowUpdatePromptOptions
Options for showing the native update prompt.
| Prop | Type | Description |
| ---------------------- | ------------------- | ------------------------------------------------------ |
| title | string | Prompt title. |
| message | string | Prompt message. |
| updateButtonText | string | Update CTA label. |
| cancelButtonText | string | Cancel CTA label. |
| updateUrl | string | Optional URL to open if the update action is selected. |
OpenUpdatePageResult
Result payload for openUpdatePage().
| Prop | Type | Description |
| ------------ | -------------------- | ----------------------------------------- |
| opened | boolean | Whether opening the update URL succeeded. |
| url | string | URL that was attempted. |
OpenUpdatePageOptions
Options for opening the update page directly.
| Prop | Type | Description |
| --------------- | ------------------- | ---------------------- |
| updateUrl | string | Optional URL override. |
PluginListenerHandle
| Prop | Type |
| ------------ | ----------------------------------------- |
| remove | () => Promise<void> |
Type Aliases
WebViewPlatform
'android' | 'ios' | 'web'
WebViewVersionState
'latest' | 'outdated' | 'unknown'
