@capacitor/android 8.5.2-nightly-20260910T151316.0 → 8.5.2
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,12 +367,6 @@ 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
|
-
}
|
|
376
370
|
if (platform == 'android' || platform == 'ios') {
|
|
377
371
|
// patch document.cookie on Android/iOS
|
|
378
372
|
win.CapacitorCookiesDescriptor =
|
|
@@ -1220,45 +1220,51 @@ public class Bridge {
|
|
|
1220
1220
|
protected Map<String, PermissionState> getPermissionStates(Plugin plugin) {
|
|
1221
1221
|
Map<String, PermissionState> permissionsResults = new HashMap<>();
|
|
1222
1222
|
CapacitorPlugin annotation = plugin.getPluginHandle().getPluginAnnotation();
|
|
1223
|
-
|
|
1224
|
-
|
|
1225
|
-
|
|
1226
|
-
|
|
1227
|
-
|
|
1228
|
-
|
|
1229
|
-
|
|
1230
|
-
|
|
1231
|
-
|
|
1232
|
-
|
|
1233
|
-
|
|
1234
|
-
|
|
1235
|
-
}
|
|
1236
|
-
} else {
|
|
1237
|
-
for (String permString : perm.strings()) {
|
|
1238
|
-
String key = perm.alias().isEmpty() ? permString : perm.alias();
|
|
1239
|
-
PermissionState permissionStatus;
|
|
1240
|
-
if (ActivityCompat.checkSelfPermission(this.getContext(), permString) == PackageManager.PERMISSION_GRANTED) {
|
|
1241
|
-
permissionStatus = PermissionState.GRANTED;
|
|
1242
|
-
} else {
|
|
1243
|
-
permissionStatus = PermissionState.PROMPT;
|
|
1244
|
-
|
|
1245
|
-
// Check if there is a cached permission state for the "Never ask again" state
|
|
1246
|
-
SharedPreferences prefs = getContext().getSharedPreferences(PERMISSION_PREFS_NAME, Activity.MODE_PRIVATE);
|
|
1247
|
-
String state = prefs.getString(permString, null);
|
|
1248
|
-
|
|
1249
|
-
if (state != null) {
|
|
1250
|
-
permissionStatus = PermissionState.byState(state);
|
|
1223
|
+
if (annotation != null) {
|
|
1224
|
+
for (Permission perm : annotation.permissions()) {
|
|
1225
|
+
// If a permission is defined with no permission constants, return GRANTED for it.
|
|
1226
|
+
// Otherwise, get its true state.
|
|
1227
|
+
if (perm.strings().length == 0 || (perm.strings().length == 1 && perm.strings()[0].isEmpty())) {
|
|
1228
|
+
String key = perm.alias();
|
|
1229
|
+
if (!key.isEmpty()) {
|
|
1230
|
+
PermissionState existingResult = permissionsResults.get(key);
|
|
1231
|
+
|
|
1232
|
+
// auto set permission state to GRANTED if the alias is empty.
|
|
1233
|
+
if (existingResult == null) {
|
|
1234
|
+
permissionsResults.put(key, PermissionState.GRANTED);
|
|
1251
1235
|
}
|
|
1252
1236
|
}
|
|
1237
|
+
} else {
|
|
1238
|
+
for (String permString : perm.strings()) {
|
|
1239
|
+
String key = perm.alias().isEmpty() ? permString : perm.alias();
|
|
1240
|
+
PermissionState permissionStatus;
|
|
1241
|
+
if (ActivityCompat.checkSelfPermission(this.getContext(), permString) == PackageManager.PERMISSION_GRANTED) {
|
|
1242
|
+
permissionStatus = PermissionState.GRANTED;
|
|
1243
|
+
} else {
|
|
1244
|
+
permissionStatus = PermissionState.PROMPT;
|
|
1245
|
+
|
|
1246
|
+
// Check if there is a cached permission state for the "Never ask again" state
|
|
1247
|
+
SharedPreferences prefs = getContext().getSharedPreferences(PERMISSION_PREFS_NAME, Activity.MODE_PRIVATE);
|
|
1248
|
+
String state = prefs.getString(permString, null);
|
|
1249
|
+
|
|
1250
|
+
if (state != null) {
|
|
1251
|
+
permissionStatus = PermissionState.byState(state);
|
|
1252
|
+
}
|
|
1253
|
+
}
|
|
1253
1254
|
|
|
1254
|
-
|
|
1255
|
+
PermissionState existingResult = permissionsResults.get(key);
|
|
1255
1256
|
|
|
1256
|
-
|
|
1257
|
-
|
|
1258
|
-
|
|
1257
|
+
// multiple permissions with the same alias must all be true, otherwise all false.
|
|
1258
|
+
if (existingResult == null || existingResult == PermissionState.GRANTED) {
|
|
1259
|
+
permissionsResults.put(key, permissionStatus);
|
|
1260
|
+
}
|
|
1259
1261
|
}
|
|
1260
1262
|
}
|
|
1261
1263
|
}
|
|
1264
|
+
} else {
|
|
1265
|
+
Logger.warn(
|
|
1266
|
+
String.format("getPermissionStates: missing @CapacitorPlugin annotation for plugin %s", plugin.getPluginHandle().getId())
|
|
1267
|
+
);
|
|
1262
1268
|
}
|
|
1263
1269
|
|
|
1264
1270
|
return permissionsResults;
|
|
@@ -502,10 +502,14 @@ public class Plugin {
|
|
|
502
502
|
private String[] getPermissionStringsForAliases(@NonNull String[] aliases) {
|
|
503
503
|
CapacitorPlugin annotation = handle.getPluginAnnotation();
|
|
504
504
|
HashSet<String> perms = new HashSet<>();
|
|
505
|
-
|
|
506
|
-
|
|
507
|
-
|
|
505
|
+
if (annotation != null) {
|
|
506
|
+
for (Permission perm : annotation.permissions()) {
|
|
507
|
+
if (Arrays.asList(aliases).contains(perm.alias())) {
|
|
508
|
+
perms.addAll(Arrays.asList(perm.strings()));
|
|
509
|
+
}
|
|
508
510
|
}
|
|
511
|
+
} else {
|
|
512
|
+
Logger.warn(String.format("getPermissionStringsForAliases: missing @CapacitorPlugin annotation for plugin %s", handle.getId()));
|
|
509
513
|
}
|
|
510
514
|
|
|
511
515
|
return perms.toArray(new String[0]);
|
|
@@ -4,11 +4,9 @@ import android.content.Context;
|
|
|
4
4
|
import android.content.pm.PackageInfo;
|
|
5
5
|
import android.content.res.Configuration;
|
|
6
6
|
import android.content.res.Resources;
|
|
7
|
-
import android.os.Build;
|
|
8
7
|
import android.util.TypedValue;
|
|
9
8
|
import android.view.View;
|
|
10
9
|
import android.view.Window;
|
|
11
|
-
import android.webkit.JavascriptInterface;
|
|
12
10
|
import android.webkit.WebView;
|
|
13
11
|
import androidx.core.graphics.Insets;
|
|
14
12
|
import androidx.core.view.ViewCompat;
|
|
@@ -33,9 +31,9 @@ public class SystemBars extends Plugin {
|
|
|
33
31
|
static final String BAR_STATUS_BAR = "StatusBar";
|
|
34
32
|
static final String BAR_GESTURE_BAR = "NavigationBar";
|
|
35
33
|
|
|
36
|
-
// TODO: In Cap 9, add an additional option "full"
|
|
37
34
|
static final String INSETS_HANDLING_CSS = "css";
|
|
38
35
|
static final String INSETS_HANDLING_DISABLE = "disable";
|
|
36
|
+
static final String INSETS_HANDLING_NATIVE = "native";
|
|
39
37
|
|
|
40
38
|
// https://issues.chromium.org/issues/40699457
|
|
41
39
|
private static final int WEBVIEW_VERSION_WITH_SAFE_AREA_FIX = 140;
|
|
@@ -61,9 +59,22 @@ public class SystemBars extends Plugin {
|
|
|
61
59
|
private String currentStatusBarStyle = STYLE_DEFAULT;
|
|
62
60
|
private String currentGestureBarStyle = STYLE_DEFAULT;
|
|
63
61
|
|
|
62
|
+
// Declare variable at this scope to help prevent adding multiple listeners.
|
|
63
|
+
private WebViewListener webViewListener;
|
|
64
|
+
|
|
65
|
+
private void warnAboutUnsupportedConfigurationValues() {
|
|
66
|
+
boolean keyboardResizeOnFullScreen = bridge.getConfig().getPluginConfiguration("Keyboard").getBoolean("resizeOnFullScreen", false);
|
|
67
|
+
|
|
68
|
+
if (!INSETS_HANDLING_DISABLE.equals(insetsHandling) && keyboardResizeOnFullScreen) {
|
|
69
|
+
Logger.warn(
|
|
70
|
+
"SystemBars",
|
|
71
|
+
"You should omit `Keyboard.resizeOnFullScreen` in your `capacitor.config.json`. Other values can lead to unexpected behavior."
|
|
72
|
+
);
|
|
73
|
+
}
|
|
74
|
+
}
|
|
75
|
+
|
|
64
76
|
@Override
|
|
65
77
|
public void load() {
|
|
66
|
-
getBridge().getWebView().addJavascriptInterface(this, "CapacitorSystemBarsAndroidInterface");
|
|
67
78
|
super.load();
|
|
68
79
|
|
|
69
80
|
initSystemBars();
|
|
@@ -73,15 +84,25 @@ public class SystemBars extends Plugin {
|
|
|
73
84
|
protected void handleOnStart() {
|
|
74
85
|
super.handleOnStart();
|
|
75
86
|
|
|
76
|
-
|
|
77
|
-
|
|
87
|
+
if (INSETS_HANDLING_DISABLE.equals(insetsHandling)) {
|
|
88
|
+
return;
|
|
89
|
+
}
|
|
90
|
+
|
|
91
|
+
if (webViewListener == null) {
|
|
92
|
+
webViewListener = new WebViewListener() {
|
|
78
93
|
@Override
|
|
79
94
|
public void onPageCommitVisible(WebView view, String url) {
|
|
80
95
|
super.onPageCommitVisible(view, url);
|
|
81
|
-
|
|
96
|
+
bridge.getWebView().evaluateJavascript(viewportMetaJSFunction, (res) -> {
|
|
97
|
+
hasViewportCover = res.equals("true");
|
|
98
|
+
|
|
99
|
+
// Request new execution tree of `setOnApplyWindowInsetsListener`
|
|
100
|
+
bridge.getWebView().requestApplyInsets();
|
|
101
|
+
});
|
|
82
102
|
}
|
|
83
|
-
}
|
|
84
|
-
|
|
103
|
+
};
|
|
104
|
+
this.getBridge().addWebViewListener(webViewListener);
|
|
105
|
+
}
|
|
85
106
|
}
|
|
86
107
|
|
|
87
108
|
@Override
|
|
@@ -93,11 +114,20 @@ public class SystemBars extends Plugin {
|
|
|
93
114
|
}
|
|
94
115
|
|
|
95
116
|
private void initSystemBars() {
|
|
117
|
+
// If you already know what the value of the `viewport-fit=` meta tag is going to be,
|
|
118
|
+
// passing it here through `initialViewportFitValueHint` can help prevent layout shifting.
|
|
119
|
+
String configuredInitialViewportFitValueHint = getConfig().getString("initialViewportFitValueHint", "");
|
|
120
|
+
hasViewportCover = "cover".equals(configuredInitialViewportFitValueHint);
|
|
121
|
+
|
|
96
122
|
String style = getConfig().getString("style", STYLE_DEFAULT).toUpperCase(Locale.US);
|
|
97
123
|
boolean hidden = getConfig().getBoolean("hidden", false);
|
|
98
124
|
|
|
99
125
|
String configuredInsetsHandling = getConfig().getString("insetsHandling", INSETS_HANDLING_CSS);
|
|
100
|
-
if (
|
|
126
|
+
if (
|
|
127
|
+
INSETS_HANDLING_CSS.equals(configuredInsetsHandling) ||
|
|
128
|
+
INSETS_HANDLING_DISABLE.equals(configuredInsetsHandling) ||
|
|
129
|
+
INSETS_HANDLING_NATIVE.equals(configuredInsetsHandling)
|
|
130
|
+
) {
|
|
101
131
|
insetsHandling = configuredInsetsHandling;
|
|
102
132
|
} else {
|
|
103
133
|
Logger.warn(
|
|
@@ -107,8 +137,9 @@ public class SystemBars extends Plugin {
|
|
|
107
137
|
insetsHandling = INSETS_HANDLING_CSS;
|
|
108
138
|
}
|
|
109
139
|
|
|
140
|
+
warnAboutUnsupportedConfigurationValues();
|
|
141
|
+
|
|
110
142
|
initWindowInsetsListener();
|
|
111
|
-
initSafeAreaCSSVariables();
|
|
112
143
|
|
|
113
144
|
getBridge().executeOnMainThread(() -> {
|
|
114
145
|
setStyle(style, "");
|
|
@@ -152,51 +183,14 @@ public class SystemBars extends Plugin {
|
|
|
152
183
|
call.resolve();
|
|
153
184
|
}
|
|
154
185
|
|
|
155
|
-
@JavascriptInterface
|
|
156
|
-
public void onDOMReady() {
|
|
157
|
-
if (INSETS_HANDLING_CSS.equals(insetsHandling)) {
|
|
158
|
-
getActivity().runOnUiThread(() -> {
|
|
159
|
-
this.bridge.getWebView().evaluateJavascript(viewportMetaJSFunction, (res) -> {
|
|
160
|
-
hasViewportCover = res.equals("true");
|
|
161
|
-
|
|
162
|
-
getBridge().getWebView().requestApplyInsets();
|
|
163
|
-
});
|
|
164
|
-
});
|
|
165
|
-
}
|
|
166
|
-
}
|
|
167
|
-
|
|
168
|
-
private Insets calcSafeAreaInsets(WindowInsetsCompat insets) {
|
|
169
|
-
Insets safeArea = insets.getInsets(WindowInsetsCompat.Type.systemBars() | WindowInsetsCompat.Type.displayCutout());
|
|
170
|
-
if (insets.isVisible(WindowInsetsCompat.Type.ime())) {
|
|
171
|
-
return Insets.of(safeArea.left, safeArea.top, safeArea.right, 0);
|
|
172
|
-
}
|
|
173
|
-
return Insets.of(safeArea.left, safeArea.top, safeArea.right, safeArea.bottom);
|
|
174
|
-
}
|
|
175
|
-
|
|
176
|
-
private void initSafeAreaCSSVariables() {
|
|
177
|
-
if (INSETS_HANDLING_CSS.equals(insetsHandling)) {
|
|
178
|
-
WindowInsetsCompat insets;
|
|
179
|
-
|
|
180
|
-
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.VANILLA_ICE_CREAM) {
|
|
181
|
-
View v = (View) this.getBridge().getWebView().getParent();
|
|
182
|
-
insets = ViewCompat.getRootWindowInsets(v);
|
|
183
|
-
} else {
|
|
184
|
-
insets = WindowInsetsCompat.CONSUMED;
|
|
185
|
-
}
|
|
186
|
-
|
|
187
|
-
if (insets != null) {
|
|
188
|
-
Insets safeAreaInsets = calcSafeAreaInsets(insets);
|
|
189
|
-
injectSafeAreaCSS(safeAreaInsets.top, safeAreaInsets.right, safeAreaInsets.bottom, safeAreaInsets.left);
|
|
190
|
-
}
|
|
191
|
-
}
|
|
192
|
-
}
|
|
193
|
-
|
|
194
186
|
private void initWindowInsetsListener() {
|
|
195
187
|
if (INSETS_HANDLING_DISABLE.equals(insetsHandling)) {
|
|
196
188
|
return;
|
|
197
189
|
}
|
|
198
190
|
|
|
199
|
-
|
|
191
|
+
View view = getActivity().getWindow().getDecorView();
|
|
192
|
+
|
|
193
|
+
ViewCompat.setOnApplyWindowInsetsListener(view, (v, insets) -> {
|
|
200
194
|
boolean shouldPassthroughInsets = getWebViewMajorVersion() >= WEBVIEW_VERSION_WITH_SAFE_AREA_FIX && hasViewportCover;
|
|
201
195
|
|
|
202
196
|
Insets systemBarsInsets = insets.getInsets(WindowInsetsCompat.Type.systemBars() | WindowInsetsCompat.Type.displayCutout());
|
|
@@ -207,10 +201,7 @@ public class SystemBars extends Plugin {
|
|
|
207
201
|
// We need to correct for a possible shown IME
|
|
208
202
|
v.setPadding(0, 0, 0, keyboardVisible ? imeInsets.bottom : 0);
|
|
209
203
|
|
|
210
|
-
|
|
211
|
-
injectSafeAreaCSS(safeAreaInsets.top, safeAreaInsets.right, safeAreaInsets.bottom, safeAreaInsets.left);
|
|
212
|
-
|
|
213
|
-
return new WindowInsetsCompat.Builder(insets)
|
|
204
|
+
WindowInsetsCompat newInsets = new WindowInsetsCompat.Builder(insets)
|
|
214
205
|
.setInsets(
|
|
215
206
|
WindowInsetsCompat.Type.systemBars() | WindowInsetsCompat.Type.displayCutout(),
|
|
216
207
|
Insets.of(
|
|
@@ -221,18 +212,20 @@ public class SystemBars extends Plugin {
|
|
|
221
212
|
)
|
|
222
213
|
)
|
|
223
214
|
.build();
|
|
224
|
-
}
|
|
225
215
|
|
|
226
|
-
|
|
227
|
-
|
|
228
|
-
|
|
229
|
-
systemBarsInsets.left,
|
|
230
|
-
systemBarsInsets.top,
|
|
231
|
-
systemBarsInsets.right,
|
|
232
|
-
keyboardVisible ? imeInsets.bottom : systemBarsInsets.bottom
|
|
233
|
-
);
|
|
216
|
+
injectSafeAreaCSS(newInsets);
|
|
217
|
+
|
|
218
|
+
return newInsets;
|
|
234
219
|
}
|
|
235
220
|
|
|
221
|
+
// We need to correct for a possible shown IME
|
|
222
|
+
v.setPadding(
|
|
223
|
+
systemBarsInsets.left,
|
|
224
|
+
systemBarsInsets.top,
|
|
225
|
+
systemBarsInsets.right,
|
|
226
|
+
keyboardVisible ? imeInsets.bottom : systemBarsInsets.bottom
|
|
227
|
+
);
|
|
228
|
+
|
|
236
229
|
// Returning `WindowInsetsCompat.CONSUMED` breaks recalculation of safe area insets
|
|
237
230
|
// So we have to explicitly set insets to `0`
|
|
238
231
|
// See: https://issues.chromium.org/issues/461332423
|
|
@@ -240,20 +233,28 @@ public class SystemBars extends Plugin {
|
|
|
240
233
|
.setInsets(WindowInsetsCompat.Type.systemBars() | WindowInsetsCompat.Type.displayCutout(), Insets.of(0, 0, 0, 0))
|
|
241
234
|
.build();
|
|
242
235
|
|
|
243
|
-
|
|
244
|
-
injectSafeAreaCSS(safeAreaInsets.top, safeAreaInsets.right, safeAreaInsets.bottom, safeAreaInsets.left);
|
|
236
|
+
injectSafeAreaCSS(newInsets);
|
|
245
237
|
|
|
246
238
|
return newInsets;
|
|
247
239
|
});
|
|
248
240
|
}
|
|
249
241
|
|
|
250
|
-
private void injectSafeAreaCSS(
|
|
242
|
+
private void injectSafeAreaCSS(WindowInsetsCompat insets) {
|
|
243
|
+
if (!INSETS_HANDLING_CSS.equals(insetsHandling)) {
|
|
244
|
+
return;
|
|
245
|
+
}
|
|
246
|
+
|
|
247
|
+
Insets systemBarsInsets = insets.getInsets(WindowInsetsCompat.Type.systemBars() | WindowInsetsCompat.Type.displayCutout());
|
|
248
|
+
boolean keyboardVisible = insets.isVisible(WindowInsetsCompat.Type.ime());
|
|
249
|
+
|
|
251
250
|
// Convert pixels to density-independent pixels
|
|
252
251
|
float density = getActivity().getResources().getDisplayMetrics().density;
|
|
253
|
-
float topPx = top / density;
|
|
254
|
-
float rightPx = right / density;
|
|
255
|
-
|
|
256
|
-
|
|
252
|
+
float topPx = systemBarsInsets.top / density;
|
|
253
|
+
float rightPx = systemBarsInsets.right / density;
|
|
254
|
+
// For native insets the value gets automatically corrected when the IME is visible (in newer WebView versions),
|
|
255
|
+
// but for these injected values we have to handle that manually (for all WebView versions).
|
|
256
|
+
float bottomPx = (keyboardVisible ? 0 : systemBarsInsets.bottom) / density;
|
|
257
|
+
float leftPx = systemBarsInsets.left / density;
|
|
257
258
|
|
|
258
259
|
// Execute JavaScript to inject the CSS
|
|
259
260
|
getBridge().executeOnMainThread(() -> {
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@capacitor/android",
|
|
3
|
-
"version": "8.5.2
|
|
3
|
+
"version": "8.5.2",
|
|
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.5.0
|
|
26
|
+
"@capacitor/core": "^8.5.0"
|
|
27
27
|
},
|
|
28
28
|
"publishConfig": {
|
|
29
29
|
"access": "public"
|