@capacitor/android 8.0.0-nightly-20251205T150637.0 → 8.0.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.
@@ -367,6 +367,12 @@ var nativeBridge = (function (exports) {
367
367
  }
368
368
  };
369
369
  const platform = getPlatformId(win);
370
+ if (platform == 'android' && typeof win.CapacitorSystemBarsAndroidInterface !== 'undefined') {
371
+ // add DOM ready listener for System Bars
372
+ document.addEventListener('DOMContentLoaded', function () {
373
+ win.CapacitorSystemBarsAndroidInterface.onDOMReady();
374
+ });
375
+ }
370
376
  if (platform == 'android' || platform == 'ios') {
371
377
  // patch document.cookie on Android/iOS
372
378
  win.CapacitorCookiesDescriptor =
@@ -102,4 +102,16 @@ public class BridgeWebViewClient extends WebViewClient {
102
102
 
103
103
  return result;
104
104
  }
105
+
106
+ @Override
107
+ public void onPageCommitVisible(WebView view, String url) {
108
+ super.onPageCommitVisible(view, url);
109
+
110
+ List<WebViewListener> webViewListeners = bridge.getWebViewListeners();
111
+ if (webViewListeners != null) {
112
+ for (WebViewListener listener : bridge.getWebViewListeners()) {
113
+ listener.onPageCommitVisible(view, url);
114
+ }
115
+ }
116
+ }
105
117
  }
@@ -54,4 +54,14 @@ public abstract class WebViewListener {
54
54
  // Override me to add behavior to the web view render process gone event
55
55
  return false;
56
56
  }
57
+
58
+ /**
59
+ * Callback for page start event.
60
+ *
61
+ * @param view The WebView for which the navigation occurred.
62
+ * @param url The URL corresponding to the page navigation that triggered this callback.
63
+ */
64
+ public void onPageCommitVisible(WebView view, String url) {
65
+ // Override me to add behavior to handle the onPageCommitVisible event
66
+ }
57
67
  }
@@ -1,22 +1,23 @@
1
1
  package com.getcapacitor.plugin;
2
2
 
3
- import android.content.pm.PackageInfo;
4
3
  import android.content.res.Configuration;
4
+ import android.os.Build;
5
5
  import android.view.View;
6
+ import android.view.ViewGroup;
6
7
  import android.view.Window;
8
+ import android.webkit.JavascriptInterface;
9
+ import android.webkit.WebView;
7
10
  import androidx.core.graphics.Insets;
8
11
  import androidx.core.view.ViewCompat;
9
12
  import androidx.core.view.WindowCompat;
10
13
  import androidx.core.view.WindowInsetsCompat;
11
14
  import androidx.core.view.WindowInsetsControllerCompat;
12
- import androidx.webkit.WebViewCompat;
13
15
  import com.getcapacitor.Plugin;
14
16
  import com.getcapacitor.PluginCall;
15
17
  import com.getcapacitor.PluginMethod;
18
+ import com.getcapacitor.WebViewListener;
16
19
  import com.getcapacitor.annotation.CapacitorPlugin;
17
20
  import java.util.Locale;
18
- import java.util.regex.Matcher;
19
- import java.util.regex.Pattern;
20
21
 
21
22
  @CapacitorPlugin
22
23
  public class SystemBars extends Plugin {
@@ -27,6 +28,9 @@ public class SystemBars extends Plugin {
27
28
  static final String BAR_STATUS_BAR = "StatusBar";
28
29
  static final String BAR_GESTURE_BAR = "NavigationBar";
29
30
 
31
+ static final String INSETS_HANDLING_CSS = "css";
32
+ static final String INSETS_HANDLING_DISABLE = "disable";
33
+
30
34
  static final String viewportMetaJSFunction = """
31
35
  function capacitorSystemBarsCheckMetaViewport() {
32
36
  const meta = document.querySelectorAll("meta[name=viewport]");
@@ -37,42 +41,52 @@ public class SystemBars extends Plugin {
37
41
  const metaContent = meta[meta.length - 1].content;
38
42
  return metaContent.includes("viewport-fit=cover");
39
43
  }
40
-
41
44
  capacitorSystemBarsCheckMetaViewport();
42
45
  """;
43
46
 
47
+ private boolean insetHandlingEnabled = true;
48
+ private boolean hasViewportCover = false;
49
+
44
50
  @Override
45
51
  public void load() {
52
+ getBridge().getWebView().addJavascriptInterface(this, "CapacitorSystemBarsAndroidInterface");
46
53
  super.load();
54
+
47
55
  initSystemBars();
48
56
  }
49
57
 
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);
58
+ @Override
59
+ protected void handleOnStart() {
60
+ super.handleOnStart();
61
+
62
+ this.getBridge().addWebViewListener(
63
+ new WebViewListener() {
64
+ @Override
65
+ public void onPageCommitVisible(WebView view, String url) {
66
+ super.onPageCommitVisible(view, url);
67
+ getBridge().getWebView().requestApplyInsets();
68
+ }
69
+ }
70
+ );
71
+ }
61
72
 
62
- return majorVersion >= 140;
73
+ @Override
74
+ protected void handleOnConfigurationChanged(Configuration newConfig) {
75
+ super.handleOnConfigurationChanged(newConfig);
76
+ setStyle(STYLE_DEFAULT, "");
63
77
  }
64
78
 
65
79
  private void initSystemBars() {
66
80
  String style = getConfig().getString("style", STYLE_DEFAULT).toUpperCase(Locale.US);
67
81
  boolean hidden = getConfig().getBoolean("hidden", false);
68
- boolean disableCSSInsets = getConfig().getBoolean("disableInsets", false);
69
82
 
70
- this.bridge.getWebView().evaluateJavascript(viewportMetaJSFunction, (res) -> {
71
- boolean hasMetaViewportCover = res.equals("true");
72
- if (!disableCSSInsets) {
73
- setupSafeAreaInsets(this.hasFixedWebView(), hasMetaViewportCover);
74
- }
75
- });
83
+ String insetsHandling = getConfig().getString("insetsHandling", "css");
84
+ if (insetsHandling.equals(INSETS_HANDLING_DISABLE)) {
85
+ insetHandlingEnabled = false;
86
+ }
87
+
88
+ initWindowInsetsListener();
89
+ initSafeAreaInsets();
76
90
 
77
91
  getBridge().executeOnMainThread(() -> {
78
92
  setStyle(style, "");
@@ -116,28 +130,63 @@ public class SystemBars extends Plugin {
116
130
  call.resolve();
117
131
  }
118
132
 
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
- }
133
+ @JavascriptInterface
134
+ public void onDOMReady() {
135
+ getActivity().runOnUiThread(() -> {
136
+ this.bridge.getWebView().evaluateJavascript(viewportMetaJSFunction, (res) -> {
137
+ hasViewportCover = res.equals("true");
124
138
 
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());
139
+ getBridge().getWebView().requestApplyInsets();
140
+ });
141
+ });
142
+ }
128
143
 
129
- int bottomInsets = safeArea.bottom;
144
+ private Insets calcSafeAreaInsets(WindowInsetsCompat insets) {
145
+ Insets safeArea = insets.getInsets(WindowInsetsCompat.Type.systemBars() | WindowInsetsCompat.Type.displayCutout());
146
+ return Insets.of(safeArea.left, safeArea.top, safeArea.right, safeArea.bottom);
147
+ }
130
148
 
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;
149
+ private void initSafeAreaInsets() {
150
+ if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.VANILLA_ICE_CREAM && insetHandlingEnabled) {
151
+ View v = (View) this.getBridge().getWebView().getParent();
152
+ WindowInsetsCompat insets = ViewCompat.getRootWindowInsets(v);
153
+ if (insets != null) {
154
+ Insets safeAreaInsets = calcSafeAreaInsets(insets);
155
+ injectSafeAreaCSS(safeAreaInsets.top, safeAreaInsets.right, safeAreaInsets.bottom, safeAreaInsets.left);
135
156
  }
157
+ }
158
+ }
136
159
 
137
- injectSafeAreaCSS(safeArea.top, safeArea.right, bottomInsets, safeArea.left);
160
+ private void initWindowInsetsListener() {
161
+ if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.VANILLA_ICE_CREAM && insetHandlingEnabled) {
162
+ ViewCompat.setOnApplyWindowInsetsListener((View) getBridge().getWebView().getParent(), (v, insets) -> {
163
+ if (hasViewportCover) {
164
+ Insets safeAreaInsets = calcSafeAreaInsets(insets);
165
+ boolean keyboardVisible = insets.isVisible(WindowInsetsCompat.Type.ime());
138
166
 
139
- return WindowInsetsCompat.CONSUMED;
140
- });
167
+ if (keyboardVisible) {
168
+ Insets imeInsets = insets.getInsets(WindowInsetsCompat.Type.ime());
169
+ setViewMargins(v, Insets.of(0, 0, 0, imeInsets.bottom));
170
+ } else {
171
+ setViewMargins(v, Insets.NONE);
172
+ }
173
+
174
+ injectSafeAreaCSS(safeAreaInsets.top, safeAreaInsets.right, safeAreaInsets.bottom, safeAreaInsets.left);
175
+ return WindowInsetsCompat.CONSUMED;
176
+ }
177
+
178
+ return insets;
179
+ });
180
+ }
181
+ }
182
+
183
+ private void setViewMargins(View v, Insets insets) {
184
+ ViewGroup.MarginLayoutParams mlp = (ViewGroup.MarginLayoutParams) v.getLayoutParams();
185
+ mlp.leftMargin = insets.left;
186
+ mlp.bottomMargin = insets.bottom;
187
+ mlp.rightMargin = insets.right;
188
+ mlp.topMargin = insets.top;
189
+ v.setLayoutParams(mlp);
141
190
  }
142
191
 
143
192
  private void injectSafeAreaCSS(int top, int right, int bottom, int left) {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@capacitor/android",
3
- "version": "8.0.0-nightly-20251205T150637.0",
3
+ "version": "8.0.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-nightly-20251205T150637.0"
26
+ "@capacitor/core": "^8.0.0"
27
27
  },
28
28
  "publishConfig": {
29
29
  "access": "public"