@capacitor/android 5.5.2-nightly-20231108T150443.0 → 5.7.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/capacitor/build.gradle +9 -9
- package/capacitor/src/main/assets/native-bridge.js +73 -9
- package/capacitor/src/main/java/com/getcapacitor/Bridge.java +17 -3
- package/capacitor/src/main/java/com/getcapacitor/CapConfig.java +11 -17
- package/capacitor/src/main/java/com/getcapacitor/PluginCall.java +7 -0
- package/capacitor/src/main/java/com/getcapacitor/plugin/CapacitorCookies.java +40 -25
- package/capacitor/src/main/java/com/getcapacitor/plugin/CapacitorHttp.java +18 -9
- package/capacitor/src/main/java/com/getcapacitor/plugin/WebView.java +7 -0
- package/capacitor/src/main/java/com/getcapacitor/plugin/util/CapacitorHttpUrlConnection.java +26 -0
- package/package.json +2 -2
package/capacitor/build.gradle
CHANGED
|
@@ -1,10 +1,10 @@
|
|
|
1
1
|
ext {
|
|
2
|
-
androidxActivityVersion = project.hasProperty('androidxActivityVersion') ? rootProject.ext.androidxActivityVersion : '1.
|
|
2
|
+
androidxActivityVersion = project.hasProperty('androidxActivityVersion') ? rootProject.ext.androidxActivityVersion : '1.7.0'
|
|
3
3
|
androidxAppCompatVersion = project.hasProperty('androidxAppCompatVersion') ? rootProject.ext.androidxAppCompatVersion : '1.6.1'
|
|
4
4
|
androidxCoordinatorLayoutVersion = project.hasProperty('androidxCoordinatorLayoutVersion') ? rootProject.ext.androidxCoordinatorLayoutVersion : '1.2.0'
|
|
5
|
-
androidxCoreVersion = project.hasProperty('androidxCoreVersion') ? rootProject.ext.androidxCoreVersion : '1.10.
|
|
6
|
-
androidxFragmentVersion = project.hasProperty('androidxFragmentVersion') ? rootProject.ext.androidxFragmentVersion : '1.6
|
|
7
|
-
androidxWebkitVersion = project.hasProperty('androidxWebkitVersion') ? rootProject.ext.androidxWebkitVersion : '1.
|
|
5
|
+
androidxCoreVersion = project.hasProperty('androidxCoreVersion') ? rootProject.ext.androidxCoreVersion : '1.10.0'
|
|
6
|
+
androidxFragmentVersion = project.hasProperty('androidxFragmentVersion') ? rootProject.ext.androidxFragmentVersion : '1.5.6'
|
|
7
|
+
androidxWebkitVersion = project.hasProperty('androidxWebkitVersion') ? rootProject.ext.androidxWebkitVersion : '1.6.1'
|
|
8
8
|
junitVersion = project.hasProperty('junitVersion') ? rootProject.ext.junitVersion : '4.13.2'
|
|
9
9
|
androidxJunitVersion = project.hasProperty('androidxJunitVersion') ? rootProject.ext.androidxJunitVersion : '1.1.5'
|
|
10
10
|
androidxEspressoCoreVersion = project.hasProperty('androidxEspressoCoreVersion') ? rootProject.ext.androidxEspressoCoreVersion : '3.5.1'
|
|
@@ -13,7 +13,7 @@ ext {
|
|
|
13
13
|
|
|
14
14
|
|
|
15
15
|
buildscript {
|
|
16
|
-
ext.kotlin_version = project.hasProperty("kotlin_version") ? rootProject.ext.kotlin_version : '1.
|
|
16
|
+
ext.kotlin_version = project.hasProperty("kotlin_version") ? rootProject.ext.kotlin_version : '1.8.20'
|
|
17
17
|
repositories {
|
|
18
18
|
google()
|
|
19
19
|
mavenCentral()
|
|
@@ -22,7 +22,7 @@ buildscript {
|
|
|
22
22
|
}
|
|
23
23
|
}
|
|
24
24
|
dependencies {
|
|
25
|
-
classpath 'com.android.tools.build:gradle:8.
|
|
25
|
+
classpath 'com.android.tools.build:gradle:8.0.0'
|
|
26
26
|
|
|
27
27
|
if (System.getenv("CAP_PUBLISH") == "true") {
|
|
28
28
|
classpath 'io.github.gradle-nexus:publish-plugin:1.3.0'
|
|
@@ -42,10 +42,10 @@ if (System.getenv("CAP_PUBLISH") == "true") {
|
|
|
42
42
|
|
|
43
43
|
android {
|
|
44
44
|
namespace "com.getcapacitor.android"
|
|
45
|
-
compileSdkVersion project.hasProperty('compileSdkVersion') ? rootProject.ext.compileSdkVersion :
|
|
45
|
+
compileSdkVersion project.hasProperty('compileSdkVersion') ? rootProject.ext.compileSdkVersion : 33
|
|
46
46
|
defaultConfig {
|
|
47
47
|
minSdkVersion project.hasProperty('minSdkVersion') ? rootProject.ext.minSdkVersion : 22
|
|
48
|
-
targetSdkVersion project.hasProperty('targetSdkVersion') ? rootProject.ext.targetSdkVersion :
|
|
48
|
+
targetSdkVersion project.hasProperty('targetSdkVersion') ? rootProject.ext.targetSdkVersion : 33
|
|
49
49
|
versionCode 1
|
|
50
50
|
versionName "1.0"
|
|
51
51
|
consumerProguardFiles 'proguard-rules.pro'
|
|
@@ -90,7 +90,7 @@ dependencies {
|
|
|
90
90
|
androidTestImplementation "androidx.test.ext:junit:$androidxJunitVersion"
|
|
91
91
|
androidTestImplementation "androidx.test.espresso:espresso-core:$androidxEspressoCoreVersion"
|
|
92
92
|
implementation "org.apache.cordova:framework:$cordovaAndroidVersion"
|
|
93
|
-
testImplementation 'org.json:json:
|
|
93
|
+
testImplementation 'org.json:json:20231013'
|
|
94
94
|
testImplementation 'org.mockito:mockito-inline:5.2.0'
|
|
95
95
|
}
|
|
96
96
|
|
|
@@ -64,8 +64,52 @@ var nativeBridge = (function (exports) {
|
|
|
64
64
|
}
|
|
65
65
|
return newFormData;
|
|
66
66
|
};
|
|
67
|
-
const convertBody = async (body) => {
|
|
68
|
-
if (body instanceof
|
|
67
|
+
const convertBody = async (body, contentType) => {
|
|
68
|
+
if (body instanceof ReadableStream) {
|
|
69
|
+
const reader = body.getReader();
|
|
70
|
+
const chunks = [];
|
|
71
|
+
while (true) {
|
|
72
|
+
const { done, value } = await reader.read();
|
|
73
|
+
if (done)
|
|
74
|
+
break;
|
|
75
|
+
chunks.push(value);
|
|
76
|
+
}
|
|
77
|
+
const concatenated = new Uint8Array(chunks.reduce((acc, chunk) => acc + chunk.length, 0));
|
|
78
|
+
let position = 0;
|
|
79
|
+
for (const chunk of chunks) {
|
|
80
|
+
concatenated.set(chunk, position);
|
|
81
|
+
position += chunk.length;
|
|
82
|
+
}
|
|
83
|
+
let data = new TextDecoder().decode(concatenated);
|
|
84
|
+
let type;
|
|
85
|
+
if (contentType === 'application/json') {
|
|
86
|
+
try {
|
|
87
|
+
data = JSON.parse(data);
|
|
88
|
+
}
|
|
89
|
+
catch (ignored) {
|
|
90
|
+
// ignore
|
|
91
|
+
}
|
|
92
|
+
type = 'json';
|
|
93
|
+
}
|
|
94
|
+
else if (contentType === 'multipart/form-data') {
|
|
95
|
+
type = 'formData';
|
|
96
|
+
}
|
|
97
|
+
else if (contentType === null || contentType === void 0 ? void 0 : contentType.startsWith('image')) {
|
|
98
|
+
type = 'image';
|
|
99
|
+
}
|
|
100
|
+
else if (contentType === 'application/octet-stream') {
|
|
101
|
+
type = 'binary';
|
|
102
|
+
}
|
|
103
|
+
else {
|
|
104
|
+
type = 'text';
|
|
105
|
+
}
|
|
106
|
+
return {
|
|
107
|
+
data,
|
|
108
|
+
type,
|
|
109
|
+
headers: { 'Content-Type': contentType || 'application/octet-stream' },
|
|
110
|
+
};
|
|
111
|
+
}
|
|
112
|
+
else if (body instanceof FormData) {
|
|
69
113
|
const formData = await convertFormData(body);
|
|
70
114
|
const boundary = `${Date.now()}`;
|
|
71
115
|
return {
|
|
@@ -235,6 +279,10 @@ var nativeBridge = (function (exports) {
|
|
|
235
279
|
callback(result.path);
|
|
236
280
|
});
|
|
237
281
|
};
|
|
282
|
+
IonicWebView.setServerAssetPath = (path) => {
|
|
283
|
+
var _a;
|
|
284
|
+
(_a = Plugins === null || Plugins === void 0 ? void 0 : Plugins.WebView) === null || _a === void 0 ? void 0 : _a.setServerAssetPath({ path });
|
|
285
|
+
};
|
|
238
286
|
IonicWebView.setServerBasePath = (path) => {
|
|
239
287
|
var _a;
|
|
240
288
|
(_a = Plugins === null || Plugins === void 0 ? void 0 : Plugins.WebView) === null || _a === void 0 ? void 0 : _a.setServerBasePath({ path });
|
|
@@ -431,9 +479,10 @@ var nativeBridge = (function (exports) {
|
|
|
431
479
|
const tag = `CapacitorHttp fetch ${Date.now()} ${resource}`;
|
|
432
480
|
console.time(tag);
|
|
433
481
|
try {
|
|
482
|
+
// intercept request & pass to the bridge
|
|
434
483
|
const { body, method } = request;
|
|
435
|
-
const { data: requestData, type, headers, } = await convertBody(body || undefined);
|
|
436
484
|
const optionHeaders = Object.fromEntries(request.headers.entries());
|
|
485
|
+
const { data: requestData, type, headers, } = await convertBody((options === null || options === void 0 ? void 0 : options.body) || body || undefined, optionHeaders['Content-Type'] || optionHeaders['content-type']);
|
|
437
486
|
const nativeResponse = await cap.nativePromise('CapacitorHttp', 'request', {
|
|
438
487
|
url: request.url,
|
|
439
488
|
method: method,
|
|
@@ -584,12 +633,22 @@ var nativeBridge = (function (exports) {
|
|
|
584
633
|
}
|
|
585
634
|
this._headers = nativeResponse.headers;
|
|
586
635
|
this.status = nativeResponse.status;
|
|
636
|
+
const responseString = typeof nativeResponse.data !== 'string'
|
|
637
|
+
? JSON.stringify(nativeResponse.data)
|
|
638
|
+
: nativeResponse.data;
|
|
587
639
|
if (this.responseType === '' ||
|
|
588
640
|
this.responseType === 'text') {
|
|
589
|
-
this.response =
|
|
590
|
-
|
|
591
|
-
|
|
592
|
-
|
|
641
|
+
this.response = responseString;
|
|
642
|
+
}
|
|
643
|
+
else if (this.responseType === 'blob') {
|
|
644
|
+
this.response = new Blob([responseString], {
|
|
645
|
+
type: 'application/json',
|
|
646
|
+
});
|
|
647
|
+
}
|
|
648
|
+
else if (this.responseType === 'arraybuffer') {
|
|
649
|
+
const encoder = new TextEncoder();
|
|
650
|
+
const uint8Array = encoder.encode(responseString);
|
|
651
|
+
this.response = uint8Array.buffer;
|
|
593
652
|
}
|
|
594
653
|
else {
|
|
595
654
|
this.response = nativeResponse.data;
|
|
@@ -656,7 +715,7 @@ var nativeBridge = (function (exports) {
|
|
|
656
715
|
}
|
|
657
716
|
let returnString = '';
|
|
658
717
|
for (const key in this._headers) {
|
|
659
|
-
if (key
|
|
718
|
+
if (key.toLowerCase() !== 'set-cookie') {
|
|
660
719
|
returnString += key + ': ' + this._headers[key] + '\r\n';
|
|
661
720
|
}
|
|
662
721
|
}
|
|
@@ -667,7 +726,12 @@ var nativeBridge = (function (exports) {
|
|
|
667
726
|
if (isRelativeURL(this._url)) {
|
|
668
727
|
return win.CapacitorWebXMLHttpRequest.getResponseHeader.call(this, name);
|
|
669
728
|
}
|
|
670
|
-
|
|
729
|
+
for (const key in this._headers) {
|
|
730
|
+
if (key.toLowerCase() === name.toLowerCase()) {
|
|
731
|
+
return this._headers[key];
|
|
732
|
+
}
|
|
733
|
+
}
|
|
734
|
+
return null;
|
|
671
735
|
};
|
|
672
736
|
Object.setPrototypeOf(xhr, prototype);
|
|
673
737
|
return xhr;
|
|
@@ -329,10 +329,27 @@ public class Bridge {
|
|
|
329
329
|
Logger.warn("Unable to get package info for 'com.android.webview'" + ex.toString());
|
|
330
330
|
}
|
|
331
331
|
|
|
332
|
+
final int amazonFireMajorWebViewVersion = extractWebViewMajorVersion(pm, "com.amazon.webview.chromium");
|
|
333
|
+
if (amazonFireMajorWebViewVersion >= config.getMinWebViewVersion()) {
|
|
334
|
+
return true;
|
|
335
|
+
}
|
|
336
|
+
|
|
332
337
|
// Could not detect any webview, return false
|
|
333
338
|
return false;
|
|
334
339
|
}
|
|
335
340
|
|
|
341
|
+
private int extractWebViewMajorVersion(final PackageManager pm, final String webViewPackageName) {
|
|
342
|
+
try {
|
|
343
|
+
final PackageInfo info = InternalUtils.getPackageInfo(pm, webViewPackageName);
|
|
344
|
+
final String majorVersionStr = info.versionName.split("\\.")[0];
|
|
345
|
+
final int majorVersion = Integer.parseInt(majorVersionStr);
|
|
346
|
+
return majorVersion;
|
|
347
|
+
} catch (Exception ex) {
|
|
348
|
+
Logger.warn(String.format("Unable to get package info for '%s' with err '%s'", webViewPackageName, ex));
|
|
349
|
+
}
|
|
350
|
+
return 0;
|
|
351
|
+
}
|
|
352
|
+
|
|
336
353
|
public boolean launchIntent(Uri url) {
|
|
337
354
|
/*
|
|
338
355
|
* Give plugins the chance to handle the url
|
|
@@ -551,9 +568,6 @@ public class Bridge {
|
|
|
551
568
|
Logger.debug("WebView background color not applied");
|
|
552
569
|
}
|
|
553
570
|
|
|
554
|
-
settings.setDisplayZoomControls(false);
|
|
555
|
-
settings.setBuiltInZoomControls(this.config.isZoomableWebView());
|
|
556
|
-
|
|
557
571
|
if (config.isInitialFocus()) {
|
|
558
572
|
webView.requestFocusFromTouch();
|
|
559
573
|
}
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
package com.getcapacitor;
|
|
2
2
|
|
|
3
|
-
import static com.getcapacitor.Bridge.
|
|
3
|
+
import static com.getcapacitor.Bridge.CAPACITOR_HTTP_SCHEME;
|
|
4
4
|
import static com.getcapacitor.Bridge.DEFAULT_ANDROID_WEBVIEW_VERSION;
|
|
5
5
|
import static com.getcapacitor.Bridge.DEFAULT_HUAWEI_WEBVIEW_VERSION;
|
|
6
6
|
import static com.getcapacitor.Bridge.MINIMUM_ANDROID_WEBVIEW_VERSION;
|
|
@@ -36,7 +36,7 @@ public class CapConfig {
|
|
|
36
36
|
private boolean html5mode = true;
|
|
37
37
|
private String serverUrl;
|
|
38
38
|
private String hostname = "localhost";
|
|
39
|
-
private String androidScheme =
|
|
39
|
+
private String androidScheme = CAPACITOR_HTTP_SCHEME;
|
|
40
40
|
private String[] allowNavigation;
|
|
41
41
|
|
|
42
42
|
// Android Config
|
|
@@ -52,7 +52,6 @@ public class CapConfig {
|
|
|
52
52
|
private int minWebViewVersion = DEFAULT_ANDROID_WEBVIEW_VERSION;
|
|
53
53
|
private int minHuaweiWebViewVersion = DEFAULT_HUAWEI_WEBVIEW_VERSION;
|
|
54
54
|
private String errorPath;
|
|
55
|
-
private boolean zoomableWebView = false;
|
|
56
55
|
|
|
57
56
|
// Embedded
|
|
58
57
|
private String startPath;
|
|
@@ -178,7 +177,6 @@ public class CapConfig {
|
|
|
178
177
|
this.minWebViewVersion = builder.minWebViewVersion;
|
|
179
178
|
this.minHuaweiWebViewVersion = builder.minHuaweiWebViewVersion;
|
|
180
179
|
this.errorPath = builder.errorPath;
|
|
181
|
-
this.zoomableWebView = builder.zoomableWebView;
|
|
182
180
|
|
|
183
181
|
// Embedded
|
|
184
182
|
this.startPath = builder.startPath;
|
|
@@ -273,7 +271,6 @@ public class CapConfig {
|
|
|
273
271
|
captureInput = JSONUtils.getBoolean(configJSON, "android.captureInput", captureInput);
|
|
274
272
|
useLegacyBridge = JSONUtils.getBoolean(configJSON, "android.useLegacyBridge", useLegacyBridge);
|
|
275
273
|
webContentsDebuggingEnabled = JSONUtils.getBoolean(configJSON, "android.webContentsDebuggingEnabled", isDebug);
|
|
276
|
-
zoomableWebView = JSONUtils.getBoolean(configJSON, "android.zoomEnabled", JSONUtils.getBoolean(configJSON, "zoomEnabled", false));
|
|
277
274
|
|
|
278
275
|
String logBehavior = JSONUtils.getString(
|
|
279
276
|
configJSON,
|
|
@@ -300,10 +297,17 @@ public class CapConfig {
|
|
|
300
297
|
private boolean validateScheme(String scheme) {
|
|
301
298
|
List<String> invalidSchemes = Arrays.asList("file", "ftp", "ftps", "ws", "wss", "about", "blob", "data");
|
|
302
299
|
if (invalidSchemes.contains(scheme)) {
|
|
303
|
-
Logger.warn(scheme + " is not an allowed scheme. Defaulting to
|
|
300
|
+
Logger.warn(scheme + " is not an allowed scheme. Defaulting to http.");
|
|
304
301
|
return false;
|
|
305
302
|
}
|
|
306
303
|
|
|
304
|
+
// Non-http(s) schemes are not allowed to modify the URL path as of Android Webview 117
|
|
305
|
+
if (!scheme.equals("http") && !scheme.equals("https")) {
|
|
306
|
+
Logger.warn(
|
|
307
|
+
"Using a non-standard scheme: " + scheme + " for Android. This is known to cause issues as of Android Webview 117."
|
|
308
|
+
);
|
|
309
|
+
}
|
|
310
|
+
|
|
307
311
|
return true;
|
|
308
312
|
}
|
|
309
313
|
|
|
@@ -359,10 +363,6 @@ public class CapConfig {
|
|
|
359
363
|
return webContentsDebuggingEnabled;
|
|
360
364
|
}
|
|
361
365
|
|
|
362
|
-
public boolean isZoomableWebView() {
|
|
363
|
-
return zoomableWebView;
|
|
364
|
-
}
|
|
365
|
-
|
|
366
366
|
public boolean isLoggingEnabled() {
|
|
367
367
|
return loggingEnabled;
|
|
368
368
|
}
|
|
@@ -538,7 +538,7 @@ public class CapConfig {
|
|
|
538
538
|
private String serverUrl;
|
|
539
539
|
private String errorPath;
|
|
540
540
|
private String hostname = "localhost";
|
|
541
|
-
private String androidScheme =
|
|
541
|
+
private String androidScheme = CAPACITOR_HTTP_SCHEME;
|
|
542
542
|
private String[] allowNavigation;
|
|
543
543
|
|
|
544
544
|
// Android Config Values
|
|
@@ -553,7 +553,6 @@ public class CapConfig {
|
|
|
553
553
|
private boolean useLegacyBridge = false;
|
|
554
554
|
private int minWebViewVersion = DEFAULT_ANDROID_WEBVIEW_VERSION;
|
|
555
555
|
private int minHuaweiWebViewVersion = DEFAULT_HUAWEI_WEBVIEW_VERSION;
|
|
556
|
-
private boolean zoomableWebView = false;
|
|
557
556
|
|
|
558
557
|
// Embedded
|
|
559
558
|
private String startPath = null;
|
|
@@ -658,11 +657,6 @@ public class CapConfig {
|
|
|
658
657
|
return this;
|
|
659
658
|
}
|
|
660
659
|
|
|
661
|
-
public Builder setZoomableWebView(boolean zoomableWebView) {
|
|
662
|
-
this.zoomableWebView = zoomableWebView;
|
|
663
|
-
return this;
|
|
664
|
-
}
|
|
665
|
-
|
|
666
660
|
public Builder setLoggingEnabled(boolean enabled) {
|
|
667
661
|
this.loggingEnabled = enabled;
|
|
668
662
|
return this;
|
|
@@ -370,6 +370,13 @@ public class PluginCall {
|
|
|
370
370
|
return defaultValue;
|
|
371
371
|
}
|
|
372
372
|
|
|
373
|
+
/**
|
|
374
|
+
* @param name of the option to check
|
|
375
|
+
* @return boolean indicating if the plugin call has an option for the provided name.
|
|
376
|
+
* @deprecated Presence of a key should not be considered significant.
|
|
377
|
+
* Use typed accessors to check the value instead.
|
|
378
|
+
*/
|
|
379
|
+
@Deprecated
|
|
373
380
|
public boolean hasOption(String name) {
|
|
374
381
|
return this.data.has(name);
|
|
375
382
|
}
|
|
@@ -39,6 +39,11 @@ public class CapacitorCookies extends Plugin {
|
|
|
39
39
|
return pluginConfig.getBoolean("enabled", false);
|
|
40
40
|
}
|
|
41
41
|
|
|
42
|
+
private boolean isAllowingInsecureCookies() {
|
|
43
|
+
PluginConfig pluginConfig = getBridge().getConfig().getPluginConfiguration("CapacitorCookies");
|
|
44
|
+
return pluginConfig.getBoolean("androidCustomSchemeAllowInsecureAccess", false);
|
|
45
|
+
}
|
|
46
|
+
|
|
42
47
|
@JavascriptInterface
|
|
43
48
|
public void setCookie(String domain, String action) {
|
|
44
49
|
cookieManager.setCookie(domain, action);
|
|
@@ -46,34 +51,44 @@ public class CapacitorCookies extends Plugin {
|
|
|
46
51
|
|
|
47
52
|
@PluginMethod
|
|
48
53
|
public void getCookies(PluginCall call) {
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
54
|
+
if (isAllowingInsecureCookies()) {
|
|
55
|
+
String url = call.getString("url");
|
|
56
|
+
JSObject cookiesMap = new JSObject();
|
|
57
|
+
HttpCookie[] cookies = cookieManager.getCookies(url);
|
|
58
|
+
for (HttpCookie cookie : cookies) {
|
|
59
|
+
cookiesMap.put(cookie.getName(), cookie.getValue());
|
|
60
|
+
}
|
|
61
|
+
call.resolve(cookiesMap);
|
|
62
|
+
} else {
|
|
63
|
+
this.bridge.eval(
|
|
64
|
+
"document.cookie",
|
|
65
|
+
value -> {
|
|
66
|
+
String cookies = value.substring(1, value.length() - 1);
|
|
67
|
+
String[] cookieArray = cookies.split(";");
|
|
68
|
+
|
|
69
|
+
JSObject cookieMap = new JSObject();
|
|
70
|
+
|
|
71
|
+
for (String cookie : cookieArray) {
|
|
72
|
+
if (cookie.length() > 0) {
|
|
73
|
+
String[] keyValue = cookie.split("=", 2);
|
|
74
|
+
|
|
75
|
+
if (keyValue.length == 2) {
|
|
76
|
+
String key = keyValue[0].trim();
|
|
77
|
+
String val = keyValue[1].trim();
|
|
78
|
+
try {
|
|
79
|
+
key = URLDecoder.decode(keyValue[0].trim(), StandardCharsets.UTF_8.name());
|
|
80
|
+
val = URLDecoder.decode(keyValue[1].trim(), StandardCharsets.UTF_8.name());
|
|
81
|
+
} catch (UnsupportedEncodingException ignored) {}
|
|
82
|
+
|
|
83
|
+
cookieMap.put(key, val);
|
|
84
|
+
}
|
|
70
85
|
}
|
|
71
86
|
}
|
|
72
|
-
}
|
|
73
87
|
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
88
|
+
call.resolve(cookieMap);
|
|
89
|
+
}
|
|
90
|
+
);
|
|
91
|
+
}
|
|
77
92
|
}
|
|
78
93
|
|
|
79
94
|
@PluginMethod
|
|
@@ -24,7 +24,7 @@ import java.util.concurrent.Executors;
|
|
|
24
24
|
)
|
|
25
25
|
public class CapacitorHttp extends Plugin {
|
|
26
26
|
|
|
27
|
-
private Map<Runnable, PluginCall> activeRequests = new HashMap<>();
|
|
27
|
+
private final Map<Runnable, PluginCall> activeRequests = new HashMap<>();
|
|
28
28
|
private final ExecutorService executor = Executors.newCachedThreadPool();
|
|
29
29
|
|
|
30
30
|
@Override
|
|
@@ -59,17 +59,26 @@ public class CapacitorHttp extends Plugin {
|
|
|
59
59
|
}
|
|
60
60
|
|
|
61
61
|
private void http(final PluginCall call, final String httpMethod) {
|
|
62
|
-
Runnable asyncHttpCall = ()
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
62
|
+
Runnable asyncHttpCall = new Runnable() {
|
|
63
|
+
@Override
|
|
64
|
+
public void run() {
|
|
65
|
+
try {
|
|
66
|
+
JSObject response = HttpRequestHandler.request(call, httpMethod, getBridge());
|
|
67
|
+
call.resolve(response);
|
|
68
|
+
} catch (Exception e) {
|
|
69
|
+
call.reject(e.getLocalizedMessage(), e.getClass().getSimpleName(), e);
|
|
70
|
+
} finally {
|
|
71
|
+
activeRequests.remove(this);
|
|
72
|
+
}
|
|
68
73
|
}
|
|
69
74
|
};
|
|
70
75
|
|
|
71
|
-
|
|
72
|
-
|
|
76
|
+
if (!executor.isShutdown()) {
|
|
77
|
+
activeRequests.put(asyncHttpCall, call);
|
|
78
|
+
executor.submit(asyncHttpCall);
|
|
79
|
+
} else {
|
|
80
|
+
call.reject("Failed to execute request - Http Plugin was shutdown");
|
|
81
|
+
}
|
|
73
82
|
}
|
|
74
83
|
|
|
75
84
|
@JavascriptInterface
|
|
@@ -14,6 +14,13 @@ public class WebView extends Plugin {
|
|
|
14
14
|
public static final String WEBVIEW_PREFS_NAME = "CapWebViewSettings";
|
|
15
15
|
public static final String CAP_SERVER_PATH = "serverBasePath";
|
|
16
16
|
|
|
17
|
+
@PluginMethod
|
|
18
|
+
public void setServerAssetPath(PluginCall call) {
|
|
19
|
+
String path = call.getString("path");
|
|
20
|
+
bridge.setServerAssetPath(path);
|
|
21
|
+
call.resolve();
|
|
22
|
+
}
|
|
23
|
+
|
|
17
24
|
@PluginMethod
|
|
18
25
|
public void setServerBasePath(PluginCall call) {
|
|
19
26
|
String path = call.getString("path");
|
package/capacitor/src/main/java/com/getcapacitor/plugin/util/CapacitorHttpUrlConnection.java
CHANGED
|
@@ -215,6 +215,14 @@ public class CapacitorHttpUrlConnection implements ICapacitorHttpUrlConnection {
|
|
|
215
215
|
}
|
|
216
216
|
os.flush();
|
|
217
217
|
}
|
|
218
|
+
} else if (contentType.contains("application/x-www-form-urlencoded")) {
|
|
219
|
+
try {
|
|
220
|
+
JSObject obj = body.toJSObject();
|
|
221
|
+
this.writeObjectRequestBody(obj);
|
|
222
|
+
} catch (Exception e) {
|
|
223
|
+
// Body is not a valid JSON, treat it as an already formatted string
|
|
224
|
+
this.writeRequestBody(body.toString());
|
|
225
|
+
}
|
|
218
226
|
} else if (bodyType != null && bodyType.equals("formData")) {
|
|
219
227
|
this.writeFormDataRequestBody(contentType, body.toJSArray());
|
|
220
228
|
} else {
|
|
@@ -234,6 +242,24 @@ public class CapacitorHttpUrlConnection implements ICapacitorHttpUrlConnection {
|
|
|
234
242
|
}
|
|
235
243
|
}
|
|
236
244
|
|
|
245
|
+
private void writeObjectRequestBody(JSObject object) throws IOException, JSONException {
|
|
246
|
+
try (DataOutputStream os = new DataOutputStream(connection.getOutputStream())) {
|
|
247
|
+
Iterator<String> keys = object.keys();
|
|
248
|
+
while (keys.hasNext()) {
|
|
249
|
+
String key = keys.next();
|
|
250
|
+
Object d = object.get(key);
|
|
251
|
+
os.writeBytes(key);
|
|
252
|
+
os.writeBytes("=");
|
|
253
|
+
os.writeBytes(URLEncoder.encode(d.toString(), "UTF-8"));
|
|
254
|
+
|
|
255
|
+
if (keys.hasNext()) {
|
|
256
|
+
os.writeBytes("&");
|
|
257
|
+
}
|
|
258
|
+
}
|
|
259
|
+
os.flush();
|
|
260
|
+
}
|
|
261
|
+
}
|
|
262
|
+
|
|
237
263
|
private void writeFormDataRequestBody(String contentType, JSArray entries) throws IOException, JSONException {
|
|
238
264
|
try (DataOutputStream os = new DataOutputStream(connection.getOutputStream())) {
|
|
239
265
|
String boundary = contentType.split(";")[1].split("=")[1];
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@capacitor/android",
|
|
3
|
-
"version": "5.
|
|
3
|
+
"version": "5.7.0",
|
|
4
4
|
"description": "Capacitor: Cross-platform apps with JavaScript and the web",
|
|
5
5
|
"homepage": "https://capacitorjs.com",
|
|
6
6
|
"author": "Ionic Team <hi@ionic.io> (https://ionic.io)",
|
|
@@ -23,7 +23,7 @@
|
|
|
23
23
|
"verify": "./gradlew clean lint build test -b capacitor/build.gradle"
|
|
24
24
|
},
|
|
25
25
|
"peerDependencies": {
|
|
26
|
-
"@capacitor/core": "^5.
|
|
26
|
+
"@capacitor/core": "^5.7.0"
|
|
27
27
|
},
|
|
28
28
|
"publishConfig": {
|
|
29
29
|
"access": "public"
|