@capacitor/android 8.0.0-alpha.2 → 8.0.0-beta.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.
@@ -1,28 +1,27 @@
1
1
  ext {
2
- androidxActivityVersion = project.hasProperty('androidxActivityVersion') ? rootProject.ext.androidxActivityVersion : '1.9.2'
3
- androidxAppCompatVersion = project.hasProperty('androidxAppCompatVersion') ? rootProject.ext.androidxAppCompatVersion : '1.7.0'
4
- androidxCoordinatorLayoutVersion = project.hasProperty('androidxCoordinatorLayoutVersion') ? rootProject.ext.androidxCoordinatorLayoutVersion : '1.2.0'
5
- androidxCoreVersion = project.hasProperty('androidxCoreVersion') ? rootProject.ext.androidxCoreVersion : '1.15.0'
6
- androidxFragmentVersion = project.hasProperty('androidxFragmentVersion') ? rootProject.ext.androidxFragmentVersion : '1.8.4'
7
- androidxWebkitVersion = project.hasProperty('androidxWebkitVersion') ? rootProject.ext.androidxWebkitVersion : '1.12.1'
2
+ androidxActivityVersion = project.hasProperty('androidxActivityVersion') ? rootProject.ext.androidxActivityVersion : '1.11.0'
3
+ androidxAppCompatVersion = project.hasProperty('androidxAppCompatVersion') ? rootProject.ext.androidxAppCompatVersion : '1.7.1'
4
+ androidxCoordinatorLayoutVersion = project.hasProperty('androidxCoordinatorLayoutVersion') ? rootProject.ext.androidxCoordinatorLayoutVersion : '1.3.0'
5
+ androidxCoreVersion = project.hasProperty('androidxCoreVersion') ? rootProject.ext.androidxCoreVersion : '1.17.0'
6
+ androidxFragmentVersion = project.hasProperty('androidxFragmentVersion') ? rootProject.ext.androidxFragmentVersion : '1.8.9'
7
+ androidxWebkitVersion = project.hasProperty('androidxWebkitVersion') ? rootProject.ext.androidxWebkitVersion : '1.14.0'
8
8
  junitVersion = project.hasProperty('junitVersion') ? rootProject.ext.junitVersion : '4.13.2'
9
- androidxJunitVersion = project.hasProperty('androidxJunitVersion') ? rootProject.ext.androidxJunitVersion : '1.2.1'
10
- androidxEspressoCoreVersion = project.hasProperty('androidxEspressoCoreVersion') ? rootProject.ext.androidxEspressoCoreVersion : '3.6.1'
11
- cordovaAndroidVersion = project.hasProperty('cordovaAndroidVersion') ? rootProject.ext.cordovaAndroidVersion : '10.1.1'
9
+ androidxJunitVersion = project.hasProperty('androidxJunitVersion') ? rootProject.ext.androidxJunitVersion : '1.3.0'
10
+ androidxEspressoCoreVersion = project.hasProperty('androidxEspressoCoreVersion') ? rootProject.ext.androidxEspressoCoreVersion : '3.7.0'
11
+ cordovaAndroidVersion = project.hasProperty('cordovaAndroidVersion') ? rootProject.ext.cordovaAndroidVersion : '14.0.1'
12
12
  }
13
13
 
14
14
 
15
15
  buildscript {
16
- ext.kotlin_version = project.hasProperty("kotlin_version") ? rootProject.ext.kotlin_version : '1.9.25'
17
16
  repositories {
18
17
  google()
19
18
  mavenCentral()
20
19
  maven {
21
- url "https://plugins.gradle.org/m2/"
20
+ url = "https://plugins.gradle.org/m2/"
22
21
  }
23
22
  }
24
23
  dependencies {
25
- classpath 'com.android.tools.build:gradle:8.7.2'
24
+ classpath 'com.android.tools.build:gradle:8.13.0'
26
25
 
27
26
  if (System.getenv("CAP_PUBLISH") == "true") {
28
27
  classpath 'io.github.gradle-nexus:publish-plugin:1.3.0'
@@ -41,8 +40,8 @@ if (System.getenv("CAP_PUBLISH") == "true") {
41
40
  }
42
41
 
43
42
  android {
44
- namespace "com.getcapacitor.android"
45
- compileSdk project.hasProperty('compileSdkVersion') ? rootProject.ext.compileSdkVersion : 36
43
+ namespace = "com.getcapacitor.android"
44
+ compileSdk = project.hasProperty('compileSdkVersion') ? rootProject.ext.compileSdkVersion : 36
46
45
  defaultConfig {
47
46
  minSdkVersion project.hasProperty('minSdkVersion') ? rootProject.ext.minSdkVersion : 24
48
47
  targetSdkVersion project.hasProperty('targetSdkVersion') ? rootProject.ext.targetSdkVersion : 36
@@ -59,9 +58,9 @@ android {
59
58
  }
60
59
  lintOptions {
61
60
  baseline file("lint-baseline.xml")
62
- abortOnError true
63
- warningsAsErrors true
64
- lintConfig file('lint.xml')
61
+ abortOnError = true
62
+ warningsAsErrors = true
63
+ lintConfig = file('lint.xml')
65
64
  }
66
65
  compileOptions {
67
66
  sourceCompatibility JavaVersion.VERSION_21
@@ -79,7 +78,6 @@ repositories {
79
78
 
80
79
  dependencies {
81
80
  implementation fileTree(dir: 'libs', include: ['*.jar'])
82
- implementation platform("org.jetbrains.kotlin:kotlin-bom:$kotlin_version")
83
81
  implementation "androidx.appcompat:appcompat:$androidxAppCompatVersion"
84
82
  implementation "androidx.core:core:$androidxCoreVersion"
85
83
  implementation "androidx.activity:activity:$androidxActivityVersion"
@@ -90,7 +88,7 @@ dependencies {
90
88
  androidTestImplementation "androidx.test.ext:junit:$androidxJunitVersion"
91
89
  androidTestImplementation "androidx.test.espresso:espresso-core:$androidxEspressoCoreVersion"
92
90
  implementation "org.apache.cordova:framework:$cordovaAndroidVersion"
93
- testImplementation 'org.json:json:20240303'
94
- testImplementation 'org.mockito:mockito-core:5.14.1'
91
+ testImplementation 'org.json:json:20250517'
92
+ testImplementation 'org.mockito:mockito-core:5.20.0'
95
93
  }
96
94
 
@@ -326,7 +326,7 @@ var nativeBridge = (function (exports) {
326
326
  c.error(result.error);
327
327
  }
328
328
  else {
329
- c.dir(result.data);
329
+ c.dir(JSON.stringify(result.data));
330
330
  }
331
331
  c.groupEnd();
332
332
  }
@@ -462,9 +462,9 @@ public class Bridge {
462
462
  if (ex instanceof SocketTimeoutException) {
463
463
  Logger.error(
464
464
  "Unable to load app. Ensure the server is running at " +
465
- appUrl +
466
- ", or modify the " +
467
- "appUrl setting in capacitor.config.json (make sure to npx cap copy after to commit changes).",
465
+ appUrl +
466
+ ", or modify the " +
467
+ "appUrl setting in capacitor.config.json (make sure to npx cap copy after to commit changes).",
468
468
  ex
469
469
  );
470
470
  }
@@ -655,6 +655,7 @@ public class Bridge {
655
655
  this.registerPlugin(com.getcapacitor.plugin.CapacitorCookies.class);
656
656
  this.registerPlugin(com.getcapacitor.plugin.WebView.class);
657
657
  this.registerPlugin(com.getcapacitor.plugin.CapacitorHttp.class);
658
+ this.registerPlugin(com.getcapacitor.plugin.SystemBars.class);
658
659
 
659
660
  for (Class<? extends Plugin> pluginClass : this.initialPlugins) {
660
661
  this.registerPlugin(pluginClass);
@@ -748,9 +749,9 @@ public class Bridge {
748
749
  private void logInvalidPluginException(Class<? extends Plugin> clazz) {
749
750
  Logger.error(
750
751
  "NativePlugin " +
751
- clazz.getName() +
752
- " is invalid. Ensure the @CapacitorPlugin annotation exists on the plugin class and" +
753
- " the class extends Plugin"
752
+ clazz.getName() +
753
+ " is invalid. Ensure the @CapacitorPlugin annotation exists on the plugin class and" +
754
+ " the class extends Plugin"
754
755
  );
755
756
  }
756
757
 
@@ -825,13 +826,13 @@ public class Bridge {
825
826
  if (Logger.shouldLog()) {
826
827
  Logger.verbose(
827
828
  "callback: " +
828
- call.getCallbackId() +
829
- ", pluginId: " +
830
- plugin.getId() +
831
- ", methodName: " +
832
- methodName +
833
- ", methodData: " +
834
- call.getData().toString()
829
+ call.getCallbackId() +
830
+ ", pluginId: " +
831
+ plugin.getId() +
832
+ ", methodName: " +
833
+ methodName +
834
+ ", methodData: " +
835
+ call.getData().toString()
835
836
  );
836
837
  }
837
838
 
@@ -1610,7 +1611,6 @@ public class Bridge {
1610
1611
 
1611
1612
  if (webView instanceof CapacitorWebView capacitorWebView) {
1612
1613
  capacitorWebView.setBridge(bridge);
1613
- capacitorWebView.edgeToEdgeHandler(bridge);
1614
1614
  }
1615
1615
 
1616
1616
  bridge.setCordovaWebView(mockWebView);
@@ -447,12 +447,7 @@ public class BridgeWebChromeClient extends WebChromeClient {
447
447
  }
448
448
 
449
449
  public boolean isValidMsg(String msg) {
450
- return !(
451
- msg.contains("%cresult %c") ||
452
- (msg.contains("%cnative %c")) ||
453
- msg.equalsIgnoreCase("[object Object]") ||
454
- msg.equalsIgnoreCase("console.groupEnd")
455
- );
450
+ return !(msg.contains("%cresult %c") || (msg.contains("%cnative %c")) || msg.equalsIgnoreCase("console.groupEnd"));
456
451
  }
457
452
 
458
453
  private Uri createImageFileUri() throws IOException {
@@ -54,7 +54,6 @@ public class CapConfig {
54
54
  private String errorPath;
55
55
  private boolean zoomableWebView = false;
56
56
  private boolean resolveServiceWorkerRequests = true;
57
- private String adjustMarginsForEdgeToEdge = "disable";
58
57
 
59
58
  // Embedded
60
59
  private String startPath;
@@ -182,7 +181,6 @@ public class CapConfig {
182
181
  this.errorPath = builder.errorPath;
183
182
  this.zoomableWebView = builder.zoomableWebView;
184
183
  this.resolveServiceWorkerRequests = builder.resolveServiceWorkerRequests;
185
- this.adjustMarginsForEdgeToEdge = builder.adjustMarginsForEdgeToEdge;
186
184
 
187
185
  // Embedded
188
186
  this.startPath = builder.startPath;
@@ -288,7 +286,6 @@ public class CapConfig {
288
286
  webContentsDebuggingEnabled = JSONUtils.getBoolean(configJSON, "android.webContentsDebuggingEnabled", isDebug);
289
287
  zoomableWebView = JSONUtils.getBoolean(configJSON, "android.zoomEnabled", JSONUtils.getBoolean(configJSON, "zoomEnabled", false));
290
288
  resolveServiceWorkerRequests = JSONUtils.getBoolean(configJSON, "android.resolveServiceWorkerRequests", true);
291
- adjustMarginsForEdgeToEdge = JSONUtils.getString(configJSON, "android.adjustMarginsForEdgeToEdge", "disable");
292
289
 
293
290
  String logBehavior = JSONUtils.getString(
294
291
  configJSON,
@@ -405,10 +402,6 @@ public class CapConfig {
405
402
  return useLegacyBridge;
406
403
  }
407
404
 
408
- public String adjustMarginsForEdgeToEdge() {
409
- return adjustMarginsForEdgeToEdge;
410
- }
411
-
412
405
  public int getMinWebViewVersion() {
413
406
  if (minWebViewVersion < MINIMUM_ANDROID_WEBVIEW_VERSION) {
414
407
  Logger.warn("Specified minimum webview version is too low, defaulting to " + MINIMUM_ANDROID_WEBVIEW_VERSION);
@@ -589,7 +582,6 @@ public class CapConfig {
589
582
  private int minHuaweiWebViewVersion = DEFAULT_HUAWEI_WEBVIEW_VERSION;
590
583
  private boolean zoomableWebView = false;
591
584
  private boolean resolveServiceWorkerRequests = true;
592
- private String adjustMarginsForEdgeToEdge = "disable";
593
585
 
594
586
  // Embedded
595
587
  private String startPath = null;
@@ -54,36 +54,4 @@ public class CapacitorWebView extends WebView {
54
54
  }
55
55
  return super.dispatchKeyEvent(event);
56
56
  }
57
-
58
- public void edgeToEdgeHandler(Bridge bridge) {
59
- String configEdgeToEdge = bridge.getConfig().adjustMarginsForEdgeToEdge();
60
-
61
- if (configEdgeToEdge.equals("disable")) return;
62
-
63
- boolean autoMargins = false;
64
- boolean forceMargins = configEdgeToEdge.equals("force");
65
-
66
- if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.VANILLA_ICE_CREAM && configEdgeToEdge.equals("auto")) {
67
- TypedValue value = new TypedValue();
68
- boolean foundOptOut = getContext().getTheme().resolveAttribute(android.R.attr.windowOptOutEdgeToEdgeEnforcement, value, true);
69
- boolean optOutValue = value.data != 0; // value is set to -1 on true as of Android 15, so we have to do this.
70
-
71
- autoMargins = !(foundOptOut && optOutValue);
72
- }
73
-
74
- if (forceMargins || autoMargins) {
75
- ViewCompat.setOnApplyWindowInsetsListener(this, (v, windowInsets) -> {
76
- Insets insets = windowInsets.getInsets(WindowInsetsCompat.Type.systemBars() | WindowInsetsCompat.Type.displayCutout());
77
- MarginLayoutParams mlp = (MarginLayoutParams) v.getLayoutParams();
78
- mlp.leftMargin = insets.left;
79
- mlp.bottomMargin = insets.bottom;
80
- mlp.rightMargin = insets.right;
81
- mlp.topMargin = insets.top;
82
- v.setLayoutParams(mlp);
83
-
84
- // Don't pass window insets to children
85
- return WindowInsetsCompat.CONSUMED;
86
- });
87
- }
88
- }
89
57
  }
@@ -64,16 +64,16 @@ public class JSExport {
64
64
  for (PluginHandle plugin : plugins) {
65
65
  lines.add(
66
66
  "(function(w) {\n" +
67
- "var a = (w.Capacitor = w.Capacitor || {});\n" +
68
- "var p = (a.Plugins = a.Plugins || {});\n" +
69
- "var t = (p['" +
70
- plugin.getId() +
71
- "'] = {});\n" +
72
- "t.addListener = function(eventName, callback) {\n" +
73
- " return w.Capacitor.addListener('" +
74
- plugin.getId() +
75
- "', eventName, callback);\n" +
76
- "}"
67
+ "var a = (w.Capacitor = w.Capacitor || {});\n" +
68
+ "var p = (a.Plugins = a.Plugins || {});\n" +
69
+ "var t = (p['" +
70
+ plugin.getId() +
71
+ "'] = {});\n" +
72
+ "t.addListener = function(eventName, callback) {\n" +
73
+ " return w.Capacitor.addListener('" +
74
+ plugin.getId() +
75
+ "', eventName, callback);\n" +
76
+ "}"
77
77
  );
78
78
  Collection<PluginMethodHandle> methods = plugin.getMethods();
79
79
  for (PluginMethodHandle method : methods) {
@@ -171,12 +171,12 @@ public class JSExport {
171
171
  case PluginMethod.RETURN_NONE:
172
172
  lines.add(
173
173
  "return w.Capacitor.nativeCallback('" +
174
- plugin.getId() +
175
- "', '" +
176
- method.getName() +
177
- "', " +
178
- CATCHALL_OPTIONS_PARAM +
179
- ")"
174
+ plugin.getId() +
175
+ "', '" +
176
+ method.getName() +
177
+ "', " +
178
+ CATCHALL_OPTIONS_PARAM +
179
+ ")"
180
180
  );
181
181
  break;
182
182
  case PluginMethod.RETURN_PROMISE:
@@ -187,14 +187,14 @@ public class JSExport {
187
187
  case PluginMethod.RETURN_CALLBACK:
188
188
  lines.add(
189
189
  "return w.Capacitor.nativeCallback('" +
190
- plugin.getId() +
191
- "', '" +
192
- method.getName() +
193
- "', " +
194
- CATCHALL_OPTIONS_PARAM +
195
- ", " +
196
- CALLBACK_PARAM +
197
- ")"
190
+ plugin.getId() +
191
+ "', '" +
192
+ method.getName() +
193
+ "', " +
194
+ CATCHALL_OPTIONS_PARAM +
195
+ ", " +
196
+ CALLBACK_PARAM +
197
+ ")"
198
198
  );
199
199
  break;
200
200
  default:
@@ -69,13 +69,13 @@ public class MessageHandler {
69
69
  Logger.verbose(
70
70
  Logger.tags("Plugin"),
71
71
  "To native (Cordova plugin): callbackId: " +
72
- callbackId +
73
- ", service: " +
74
- service +
75
- ", action: " +
76
- action +
77
- ", actionArgs: " +
78
- actionArgs
72
+ callbackId +
73
+ ", service: " +
74
+ service +
75
+ ", action: " +
76
+ action +
77
+ ", actionArgs: " +
78
+ actionArgs
79
79
  );
80
80
 
81
81
  this.callCordovaPluginMethod(callbackId, service, action, actionArgs);
@@ -47,30 +47,30 @@ public class CapacitorCookies extends Plugin {
47
47
  @PluginMethod
48
48
  public void getCookies(PluginCall call) {
49
49
  this.bridge.eval("document.cookie", (value) -> {
50
- String cookies = value.substring(1, value.length() - 1);
51
- String[] cookieArray = cookies.split(";");
50
+ String cookies = value.substring(1, value.length() - 1);
51
+ String[] cookieArray = cookies.split(";");
52
52
 
53
- JSObject cookieMap = new JSObject();
53
+ JSObject cookieMap = new JSObject();
54
54
 
55
- for (String cookie : cookieArray) {
56
- if (cookie.length() > 0) {
57
- String[] keyValue = cookie.split("=", 2);
55
+ for (String cookie : cookieArray) {
56
+ if (cookie.length() > 0) {
57
+ String[] keyValue = cookie.split("=", 2);
58
58
 
59
- if (keyValue.length == 2) {
60
- String key = keyValue[0].trim();
61
- String val = keyValue[1].trim();
62
- try {
63
- key = URLDecoder.decode(keyValue[0].trim(), StandardCharsets.UTF_8.name());
64
- val = URLDecoder.decode(keyValue[1].trim(), StandardCharsets.UTF_8.name());
65
- } catch (UnsupportedEncodingException ignored) {}
59
+ if (keyValue.length == 2) {
60
+ String key = keyValue[0].trim();
61
+ String val = keyValue[1].trim();
62
+ try {
63
+ key = URLDecoder.decode(keyValue[0].trim(), StandardCharsets.UTF_8.name());
64
+ val = URLDecoder.decode(keyValue[1].trim(), StandardCharsets.UTF_8.name());
65
+ } catch (UnsupportedEncodingException ignored) {}
66
66
 
67
- cookieMap.put(key, val);
68
- }
67
+ cookieMap.put(key, val);
69
68
  }
70
69
  }
70
+ }
71
71
 
72
- call.resolve(cookieMap);
73
- });
72
+ call.resolve(cookieMap);
73
+ });
74
74
  }
75
75
 
76
76
  @PluginMethod
@@ -0,0 +1,220 @@
1
+ package com.getcapacitor.plugin;
2
+
3
+ import android.content.pm.PackageInfo;
4
+ import android.content.res.Configuration;
5
+ import android.view.View;
6
+ import android.view.Window;
7
+ import androidx.core.graphics.Insets;
8
+ import androidx.core.view.ViewCompat;
9
+ import androidx.core.view.WindowCompat;
10
+ import androidx.core.view.WindowInsetsCompat;
11
+ import androidx.core.view.WindowInsetsControllerCompat;
12
+ import androidx.webkit.WebViewCompat;
13
+ import com.getcapacitor.Plugin;
14
+ import com.getcapacitor.PluginCall;
15
+ import com.getcapacitor.PluginMethod;
16
+ import com.getcapacitor.annotation.CapacitorPlugin;
17
+ import java.util.Locale;
18
+ import java.util.regex.Matcher;
19
+ import java.util.regex.Pattern;
20
+
21
+ @CapacitorPlugin
22
+ public class SystemBars extends Plugin {
23
+
24
+ static final String STYLE_LIGHT = "LIGHT";
25
+ static final String STYLE_DARK = "DARK";
26
+ static final String STYLE_DEFAULT = "DEFAULT";
27
+ static final String BAR_STATUS_BAR = "StatusBar";
28
+ static final String BAR_GESTURE_BAR = "NavigationBar";
29
+
30
+ static final String viewportMetaJSFunction = """
31
+ function capacitorSystemBarsCheckMetaViewport() {
32
+ const meta = document.querySelectorAll("meta[name=viewport]");
33
+ if (meta.length == 0) {
34
+ return false;
35
+ }
36
+ // get the last found meta viewport tag
37
+ const metaContent = meta[meta.length - 1].content;
38
+ return metaContent.includes("viewport-fit=cover");
39
+ }
40
+
41
+ capacitorSystemBarsCheckMetaViewport();
42
+ """;
43
+
44
+ @Override
45
+ public void load() {
46
+ super.load();
47
+ initSystemBars();
48
+ }
49
+
50
+ private boolean hasFixedWebView() {
51
+ PackageInfo packageInfo = WebViewCompat.getCurrentWebViewPackage(bridge.getContext());
52
+ Pattern pattern = Pattern.compile("(\\d+)");
53
+ Matcher matcher = pattern.matcher(packageInfo.versionName);
54
+
55
+ if (!matcher.find()) {
56
+ return false;
57
+ }
58
+
59
+ String majorVersionStr = matcher.group(0);
60
+ int majorVersion = Integer.parseInt(majorVersionStr);
61
+
62
+ return majorVersion >= 140;
63
+ }
64
+
65
+ private void initSystemBars() {
66
+ String style = getConfig().getString("style", STYLE_DEFAULT).toUpperCase(Locale.US);
67
+ boolean hidden = getConfig().getBoolean("hidden", false);
68
+ boolean disableCSSInsets = getConfig().getBoolean("disableInsets", false);
69
+
70
+ this.bridge.getWebView().evaluateJavascript(viewportMetaJSFunction, (res) -> {
71
+ boolean hasMetaViewportCover = res.equals("true");
72
+ if (!disableCSSInsets) {
73
+ setupSafeAreaInsets(this.hasFixedWebView(), hasMetaViewportCover);
74
+ }
75
+ });
76
+
77
+ getBridge().executeOnMainThread(() -> {
78
+ setStyle(style, "");
79
+ setHidden(hidden, "");
80
+ });
81
+ }
82
+
83
+ @PluginMethod
84
+ public void setStyle(final PluginCall call) {
85
+ String bar = call.getString("bar", "");
86
+ String style = call.getString("style", STYLE_DEFAULT);
87
+
88
+ getBridge().executeOnMainThread(() -> {
89
+ setStyle(style, bar);
90
+ call.resolve();
91
+ });
92
+ }
93
+
94
+ @PluginMethod
95
+ public void show(final PluginCall call) {
96
+ String bar = call.getString("bar", "");
97
+
98
+ getBridge().executeOnMainThread(() -> {
99
+ setHidden(false, bar);
100
+ call.resolve();
101
+ });
102
+ }
103
+
104
+ @PluginMethod
105
+ public void hide(final PluginCall call) {
106
+ String bar = call.getString("bar", "");
107
+
108
+ getBridge().executeOnMainThread(() -> {
109
+ setHidden(true, bar);
110
+ call.resolve();
111
+ });
112
+ }
113
+
114
+ @PluginMethod
115
+ public void setAnimation(final PluginCall call) {
116
+ call.resolve();
117
+ }
118
+
119
+ private void setupSafeAreaInsets(boolean hasFixedWebView, boolean hasMetaViewportCover) {
120
+ ViewCompat.setOnApplyWindowInsetsListener((View) getBridge().getWebView().getParent(), (v, insets) -> {
121
+ if (hasFixedWebView && hasMetaViewportCover) {
122
+ return insets;
123
+ }
124
+
125
+ Insets safeArea = insets.getInsets(WindowInsetsCompat.Type.systemBars() | WindowInsetsCompat.Type.displayCutout());
126
+ Insets imeInsets = insets.getInsets(WindowInsetsCompat.Type.ime());
127
+ boolean keyboardVisible = insets.isVisible(WindowInsetsCompat.Type.ime());
128
+
129
+ int bottomInsets = safeArea.bottom;
130
+
131
+ if (keyboardVisible) {
132
+ // When https://issues.chromium.org/issues/457682720 is fixed and released,
133
+ // add behind a WebView version check
134
+ bottomInsets = imeInsets.bottom - bottomInsets;
135
+ }
136
+
137
+ injectSafeAreaCSS(safeArea.top, safeArea.right, bottomInsets, safeArea.left);
138
+
139
+ return WindowInsetsCompat.CONSUMED;
140
+ });
141
+ }
142
+
143
+ private void injectSafeAreaCSS(int top, int right, int bottom, int left) {
144
+ // Convert pixels to density-independent pixels
145
+ float density = getActivity().getResources().getDisplayMetrics().density;
146
+ float topPx = top / density;
147
+ float rightPx = right / density;
148
+ float bottomPx = bottom / density;
149
+ float leftPx = left / density;
150
+
151
+ // Execute JavaScript to inject the CSS
152
+ getBridge().executeOnMainThread(() -> {
153
+ if (bridge != null && bridge.getWebView() != null) {
154
+ String script = String.format(
155
+ Locale.US,
156
+ """
157
+ try {
158
+ document.documentElement.style.setProperty("--safe-area-inset-top", "%dpx");
159
+ document.documentElement.style.setProperty("--safe-area-inset-right", "%dpx");
160
+ document.documentElement.style.setProperty("--safe-area-inset-bottom", "%dpx");
161
+ document.documentElement.style.setProperty("--safe-area-inset-left", "%dpx");
162
+ } catch(e) { console.error('Error injecting safe area CSS:', e); }
163
+ """,
164
+ (int) topPx,
165
+ (int) rightPx,
166
+ (int) bottomPx,
167
+ (int) leftPx
168
+ );
169
+
170
+ bridge.getWebView().evaluateJavascript(script, null);
171
+ }
172
+ });
173
+ }
174
+
175
+ private void setStyle(String style, String bar) {
176
+ if (style.equals(STYLE_DEFAULT)) {
177
+ style = getStyleForTheme();
178
+ }
179
+
180
+ Window window = getActivity().getWindow();
181
+ WindowInsetsControllerCompat windowInsetsControllerCompat = WindowCompat.getInsetsController(window, window.getDecorView());
182
+ if (bar.isEmpty() || bar.equals(BAR_STATUS_BAR)) {
183
+ windowInsetsControllerCompat.setAppearanceLightStatusBars(!style.equals(STYLE_DARK));
184
+ }
185
+
186
+ if (bar.isEmpty() || bar.equals(BAR_GESTURE_BAR)) {
187
+ windowInsetsControllerCompat.setAppearanceLightNavigationBars(!style.equals(STYLE_DARK));
188
+ }
189
+ }
190
+
191
+ private void setHidden(boolean hide, String bar) {
192
+ Window window = getActivity().getWindow();
193
+ WindowInsetsControllerCompat windowInsetsControllerCompat = WindowCompat.getInsetsController(window, window.getDecorView());
194
+
195
+ if (hide) {
196
+ if (bar.isEmpty() || bar.equals(BAR_STATUS_BAR)) {
197
+ windowInsetsControllerCompat.hide(WindowInsetsCompat.Type.statusBars());
198
+ }
199
+ if (bar.isEmpty() || bar.equals(BAR_GESTURE_BAR)) {
200
+ windowInsetsControllerCompat.hide(WindowInsetsCompat.Type.navigationBars());
201
+ }
202
+ return;
203
+ }
204
+
205
+ if (bar.isEmpty() || bar.equals(BAR_STATUS_BAR)) {
206
+ windowInsetsControllerCompat.show(WindowInsetsCompat.Type.systemBars());
207
+ }
208
+ if (bar.isEmpty() || bar.equals(BAR_GESTURE_BAR)) {
209
+ windowInsetsControllerCompat.show(WindowInsetsCompat.Type.navigationBars());
210
+ }
211
+ }
212
+
213
+ private String getStyleForTheme() {
214
+ int currentNightMode = getActivity().getResources().getConfiguration().uiMode & Configuration.UI_MODE_NIGHT_MASK;
215
+ if (currentNightMode != Configuration.UI_MODE_NIGHT_YES) {
216
+ return STYLE_LIGHT;
217
+ }
218
+ return STYLE_DARK;
219
+ }
220
+ }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@capacitor/android",
3
- "version": "8.0.0-alpha.2",
3
+ "version": "8.0.0-beta.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": "^8.0.0-alpha.2"
26
+ "@capacitor/core": "^8.0.0-beta.0"
27
27
  },
28
28
  "publishConfig": {
29
29
  "access": "public"
@@ -1,15 +0,0 @@
1
- <?xml version="1.0" encoding="utf-8"?>
2
- <androidx.coordinatorlayout.widget.CoordinatorLayout xmlns:android="http://schemas.android.com/apk/res/android"
3
- xmlns:app="http://schemas.android.com/apk/res-auto"
4
- xmlns:tools="http://schemas.android.com/tools"
5
- android:layout_width="match_parent"
6
- android:layout_height="match_parent"
7
- tools:context="com.getcapacitor.BridgeActivity"
8
- >
9
-
10
- <com.getcapacitor.CapacitorWebView
11
- android:id="@+id/webview"
12
- android:layout_width="fill_parent"
13
- android:layout_height="fill_parent" />
14
-
15
- </androidx.coordinatorlayout.widget.CoordinatorLayout>