@capacitor/android 4.0.1-alpha.0 → 4.0.2-nightly-76f28e70.0
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.
- package/CHANGELOG.md +126 -1
- package/capacitor/build.gradle +9 -7
- package/capacitor/proguard-rules.pro +26 -0
- package/capacitor/src/main/assets/native-bridge.js +8 -0
- package/capacitor/src/main/java/com/getcapacitor/AppUUID.java +65 -0
- package/capacitor/src/main/java/com/getcapacitor/Bridge.java +147 -13
- package/capacitor/src/main/java/com/getcapacitor/BridgeActivity.java +11 -54
- package/capacitor/src/main/java/com/getcapacitor/BridgeWebChromeClient.java +4 -5
- package/capacitor/src/main/java/com/getcapacitor/BridgeWebViewClient.java +11 -0
- package/capacitor/src/main/java/com/getcapacitor/CapConfig.java +65 -2
- package/capacitor/src/main/java/com/getcapacitor/CapacitorWebView.java +1 -0
- package/capacitor/src/main/java/com/getcapacitor/FileUtils.java +6 -1
- package/capacitor/src/main/java/com/getcapacitor/JSExport.java +1 -1
- package/capacitor/src/main/java/com/getcapacitor/MessageHandler.java +31 -4
- package/capacitor/src/main/java/com/getcapacitor/Plugin.java +16 -10
- package/capacitor/src/main/java/com/getcapacitor/PluginCall.java +28 -9
- package/capacitor/src/main/java/com/getcapacitor/PluginHandle.java +4 -0
- package/capacitor/src/main/java/com/getcapacitor/ProcessedRoute.java +28 -0
- package/capacitor/src/main/java/com/getcapacitor/RouteProcessor.java +8 -0
- package/capacitor/src/main/java/com/getcapacitor/WebViewLocalServer.java +27 -5
- package/capacitor/src/main/java/com/getcapacitor/cordova/CapacitorCordovaCookieManager.java +1 -2
- package/capacitor/src/main/java/com/getcapacitor/cordova/MockCordovaWebViewImpl.java +5 -0
- package/capacitor/src/main/res/values/colors.xml +4 -4
- package/capacitor/src/main/res/values/strings.xml +0 -5
- package/capacitor/src/main/res/values/styles.xml +0 -9
- package/package.json +4 -3
- 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
|
|
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)
|
package/capacitor/build.gradle
CHANGED
|
@@ -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.
|
|
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.
|
|
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.
|
|
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 :
|
|
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 :
|
|
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.
|
|
51
|
-
targetCompatibility JavaVersion.
|
|
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
|
|
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
|
-
|
|
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
|
-
|
|
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);
|