@capacitor/android 8.1.0 → 8.1.1-dev-20260305T150856.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/src/main/java/com/getcapacitor/Bridge.java +79 -101
- package/capacitor/src/main/java/com/getcapacitor/BridgeActivity.java +10 -4
- package/capacitor/src/main/java/com/getcapacitor/MessageHandler.java +16 -46
- package/capacitor/src/main/java/com/getcapacitor/WebViewLocalServer.java +26 -6
- package/capacitor/src/main/java/com/getcapacitor/cordova/CordovaPlugin.java +148 -0
- package/capacitor/src/main/java/com/getcapacitor/cordova/MockCordovaInterfaceImpl.java +1 -1
- package/capacitor/src/main/java/com/getcapacitor/cordova/MockCordovaWebViewImpl.java +2 -2
- package/package.json +2 -2
|
@@ -35,8 +35,6 @@ import androidx.webkit.WebViewFeature;
|
|
|
35
35
|
import com.getcapacitor.android.R;
|
|
36
36
|
import com.getcapacitor.annotation.CapacitorPlugin;
|
|
37
37
|
import com.getcapacitor.annotation.Permission;
|
|
38
|
-
import com.getcapacitor.cordova.MockCordovaInterfaceImpl;
|
|
39
|
-
import com.getcapacitor.cordova.MockCordovaWebViewImpl;
|
|
40
38
|
import com.getcapacitor.util.HostMask;
|
|
41
39
|
import com.getcapacitor.util.InternalUtils;
|
|
42
40
|
import com.getcapacitor.util.PermissionHelper;
|
|
@@ -53,13 +51,9 @@ import java.util.LinkedList;
|
|
|
53
51
|
import java.util.List;
|
|
54
52
|
import java.util.Map;
|
|
55
53
|
import java.util.Set;
|
|
54
|
+
import java.util.function.Function;
|
|
56
55
|
import java.util.regex.Matcher;
|
|
57
56
|
import java.util.regex.Pattern;
|
|
58
|
-
import org.apache.cordova.ConfigXmlParser;
|
|
59
|
-
import org.apache.cordova.CordovaPreferences;
|
|
60
|
-
import org.apache.cordova.CordovaWebView;
|
|
61
|
-
import org.apache.cordova.PluginEntry;
|
|
62
|
-
import org.apache.cordova.PluginManager;
|
|
63
57
|
import org.json.JSONException;
|
|
64
58
|
|
|
65
59
|
/**
|
|
@@ -125,9 +119,6 @@ public class Bridge {
|
|
|
125
119
|
private Boolean canInjectJS = true;
|
|
126
120
|
// A reference to the main WebView for the app
|
|
127
121
|
private final WebView webView;
|
|
128
|
-
public final MockCordovaInterfaceImpl cordovaInterface;
|
|
129
|
-
private CordovaWebView cordovaWebView;
|
|
130
|
-
private CordovaPreferences preferences;
|
|
131
122
|
private BridgeWebViewClient webViewClient;
|
|
132
123
|
private App app;
|
|
133
124
|
|
|
@@ -147,6 +138,8 @@ public class Bridge {
|
|
|
147
138
|
// A map of Plugin Id's to PluginHandle's
|
|
148
139
|
private Map<String, PluginHandle> plugins = new HashMap<>();
|
|
149
140
|
|
|
141
|
+
private Map<String, MessageHandler.Interceptor> interceptors = new HashMap<>();
|
|
142
|
+
|
|
150
143
|
// Stored plugin calls that we're keeping around to call again someday
|
|
151
144
|
private Map<String, PluginCall> savedCalls = new HashMap<>();
|
|
152
145
|
|
|
@@ -169,26 +162,6 @@ public class Bridge {
|
|
|
169
162
|
// A pre-determined path to load the bridge
|
|
170
163
|
private ServerPath serverPath;
|
|
171
164
|
|
|
172
|
-
/**
|
|
173
|
-
* Create the Bridge with a reference to the main {@link Activity} for the
|
|
174
|
-
* app, and a reference to the {@link WebView} our app will use.
|
|
175
|
-
* @param context
|
|
176
|
-
* @param webView
|
|
177
|
-
* @deprecated Use {@link Bridge.Builder} to create Bridge instances
|
|
178
|
-
*/
|
|
179
|
-
@Deprecated
|
|
180
|
-
public Bridge(
|
|
181
|
-
AppCompatActivity context,
|
|
182
|
-
WebView webView,
|
|
183
|
-
List<Class<? extends Plugin>> initialPlugins,
|
|
184
|
-
MockCordovaInterfaceImpl cordovaInterface,
|
|
185
|
-
PluginManager pluginManager,
|
|
186
|
-
CordovaPreferences preferences,
|
|
187
|
-
CapConfig config
|
|
188
|
-
) {
|
|
189
|
-
this(context, null, null, webView, initialPlugins, new ArrayList<>(), cordovaInterface, pluginManager, preferences, config);
|
|
190
|
-
}
|
|
191
|
-
|
|
192
165
|
private Bridge(
|
|
193
166
|
AppCompatActivity context,
|
|
194
167
|
ServerPath serverPath,
|
|
@@ -196,9 +169,6 @@ public class Bridge {
|
|
|
196
169
|
WebView webView,
|
|
197
170
|
List<Class<? extends Plugin>> initialPlugins,
|
|
198
171
|
List<Plugin> pluginInstances,
|
|
199
|
-
MockCordovaInterfaceImpl cordovaInterface,
|
|
200
|
-
PluginManager pluginManager,
|
|
201
|
-
CordovaPreferences preferences,
|
|
202
172
|
CapConfig config
|
|
203
173
|
) {
|
|
204
174
|
this.app = new App();
|
|
@@ -209,8 +179,6 @@ public class Bridge {
|
|
|
209
179
|
this.webViewClient = new BridgeWebViewClient(this);
|
|
210
180
|
this.initialPlugins = initialPlugins;
|
|
211
181
|
this.pluginInstances = pluginInstances;
|
|
212
|
-
this.cordovaInterface = cordovaInterface;
|
|
213
|
-
this.preferences = preferences;
|
|
214
182
|
|
|
215
183
|
// Start our plugin execution threads and handlers
|
|
216
184
|
handlerThread.start();
|
|
@@ -218,11 +186,10 @@ public class Bridge {
|
|
|
218
186
|
|
|
219
187
|
this.config = config != null ? config : CapConfig.loadDefault(getActivity());
|
|
220
188
|
Logger.init(this.config);
|
|
221
|
-
|
|
222
189
|
// Initialize web view and message handler for it
|
|
223
190
|
this.initWebView();
|
|
224
191
|
this.setAllowedOriginRules();
|
|
225
|
-
this.msgHandler = new MessageHandler(this, webView
|
|
192
|
+
this.msgHandler = new MessageHandler(this, webView);
|
|
226
193
|
|
|
227
194
|
// Grab any intent info that our app was launched with
|
|
228
195
|
Intent intent = context.getIntent();
|
|
@@ -450,12 +417,30 @@ public class Bridge {
|
|
|
450
417
|
return false;
|
|
451
418
|
}
|
|
452
419
|
|
|
420
|
+
private Plugin cordova() {
|
|
421
|
+
PluginHandle handle = getPlugin("__CordovaHandle");
|
|
422
|
+
if (handle != null) {
|
|
423
|
+
return handle.getInstance();
|
|
424
|
+
}
|
|
425
|
+
return null;
|
|
426
|
+
}
|
|
427
|
+
|
|
453
428
|
public boolean isDeployDisabled() {
|
|
454
|
-
|
|
429
|
+
Plugin cordova = this.cordova();
|
|
430
|
+
if (cordova != null) {
|
|
431
|
+
return cordova.hasPermission("DisableDeploy");
|
|
432
|
+
} else {
|
|
433
|
+
return false;
|
|
434
|
+
}
|
|
455
435
|
}
|
|
456
436
|
|
|
457
437
|
public boolean shouldKeepRunning() {
|
|
458
|
-
|
|
438
|
+
Plugin cordova = this.cordova();
|
|
439
|
+
if (cordova != null) {
|
|
440
|
+
return cordova.hasPermission("KeepRunning");
|
|
441
|
+
} else {
|
|
442
|
+
return false;
|
|
443
|
+
}
|
|
459
444
|
}
|
|
460
445
|
|
|
461
446
|
public void handleAppUrlLoadError(Exception ex) {
|
|
@@ -474,10 +459,6 @@ public class Bridge {
|
|
|
474
459
|
return (getActivity().getApplicationInfo().flags & ApplicationInfo.FLAG_DEBUGGABLE) != 0;
|
|
475
460
|
}
|
|
476
461
|
|
|
477
|
-
protected void setCordovaWebView(CordovaWebView cordovaWebView) {
|
|
478
|
-
this.cordovaWebView = cordovaWebView;
|
|
479
|
-
}
|
|
480
|
-
|
|
481
462
|
/**
|
|
482
463
|
* Get the Context for the App
|
|
483
464
|
* @return
|
|
@@ -567,6 +548,14 @@ public class Bridge {
|
|
|
567
548
|
return this.config;
|
|
568
549
|
}
|
|
569
550
|
|
|
551
|
+
public MessageHandler.Interceptor getCallInterceptor(String type) {
|
|
552
|
+
return this.interceptors.get(type);
|
|
553
|
+
}
|
|
554
|
+
|
|
555
|
+
public void registerInterceptor(String type, MessageHandler.Interceptor interceptor) {
|
|
556
|
+
this.interceptors.put(type, interceptor);
|
|
557
|
+
}
|
|
558
|
+
|
|
570
559
|
public void reset() {
|
|
571
560
|
savedCalls = new HashMap<>();
|
|
572
561
|
for (PluginHandle handle : this.plugins.values()) {
|
|
@@ -1132,11 +1121,14 @@ public class Bridge {
|
|
|
1132
1121
|
if (plugin == null) {
|
|
1133
1122
|
boolean permissionHandled = false;
|
|
1134
1123
|
Logger.debug("Unable to find a Capacitor plugin to handle permission requestCode, trying Cordova plugins " + requestCode);
|
|
1135
|
-
|
|
1136
|
-
|
|
1137
|
-
|
|
1138
|
-
|
|
1124
|
+
PluginHandle cordovaHandle = getPlugin("__CordovaPlugin");
|
|
1125
|
+
|
|
1126
|
+
if (cordovaHandle != null) {
|
|
1127
|
+
Plugin cordovaPlugin = cordovaHandle.getInstance();
|
|
1128
|
+
cordovaPlugin.handleRequestPermissionsResult(requestCode, permissions, grantResults);
|
|
1129
|
+
permissionHandled = cordovaPlugin.hasDefinedRequiredPermissions();
|
|
1139
1130
|
}
|
|
1131
|
+
|
|
1140
1132
|
return permissionHandled;
|
|
1141
1133
|
}
|
|
1142
1134
|
|
|
@@ -1271,7 +1263,13 @@ public class Bridge {
|
|
|
1271
1263
|
|
|
1272
1264
|
if (plugin == null || plugin.getInstance() == null) {
|
|
1273
1265
|
Logger.debug("Unable to find a Capacitor plugin to handle requestCode, trying Cordova plugins " + requestCode);
|
|
1274
|
-
|
|
1266
|
+
PluginHandle cordovaHandle = getPlugin("__CordovaPlugin");
|
|
1267
|
+
if (cordovaHandle != null) {
|
|
1268
|
+
Plugin cordovaPlugin = cordovaHandle.getInstance();
|
|
1269
|
+
cordovaPlugin.handleOnActivityResult(requestCode, resultCode, data);
|
|
1270
|
+
// This is a bit hacky but required to return the boolean out of the cordova interface
|
|
1271
|
+
return cordovaPlugin.hasRequiredPermissions();
|
|
1272
|
+
}
|
|
1275
1273
|
}
|
|
1276
1274
|
|
|
1277
1275
|
// deprecated, to be removed
|
|
@@ -1301,10 +1299,6 @@ public class Bridge {
|
|
|
1301
1299
|
for (PluginHandle plugin : plugins.values()) {
|
|
1302
1300
|
plugin.getInstance().handleOnNewIntent(intent);
|
|
1303
1301
|
}
|
|
1304
|
-
|
|
1305
|
-
if (cordovaWebView != null) {
|
|
1306
|
-
cordovaWebView.onNewIntent(intent);
|
|
1307
|
-
}
|
|
1308
1302
|
}
|
|
1309
1303
|
|
|
1310
1304
|
/**
|
|
@@ -1333,10 +1327,6 @@ public class Bridge {
|
|
|
1333
1327
|
for (PluginHandle plugin : plugins.values()) {
|
|
1334
1328
|
plugin.getInstance().handleOnStart();
|
|
1335
1329
|
}
|
|
1336
|
-
|
|
1337
|
-
if (cordovaWebView != null) {
|
|
1338
|
-
cordovaWebView.handleStart();
|
|
1339
|
-
}
|
|
1340
1330
|
}
|
|
1341
1331
|
|
|
1342
1332
|
/**
|
|
@@ -1346,10 +1336,6 @@ public class Bridge {
|
|
|
1346
1336
|
for (PluginHandle plugin : plugins.values()) {
|
|
1347
1337
|
plugin.getInstance().handleOnResume();
|
|
1348
1338
|
}
|
|
1349
|
-
|
|
1350
|
-
if (cordovaWebView != null) {
|
|
1351
|
-
cordovaWebView.handleResume(this.shouldKeepRunning());
|
|
1352
|
-
}
|
|
1353
1339
|
}
|
|
1354
1340
|
|
|
1355
1341
|
/**
|
|
@@ -1359,11 +1345,6 @@ public class Bridge {
|
|
|
1359
1345
|
for (PluginHandle plugin : plugins.values()) {
|
|
1360
1346
|
plugin.getInstance().handleOnPause();
|
|
1361
1347
|
}
|
|
1362
|
-
|
|
1363
|
-
if (cordovaWebView != null) {
|
|
1364
|
-
boolean keepRunning = this.shouldKeepRunning() || cordovaInterface.getActivityResultCallback() != null;
|
|
1365
|
-
cordovaWebView.handlePause(keepRunning);
|
|
1366
|
-
}
|
|
1367
1348
|
}
|
|
1368
1349
|
|
|
1369
1350
|
/**
|
|
@@ -1373,10 +1354,6 @@ public class Bridge {
|
|
|
1373
1354
|
for (PluginHandle plugin : plugins.values()) {
|
|
1374
1355
|
plugin.getInstance().handleOnStop();
|
|
1375
1356
|
}
|
|
1376
|
-
|
|
1377
|
-
if (cordovaWebView != null) {
|
|
1378
|
-
cordovaWebView.handleStop();
|
|
1379
|
-
}
|
|
1380
1357
|
}
|
|
1381
1358
|
|
|
1382
1359
|
/**
|
|
@@ -1388,10 +1365,6 @@ public class Bridge {
|
|
|
1388
1365
|
}
|
|
1389
1366
|
|
|
1390
1367
|
handlerThread.quitSafely();
|
|
1391
|
-
|
|
1392
|
-
if (cordovaWebView != null) {
|
|
1393
|
-
cordovaWebView.handleDestroy();
|
|
1394
|
-
}
|
|
1395
1368
|
}
|
|
1396
1369
|
|
|
1397
1370
|
/**
|
|
@@ -1578,49 +1551,54 @@ public class Bridge {
|
|
|
1578
1551
|
|
|
1579
1552
|
public Bridge create() {
|
|
1580
1553
|
// Cordova initialization
|
|
1581
|
-
ConfigXmlParser parser = new ConfigXmlParser();
|
|
1582
|
-
parser.parse(activity.getApplicationContext());
|
|
1583
|
-
CordovaPreferences preferences = parser.getPreferences();
|
|
1584
|
-
preferences.setPreferencesBundle(activity.getIntent().getExtras());
|
|
1585
|
-
List<PluginEntry> pluginEntries = parser.getPluginEntries();
|
|
1586
|
-
|
|
1587
|
-
MockCordovaInterfaceImpl cordovaInterface = new MockCordovaInterfaceImpl(activity);
|
|
1588
|
-
if (instanceState != null) {
|
|
1589
|
-
cordovaInterface.restoreInstanceState(instanceState);
|
|
1590
|
-
}
|
|
1591
|
-
|
|
1592
1554
|
WebView webView = this.fragment != null ? fragment.getView().findViewById(R.id.webview) : activity.findViewById(R.id.webview);
|
|
1593
|
-
MockCordovaWebViewImpl mockWebView = new MockCordovaWebViewImpl(activity.getApplicationContext());
|
|
1594
|
-
mockWebView.init(cordovaInterface, pluginEntries, preferences, webView);
|
|
1595
|
-
PluginManager pluginManager = mockWebView.getPluginManager();
|
|
1596
|
-
cordovaInterface.onCordovaInit(pluginManager);
|
|
1597
1555
|
|
|
1598
1556
|
// Bridge initialization
|
|
1599
|
-
Bridge bridge = new Bridge(
|
|
1600
|
-
activity,
|
|
1601
|
-
serverPath,
|
|
1602
|
-
fragment,
|
|
1603
|
-
webView,
|
|
1604
|
-
plugins,
|
|
1605
|
-
pluginInstances,
|
|
1606
|
-
cordovaInterface,
|
|
1607
|
-
pluginManager,
|
|
1608
|
-
preferences,
|
|
1609
|
-
config
|
|
1610
|
-
);
|
|
1557
|
+
Bridge bridge = new Bridge(activity, serverPath, fragment, webView, plugins, pluginInstances, config);
|
|
1611
1558
|
|
|
1612
1559
|
if (webView instanceof CapacitorWebView capacitorWebView) {
|
|
1613
1560
|
capacitorWebView.setBridge(bridge);
|
|
1614
1561
|
}
|
|
1615
1562
|
|
|
1616
|
-
bridge.setCordovaWebView(mockWebView);
|
|
1617
1563
|
bridge.setWebViewListeners(webViewListeners);
|
|
1618
1564
|
bridge.setRouteProcessor(routeProcessor);
|
|
1619
1565
|
|
|
1620
1566
|
if (instanceState != null) {
|
|
1567
|
+
PluginHandle maybeCordova = bridge.getPlugin("__CordovaPlugin");
|
|
1568
|
+
if (maybeCordova != null) {
|
|
1569
|
+
maybeCordova.getInstance().restoreState(instanceState);
|
|
1570
|
+
}
|
|
1621
1571
|
bridge.restoreInstanceState(instanceState);
|
|
1622
1572
|
}
|
|
1623
1573
|
|
|
1574
|
+
bridge.registerInterceptor("message", (postData) -> {
|
|
1575
|
+
try {
|
|
1576
|
+
String callbackId = postData.getString("callbackId");
|
|
1577
|
+
String pluginId = postData.getString("pluginId");
|
|
1578
|
+
String methodName = postData.getString("methodName");
|
|
1579
|
+
JSObject methodData = postData.getJSObject("options", new JSObject());
|
|
1580
|
+
|
|
1581
|
+
Logger.verbose(
|
|
1582
|
+
Logger.tags("Plugin"),
|
|
1583
|
+
"To native (Capacitor plugin): callbackId: " +
|
|
1584
|
+
callbackId +
|
|
1585
|
+
", pluginId: " +
|
|
1586
|
+
pluginId +
|
|
1587
|
+
", methodName: " +
|
|
1588
|
+
methodName
|
|
1589
|
+
);
|
|
1590
|
+
|
|
1591
|
+
PluginCall call = new PluginCall(bridge.msgHandler, pluginId, callbackId, methodName, methodData);
|
|
1592
|
+
bridge.callPluginMethod(pluginId, methodName, call);
|
|
1593
|
+
} catch (JSONException e) {
|
|
1594
|
+
Logger.error(e.getMessage());
|
|
1595
|
+
}
|
|
1596
|
+
});
|
|
1597
|
+
|
|
1598
|
+
bridge.registerInterceptor("js.error", (postData) -> {
|
|
1599
|
+
Logger.error("JavaScript Error: " + postData.toString());
|
|
1600
|
+
});
|
|
1601
|
+
|
|
1624
1602
|
return bridge;
|
|
1625
1603
|
}
|
|
1626
1604
|
}
|
|
@@ -66,7 +66,9 @@ public class BridgeActivity extends AppCompatActivity {
|
|
|
66
66
|
@Override
|
|
67
67
|
public void onSaveInstanceState(Bundle outState) {
|
|
68
68
|
super.onSaveInstanceState(outState);
|
|
69
|
-
bridge
|
|
69
|
+
if (bridge != null) {
|
|
70
|
+
bridge.saveInstanceState(outState);
|
|
71
|
+
}
|
|
70
72
|
}
|
|
71
73
|
|
|
72
74
|
@Override
|
|
@@ -82,8 +84,10 @@ public class BridgeActivity extends AppCompatActivity {
|
|
|
82
84
|
@Override
|
|
83
85
|
public void onRestart() {
|
|
84
86
|
super.onRestart();
|
|
85
|
-
this.bridge
|
|
86
|
-
|
|
87
|
+
if (this.bridge != null) {
|
|
88
|
+
this.bridge.onRestart();
|
|
89
|
+
Logger.debug("App restarted");
|
|
90
|
+
}
|
|
87
91
|
}
|
|
88
92
|
|
|
89
93
|
@Override
|
|
@@ -131,7 +135,9 @@ public class BridgeActivity extends AppCompatActivity {
|
|
|
131
135
|
@Override
|
|
132
136
|
public void onDetachedFromWindow() {
|
|
133
137
|
super.onDetachedFromWindow();
|
|
134
|
-
this.bridge
|
|
138
|
+
if (this.bridge != null) {
|
|
139
|
+
this.bridge.onDetachedFromWindow();
|
|
140
|
+
}
|
|
135
141
|
}
|
|
136
142
|
|
|
137
143
|
/**
|
|
@@ -5,7 +5,7 @@ import android.webkit.WebView;
|
|
|
5
5
|
import androidx.webkit.JavaScriptReplyProxy;
|
|
6
6
|
import androidx.webkit.WebViewCompat;
|
|
7
7
|
import androidx.webkit.WebViewFeature;
|
|
8
|
-
import
|
|
8
|
+
import java.util.function.Function;
|
|
9
9
|
|
|
10
10
|
/**
|
|
11
11
|
* MessageHandler handles messages from the WebView, dispatching them
|
|
@@ -13,15 +13,18 @@ import org.apache.cordova.PluginManager;
|
|
|
13
13
|
*/
|
|
14
14
|
public class MessageHandler {
|
|
15
15
|
|
|
16
|
+
@FunctionalInterface
|
|
17
|
+
public interface Interceptor {
|
|
18
|
+
void intercept(JSObject object);
|
|
19
|
+
}
|
|
20
|
+
|
|
16
21
|
private Bridge bridge;
|
|
17
22
|
private WebView webView;
|
|
18
|
-
private PluginManager cordovaPluginManager;
|
|
19
23
|
private JavaScriptReplyProxy javaScriptReplyProxy;
|
|
20
24
|
|
|
21
|
-
public MessageHandler(Bridge bridge, WebView webView
|
|
25
|
+
public MessageHandler(Bridge bridge, WebView webView) {
|
|
22
26
|
this.bridge = bridge;
|
|
23
27
|
this.webView = webView;
|
|
24
|
-
this.cordovaPluginManager = cordovaPluginManager;
|
|
25
28
|
|
|
26
29
|
if (WebViewFeature.isFeatureSupported(WebViewFeature.WEB_MESSAGE_LISTENER) && !bridge.getConfig().isUsingLegacyBridge()) {
|
|
27
30
|
WebViewCompat.WebMessageListener capListener = (view, message, sourceOrigin, isMainFrame, replyProxy) -> {
|
|
@@ -42,6 +45,11 @@ public class MessageHandler {
|
|
|
42
45
|
}
|
|
43
46
|
}
|
|
44
47
|
|
|
48
|
+
@Deprecated
|
|
49
|
+
public MessageHandler(Bridge bridge, WebView webView, Object cordovaPluginManager) {
|
|
50
|
+
this(bridge, webView);
|
|
51
|
+
}
|
|
52
|
+
|
|
45
53
|
/**
|
|
46
54
|
* The main message handler that will be called from JavaScript
|
|
47
55
|
* to send a message to the native bridge.
|
|
@@ -55,43 +63,11 @@ public class MessageHandler {
|
|
|
55
63
|
|
|
56
64
|
String type = postData.getString("type");
|
|
57
65
|
|
|
58
|
-
|
|
59
|
-
boolean isCordovaPlugin = typeIsNotNull && type.equals("cordova");
|
|
60
|
-
boolean isJavaScriptError = typeIsNotNull && type.equals("js.error");
|
|
61
|
-
|
|
62
|
-
String callbackId = postData.getString("callbackId");
|
|
63
|
-
|
|
64
|
-
if (isCordovaPlugin) {
|
|
65
|
-
String service = postData.getString("service");
|
|
66
|
-
String action = postData.getString("action");
|
|
67
|
-
String actionArgs = postData.getString("actionArgs");
|
|
68
|
-
|
|
69
|
-
Logger.verbose(
|
|
70
|
-
Logger.tags("Plugin"),
|
|
71
|
-
"To native (Cordova plugin): callbackId: " +
|
|
72
|
-
callbackId +
|
|
73
|
-
", service: " +
|
|
74
|
-
service +
|
|
75
|
-
", action: " +
|
|
76
|
-
action +
|
|
77
|
-
", actionArgs: " +
|
|
78
|
-
actionArgs
|
|
79
|
-
);
|
|
80
|
-
|
|
81
|
-
this.callCordovaPluginMethod(callbackId, service, action, actionArgs);
|
|
82
|
-
} else if (isJavaScriptError) {
|
|
83
|
-
Logger.error("JavaScript Error: " + jsonStr);
|
|
84
|
-
} else {
|
|
85
|
-
String pluginId = postData.getString("pluginId");
|
|
86
|
-
String methodName = postData.getString("methodName");
|
|
87
|
-
JSObject methodData = postData.getJSObject("options", new JSObject());
|
|
88
|
-
|
|
89
|
-
Logger.verbose(
|
|
90
|
-
Logger.tags("Plugin"),
|
|
91
|
-
"To native (Capacitor plugin): callbackId: " + callbackId + ", pluginId: " + pluginId + ", methodName: " + methodName
|
|
92
|
-
);
|
|
66
|
+
if (type == null) type = "message";
|
|
93
67
|
|
|
94
|
-
|
|
68
|
+
Interceptor interceptor = bridge.getCallInterceptor(type);
|
|
69
|
+
if (interceptor != null) {
|
|
70
|
+
interceptor.intercept(postData);
|
|
95
71
|
}
|
|
96
72
|
} catch (Exception ex) {
|
|
97
73
|
Logger.error("Post message error:", ex);
|
|
@@ -148,10 +124,4 @@ public class MessageHandler {
|
|
|
148
124
|
PluginCall call = new PluginCall(this, pluginId, callbackId, methodName, methodData);
|
|
149
125
|
bridge.callPluginMethod(pluginId, methodName, call);
|
|
150
126
|
}
|
|
151
|
-
|
|
152
|
-
private void callCordovaPluginMethod(String callbackId, String service, String action, String actionArgs) {
|
|
153
|
-
bridge.execute(() -> {
|
|
154
|
-
cordovaPluginManager.exec(service, action, callbackId, actionArgs);
|
|
155
|
-
});
|
|
156
|
-
}
|
|
157
127
|
}
|
|
@@ -128,9 +128,22 @@ public class WebViewLocalServer {
|
|
|
128
128
|
return reasonPhrase;
|
|
129
129
|
}
|
|
130
130
|
|
|
131
|
+
/**
|
|
132
|
+
* @deprecated This method may return incorrect headers in concurrent range requests.
|
|
133
|
+
* <p>
|
|
134
|
+
* Use {@link #buildDefaultResponseHeaders()} instead, which returns a copy of the map.
|
|
135
|
+
* </p>
|
|
136
|
+
* This method will be removed in a future major version of Capacitor.
|
|
137
|
+
* </p>
|
|
138
|
+
*/
|
|
139
|
+
@Deprecated(forRemoval = true) // adjust version as appropriate
|
|
131
140
|
public Map<String, String> getResponseHeaders() {
|
|
132
141
|
return responseHeaders;
|
|
133
142
|
}
|
|
143
|
+
|
|
144
|
+
public Map<String, String> buildDefaultResponseHeaders() {
|
|
145
|
+
return new HashMap<>(responseHeaders);
|
|
146
|
+
}
|
|
134
147
|
}
|
|
135
148
|
|
|
136
149
|
WebViewLocalServer(Context context, Bridge bridge, JSInjector jsInjector, ArrayList<String> authorities, boolean html5mode) {
|
|
@@ -329,7 +342,7 @@ public class WebViewLocalServer {
|
|
|
329
342
|
if (request.getRequestHeaders().get("Range") != null) {
|
|
330
343
|
InputStream responseStream = new LollipopLazyInputStream(handler, request);
|
|
331
344
|
String mimeType = getMimeType(path, responseStream);
|
|
332
|
-
Map<String, String> tempResponseHeaders = handler.
|
|
345
|
+
Map<String, String> tempResponseHeaders = handler.buildDefaultResponseHeaders();
|
|
333
346
|
int statusCode = 206;
|
|
334
347
|
try {
|
|
335
348
|
int totalRange = responseStream.available();
|
|
@@ -337,6 +350,13 @@ public class WebViewLocalServer {
|
|
|
337
350
|
String[] parts = rangeString.split("=");
|
|
338
351
|
String[] streamParts = parts[1].split("-");
|
|
339
352
|
String fromRange = streamParts[0];
|
|
353
|
+
int bytesToSkip;
|
|
354
|
+
try {
|
|
355
|
+
bytesToSkip = Integer.parseInt(fromRange);
|
|
356
|
+
if (bytesToSkip > 0) {
|
|
357
|
+
responseStream.skip(bytesToSkip);
|
|
358
|
+
}
|
|
359
|
+
} catch (NumberFormatException ignored) {}
|
|
340
360
|
int range = totalRange - 1;
|
|
341
361
|
if (streamParts.length > 1) {
|
|
342
362
|
range = Integer.parseInt(streamParts[1]);
|
|
@@ -365,7 +385,7 @@ public class WebViewLocalServer {
|
|
|
365
385
|
handler.getEncoding(),
|
|
366
386
|
statusCode,
|
|
367
387
|
handler.getReasonPhrase(),
|
|
368
|
-
handler.
|
|
388
|
+
handler.buildDefaultResponseHeaders(),
|
|
369
389
|
responseStream
|
|
370
390
|
);
|
|
371
391
|
}
|
|
@@ -376,7 +396,7 @@ public class WebViewLocalServer {
|
|
|
376
396
|
handler.getEncoding(),
|
|
377
397
|
handler.getStatusCode(),
|
|
378
398
|
handler.getReasonPhrase(),
|
|
379
|
-
handler.
|
|
399
|
+
handler.buildDefaultResponseHeaders(),
|
|
380
400
|
null
|
|
381
401
|
);
|
|
382
402
|
}
|
|
@@ -411,7 +431,7 @@ public class WebViewLocalServer {
|
|
|
411
431
|
handler.getEncoding(),
|
|
412
432
|
statusCode,
|
|
413
433
|
handler.getReasonPhrase(),
|
|
414
|
-
handler.
|
|
434
|
+
handler.buildDefaultResponseHeaders(),
|
|
415
435
|
responseStream
|
|
416
436
|
);
|
|
417
437
|
}
|
|
@@ -442,7 +462,7 @@ public class WebViewLocalServer {
|
|
|
442
462
|
handler.getEncoding(),
|
|
443
463
|
statusCode,
|
|
444
464
|
handler.getReasonPhrase(),
|
|
445
|
-
handler.
|
|
465
|
+
handler.buildDefaultResponseHeaders(),
|
|
446
466
|
responseStream
|
|
447
467
|
);
|
|
448
468
|
}
|
|
@@ -517,7 +537,7 @@ public class WebViewLocalServer {
|
|
|
517
537
|
handler.getEncoding(),
|
|
518
538
|
handler.getStatusCode(),
|
|
519
539
|
handler.getReasonPhrase(),
|
|
520
|
-
handler.
|
|
540
|
+
handler.buildDefaultResponseHeaders(),
|
|
521
541
|
responseStream
|
|
522
542
|
);
|
|
523
543
|
}
|
|
@@ -0,0 +1,148 @@
|
|
|
1
|
+
package com.getcapacitor.cordova;
|
|
2
|
+
|
|
3
|
+
import android.content.Intent;
|
|
4
|
+
import android.os.Bundle;
|
|
5
|
+
import android.webkit.WebView;
|
|
6
|
+
import com.getcapacitor.Logger;
|
|
7
|
+
import com.getcapacitor.Plugin;
|
|
8
|
+
import com.getcapacitor.android.R;
|
|
9
|
+
import com.getcapacitor.annotation.CapacitorPlugin;
|
|
10
|
+
import java.util.List;
|
|
11
|
+
import org.apache.cordova.ConfigXmlParser;
|
|
12
|
+
import org.apache.cordova.CordovaInterface;
|
|
13
|
+
import org.apache.cordova.CordovaPreferences;
|
|
14
|
+
import org.apache.cordova.CordovaWebView;
|
|
15
|
+
import org.apache.cordova.PluginEntry;
|
|
16
|
+
import org.apache.cordova.PluginManager;
|
|
17
|
+
import org.json.JSONException;
|
|
18
|
+
|
|
19
|
+
@CapacitorPlugin(name = "__CordovaPlugin")
|
|
20
|
+
public class CordovaPlugin extends Plugin {
|
|
21
|
+
|
|
22
|
+
private MockCordovaInterfaceImpl cordovaInterface;
|
|
23
|
+
private CordovaWebView webView;
|
|
24
|
+
private CordovaPreferences preferences;
|
|
25
|
+
|
|
26
|
+
private boolean pluginHadActivityResult = false;
|
|
27
|
+
private boolean pluginHadPermissionResult = false;
|
|
28
|
+
|
|
29
|
+
@Override
|
|
30
|
+
public void load() {
|
|
31
|
+
ConfigXmlParser parser = new ConfigXmlParser();
|
|
32
|
+
parser.parse(getActivity().getApplicationContext());
|
|
33
|
+
preferences = parser.getPreferences();
|
|
34
|
+
preferences.setPreferencesBundle(getActivity().getIntent().getExtras());
|
|
35
|
+
List<PluginEntry> pluginEntries = parser.getPluginEntries();
|
|
36
|
+
|
|
37
|
+
cordovaInterface = new MockCordovaInterfaceImpl(getActivity());
|
|
38
|
+
|
|
39
|
+
MockCordovaWebViewImpl mockWebView = new MockCordovaWebViewImpl(getActivity().getApplicationContext());
|
|
40
|
+
mockWebView.init(cordovaInterface, pluginEntries, preferences, bridge.getWebView());
|
|
41
|
+
webView = mockWebView;
|
|
42
|
+
PluginManager pluginManager = mockWebView.getPluginManager();
|
|
43
|
+
cordovaInterface.onCordovaInit(pluginManager);
|
|
44
|
+
|
|
45
|
+
bridge.registerInterceptor("cordova", (postData) -> {
|
|
46
|
+
String callbackId = postData.getString("callbackId");
|
|
47
|
+
|
|
48
|
+
String service = postData.getString("service");
|
|
49
|
+
String action = postData.getString("action");
|
|
50
|
+
String actionArgs = postData.getString("actionArgs");
|
|
51
|
+
|
|
52
|
+
Logger.verbose(
|
|
53
|
+
Logger.tags("Plugin"),
|
|
54
|
+
"To native (Cordova plugin): callbackId: " +
|
|
55
|
+
callbackId +
|
|
56
|
+
", service: " +
|
|
57
|
+
service +
|
|
58
|
+
", action: " +
|
|
59
|
+
action +
|
|
60
|
+
", actionArgs: " +
|
|
61
|
+
actionArgs
|
|
62
|
+
);
|
|
63
|
+
|
|
64
|
+
bridge.execute(() -> {
|
|
65
|
+
pluginManager.exec(service, action, callbackId, actionArgs);
|
|
66
|
+
});
|
|
67
|
+
});
|
|
68
|
+
}
|
|
69
|
+
|
|
70
|
+
@Override
|
|
71
|
+
protected void restoreState(Bundle state) {
|
|
72
|
+
if (state != null) {
|
|
73
|
+
cordovaInterface.restoreInstanceState(state);
|
|
74
|
+
}
|
|
75
|
+
}
|
|
76
|
+
|
|
77
|
+
@Override
|
|
78
|
+
protected void handleRequestPermissionsResult(int requestCode, String[] permissions, int[] grantResults) {
|
|
79
|
+
try {
|
|
80
|
+
pluginHadPermissionResult = cordovaInterface.handlePermissionResult(requestCode, permissions, grantResults);
|
|
81
|
+
} catch (JSONException e) {
|
|
82
|
+
Logger.debug("Error on Cordova plugin permissions request " + e.getMessage());
|
|
83
|
+
}
|
|
84
|
+
}
|
|
85
|
+
|
|
86
|
+
@Override
|
|
87
|
+
public boolean hasPermission(String permission) {
|
|
88
|
+
if (permission.equals("DisableDeploy")) {
|
|
89
|
+
return preferences.getBoolean(permission, false);
|
|
90
|
+
}
|
|
91
|
+
|
|
92
|
+
if (permission.equals("KeepRunning")) {
|
|
93
|
+
return preferences.getBoolean(permission, true);
|
|
94
|
+
}
|
|
95
|
+
|
|
96
|
+
return false;
|
|
97
|
+
}
|
|
98
|
+
|
|
99
|
+
@Override
|
|
100
|
+
public boolean hasDefinedRequiredPermissions() {
|
|
101
|
+
boolean currentPermissionResult = pluginHadPermissionResult;
|
|
102
|
+
pluginHadPermissionResult = false;
|
|
103
|
+
return currentPermissionResult;
|
|
104
|
+
}
|
|
105
|
+
|
|
106
|
+
@Override
|
|
107
|
+
protected void handleOnActivityResult(int requestCode, int resultCode, Intent data) {
|
|
108
|
+
pluginHadActivityResult = cordovaInterface.onActivityResult(requestCode, resultCode, data);
|
|
109
|
+
}
|
|
110
|
+
|
|
111
|
+
@Override
|
|
112
|
+
public boolean hasRequiredPermissions() {
|
|
113
|
+
boolean currentActivityResult = pluginHadActivityResult;
|
|
114
|
+
pluginHadActivityResult = false;
|
|
115
|
+
return currentActivityResult;
|
|
116
|
+
}
|
|
117
|
+
|
|
118
|
+
@Override
|
|
119
|
+
protected void handleOnNewIntent(Intent intent) {
|
|
120
|
+
webView.onNewIntent(intent);
|
|
121
|
+
}
|
|
122
|
+
|
|
123
|
+
@Override
|
|
124
|
+
protected void handleOnStart() {
|
|
125
|
+
webView.handleStart();
|
|
126
|
+
}
|
|
127
|
+
|
|
128
|
+
@Override
|
|
129
|
+
protected void handleOnResume() {
|
|
130
|
+
webView.handleResume(bridge.shouldKeepRunning());
|
|
131
|
+
}
|
|
132
|
+
|
|
133
|
+
@Override
|
|
134
|
+
protected void handleOnPause() {
|
|
135
|
+
boolean keepRunning = bridge.shouldKeepRunning() || cordovaInterface.getActivityResultCallback() != null;
|
|
136
|
+
webView.handlePause(keepRunning);
|
|
137
|
+
}
|
|
138
|
+
|
|
139
|
+
@Override
|
|
140
|
+
protected void handleOnStop() {
|
|
141
|
+
webView.handleStop();
|
|
142
|
+
}
|
|
143
|
+
|
|
144
|
+
@Override
|
|
145
|
+
protected void handleOnDestroy() {
|
|
146
|
+
webView.handleDestroy();
|
|
147
|
+
}
|
|
148
|
+
}
|
|
@@ -7,7 +7,7 @@ import org.apache.cordova.CordovaInterfaceImpl;
|
|
|
7
7
|
import org.apache.cordova.CordovaPlugin;
|
|
8
8
|
import org.json.JSONException;
|
|
9
9
|
|
|
10
|
-
|
|
10
|
+
class MockCordovaInterfaceImpl extends CordovaInterfaceImpl {
|
|
11
11
|
|
|
12
12
|
public MockCordovaInterfaceImpl(AppCompatActivity activity) {
|
|
13
13
|
super(activity, Executors.newCachedThreadPool());
|
|
@@ -20,7 +20,7 @@ import org.apache.cordova.PluginEntry;
|
|
|
20
20
|
import org.apache.cordova.PluginManager;
|
|
21
21
|
import org.apache.cordova.PluginResult;
|
|
22
22
|
|
|
23
|
-
|
|
23
|
+
class MockCordovaWebViewImpl implements CordovaWebView {
|
|
24
24
|
|
|
25
25
|
private Context context;
|
|
26
26
|
private PluginManager pluginManager;
|
|
@@ -32,7 +32,7 @@ public class MockCordovaWebViewImpl implements CordovaWebView {
|
|
|
32
32
|
private WebView webView;
|
|
33
33
|
private boolean hasPausedEver;
|
|
34
34
|
|
|
35
|
-
|
|
35
|
+
MockCordovaWebViewImpl(Context context) {
|
|
36
36
|
this.context = context;
|
|
37
37
|
}
|
|
38
38
|
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@capacitor/android",
|
|
3
|
-
"version": "8.1.0",
|
|
3
|
+
"version": "8.1.1-dev-20260305T150856.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.1.0"
|
|
26
|
+
"@capacitor/core": "^8.1.0-dev-20260305T150856.0"
|
|
27
27
|
},
|
|
28
28
|
"publishConfig": {
|
|
29
29
|
"access": "public"
|