@capacitor/android 3.4.3 → 3.6.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/CHANGELOG.md CHANGED
@@ -3,6 +3,40 @@
3
3
  All notable changes to this project will be documented in this file.
4
4
  See [Conventional Commits](https://conventionalcommits.org) for commit guidelines.
5
5
 
6
+ # [3.6.0](https://github.com/ionic-team/capacitor/compare/3.5.1...3.6.0) (2022-06-17)
7
+
8
+
9
+ ### Features
10
+
11
+ * **android:** update support for Portals for Capacitor to include Live Updates ([#5660](https://github.com/ionic-team/capacitor/issues/5660)) ([62f0a5e](https://github.com/ionic-team/capacitor/commit/62f0a5eaa40776aad79dbf8f8c0900037d3cc97e))
12
+ * **iOS, Android:** add AppUUID Lib for plugins ([#5690](https://github.com/ionic-team/capacitor/issues/5690)) ([05e76cf](https://github.com/ionic-team/capacitor/commit/05e76cf526a44e07fa75f9482fa2223a13918638))
13
+
14
+
15
+
16
+
17
+
18
+ ## [3.5.1](https://github.com/ionic-team/capacitor/compare/3.5.0...3.5.1) (2022-05-04)
19
+
20
+
21
+ ### Bug Fixes
22
+
23
+ * **android:** move initialFocus on webview into config ([#5579](https://github.com/ionic-team/capacitor/issues/5579)) ([8b4e861](https://github.com/ionic-team/capacitor/commit/8b4e861514b0fbe08e9296f49c280234f54742e1))
24
+
25
+
26
+
27
+
28
+
29
+ # [3.5.0](https://github.com/ionic-team/capacitor/compare/3.4.3...3.5.0) (2022-04-22)
30
+
31
+
32
+ ### Features
33
+
34
+ * **android:** Add overridable routing for WebViewLocalServer ([#5553](https://github.com/ionic-team/capacitor/issues/5553)) ([3bb288e](https://github.com/ionic-team/capacitor/commit/3bb288e848c5c0e49c1e58c0782e0b1ffd7b1f31))
35
+
36
+
37
+
38
+
39
+
6
40
  ## [3.4.3](https://github.com/ionic-team/capacitor/compare/3.4.2...3.4.3) (2022-03-04)
7
41
 
8
42
  **Note:** Version bump only for package @capacitor/android
@@ -0,0 +1,65 @@
1
+ package com.getcapacitor;
2
+
3
+ import android.content.Context;
4
+ import android.content.SharedPreferences;
5
+ import androidx.appcompat.app.AppCompatActivity;
6
+ import java.nio.charset.StandardCharsets;
7
+ import java.security.MessageDigest;
8
+ import java.security.NoSuchAlgorithmException;
9
+ import java.util.Objects;
10
+ import java.util.UUID;
11
+
12
+ public final class AppUUID {
13
+
14
+ private static final String KEY = "CapacitorAppUUID";
15
+
16
+ public static String getAppUUID(AppCompatActivity activity) throws Exception {
17
+ assertAppUUID(activity);
18
+ return readUUID(activity);
19
+ }
20
+
21
+ public static void regenerateAppUUID(AppCompatActivity activity) throws Exception {
22
+ try {
23
+ String uuid = generateUUID();
24
+ writeUUID(activity, uuid);
25
+ } catch (NoSuchAlgorithmException ex) {
26
+ throw new Exception("Capacitor App UUID could not be generated.");
27
+ }
28
+ }
29
+
30
+ private static void assertAppUUID(AppCompatActivity activity) throws Exception {
31
+ String uuid = readUUID(activity);
32
+ if (uuid.equals("")) {
33
+ regenerateAppUUID(activity);
34
+ }
35
+ }
36
+
37
+ private static String generateUUID() throws NoSuchAlgorithmException {
38
+ MessageDigest salt = MessageDigest.getInstance("SHA-256");
39
+ salt.update(UUID.randomUUID().toString().getBytes(StandardCharsets.UTF_8));
40
+ return bytesToHex(salt.digest());
41
+ }
42
+
43
+ private static String readUUID(AppCompatActivity activity) {
44
+ SharedPreferences sharedPref = activity.getPreferences(Context.MODE_PRIVATE);
45
+ return sharedPref.getString(KEY, "");
46
+ }
47
+
48
+ private static void writeUUID(AppCompatActivity activity, String uuid) {
49
+ SharedPreferences sharedPref = activity.getPreferences(Context.MODE_PRIVATE);
50
+ SharedPreferences.Editor editor = sharedPref.edit();
51
+ editor.putString(KEY, uuid);
52
+ editor.apply();
53
+ }
54
+
55
+ private static String bytesToHex(byte[] bytes) {
56
+ byte[] HEX_ARRAY = "0123456789ABCDEF".getBytes(StandardCharsets.US_ASCII);
57
+ byte[] hexChars = new byte[bytes.length * 2];
58
+ for (int j = 0; j < bytes.length; j++) {
59
+ int v = bytes[j] & 0xFF;
60
+ hexChars[j * 2] = HEX_ARRAY[v >>> 4];
61
+ hexChars[j * 2 + 1] = HEX_ARRAY[v & 0x0F];
62
+ }
63
+ return new String(hexChars, StandardCharsets.UTF_8);
64
+ }
65
+ }
@@ -130,6 +130,9 @@ public class Bridge {
130
130
  // A list of listeners that trigger when webView events occur
131
131
  private List<WebViewListener> webViewListeners = new ArrayList<>();
132
132
 
133
+ // An interface to manipulate route resolving
134
+ private RouteProcessor routeProcessor;
135
+
133
136
  /**
134
137
  * Create the Bridge with a reference to the main {@link Activity} for the
135
138
  * app, and a reference to the {@link WebView} our app will use.
@@ -444,7 +447,10 @@ public class Bridge {
444
447
  Logger.debug("WebView background color not applied");
445
448
  }
446
449
 
447
- webView.requestFocusFromTouch();
450
+ if (config.isInitialFocus()) {
451
+ webView.requestFocusFromTouch();
452
+ }
453
+
448
454
  WebView.setWebContentsDebuggingEnabled(this.config.isWebContentsDebuggingEnabled());
449
455
  }
450
456
 
@@ -1190,6 +1196,14 @@ public class Bridge {
1190
1196
  this.webViewListeners = webViewListeners;
1191
1197
  }
1192
1198
 
1199
+ RouteProcessor getRouteProcessor() {
1200
+ return routeProcessor;
1201
+ }
1202
+
1203
+ void setRouteProcessor(RouteProcessor routeProcessor) {
1204
+ this.routeProcessor = routeProcessor;
1205
+ }
1206
+
1193
1207
  /**
1194
1208
  * Add a listener that the WebViewClient can trigger on certain events.
1195
1209
  * @param webViewListener A {@link WebViewListener} to add.
@@ -1213,6 +1227,7 @@ public class Bridge {
1213
1227
  private List<Class<? extends Plugin>> plugins = new ArrayList<>();
1214
1228
  private AppCompatActivity activity;
1215
1229
  private Fragment fragment;
1230
+ private RouteProcessor routeProcessor;
1216
1231
  private final List<WebViewListener> webViewListeners = new ArrayList<>();
1217
1232
 
1218
1233
  public Builder(AppCompatActivity activity) {
@@ -1265,6 +1280,11 @@ public class Bridge {
1265
1280
  return this;
1266
1281
  }
1267
1282
 
1283
+ public Builder setRouteProcessor(RouteProcessor routeProcessor) {
1284
+ this.routeProcessor = routeProcessor;
1285
+ return this;
1286
+ }
1287
+
1268
1288
  public Bridge create() {
1269
1289
  // Cordova initialization
1270
1290
  ConfigXmlParser parser = new ConfigXmlParser();
@@ -1288,6 +1308,7 @@ public class Bridge {
1288
1308
  Bridge bridge = new Bridge(activity, fragment, webView, plugins, cordovaInterface, pluginManager, preferences, config);
1289
1309
  bridge.setCordovaWebView(mockWebView);
1290
1310
  bridge.setWebViewListeners(webViewListeners);
1311
+ bridge.setRouteProcessor(routeProcessor);
1291
1312
 
1292
1313
  if (instanceState != null) {
1293
1314
  bridge.restoreInstanceState(instanceState);
@@ -12,11 +12,11 @@ public class BridgeActivity extends AppCompatActivity {
12
12
 
13
13
  protected Bridge bridge;
14
14
  protected boolean keepRunning = true;
15
- private CapConfig config;
15
+ protected CapConfig config;
16
16
 
17
- private int activityDepth = 0;
18
- private List<Class<? extends Plugin>> initialPlugins = new ArrayList<>();
19
- private final Bridge.Builder bridgeBuilder = new Bridge.Builder(this);
17
+ protected int activityDepth = 0;
18
+ protected List<Class<? extends Plugin>> initialPlugins = new ArrayList<>();
19
+ protected final Bridge.Builder bridgeBuilder = new Bridge.Builder(this);
20
20
 
21
21
  @Override
22
22
  protected void onCreate(Bundle savedInstanceState) {
@@ -66,7 +66,7 @@ public class BridgeActivity extends AppCompatActivity {
66
66
  this.load();
67
67
  }
68
68
 
69
- private void load() {
69
+ protected void load() {
70
70
  Logger.debug("Starting BridgeActivity");
71
71
 
72
72
  bridge = bridgeBuilder.addPlugins(initialPlugins).setConfig(config).create();
@@ -40,6 +40,7 @@ public class CapConfig {
40
40
  private boolean captureInput = false;
41
41
  private boolean webContentsDebuggingEnabled = false;
42
42
  private boolean loggingEnabled = true;
43
+ private boolean initialFocus = true;
43
44
 
44
45
  // Embedded
45
46
  private String startPath;
@@ -116,6 +117,7 @@ public class CapConfig {
116
117
  this.captureInput = builder.captureInput;
117
118
  this.webContentsDebuggingEnabled = builder.webContentsDebuggingEnabled;
118
119
  this.loggingEnabled = builder.loggingEnabled;
120
+ this.initialFocus = builder.initialFocus;
119
121
 
120
122
  // Embedded
121
123
  this.startPath = builder.startPath;
@@ -187,6 +189,8 @@ public class CapConfig {
187
189
  loggingEnabled = isDebug;
188
190
  }
189
191
 
192
+ initialFocus = JSONUtils.getBoolean(configJSON, "android.initialFocus", initialFocus);
193
+
190
194
  // Plugins
191
195
  pluginsConfiguration = deserializePluginsConfig(JSONUtils.getObject(configJSON, "plugins"));
192
196
  }
@@ -243,6 +247,10 @@ public class CapConfig {
243
247
  return loggingEnabled;
244
248
  }
245
249
 
250
+ public boolean isInitialFocus() {
251
+ return initialFocus;
252
+ }
253
+
246
254
  public PluginConfig getPluginConfiguration(String pluginId) {
247
255
  PluginConfig pluginConfig = pluginsConfiguration.get(pluginId);
248
256
  if (pluginConfig == null) {
@@ -398,6 +406,7 @@ public class CapConfig {
398
406
  private boolean captureInput = false;
399
407
  private Boolean webContentsDebuggingEnabled = null;
400
408
  private boolean loggingEnabled = true;
409
+ private boolean initialFocus = false;
401
410
 
402
411
  // Embedded
403
412
  private String startPath = null;
@@ -496,5 +505,10 @@ public class CapConfig {
496
505
  this.loggingEnabled = enabled;
497
506
  return this;
498
507
  }
508
+
509
+ public Builder setInitialFocus(boolean focus) {
510
+ this.initialFocus = focus;
511
+ return this;
512
+ }
499
513
  }
500
514
  }
@@ -0,0 +1,28 @@
1
+ package com.getcapacitor;
2
+
3
+ /**
4
+ * An data class used in conjunction with RouteProcessor.
5
+ *
6
+ * @see com.getcapacitor.RouteProcessor
7
+ */
8
+ public class ProcessedRoute {
9
+
10
+ private String path;
11
+ private boolean isAsset;
12
+
13
+ public String getPath() {
14
+ return path;
15
+ }
16
+
17
+ public void setPath(String path) {
18
+ this.path = path;
19
+ }
20
+
21
+ public boolean isAsset() {
22
+ return isAsset;
23
+ }
24
+
25
+ public void setAsset(boolean asset) {
26
+ isAsset = asset;
27
+ }
28
+ }
@@ -0,0 +1,8 @@
1
+ package com.getcapacitor;
2
+
3
+ /**
4
+ * An interface used in the processing of routes
5
+ */
6
+ public interface RouteProcessor {
7
+ ProcessedRoute process(String basePath, String path);
8
+ }
@@ -24,7 +24,6 @@ import android.webkit.WebResourceResponse;
24
24
  import java.io.IOException;
25
25
  import java.io.InputStream;
26
26
  import java.net.HttpURLConnection;
27
- import java.net.SocketTimeoutException;
28
27
  import java.net.URL;
29
28
  import java.net.URLConnection;
30
29
  import java.nio.charset.StandardCharsets;
@@ -256,6 +255,12 @@ public class WebViewLocalServer {
256
255
  InputStream responseStream;
257
256
  try {
258
257
  String startPath = this.basePath + "/index.html";
258
+ if (bridge.getRouteProcessor() != null) {
259
+ ProcessedRoute processedRoute = bridge.getRouteProcessor().process(this.basePath, "/index.html");
260
+ startPath = processedRoute.getPath();
261
+ isAsset = processedRoute.isAsset();
262
+ }
263
+
259
264
  if (isAsset) {
260
265
  responseStream = protocolHandler.openAsset(startPath);
261
266
  } else {
@@ -467,13 +472,25 @@ public class WebViewLocalServer {
467
472
  public InputStream handle(Uri url) {
468
473
  InputStream stream = null;
469
474
  String path = url.getPath();
475
+
476
+ // Pass path to routeProcessor if present
477
+ RouteProcessor routeProcessor = bridge.getRouteProcessor();
478
+ if (routeProcessor != null) {
479
+ ProcessedRoute processedRoute = bridge.getRouteProcessor().process("", path);
480
+ path = processedRoute.getPath();
481
+ isAsset = processedRoute.isAsset();
482
+ }
483
+
470
484
  try {
471
485
  if (path.startsWith(capacitorContentStart)) {
472
486
  stream = protocolHandler.openContentUrl(url);
473
- } else if (path.startsWith(capacitorFileStart) || !isAsset) {
474
- if (!path.startsWith(capacitorFileStart)) {
487
+ } else if (path.startsWith(capacitorFileStart)) {
488
+ stream = protocolHandler.openFile(path);
489
+ } else if (!isAsset) {
490
+ if (routeProcessor == null) {
475
491
  path = basePath + url.getPath();
476
492
  }
493
+
477
494
  stream = protocolHandler.openFile(path);
478
495
  } else {
479
496
  stream = protocolHandler.openAsset(assetPath + path);
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@capacitor/android",
3
- "version": "3.4.3",
3
+ "version": "3.6.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)",
@@ -22,10 +22,10 @@
22
22
  "verify": "./gradlew clean lint build test -b capacitor/build.gradle"
23
23
  },
24
24
  "peerDependencies": {
25
- "@capacitor/core": "^3.4.0"
25
+ "@capacitor/core": "^3.6.0"
26
26
  },
27
27
  "publishConfig": {
28
28
  "access": "public"
29
29
  },
30
- "gitHead": "33e9b342790ddedfb654c589ffde18b101d4cd98"
30
+ "gitHead": "1e06a199a44bb5321f0fb48b5fbca961cc1dbb50"
31
31
  }