@capacitor/android 4.0.1-alpha.0 → 4.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 (27) hide show
  1. package/CHANGELOG.md +126 -1
  2. package/capacitor/build.gradle +9 -7
  3. package/capacitor/proguard-rules.pro +26 -0
  4. package/capacitor/src/main/assets/native-bridge.js +8 -0
  5. package/capacitor/src/main/java/com/getcapacitor/AppUUID.java +65 -0
  6. package/capacitor/src/main/java/com/getcapacitor/Bridge.java +147 -13
  7. package/capacitor/src/main/java/com/getcapacitor/BridgeActivity.java +11 -54
  8. package/capacitor/src/main/java/com/getcapacitor/BridgeWebChromeClient.java +4 -5
  9. package/capacitor/src/main/java/com/getcapacitor/BridgeWebViewClient.java +11 -0
  10. package/capacitor/src/main/java/com/getcapacitor/CapConfig.java +65 -2
  11. package/capacitor/src/main/java/com/getcapacitor/CapacitorWebView.java +1 -0
  12. package/capacitor/src/main/java/com/getcapacitor/FileUtils.java +6 -1
  13. package/capacitor/src/main/java/com/getcapacitor/JSExport.java +1 -1
  14. package/capacitor/src/main/java/com/getcapacitor/MessageHandler.java +31 -4
  15. package/capacitor/src/main/java/com/getcapacitor/Plugin.java +16 -10
  16. package/capacitor/src/main/java/com/getcapacitor/PluginCall.java +28 -9
  17. package/capacitor/src/main/java/com/getcapacitor/PluginHandle.java +4 -0
  18. package/capacitor/src/main/java/com/getcapacitor/ProcessedRoute.java +28 -0
  19. package/capacitor/src/main/java/com/getcapacitor/RouteProcessor.java +8 -0
  20. package/capacitor/src/main/java/com/getcapacitor/WebViewLocalServer.java +27 -5
  21. package/capacitor/src/main/java/com/getcapacitor/cordova/CapacitorCordovaCookieManager.java +1 -2
  22. package/capacitor/src/main/java/com/getcapacitor/cordova/MockCordovaWebViewImpl.java +5 -0
  23. package/capacitor/src/main/res/values/colors.xml +4 -4
  24. package/capacitor/src/main/res/values/strings.xml +0 -5
  25. package/capacitor/src/main/res/values/styles.xml +0 -9
  26. package/package.json +4 -3
  27. package/capacitor/src/main/res/drawable/ic_transparent.xml +0 -12
package/CHANGELOG.md CHANGED
@@ -3,7 +3,120 @@
3
3
  All notable changes to this project will be documented in this file.
4
4
  See [Conventional Commits](https://conventionalcommits.org) for commit guidelines.
5
5
 
6
- ## [4.0.1-alpha.0](https://github.com/ionic-team/capacitor/compare/3.4.1...4.0.1-alpha.0) (2022-03-25)
6
+ ## [4.0.1](https://github.com/ionic-team/capacitor/compare/4.0.0...4.0.1) (2022-07-28)
7
+
8
+ **Note:** Version bump only for package @capacitor/android
9
+
10
+
11
+
12
+
13
+
14
+ # [4.0.0](https://github.com/ionic-team/capacitor/compare/4.0.0-beta.2...4.0.0) (2022-07-27)
15
+
16
+
17
+ ### Bug Fixes
18
+
19
+ * **android:** Publish proguard-rules.pro on npm ([#5761](https://github.com/ionic-team/capacitor/issues/5761)) ([df77103](https://github.com/ionic-team/capacitor/commit/df77103ca411fa452239099769289eeeea2404d2))
20
+
21
+
22
+ ### Features
23
+
24
+ * **android:** Add android.minWebviewVersion configuration option ([#5768](https://github.com/ionic-team/capacitor/issues/5768)) ([ad83827](https://github.com/ionic-team/capacitor/commit/ad838279e9cd190ce6f1a020a0ac9e3916786324))
25
+ * **android:** Add Optional Data Param for Error Object ([#5719](https://github.com/ionic-team/capacitor/issues/5719)) ([174172b](https://github.com/ionic-team/capacitor/commit/174172b6c64dc9117c48ed0e20c25e0b6c2fb625))
26
+ * **android:** Use addWebMessageListener where available ([#5427](https://github.com/ionic-team/capacitor/issues/5427)) ([c2dfe80](https://github.com/ionic-team/capacitor/commit/c2dfe808446717412b35e82713d123b7a052f264))
27
+ * Add option for custom error page ([#5723](https://github.com/ionic-team/capacitor/issues/5723)) ([e8bdef3](https://github.com/ionic-team/capacitor/commit/e8bdef3b4634e4ad45fa8fc34c7c0ab8dfa383f3))
28
+
29
+
30
+
31
+
32
+
33
+ # [4.0.0-beta.2](https://github.com/ionic-team/capacitor/compare/4.0.0-beta.1...4.0.0-beta.2) (2022-07-08)
34
+
35
+ **Note:** Version bump only for package @capacitor/android
36
+
37
+
38
+
39
+
40
+
41
+ # [4.0.0-beta.1](https://github.com/ionic-team/capacitor/compare/4.0.0-beta.0...4.0.0-beta.1) (2022-06-27)
42
+
43
+ **Note:** Version bump only for package @capacitor/android
44
+
45
+
46
+
47
+
48
+
49
+ # [4.0.0-beta.0](https://github.com/ionic-team/capacitor/compare/3.6.0...4.0.0-beta.0) (2022-06-17)
50
+
51
+
52
+ ### Bug Fixes
53
+
54
+ * **android:** make removeAllListeners return a promise ([#5527](https://github.com/ionic-team/capacitor/issues/5527)) ([6f4d858](https://github.com/ionic-team/capacitor/commit/6f4d858ea879d97109c0c7da2d664d04806adc2a))
55
+ * **android:** prevent app from loading if server.url is invalid ([d4a0dea](https://github.com/ionic-team/capacitor/commit/d4a0deaa37eda4476f0be030e266c2c1260fc6e8))
56
+
57
+
58
+ ### Features
59
+
60
+ * **android:** don't allow server.androidScheme to be set to schemes handled by WebView ([01285ba](https://github.com/ionic-team/capacitor/commit/01285ba253d602b08a41240ad2ccf370730d51a3))
61
+ * **android:** set default targetSDK to 31 ([#5442](https://github.com/ionic-team/capacitor/issues/5442)) ([4442459](https://github.com/ionic-team/capacitor/commit/4442459b24cdbac25cb1e4de11583d22c21452b3))
62
+ * **android:** set default targetSDK to 32 ([#5611](https://github.com/ionic-team/capacitor/issues/5611)) ([416b966](https://github.com/ionic-team/capacitor/commit/416b9662fbf6233d23216c0c0441862603c3a723))
63
+ * **android:** Upgrade gradle to 7.4 ([#5445](https://github.com/ionic-team/capacitor/issues/5445)) ([28eaf18](https://github.com/ionic-team/capacitor/commit/28eaf1851fa7a912917dbb40c68fb4dd583d08ad))
64
+ * **android:** Use java 11 ([#5552](https://github.com/ionic-team/capacitor/issues/5552)) ([e47959f](https://github.com/ionic-team/capacitor/commit/e47959fcbd6a89b97b1275a5814fdb4e7ce30672))
65
+
66
+
67
+
68
+
69
+
70
+ # [3.6.0](https://github.com/ionic-team/capacitor/compare/3.5.1...3.6.0) (2022-06-17)
71
+
72
+
73
+ ### Features
74
+
75
+ * **android:** update support for Portals for Capacitor to include Live Updates ([#5660](https://github.com/ionic-team/capacitor/issues/5660)) ([62f0a5e](https://github.com/ionic-team/capacitor/commit/62f0a5eaa40776aad79dbf8f8c0900037d3cc97e))
76
+ * **iOS, Android:** add AppUUID Lib for plugins ([#5690](https://github.com/ionic-team/capacitor/issues/5690)) ([05e76cf](https://github.com/ionic-team/capacitor/commit/05e76cf526a44e07fa75f9482fa2223a13918638))
77
+
78
+
79
+
80
+ # [4.0.0-alpha.2](https://github.com/ionic-team/capacitor/compare/3.4.1...4.0.0-alpha.2) (2022-05-12)
81
+
82
+
83
+ ### Bug Fixes
84
+
85
+ * **android:** make removeAllListeners return a promise ([#5527](https://github.com/ionic-team/capacitor/issues/5527)) ([6f4d858](https://github.com/ionic-team/capacitor/commit/6f4d858ea879d97109c0c7da2d664d04806adc2a))
86
+ * **android:** prevent app from loading if server.url is invalid ([d4a0dea](https://github.com/ionic-team/capacitor/commit/d4a0deaa37eda4476f0be030e266c2c1260fc6e8))
87
+
88
+
89
+ ### Features
90
+
91
+ * **android:** don't allow server.androidScheme to be set to schemes handled by WebView ([01285ba](https://github.com/ionic-team/capacitor/commit/01285ba253d602b08a41240ad2ccf370730d51a3))
92
+ * **android:** set default targetSDK to 31 ([#5442](https://github.com/ionic-team/capacitor/issues/5442)) ([4442459](https://github.com/ionic-team/capacitor/commit/4442459b24cdbac25cb1e4de11583d22c21452b3))
93
+ * **android:** Upgrade gradle to 7.4 ([#5445](https://github.com/ionic-team/capacitor/issues/5445)) ([28eaf18](https://github.com/ionic-team/capacitor/commit/28eaf1851fa7a912917dbb40c68fb4dd583d08ad))
94
+ * **android:** Use java 11 ([#5552](https://github.com/ionic-team/capacitor/issues/5552)) ([e47959f](https://github.com/ionic-team/capacitor/commit/e47959fcbd6a89b97b1275a5814fdb4e7ce30672))
95
+
96
+
97
+
98
+
99
+ ## [3.5.1](https://github.com/ionic-team/capacitor/compare/3.5.0...3.5.1) (2022-05-04)
100
+
101
+
102
+ ### Bug Fixes
103
+
104
+ * **android:** move initialFocus on webview into config ([#5579](https://github.com/ionic-team/capacitor/issues/5579)) ([8b4e861](https://github.com/ionic-team/capacitor/commit/8b4e861514b0fbe08e9296f49c280234f54742e1))
105
+
106
+
107
+
108
+
109
+
110
+ # [3.5.0](https://github.com/ionic-team/capacitor/compare/3.4.3...3.5.0) (2022-04-22)
111
+
112
+
113
+ ### Features
114
+
115
+ * **android:** Add overridable routing for WebViewLocalServer ([#5553](https://github.com/ionic-team/capacitor/issues/5553)) ([3bb288e](https://github.com/ionic-team/capacitor/commit/3bb288e848c5c0e49c1e58c0782e0b1ffd7b1f31))
116
+
117
+
118
+
119
+ # [4.0.0-alpha.1](https://github.com/ionic-team/capacitor/compare/3.4.1...4.0.0-alpha.1) (2022-03-25)
7
120
 
8
121
 
9
122
  ### Features
@@ -13,6 +126,18 @@ See [Conventional Commits](https://conventionalcommits.org) for commit guideline
13
126
 
14
127
 
15
128
 
129
+ ## [3.4.3](https://github.com/ionic-team/capacitor/compare/3.4.2...3.4.3) (2022-03-04)
130
+
131
+ **Note:** Version bump only for package @capacitor/android
132
+
133
+
134
+
135
+
136
+
137
+ ## [3.4.2](https://github.com/ionic-team/capacitor/compare/3.4.1...3.4.2) (2022-03-03)
138
+
139
+ **Note:** Version bump only for package @capacitor/android
140
+
16
141
 
17
142
 
18
143
  ## [3.4.1](https://github.com/ionic-team/capacitor/compare/3.4.0...3.4.1) (2022-02-09)
@@ -1,9 +1,10 @@
1
1
  ext {
2
2
  androidxActivityVersion = project.hasProperty('androidxActivityVersion') ? rootProject.ext.androidxActivityVersion : '1.4.0'
3
- androidxAppCompatVersion = project.hasProperty('androidxAppCompatVersion') ? rootProject.ext.androidxAppCompatVersion : '1.4.1'
3
+ androidxAppCompatVersion = project.hasProperty('androidxAppCompatVersion') ? rootProject.ext.androidxAppCompatVersion : '1.4.2'
4
4
  androidxCoordinatorLayoutVersion = project.hasProperty('androidxCoordinatorLayoutVersion') ? rootProject.ext.androidxCoordinatorLayoutVersion : '1.2.0'
5
- androidxCoreVersion = project.hasProperty('androidxCoreVersion') ? rootProject.ext.androidxCoreVersion : '1.7.0'
5
+ androidxCoreVersion = project.hasProperty('androidxCoreVersion') ? rootProject.ext.androidxCoreVersion : '1.8.0'
6
6
  androidxFragmentVersion = project.hasProperty('androidxFragmentVersion') ? rootProject.ext.androidxFragmentVersion : '1.4.1'
7
+ androidxWebkitVersion = project.hasProperty('androidxWebkitVersion') ? rootProject.ext.androidxWebkitVersion : '1.4.0'
7
8
  junitVersion = project.hasProperty('junitVersion') ? rootProject.ext.junitVersion : '4.13.2'
8
9
  androidxJunitVersion = project.hasProperty('androidxJunitVersion') ? rootProject.ext.androidxJunitVersion : '1.1.3'
9
10
  androidxEspressoCoreVersion = project.hasProperty('androidxEspressoCoreVersion') ? rootProject.ext.androidxEspressoCoreVersion : '3.4.0'
@@ -17,7 +18,7 @@ buildscript {
17
18
  mavenCentral()
18
19
  }
19
20
  dependencies {
20
- classpath 'com.android.tools.build:gradle:7.1.1'
21
+ classpath 'com.android.tools.build:gradle:7.2.1'
21
22
  }
22
23
  }
23
24
 
@@ -26,10 +27,10 @@ tasks.withType(Javadoc).all { enabled = false }
26
27
  apply plugin: 'com.android.library'
27
28
 
28
29
  android {
29
- compileSdkVersion project.hasProperty('compileSdkVersion') ? rootProject.ext.compileSdkVersion : 31
30
+ compileSdkVersion project.hasProperty('compileSdkVersion') ? rootProject.ext.compileSdkVersion : 32
30
31
  defaultConfig {
31
32
  minSdkVersion project.hasProperty('minSdkVersion') ? rootProject.ext.minSdkVersion : 22
32
- targetSdkVersion project.hasProperty('targetSdkVersion') ? rootProject.ext.targetSdkVersion : 31
33
+ targetSdkVersion project.hasProperty('targetSdkVersion') ? rootProject.ext.targetSdkVersion : 32
33
34
  versionCode 1
34
35
  versionName "1.0"
35
36
  consumerProguardFiles 'proguard-rules.pro'
@@ -47,8 +48,8 @@ android {
47
48
  warningsAsErrors true
48
49
  }
49
50
  compileOptions {
50
- sourceCompatibility JavaVersion.VERSION_1_8
51
- targetCompatibility JavaVersion.VERSION_1_8
51
+ sourceCompatibility JavaVersion.VERSION_11
52
+ targetCompatibility JavaVersion.VERSION_11
52
53
  }
53
54
  }
54
55
 
@@ -64,6 +65,7 @@ dependencies {
64
65
  implementation "androidx.activity:activity:$androidxActivityVersion"
65
66
  implementation "androidx.fragment:fragment:$androidxFragmentVersion"
66
67
  implementation "androidx.coordinatorlayout:coordinatorlayout:$androidxCoordinatorLayoutVersion"
68
+ implementation "androidx.webkit:webkit:$androidxWebkitVersion"
67
69
  testImplementation "junit:junit:$junitVersion"
68
70
  androidTestImplementation "androidx.test.ext:junit:$androidxJunitVersion"
69
71
  androidTestImplementation "androidx.test.espresso:espresso-core:$androidxEspressoCoreVersion"
@@ -0,0 +1,26 @@
1
+ # Add project specific ProGuard rules here.
2
+ # You can control the set of applied configuration files using the
3
+ # proguardFiles setting in build.gradle.
4
+ #
5
+ # For more details, see
6
+ # http://developer.android.com/guide/developing/tools/proguard.html
7
+
8
+ # Rules for Capacitor v3 plugins and annotations
9
+ -keep @com.getcapacitor.annotation.CapacitorPlugin public class * {
10
+ @com.getcapacitor.annotation.PermissionCallback <methods>;
11
+ @com.getcapacitor.annotation.ActivityCallback <methods>;
12
+ @com.getcapacitor.annotation.Permission <methods>;
13
+ @com.getcapacitor.PluginMethod public <methods>;
14
+ }
15
+
16
+ # Rules for Capacitor v2 plugins and annotations
17
+ # These are deprecated but can still be used with Capacitor for now
18
+ -keep @com.getcapacitor.NativePlugin public class * {
19
+ @com.getcapacitor.PluginMethod public <methods>;
20
+ }
21
+
22
+ # Rules for Cordova plugins
23
+ -keep public class * extends org.apache.cordova.* {
24
+ public <methods>;
25
+ public <fields>;
26
+ }
@@ -384,10 +384,18 @@ const nativeBridge = (function (exports) {
384
384
  }
385
385
  return null;
386
386
  };
387
+ if (win === null || win === void 0 ? void 0 : win.androidBridge) {
388
+ win.androidBridge.onmessage = function (event) {
389
+ returnResult(JSON.parse(event.data));
390
+ };
391
+ }
387
392
  /**
388
393
  * Process a response from the native layer.
389
394
  */
390
395
  cap.fromNative = result => {
396
+ returnResult(result);
397
+ };
398
+ const returnResult = (result) => {
391
399
  var _a, _b;
392
400
  if (cap.isLoggingEnabled && result.pluginId !== 'Console') {
393
401
  cap.logFromNative(result);
@@ -0,0 +1,65 @@
1
+ package com.getcapacitor;
2
+
3
+ import android.content.Context;
4
+ import android.content.SharedPreferences;
5
+ import androidx.appcompat.app.AppCompatActivity;
6
+ import java.nio.charset.StandardCharsets;
7
+ import java.security.MessageDigest;
8
+ import java.security.NoSuchAlgorithmException;
9
+ import java.util.Objects;
10
+ import java.util.UUID;
11
+
12
+ public final class AppUUID {
13
+
14
+ private static final String KEY = "CapacitorAppUUID";
15
+
16
+ public static String getAppUUID(AppCompatActivity activity) throws Exception {
17
+ assertAppUUID(activity);
18
+ return readUUID(activity);
19
+ }
20
+
21
+ public static void regenerateAppUUID(AppCompatActivity activity) throws Exception {
22
+ try {
23
+ String uuid = generateUUID();
24
+ writeUUID(activity, uuid);
25
+ } catch (NoSuchAlgorithmException ex) {
26
+ throw new Exception("Capacitor App UUID could not be generated.");
27
+ }
28
+ }
29
+
30
+ private static void assertAppUUID(AppCompatActivity activity) throws Exception {
31
+ String uuid = readUUID(activity);
32
+ if (uuid.equals("")) {
33
+ regenerateAppUUID(activity);
34
+ }
35
+ }
36
+
37
+ private static String generateUUID() throws NoSuchAlgorithmException {
38
+ MessageDigest salt = MessageDigest.getInstance("SHA-256");
39
+ salt.update(UUID.randomUUID().toString().getBytes(StandardCharsets.UTF_8));
40
+ return bytesToHex(salt.digest());
41
+ }
42
+
43
+ private static String readUUID(AppCompatActivity activity) {
44
+ SharedPreferences sharedPref = activity.getPreferences(Context.MODE_PRIVATE);
45
+ return sharedPref.getString(KEY, "");
46
+ }
47
+
48
+ private static void writeUUID(AppCompatActivity activity, String uuid) {
49
+ SharedPreferences sharedPref = activity.getPreferences(Context.MODE_PRIVATE);
50
+ SharedPreferences.Editor editor = sharedPref.edit();
51
+ editor.putString(KEY, uuid);
52
+ editor.apply();
53
+ }
54
+
55
+ private static String bytesToHex(byte[] bytes) {
56
+ byte[] HEX_ARRAY = "0123456789ABCDEF".getBytes(StandardCharsets.US_ASCII);
57
+ byte[] hexChars = new byte[bytes.length * 2];
58
+ for (int j = 0; j < bytes.length; j++) {
59
+ int v = bytes[j] & 0xFF;
60
+ hexChars[j * 2] = HEX_ARRAY[v >>> 4];
61
+ hexChars[j * 2 + 1] = HEX_ARRAY[v & 0x0F];
62
+ }
63
+ return new String(hexChars, StandardCharsets.UTF_8);
64
+ }
65
+ }
@@ -1,5 +1,6 @@
1
1
  package com.getcapacitor;
2
2
 
3
+ import android.annotation.SuppressLint;
3
4
  import android.app.Activity;
4
5
  import android.content.ActivityNotFoundException;
5
6
  import android.content.Context;
@@ -10,6 +11,7 @@ import android.content.pm.PackageInfo;
10
11
  import android.content.pm.PackageManager;
11
12
  import android.content.res.Configuration;
12
13
  import android.net.Uri;
14
+ import android.os.Build;
13
15
  import android.os.Bundle;
14
16
  import android.os.Handler;
15
17
  import android.os.HandlerThread;
@@ -22,6 +24,7 @@ import androidx.activity.result.contract.ActivityResultContract;
22
24
  import androidx.annotation.NonNull;
23
25
  import androidx.appcompat.app.AppCompatActivity;
24
26
  import androidx.core.app.ActivityCompat;
27
+ import androidx.core.content.pm.PackageInfoCompat;
25
28
  import androidx.fragment.app.Fragment;
26
29
  import com.getcapacitor.android.R;
27
30
  import com.getcapacitor.annotation.CapacitorPlugin;
@@ -37,9 +40,11 @@ import java.net.URL;
37
40
  import java.util.ArrayList;
38
41
  import java.util.Arrays;
39
42
  import java.util.HashMap;
43
+ import java.util.HashSet;
40
44
  import java.util.LinkedList;
41
45
  import java.util.List;
42
46
  import java.util.Map;
47
+ import java.util.Set;
43
48
  import org.apache.cordova.ConfigXmlParser;
44
49
  import org.apache.cordova.CordovaPreferences;
45
50
  import org.apache.cordova.CordovaWebView;
@@ -72,6 +77,7 @@ public class Bridge {
72
77
  private static final String BUNDLE_PLUGIN_CALL_BUNDLE_KEY = "capacitorLastPluginCallBundle";
73
78
  private static final String LAST_BINARY_VERSION_CODE = "lastBinaryVersionCode";
74
79
  private static final String LAST_BINARY_VERSION_NAME = "lastBinaryVersionName";
80
+ private static final String MINIMUM_ANDROID_WEBVIEW_ERROR = "System WebView is not supported";
75
81
 
76
82
  // The name of the directory we use to look for index.html and the rest of our web assets
77
83
  public static final String DEFAULT_WEB_ASSET_DIR = "public";
@@ -79,6 +85,8 @@ public class Bridge {
79
85
  public static final String CAPACITOR_HTTPS_SCHEME = "https";
80
86
  public static final String CAPACITOR_FILE_START = "/_capacitor_file_";
81
87
  public static final String CAPACITOR_CONTENT_START = "/_capacitor_content_";
88
+ public static final int DEFAULT_ANDROID_WEBVIEW_VERSION = 60;
89
+ public static final int MINIMUM_ANDROID_WEBVIEW_VERSION = 55;
82
90
 
83
91
  // Loaded Capacitor config
84
92
  private CapConfig config;
@@ -92,6 +100,7 @@ public class Bridge {
92
100
  private String appUrl;
93
101
  private String appUrlConfig;
94
102
  private HostMask appAllowNavigationMask;
103
+ private Set<String> allowedOriginRules = new HashSet<String>();
95
104
  // A reference to the main WebView for the app
96
105
  private final WebView webView;
97
106
  public final MockCordovaInterfaceImpl cordovaInterface;
@@ -130,6 +139,9 @@ public class Bridge {
130
139
  // A list of listeners that trigger when webView events occur
131
140
  private List<WebViewListener> webViewListeners = new ArrayList<>();
132
141
 
142
+ // An interface to manipulate route resolving
143
+ private RouteProcessor routeProcessor;
144
+
133
145
  /**
134
146
  * Create the Bridge with a reference to the main {@link Activity} for the
135
147
  * app, and a reference to the {@link WebView} our app will use.
@@ -178,6 +190,7 @@ public class Bridge {
178
190
 
179
191
  // Initialize web view and message handler for it
180
192
  this.initWebView();
193
+ this.setAllowedOriginRules();
181
194
  this.msgHandler = new MessageHandler(this, webView, pluginManager);
182
195
 
183
196
  // Grab any intent info that our app was launched with
@@ -190,6 +203,25 @@ public class Bridge {
190
203
  this.loadWebView();
191
204
  }
192
205
 
206
+ private void setAllowedOriginRules() {
207
+ String[] appAllowNavigationConfig = this.config.getAllowNavigation();
208
+ String authority = this.getHost();
209
+ String scheme = this.getScheme();
210
+ allowedOriginRules.add(scheme + "://" + authority);
211
+ if (this.getServerUrl() != null) {
212
+ allowedOriginRules.add(this.getServerUrl());
213
+ }
214
+ if (appAllowNavigationConfig != null) {
215
+ for (String allowNavigation : appAllowNavigationConfig) {
216
+ if (!allowNavigation.startsWith("http")) {
217
+ allowedOriginRules.add("https://" + allowNavigation);
218
+ } else {
219
+ allowedOriginRules.add(allowNavigation);
220
+ }
221
+ }
222
+ }
223
+ }
224
+
193
225
  public App getApp() {
194
226
  return app;
195
227
  }
@@ -199,14 +231,13 @@ public class Bridge {
199
231
  String[] appAllowNavigationConfig = this.config.getAllowNavigation();
200
232
 
201
233
  ArrayList<String> authorities = new ArrayList<>();
234
+
202
235
  if (appAllowNavigationConfig != null) {
203
236
  authorities.addAll(Arrays.asList(appAllowNavigationConfig));
204
237
  }
205
238
  this.appAllowNavigationMask = HostMask.Parser.parse(appAllowNavigationConfig);
206
-
207
239
  String authority = this.getHost();
208
240
  authorities.add(authority);
209
-
210
241
  String scheme = this.getScheme();
211
242
 
212
243
  localUrl = scheme + "://" + authority;
@@ -215,7 +246,10 @@ public class Bridge {
215
246
  try {
216
247
  URL appUrlObject = new URL(appUrlConfig);
217
248
  authorities.add(appUrlObject.getAuthority());
218
- } catch (Exception ex) {}
249
+ } catch (Exception ex) {
250
+ Logger.error("Provided server url is invalid: " + ex.getMessage());
251
+ return;
252
+ }
219
253
  localUrl = appUrlConfig;
220
254
  appUrl = appUrlConfig;
221
255
  } else {
@@ -230,7 +264,6 @@ public class Bridge {
230
264
  if (appUrlPath != null && !appUrlPath.trim().isEmpty()) {
231
265
  appUrl += appUrlPath;
232
266
  }
233
-
234
267
  final boolean html5mode = this.config.isHTML5Mode();
235
268
 
236
269
  // Start the local web server
@@ -250,10 +283,60 @@ public class Bridge {
250
283
  setServerBasePath(path);
251
284
  }
252
285
  }
286
+
287
+ if (!this.isMinimumWebViewInstalled()) {
288
+ String errorUrl = this.getErrorUrl();
289
+ if (errorUrl != null) {
290
+ webView.loadUrl(errorUrl);
291
+ return;
292
+ } else {
293
+ Logger.error(MINIMUM_ANDROID_WEBVIEW_ERROR);
294
+ }
295
+ }
296
+
253
297
  // Get to work
254
298
  webView.loadUrl(appUrl);
255
299
  }
256
300
 
301
+ @SuppressLint("WebViewApiAvailability")
302
+ public boolean isMinimumWebViewInstalled() {
303
+ PackageManager pm = getContext().getPackageManager();
304
+
305
+ // Check getCurrentWebViewPackage() directly if above Android 8
306
+ if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
307
+ PackageInfo info = WebView.getCurrentWebViewPackage();
308
+ String majorVersionStr = info.versionName.split("\\.")[0];
309
+ int majorVersion = Integer.parseInt(majorVersionStr);
310
+ return majorVersion >= config.getMinWebViewVersion();
311
+ }
312
+
313
+ // Otherwise manually check WebView versions
314
+ try {
315
+ String webViewPackage = "com.google.android.webview";
316
+ if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N) {
317
+ webViewPackage = "com.android.chrome";
318
+ }
319
+ PackageInfo info = pm.getPackageInfo(webViewPackage, 0);
320
+ String majorVersionStr = info.versionName.split("\\.")[0];
321
+ int majorVersion = Integer.parseInt(majorVersionStr);
322
+ return majorVersion >= config.getMinWebViewVersion();
323
+ } catch (Exception ex) {
324
+ Logger.warn("Unable to get package info for 'com.google.android.webview'" + ex.toString());
325
+ }
326
+
327
+ try {
328
+ PackageInfo info = pm.getPackageInfo("com.android.webview", 0);
329
+ String majorVersionStr = info.versionName.split("\\.")[0];
330
+ int majorVersion = Integer.parseInt(majorVersionStr);
331
+ return majorVersion >= config.getMinWebViewVersion();
332
+ } catch (Exception ex) {
333
+ Logger.warn("Unable to get package info for 'com.android.webview'" + ex.toString());
334
+ }
335
+
336
+ // Could not detect any webview, return false
337
+ return false;
338
+ }
339
+
257
340
  public boolean launchIntent(Uri url) {
258
341
  /*
259
342
  * Give plugins the chance to handle the url
@@ -290,7 +373,7 @@ public class Bridge {
290
373
 
291
374
  try {
292
375
  PackageInfo pInfo = getContext().getPackageManager().getPackageInfo(getContext().getPackageName(), 0);
293
- versionCode = Integer.toString(pInfo.versionCode);
376
+ versionCode = Integer.toString((int) PackageInfoCompat.getLongVersionCode(pInfo));
294
377
  versionName = pInfo.versionName;
295
378
  } catch (Exception ex) {
296
379
  Logger.error("Unable to get package info", ex);
@@ -401,6 +484,25 @@ public class Bridge {
401
484
  return this.config.getServerUrl();
402
485
  }
403
486
 
487
+ public String getErrorUrl() {
488
+ String errorPath = this.config.getErrorPath();
489
+
490
+ if (errorPath != null && !errorPath.trim().isEmpty()) {
491
+ String authority = this.getHost();
492
+ String scheme = this.getScheme();
493
+
494
+ String localUrl = scheme + "://" + authority;
495
+
496
+ return localUrl + "/" + errorPath;
497
+ }
498
+
499
+ return null;
500
+ }
501
+
502
+ public String getAppUrl() {
503
+ return appUrl;
504
+ }
505
+
404
506
  public CapConfig getConfig() {
405
507
  return this.config;
406
508
  }
@@ -418,7 +520,6 @@ public class Bridge {
418
520
  settings.setDomStorageEnabled(true);
419
521
  settings.setGeolocationEnabled(true);
420
522
  settings.setDatabaseEnabled(true);
421
- settings.setAppCacheEnabled(true);
422
523
  settings.setMediaPlaybackRequiresUserGesture(false);
423
524
  settings.setJavaScriptCanOpenWindowsAutomatically(true);
424
525
  if (this.config.isMixedContentAllowed()) {
@@ -444,7 +545,10 @@ public class Bridge {
444
545
  Logger.debug("WebView background color not applied");
445
546
  }
446
547
 
447
- webView.requestFocusFromTouch();
548
+ if (config.isInitialFocus()) {
549
+ webView.requestFocusFromTouch();
550
+ }
551
+
448
552
  WebView.setWebContentsDebuggingEnabled(this.config.isWebContentsDebuggingEnabled());
449
553
  }
450
554
 
@@ -469,6 +573,17 @@ public class Bridge {
469
573
  }
470
574
  }
471
575
 
576
+ @SuppressWarnings("deprecation")
577
+ private String getLegacyPluginName(Class<? extends Plugin> pluginClass) {
578
+ NativePlugin legacyPluginAnnotation = pluginClass.getAnnotation(NativePlugin.class);
579
+ if (legacyPluginAnnotation == null) {
580
+ Logger.error("Plugin doesn't have the @CapacitorPlugin annotation. Please add it");
581
+ return null;
582
+ }
583
+
584
+ return legacyPluginAnnotation.name();
585
+ }
586
+
472
587
  /**
473
588
  * Register a plugin class
474
589
  * @param pluginClass a class inheriting from Plugin
@@ -478,14 +593,10 @@ public class Bridge {
478
593
 
479
594
  CapacitorPlugin pluginAnnotation = pluginClass.getAnnotation(CapacitorPlugin.class);
480
595
  if (pluginAnnotation == null) {
481
- NativePlugin legacyPluginAnnotation = pluginClass.getAnnotation(NativePlugin.class);
482
-
483
- if (legacyPluginAnnotation == null) {
484
- Logger.error("Plugin doesn't have the @CapacitorPlugin annotation. Please add it");
596
+ pluginName = this.getLegacyPluginName(pluginClass);
597
+ if (pluginName == null) {
485
598
  return;
486
599
  }
487
-
488
- pluginName = legacyPluginAnnotation.name();
489
600
  } else {
490
601
  pluginName = pluginAnnotation.name();
491
602
  }
@@ -524,6 +635,7 @@ public class Bridge {
524
635
  * @return
525
636
  */
526
637
  @Deprecated
638
+ @SuppressWarnings("deprecation")
527
639
  public PluginHandle getPluginWithRequestCode(int requestCode) {
528
640
  for (PluginHandle handle : this.plugins.values()) {
529
641
  int[] requestCodes;
@@ -839,6 +951,7 @@ public class Bridge {
839
951
  }
840
952
 
841
953
  @Deprecated
954
+ @SuppressWarnings("deprecation")
842
955
  public void startActivityForPluginWithResult(PluginCall call, Intent intent, int requestCode) {
843
956
  Logger.debug("Starting activity for result");
844
957
 
@@ -856,6 +969,7 @@ public class Bridge {
856
969
  * @param grantResults the set of granted/denied permissions
857
970
  * @return true if permission code was handled by a plugin explicitly, false if not
858
971
  */
972
+ @SuppressWarnings("deprecation")
859
973
  boolean onRequestPermissionsResult(int requestCode, String[] permissions, int[] grantResults) {
860
974
  PluginHandle plugin = getPluginWithRequestCode(requestCode);
861
975
 
@@ -995,6 +1109,7 @@ public class Bridge {
995
1109
  * @param resultCode
996
1110
  * @param data
997
1111
  */
1112
+ @SuppressWarnings("deprecation")
998
1113
  boolean onActivityResult(int requestCode, int resultCode, Intent data) {
999
1114
  PluginHandle plugin = getPluginWithRequestCode(requestCode);
1000
1115
 
@@ -1174,6 +1289,10 @@ public class Bridge {
1174
1289
  return appAllowNavigationMask;
1175
1290
  }
1176
1291
 
1292
+ public Set<String> getAllowedOriginRules() {
1293
+ return allowedOriginRules;
1294
+ }
1295
+
1177
1296
  public BridgeWebViewClient getWebViewClient() {
1178
1297
  return this.webViewClient;
1179
1298
  }
@@ -1190,6 +1309,14 @@ public class Bridge {
1190
1309
  this.webViewListeners = webViewListeners;
1191
1310
  }
1192
1311
 
1312
+ RouteProcessor getRouteProcessor() {
1313
+ return routeProcessor;
1314
+ }
1315
+
1316
+ void setRouteProcessor(RouteProcessor routeProcessor) {
1317
+ this.routeProcessor = routeProcessor;
1318
+ }
1319
+
1193
1320
  /**
1194
1321
  * Add a listener that the WebViewClient can trigger on certain events.
1195
1322
  * @param webViewListener A {@link WebViewListener} to add.
@@ -1213,6 +1340,7 @@ public class Bridge {
1213
1340
  private List<Class<? extends Plugin>> plugins = new ArrayList<>();
1214
1341
  private AppCompatActivity activity;
1215
1342
  private Fragment fragment;
1343
+ private RouteProcessor routeProcessor;
1216
1344
  private final List<WebViewListener> webViewListeners = new ArrayList<>();
1217
1345
 
1218
1346
  public Builder(AppCompatActivity activity) {
@@ -1265,6 +1393,11 @@ public class Bridge {
1265
1393
  return this;
1266
1394
  }
1267
1395
 
1396
+ public Builder setRouteProcessor(RouteProcessor routeProcessor) {
1397
+ this.routeProcessor = routeProcessor;
1398
+ return this;
1399
+ }
1400
+
1268
1401
  public Bridge create() {
1269
1402
  // Cordova initialization
1270
1403
  ConfigXmlParser parser = new ConfigXmlParser();
@@ -1288,6 +1421,7 @@ public class Bridge {
1288
1421
  Bridge bridge = new Bridge(activity, fragment, webView, plugins, cordovaInterface, pluginManager, preferences, config);
1289
1422
  bridge.setCordovaWebView(mockWebView);
1290
1423
  bridge.setWebViewListeners(webViewListeners);
1424
+ bridge.setRouteProcessor(routeProcessor);
1291
1425
 
1292
1426
  if (instanceState != null) {
1293
1427
  bridge.restoreInstanceState(instanceState);