@capawesome/capacitor-system-webview 0.0.1

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.
Files changed (35) hide show
  1. package/CapawesomeCapacitorSystemWebView.podspec +17 -0
  2. package/LICENSE +21 -0
  3. package/Package.swift +28 -0
  4. package/README.md +227 -0
  5. package/android/build.gradle +60 -0
  6. package/android/src/main/AndroidManifest.xml +1 -0
  7. package/android/src/main/java/io/capawesome/capacitorjs/plugins/systemwebview/SystemWebView.java +94 -0
  8. package/android/src/main/java/io/capawesome/capacitorjs/plugins/systemwebview/SystemWebViewPlugin.java +116 -0
  9. package/android/src/main/java/io/capawesome/capacitorjs/plugins/systemwebview/classes/CustomException.java +20 -0
  10. package/android/src/main/java/io/capawesome/capacitorjs/plugins/systemwebview/classes/CustomExceptions.java +15 -0
  11. package/android/src/main/java/io/capawesome/capacitorjs/plugins/systemwebview/classes/options/IsUpdateRequiredOptions.java +21 -0
  12. package/android/src/main/java/io/capawesome/capacitorjs/plugins/systemwebview/classes/results/GetInfoResult.java +35 -0
  13. package/android/src/main/java/io/capawesome/capacitorjs/plugins/systemwebview/classes/results/IsUpdateRequiredResult.java +22 -0
  14. package/android/src/main/java/io/capawesome/capacitorjs/plugins/systemwebview/interfaces/Callback.java +5 -0
  15. package/android/src/main/java/io/capawesome/capacitorjs/plugins/systemwebview/interfaces/EmptyCallback.java +5 -0
  16. package/android/src/main/java/io/capawesome/capacitorjs/plugins/systemwebview/interfaces/NonEmptyResultCallback.java +7 -0
  17. package/android/src/main/java/io/capawesome/capacitorjs/plugins/systemwebview/interfaces/Result.java +7 -0
  18. package/android/src/main/res/.gitkeep +0 -0
  19. package/dist/docs.json +190 -0
  20. package/dist/esm/definitions.d.ts +112 -0
  21. package/dist/esm/definitions.js +27 -0
  22. package/dist/esm/definitions.js.map +1 -0
  23. package/dist/esm/index.d.ts +4 -0
  24. package/dist/esm/index.js +7 -0
  25. package/dist/esm/index.js.map +1 -0
  26. package/dist/esm/web.d.ts +7 -0
  27. package/dist/esm/web.js +13 -0
  28. package/dist/esm/web.js.map +1 -0
  29. package/dist/plugin.cjs.js +54 -0
  30. package/dist/plugin.cjs.js.map +1 -0
  31. package/dist/plugin.js +57 -0
  32. package/dist/plugin.js.map +1 -0
  33. package/ios/Plugin/Info.plist +24 -0
  34. package/ios/Plugin/SystemWebViewPlugin.swift +29 -0
  35. package/package.json +91 -0
@@ -0,0 +1,17 @@
1
+ require 'json'
2
+
3
+ package = JSON.parse(File.read(File.join(__dir__, 'package.json')))
4
+
5
+ Pod::Spec.new do |s|
6
+ s.name = 'CapawesomeCapacitorSystemWebView'
7
+ s.version = package['version']
8
+ s.summary = package['description']
9
+ s.license = package['license']
10
+ s.homepage = package['repository']['url']
11
+ s.author = package['author']
12
+ s.source = { :git => package['repository']['url'], :tag => s.version.to_s }
13
+ s.source_files = 'ios/Plugin/**/*.{swift,h,m,c,cc,mm,cpp}'
14
+ s.ios.deployment_target = '15.0'
15
+ s.dependency 'Capacitor'
16
+ s.swift_version = '5.1'
17
+ end
package/LICENSE ADDED
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2026 Robin Genz
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
package/Package.swift ADDED
@@ -0,0 +1,28 @@
1
+ // swift-tools-version: 5.9
2
+ import PackageDescription
3
+
4
+ let package = Package(
5
+ name: "CapawesomeCapacitorSystemWebView",
6
+ platforms: [.iOS(.v15)],
7
+ products: [
8
+ .library(
9
+ name: "CapawesomeCapacitorSystemWebView",
10
+ targets: ["SystemWebViewPlugin"])
11
+ ],
12
+ dependencies: [
13
+ .package(url: "https://github.com/ionic-team/capacitor-swift-pm.git", from: "8.0.0")
14
+ ],
15
+ targets: [
16
+ .target(
17
+ name: "SystemWebViewPlugin",
18
+ dependencies: [
19
+ .product(name: "Capacitor", package: "capacitor-swift-pm"),
20
+ .product(name: "Cordova", package: "capacitor-swift-pm")
21
+ ],
22
+ path: "ios/Plugin"),
23
+ .testTarget(
24
+ name: "SystemWebViewPluginTests",
25
+ dependencies: ["SystemWebViewPlugin"],
26
+ path: "ios/PluginTests")
27
+ ]
28
+ )
package/README.md ADDED
@@ -0,0 +1,227 @@
1
+ # Capacitor System WebView Plugin
2
+
3
+ Capacitor plugin to detect an outdated Android System WebView and guide users to update it.
4
+
5
+ <div class="capawesome-z29o10a">
6
+ <a href="https://cloud.capawesome.io/" target="_blank">
7
+ <img alt="Deliver Live Updates to your Capacitor app with Capawesome Cloud" src="https://cloud.capawesome.io/assets/banners/cloud-build-and-deploy-capacitor-apps.png?t=1" />
8
+ </a>
9
+ </div>
10
+
11
+ ## Features
12
+
13
+ - 🔍 **Detection**: Read the package name and version of the active Android System WebView provider.
14
+ - ⚠️ **Outdated check**: Compare the installed Chromium major version against the minimum your app requires.
15
+ - 🛒 **Update flow**: Send users straight to the Play Store entry of their active WebView provider.
16
+ - 🤝 **Compatibility**: Works alongside the [App Update](https://capawesome.io/docs/sdks/capacitor/app-update/), [Device Info](https://capawesome.io/docs/sdks/capacitor/device-info/) and [Dialog](https://capawesome.io/docs/sdks/capacitor/dialog/) plugins.
17
+ - 🔁 **Up-to-date**: Always supports the latest Capacitor version.
18
+
19
+ Missing a feature? Just [open an issue](https://github.com/capawesome-team/capacitor-plugins/issues) and we'll take a look!
20
+
21
+ ## Newsletter
22
+
23
+ Stay up to date with the latest news and updates about the Capawesome, Capacitor, and Ionic ecosystem by subscribing to our [Capawesome Newsletter](https://cloud.capawesome.io/newsletter/).
24
+
25
+ ## Compatibility
26
+
27
+ | Plugin Version | Capacitor Version | Status |
28
+ | -------------- | ----------------- | -------------- |
29
+ | 0.x.x | >=8.x.x | Active support |
30
+
31
+ ## Installation
32
+
33
+ You can use our **AI-Assisted Setup** to install the plugin.
34
+ Add the [Capawesome Skills](https://github.com/capawesome-team/skills) to your AI tool using the following command:
35
+
36
+ ```bash
37
+ npx skills add capawesome-team/skills --skill capacitor-plugins
38
+ ```
39
+
40
+ Then use the following prompt:
41
+
42
+ ```
43
+ Use the `capacitor-plugins` skill from `capawesome-team/skills` to install the `@capawesome/capacitor-system-webview` plugin in my project.
44
+ ```
45
+
46
+ If you prefer **Manual Setup**, install the plugin by running the following commands and follow the platform-specific instructions below:
47
+
48
+ ```bash
49
+ npm install @capawesome/capacitor-system-webview
50
+ npx cap sync
51
+ ```
52
+
53
+ This plugin is only available on **Android**. On iOS and Web, all methods reject as unimplemented (see [iOS](#ios) below).
54
+
55
+ ### Android
56
+
57
+ #### Variables
58
+
59
+ This plugin will use the following project variables (defined in your app's `variables.gradle` file):
60
+
61
+ - `$androidxWebkitVersion` version of `androidx.webkit:webkit` (default: `1.14.0`)
62
+
63
+ ### iOS
64
+
65
+ This plugin has **no iOS implementation** and does not need one. On iOS, the `WKWebView` is part of the operating system and is updated together with iOS itself. It cannot be updated separately, so there is nothing for an app to detect or fix.
66
+
67
+ All methods reject as unimplemented on iOS.
68
+
69
+ ## Configuration
70
+
71
+ No configuration required for this plugin.
72
+
73
+ ## Usage
74
+
75
+ The recommended pattern is to check whether an update is required on app start, prompt the user with the [Dialog](https://capawesome.io/docs/sdks/capacitor/dialog/) plugin, and then open the Play Store:
76
+
77
+ ```typescript
78
+ import { Dialog } from '@capacitor/dialog';
79
+ import { SystemWebView } from '@capawesome/capacitor-system-webview';
80
+
81
+ const promptForUpdateIfRequired = async () => {
82
+ const { required } = await SystemWebView.isUpdateRequired({
83
+ minMajorVersion: 105,
84
+ });
85
+ if (!required) {
86
+ return;
87
+ }
88
+ const { value } = await Dialog.confirm({
89
+ title: 'Update required',
90
+ message:
91
+ 'Your Android System WebView is outdated. Please update it to continue using all features of this app.',
92
+ okButtonTitle: 'Update',
93
+ });
94
+ if (value) {
95
+ await SystemWebView.openAppStore();
96
+ }
97
+ };
98
+
99
+ const getInfo = async () => {
100
+ const info = await SystemWebView.getInfo();
101
+ return info;
102
+ };
103
+ ```
104
+
105
+ > [!NOTE]
106
+ > A WebView update only takes effect the next time the app process is started. The currently running app keeps using the old WebView until it is restarted.
107
+
108
+ ## API
109
+
110
+ <docgen-index>
111
+
112
+ * [`getInfo()`](#getinfo)
113
+ * [`isUpdateRequired(...)`](#isupdaterequired)
114
+ * [`openAppStore()`](#openappstore)
115
+ * [Interfaces](#interfaces)
116
+
117
+ </docgen-index>
118
+
119
+ <docgen-api>
120
+ <!--Update the source file JSDoc comments and rerun docgen to update the docs below-->
121
+
122
+ ### getInfo()
123
+
124
+ ```typescript
125
+ getInfo() => Promise<GetInfoResult>
126
+ ```
127
+
128
+ Get information about the active Android System WebView provider.
129
+
130
+ Only available on Android.
131
+
132
+ **Returns:** <code>Promise&lt;<a href="#getinforesult">GetInfoResult</a>&gt;</code>
133
+
134
+ **Since:** 0.1.0
135
+
136
+ --------------------
137
+
138
+
139
+ ### isUpdateRequired(...)
140
+
141
+ ```typescript
142
+ isUpdateRequired(options: IsUpdateRequiredOptions) => Promise<IsUpdateRequiredResult>
143
+ ```
144
+
145
+ Check whether the active Android System WebView is older than the minimum
146
+ Chromium major version required by your app.
147
+
148
+ Only available on Android.
149
+
150
+ | Param | Type |
151
+ | ------------- | --------------------------------------------------------------------------- |
152
+ | **`options`** | <code><a href="#isupdaterequiredoptions">IsUpdateRequiredOptions</a></code> |
153
+
154
+ **Returns:** <code>Promise&lt;<a href="#isupdaterequiredresult">IsUpdateRequiredResult</a>&gt;</code>
155
+
156
+ **Since:** 0.1.0
157
+
158
+ --------------------
159
+
160
+
161
+ ### openAppStore()
162
+
163
+ ```typescript
164
+ openAppStore() => Promise<void>
165
+ ```
166
+
167
+ Open the Play Store entry of the active Android System WebView provider so
168
+ the user can update it.
169
+
170
+ Only available on Android.
171
+
172
+ **Since:** 0.1.0
173
+
174
+ --------------------
175
+
176
+
177
+ ### Interfaces
178
+
179
+
180
+ #### GetInfoResult
181
+
182
+ | Prop | Type | Description | Since |
183
+ | ------------------ | --------------------------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | ----- |
184
+ | **`majorVersion`** | <code>number \| null</code> | The Chromium major version of the active WebView provider. This is the integer before the first dot of the `versionName` (e.g. `126` for `126.0.6478.122`). `null` if the `versionName` is not a Chromium-style version, which can happen with OEM WebView forks. | 0.1.0 |
185
+ | **`packageName`** | <code>string</code> | The package name of the active WebView provider. | 0.1.0 |
186
+ | **`versionName`** | <code>string</code> | The version name of the active WebView provider. | 0.1.0 |
187
+
188
+
189
+ #### IsUpdateRequiredResult
190
+
191
+ | Prop | Type | Description | Since |
192
+ | -------------- | -------------------- | ------------------------------------------------------------------------------------------- | ----- |
193
+ | **`required`** | <code>boolean</code> | `true` if the active WebView is older than the required minimum version, otherwise `false`. | 0.1.0 |
194
+
195
+
196
+ #### IsUpdateRequiredOptions
197
+
198
+ | Prop | Type | Description | Since |
199
+ | --------------------- | ------------------- | ----------------------------------------------------------------------------------------------------------------------------------------------- | ----- |
200
+ | **`minMajorVersion`** | <code>number</code> | The minimum Chromium major version your app requires. The active WebView is considered outdated if its `majorVersion` is lower than this value. | 0.1.0 |
201
+
202
+ </docgen-api>
203
+
204
+ ## Why Outdated System WebViews Matter
205
+
206
+ On Android, your Capacitor app runs inside the Android System WebView, which is updated independently of the operating system. Many devices run an ancient WebView because the user has disabled automatic updates, is offline, or uses a custom ROM. When that happens, modern web features your app relies on may simply be missing, causing hard-to-diagnose "the app is broken" support tickets.
207
+
208
+ Because "outdated" depends on which web features your app's bundle actually needs, this plugin never hardcodes a threshold. Instead, your app declares the minimum Chromium major version it requires via `isUpdateRequired(...)`.
209
+
210
+ The following table gives a rough idea of when some popular web features became available in Chromium (and therefore the System WebView):
211
+
212
+ | Chromium major | Rough web-feature baseline |
213
+ | -------------- | --------------------------------------------- |
214
+ | 97+ | Array `findLast` / `findLastIndex` |
215
+ | 105+ | CSS `:has()` selector and container queries |
216
+ | 112+ | Native CSS nesting |
217
+ | 114+ | CSS `text-wrap: balance` |
218
+
219
+ Pick the minimum version based on the features your app uses and pass it as `minMajorVersion`.
220
+
221
+ ## Changelog
222
+
223
+ See [CHANGELOG.md](https://github.com/capawesome-team/capacitor-plugins/blob/main/packages/system-webview/CHANGELOG.md).
224
+
225
+ ## License
226
+
227
+ See [LICENSE](https://github.com/capawesome-team/capacitor-plugins/blob/main/packages/system-webview/LICENSE).
@@ -0,0 +1,60 @@
1
+ ext {
2
+ junitVersion = project.hasProperty('junitVersion') ? rootProject.ext.junitVersion : '4.13.2'
3
+ androidxAppCompatVersion = project.hasProperty('androidxAppCompatVersion') ? rootProject.ext.androidxAppCompatVersion : '1.7.1'
4
+ androidxJunitVersion = project.hasProperty('androidxJunitVersion') ? rootProject.ext.androidxJunitVersion : '1.3.0'
5
+ androidxEspressoCoreVersion = project.hasProperty('androidxEspressoCoreVersion') ? rootProject.ext.androidxEspressoCoreVersion : '3.7.0'
6
+ androidxWebkitVersion = project.hasProperty('androidxWebkitVersion') ? rootProject.ext.androidxWebkitVersion : '1.14.0'
7
+ }
8
+
9
+ buildscript {
10
+ repositories {
11
+ google()
12
+ mavenCentral()
13
+ }
14
+ dependencies {
15
+ classpath 'com.android.tools.build:gradle:8.13.0'
16
+ }
17
+ }
18
+
19
+ apply plugin: 'com.android.library'
20
+
21
+ android {
22
+ namespace = "io.capawesome.capacitorjs.plugins.systemwebview"
23
+ compileSdk = project.hasProperty('compileSdkVersion') ? rootProject.ext.compileSdkVersion : 36
24
+ defaultConfig {
25
+ minSdkVersion project.hasProperty('minSdkVersion') ? rootProject.ext.minSdkVersion : 24
26
+ targetSdkVersion project.hasProperty('targetSdkVersion') ? rootProject.ext.targetSdkVersion : 36
27
+ versionCode 1
28
+ versionName "1.0"
29
+ testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner"
30
+ }
31
+ buildTypes {
32
+ release {
33
+ minifyEnabled false
34
+ proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'
35
+ }
36
+ }
37
+ lintOptions {
38
+ abortOnError = false
39
+ }
40
+ compileOptions {
41
+ sourceCompatibility JavaVersion.VERSION_21
42
+ targetCompatibility JavaVersion.VERSION_21
43
+ }
44
+ }
45
+
46
+ repositories {
47
+ google()
48
+ mavenCentral()
49
+ }
50
+
51
+
52
+ dependencies {
53
+ implementation fileTree(dir: 'libs', include: ['*.jar'])
54
+ implementation project(':capacitor-android')
55
+ implementation "androidx.appcompat:appcompat:$androidxAppCompatVersion"
56
+ implementation "androidx.webkit:webkit:$androidxWebkitVersion"
57
+ testImplementation "junit:junit:$junitVersion"
58
+ androidTestImplementation "androidx.test.ext:junit:$androidxJunitVersion"
59
+ androidTestImplementation "androidx.test.espresso:espresso-core:$androidxEspressoCoreVersion"
60
+ }
@@ -0,0 +1 @@
1
+ <manifest xmlns:android="http://schemas.android.com/apk/res/android"></manifest>
@@ -0,0 +1,94 @@
1
+ package io.capawesome.capacitorjs.plugins.systemwebview;
2
+
3
+ import android.content.ActivityNotFoundException;
4
+ import android.content.Context;
5
+ import android.content.Intent;
6
+ import android.content.pm.PackageInfo;
7
+ import android.net.Uri;
8
+ import androidx.annotation.NonNull;
9
+ import androidx.annotation.Nullable;
10
+ import androidx.webkit.WebViewCompat;
11
+ import io.capawesome.capacitorjs.plugins.systemwebview.classes.CustomExceptions;
12
+ import io.capawesome.capacitorjs.plugins.systemwebview.classes.options.IsUpdateRequiredOptions;
13
+ import io.capawesome.capacitorjs.plugins.systemwebview.classes.results.GetInfoResult;
14
+ import io.capawesome.capacitorjs.plugins.systemwebview.classes.results.IsUpdateRequiredResult;
15
+ import io.capawesome.capacitorjs.plugins.systemwebview.interfaces.EmptyCallback;
16
+ import io.capawesome.capacitorjs.plugins.systemwebview.interfaces.NonEmptyResultCallback;
17
+
18
+ public class SystemWebView {
19
+
20
+ @NonNull
21
+ private final SystemWebViewPlugin plugin;
22
+
23
+ public SystemWebView(@NonNull SystemWebViewPlugin plugin) {
24
+ this.plugin = plugin;
25
+ }
26
+
27
+ public void getInfo(@NonNull NonEmptyResultCallback<GetInfoResult> callback) throws Exception {
28
+ PackageInfo packageInfo = getCurrentWebViewPackage();
29
+ String versionName = packageInfo.versionName;
30
+ if (versionName == null) {
31
+ throw CustomExceptions.WEB_VIEW_PACKAGE_UNAVAILABLE;
32
+ }
33
+ Integer majorVersion = parseMajorVersion(versionName);
34
+ callback.success(new GetInfoResult(packageInfo.packageName, versionName, majorVersion));
35
+ }
36
+
37
+ public void isUpdateRequired(
38
+ @NonNull IsUpdateRequiredOptions options,
39
+ @NonNull NonEmptyResultCallback<IsUpdateRequiredResult> callback
40
+ ) throws Exception {
41
+ PackageInfo packageInfo = getCurrentWebViewPackage();
42
+ Integer majorVersion = parseMajorVersion(packageInfo.versionName);
43
+ if (majorVersion == null) {
44
+ throw CustomExceptions.VERSION_UNPARSEABLE;
45
+ }
46
+ boolean required = majorVersion < options.getMinMajorVersion();
47
+ callback.success(new IsUpdateRequiredResult(required));
48
+ }
49
+
50
+ public void openAppStore(@NonNull EmptyCallback callback) throws Exception {
51
+ PackageInfo packageInfo = getCurrentWebViewPackage();
52
+ String packageName = packageInfo.packageName;
53
+ try {
54
+ startAppStoreIntent("market://details?id=" + packageName);
55
+ } catch (ActivityNotFoundException exception) {
56
+ try {
57
+ startAppStoreIntent("https://play.google.com/store/apps/details?id=" + packageName);
58
+ } catch (ActivityNotFoundException fallbackException) {
59
+ throw CustomExceptions.OPEN_FAILED;
60
+ }
61
+ }
62
+ callback.success();
63
+ }
64
+
65
+ @NonNull
66
+ private PackageInfo getCurrentWebViewPackage() throws Exception {
67
+ Context context = plugin.getContext();
68
+ PackageInfo packageInfo = WebViewCompat.getCurrentWebViewPackage(context);
69
+ if (packageInfo == null) {
70
+ throw CustomExceptions.WEB_VIEW_PACKAGE_UNAVAILABLE;
71
+ }
72
+ return packageInfo;
73
+ }
74
+
75
+ @Nullable
76
+ private Integer parseMajorVersion(@Nullable String versionName) {
77
+ if (versionName == null) {
78
+ return null;
79
+ }
80
+ int separatorIndex = versionName.indexOf('.');
81
+ String majorPart = separatorIndex >= 0 ? versionName.substring(0, separatorIndex) : versionName;
82
+ try {
83
+ return Integer.parseInt(majorPart.trim());
84
+ } catch (NumberFormatException exception) {
85
+ return null;
86
+ }
87
+ }
88
+
89
+ private void startAppStoreIntent(@NonNull String url) {
90
+ Intent intent = new Intent(Intent.ACTION_VIEW, Uri.parse(url));
91
+ intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
92
+ plugin.getContext().startActivity(intent);
93
+ }
94
+ }
@@ -0,0 +1,116 @@
1
+ package io.capawesome.capacitorjs.plugins.systemwebview;
2
+
3
+ import androidx.annotation.NonNull;
4
+ import androidx.annotation.Nullable;
5
+ import com.getcapacitor.Logger;
6
+ import com.getcapacitor.Plugin;
7
+ import com.getcapacitor.PluginCall;
8
+ import com.getcapacitor.PluginMethod;
9
+ import com.getcapacitor.annotation.CapacitorPlugin;
10
+ import io.capawesome.capacitorjs.plugins.systemwebview.classes.CustomException;
11
+ import io.capawesome.capacitorjs.plugins.systemwebview.classes.options.IsUpdateRequiredOptions;
12
+ import io.capawesome.capacitorjs.plugins.systemwebview.classes.results.GetInfoResult;
13
+ import io.capawesome.capacitorjs.plugins.systemwebview.classes.results.IsUpdateRequiredResult;
14
+ import io.capawesome.capacitorjs.plugins.systemwebview.interfaces.EmptyCallback;
15
+ import io.capawesome.capacitorjs.plugins.systemwebview.interfaces.NonEmptyResultCallback;
16
+ import io.capawesome.capacitorjs.plugins.systemwebview.interfaces.Result;
17
+
18
+ @CapacitorPlugin(name = "SystemWebView")
19
+ public class SystemWebViewPlugin extends Plugin {
20
+
21
+ public static final String ERROR_UNKNOWN_ERROR = "An unknown error occurred.";
22
+ public static final String TAG = "SystemWebViewPlugin";
23
+
24
+ private SystemWebView implementation;
25
+
26
+ @Override
27
+ public void load() {
28
+ implementation = new SystemWebView(this);
29
+ }
30
+
31
+ @PluginMethod
32
+ public void getInfo(PluginCall call) {
33
+ try {
34
+ NonEmptyResultCallback<GetInfoResult> callback = new NonEmptyResultCallback<>() {
35
+ @Override
36
+ public void success(@NonNull GetInfoResult result) {
37
+ resolveCall(call, result);
38
+ }
39
+
40
+ @Override
41
+ public void error(@NonNull Exception exception) {
42
+ rejectCall(call, exception);
43
+ }
44
+ };
45
+ implementation.getInfo(callback);
46
+ } catch (Exception exception) {
47
+ rejectCall(call, exception);
48
+ }
49
+ }
50
+
51
+ @PluginMethod
52
+ public void isUpdateRequired(PluginCall call) {
53
+ try {
54
+ IsUpdateRequiredOptions options = new IsUpdateRequiredOptions(call);
55
+ NonEmptyResultCallback<IsUpdateRequiredResult> callback = new NonEmptyResultCallback<>() {
56
+ @Override
57
+ public void success(@NonNull IsUpdateRequiredResult result) {
58
+ resolveCall(call, result);
59
+ }
60
+
61
+ @Override
62
+ public void error(@NonNull Exception exception) {
63
+ rejectCall(call, exception);
64
+ }
65
+ };
66
+ implementation.isUpdateRequired(options, callback);
67
+ } catch (Exception exception) {
68
+ rejectCall(call, exception);
69
+ }
70
+ }
71
+
72
+ @PluginMethod
73
+ public void openAppStore(PluginCall call) {
74
+ try {
75
+ EmptyCallback callback = new EmptyCallback() {
76
+ @Override
77
+ public void success() {
78
+ resolveCall(call);
79
+ }
80
+
81
+ @Override
82
+ public void error(@NonNull Exception exception) {
83
+ rejectCall(call, exception);
84
+ }
85
+ };
86
+ implementation.openAppStore(callback);
87
+ } catch (Exception exception) {
88
+ rejectCall(call, exception);
89
+ }
90
+ }
91
+
92
+ private void rejectCall(@NonNull PluginCall call, @NonNull Exception exception) {
93
+ String message = exception.getMessage();
94
+ if (message == null) {
95
+ message = ERROR_UNKNOWN_ERROR;
96
+ }
97
+ String code = null;
98
+ if (exception instanceof CustomException) {
99
+ code = ((CustomException) exception).getCode();
100
+ }
101
+ Logger.error(TAG, message, exception);
102
+ call.reject(message, code);
103
+ }
104
+
105
+ private void resolveCall(@NonNull PluginCall call) {
106
+ call.resolve();
107
+ }
108
+
109
+ private void resolveCall(@NonNull PluginCall call, @Nullable Result result) {
110
+ if (result == null) {
111
+ call.resolve();
112
+ } else {
113
+ call.resolve(result.toJSObject());
114
+ }
115
+ }
116
+ }
@@ -0,0 +1,20 @@
1
+ package io.capawesome.capacitorjs.plugins.systemwebview.classes;
2
+
3
+ import androidx.annotation.NonNull;
4
+ import androidx.annotation.Nullable;
5
+
6
+ public class CustomException extends Exception {
7
+
8
+ @Nullable
9
+ private final String code;
10
+
11
+ public CustomException(@Nullable String code, @NonNull String message) {
12
+ super(message);
13
+ this.code = code;
14
+ }
15
+
16
+ @Nullable
17
+ public String getCode() {
18
+ return code;
19
+ }
20
+ }
@@ -0,0 +1,15 @@
1
+ package io.capawesome.capacitorjs.plugins.systemwebview.classes;
2
+
3
+ public class CustomExceptions {
4
+
5
+ public static final CustomException MIN_MAJOR_VERSION_MISSING = new CustomException(null, "minMajorVersion must be provided.");
6
+ public static final CustomException OPEN_FAILED = new CustomException("OPEN_FAILED", "The Play Store could not be opened.");
7
+ public static final CustomException VERSION_UNPARSEABLE = new CustomException(
8
+ "VERSION_UNPARSEABLE",
9
+ "The WebView version name is not a Chromium-style version and could not be parsed."
10
+ );
11
+ public static final CustomException WEB_VIEW_PACKAGE_UNAVAILABLE = new CustomException(
12
+ "WEB_VIEW_PACKAGE_UNAVAILABLE",
13
+ "The active WebView package could not be determined."
14
+ );
15
+ }
@@ -0,0 +1,21 @@
1
+ package io.capawesome.capacitorjs.plugins.systemwebview.classes.options;
2
+
3
+ import com.getcapacitor.PluginCall;
4
+ import io.capawesome.capacitorjs.plugins.systemwebview.classes.CustomExceptions;
5
+
6
+ public class IsUpdateRequiredOptions {
7
+
8
+ private final int minMajorVersion;
9
+
10
+ public IsUpdateRequiredOptions(PluginCall call) throws Exception {
11
+ Integer minMajorVersion = call.getInt("minMajorVersion");
12
+ if (minMajorVersion == null) {
13
+ throw CustomExceptions.MIN_MAJOR_VERSION_MISSING;
14
+ }
15
+ this.minMajorVersion = minMajorVersion;
16
+ }
17
+
18
+ public int getMinMajorVersion() {
19
+ return minMajorVersion;
20
+ }
21
+ }
@@ -0,0 +1,35 @@
1
+ package io.capawesome.capacitorjs.plugins.systemwebview.classes.results;
2
+
3
+ import androidx.annotation.NonNull;
4
+ import androidx.annotation.Nullable;
5
+ import com.getcapacitor.JSObject;
6
+ import io.capawesome.capacitorjs.plugins.systemwebview.interfaces.Result;
7
+ import org.json.JSONObject;
8
+
9
+ public class GetInfoResult implements Result {
10
+
11
+ @Nullable
12
+ private final Integer majorVersion;
13
+
14
+ @NonNull
15
+ private final String packageName;
16
+
17
+ @NonNull
18
+ private final String versionName;
19
+
20
+ public GetInfoResult(@NonNull String packageName, @NonNull String versionName, @Nullable Integer majorVersion) {
21
+ this.packageName = packageName;
22
+ this.versionName = versionName;
23
+ this.majorVersion = majorVersion;
24
+ }
25
+
26
+ @Override
27
+ @NonNull
28
+ public JSObject toJSObject() {
29
+ JSObject result = new JSObject();
30
+ result.put("packageName", packageName);
31
+ result.put("versionName", versionName);
32
+ result.put("majorVersion", majorVersion == null ? JSONObject.NULL : majorVersion);
33
+ return result;
34
+ }
35
+ }