@capacitor/android 4.0.0-alpha.2 → 4.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.
package/CHANGELOG.md CHANGED
@@ -3,6 +3,37 @@
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
+ # [4.0.0-beta.0](https://github.com/ionic-team/capacitor/compare/3.6.0...4.0.0-beta.0) (2022-06-17)
7
+
8
+
9
+ ### Bug Fixes
10
+
11
+ * **android:** make removeAllListeners return a promise ([#5527](https://github.com/ionic-team/capacitor/issues/5527)) ([6f4d858](https://github.com/ionic-team/capacitor/commit/6f4d858ea879d97109c0c7da2d664d04806adc2a))
12
+ * **android:** prevent app from loading if server.url is invalid ([d4a0dea](https://github.com/ionic-team/capacitor/commit/d4a0deaa37eda4476f0be030e266c2c1260fc6e8))
13
+
14
+
15
+ ### Features
16
+
17
+ * **android:** don't allow server.androidScheme to be set to schemes handled by WebView ([01285ba](https://github.com/ionic-team/capacitor/commit/01285ba253d602b08a41240ad2ccf370730d51a3))
18
+ * **android:** set default targetSDK to 31 ([#5442](https://github.com/ionic-team/capacitor/issues/5442)) ([4442459](https://github.com/ionic-team/capacitor/commit/4442459b24cdbac25cb1e4de11583d22c21452b3))
19
+ * **android:** set default targetSDK to 32 ([#5611](https://github.com/ionic-team/capacitor/issues/5611)) ([416b966](https://github.com/ionic-team/capacitor/commit/416b9662fbf6233d23216c0c0441862603c3a723))
20
+ * **android:** Upgrade gradle to 7.4 ([#5445](https://github.com/ionic-team/capacitor/issues/5445)) ([28eaf18](https://github.com/ionic-team/capacitor/commit/28eaf1851fa7a912917dbb40c68fb4dd583d08ad))
21
+ * **android:** Use java 11 ([#5552](https://github.com/ionic-team/capacitor/issues/5552)) ([e47959f](https://github.com/ionic-team/capacitor/commit/e47959fcbd6a89b97b1275a5814fdb4e7ce30672))
22
+
23
+
24
+
25
+
26
+
27
+ # [3.6.0](https://github.com/ionic-team/capacitor/compare/3.5.1...3.6.0) (2022-06-17)
28
+
29
+
30
+ ### Features
31
+
32
+ * **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))
33
+ * **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))
34
+
35
+
36
+
6
37
  # [4.0.0-alpha.2](https://github.com/ionic-team/capacitor/compare/3.4.1...4.0.0-alpha.2) (2022-05-12)
7
38
 
8
39
 
@@ -22,6 +53,25 @@ See [Conventional Commits](https://conventionalcommits.org) for commit guideline
22
53
 
23
54
 
24
55
 
56
+ ## [3.5.1](https://github.com/ionic-team/capacitor/compare/3.5.0...3.5.1) (2022-05-04)
57
+
58
+
59
+ ### Bug Fixes
60
+
61
+ * **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))
62
+
63
+
64
+
65
+
66
+
67
+ # [3.5.0](https://github.com/ionic-team/capacitor/compare/3.4.3...3.5.0) (2022-04-22)
68
+
69
+
70
+ ### Features
71
+
72
+ * **android:** Add overridable routing for WebViewLocalServer ([#5553](https://github.com/ionic-team/capacitor/issues/5553)) ([3bb288e](https://github.com/ionic-team/capacitor/commit/3bb288e848c5c0e49c1e58c0782e0b1ffd7b1f31))
73
+
74
+
25
75
 
26
76
  # [4.0.0-alpha.1](https://github.com/ionic-team/capacitor/compare/3.4.1...4.0.0-alpha.1) (2022-03-25)
27
77
 
@@ -33,6 +83,18 @@ See [Conventional Commits](https://conventionalcommits.org) for commit guideline
33
83
 
34
84
 
35
85
 
86
+ ## [3.4.3](https://github.com/ionic-team/capacitor/compare/3.4.2...3.4.3) (2022-03-04)
87
+
88
+ **Note:** Version bump only for package @capacitor/android
89
+
90
+
91
+
92
+
93
+
94
+ ## [3.4.2](https://github.com/ionic-team/capacitor/compare/3.4.1...3.4.2) (2022-03-03)
95
+
96
+ **Note:** Version bump only for package @capacitor/android
97
+
36
98
 
37
99
 
38
100
  ## [3.4.1](https://github.com/ionic-team/capacitor/compare/3.4.0...3.4.1) (2022-02-09)
@@ -1,8 +1,8 @@
1
1
  ext {
2
2
  androidxActivityVersion = project.hasProperty('androidxActivityVersion') ? rootProject.ext.androidxActivityVersion : '1.4.0'
3
- androidxAppCompatVersion = project.hasProperty('androidxAppCompatVersion') ? rootProject.ext.androidxAppCompatVersion : '1.4.1'
3
+ androidxAppCompatVersion = project.hasProperty('androidxAppCompatVersion') ? rootProject.ext.androidxAppCompatVersion : '1.4.2'
4
4
  androidxCoordinatorLayoutVersion = project.hasProperty('androidxCoordinatorLayoutVersion') ? rootProject.ext.androidxCoordinatorLayoutVersion : '1.2.0'
5
- androidxCoreVersion = project.hasProperty('androidxCoreVersion') ? rootProject.ext.androidxCoreVersion : '1.7.0'
5
+ androidxCoreVersion = project.hasProperty('androidxCoreVersion') ? rootProject.ext.androidxCoreVersion : '1.8.0'
6
6
  androidxFragmentVersion = project.hasProperty('androidxFragmentVersion') ? rootProject.ext.androidxFragmentVersion : '1.4.1'
7
7
  junitVersion = project.hasProperty('junitVersion') ? rootProject.ext.junitVersion : '4.13.2'
8
8
  androidxJunitVersion = project.hasProperty('androidxJunitVersion') ? rootProject.ext.androidxJunitVersion : '1.1.3'
@@ -17,7 +17,7 @@ buildscript {
17
17
  mavenCentral()
18
18
  }
19
19
  dependencies {
20
- classpath 'com.android.tools.build:gradle:7.1.1'
20
+ classpath 'com.android.tools.build:gradle:7.2.1'
21
21
  }
22
22
  }
23
23
 
@@ -26,10 +26,10 @@ tasks.withType(Javadoc).all { enabled = false }
26
26
  apply plugin: 'com.android.library'
27
27
 
28
28
  android {
29
- compileSdkVersion project.hasProperty('compileSdkVersion') ? rootProject.ext.compileSdkVersion : 31
29
+ compileSdkVersion project.hasProperty('compileSdkVersion') ? rootProject.ext.compileSdkVersion : 32
30
30
  defaultConfig {
31
31
  minSdkVersion project.hasProperty('minSdkVersion') ? rootProject.ext.minSdkVersion : 22
32
- targetSdkVersion project.hasProperty('targetSdkVersion') ? rootProject.ext.targetSdkVersion : 31
32
+ targetSdkVersion project.hasProperty('targetSdkVersion') ? rootProject.ext.targetSdkVersion : 32
33
33
  versionCode 1
34
34
  versionName "1.0"
35
35
  consumerProguardFiles 'proguard-rules.pro'
@@ -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
+ }
@@ -22,6 +22,7 @@ import androidx.activity.result.contract.ActivityResultContract;
22
22
  import androidx.annotation.NonNull;
23
23
  import androidx.appcompat.app.AppCompatActivity;
24
24
  import androidx.core.app.ActivityCompat;
25
+ import androidx.core.content.pm.PackageInfoCompat;
25
26
  import androidx.fragment.app.Fragment;
26
27
  import com.getcapacitor.android.R;
27
28
  import com.getcapacitor.annotation.CapacitorPlugin;
@@ -130,6 +131,9 @@ public class Bridge {
130
131
  // A list of listeners that trigger when webView events occur
131
132
  private List<WebViewListener> webViewListeners = new ArrayList<>();
132
133
 
134
+ // An interface to manipulate route resolving
135
+ private RouteProcessor routeProcessor;
136
+
133
137
  /**
134
138
  * Create the Bridge with a reference to the main {@link Activity} for the
135
139
  * app, and a reference to the {@link WebView} our app will use.
@@ -293,7 +297,7 @@ public class Bridge {
293
297
 
294
298
  try {
295
299
  PackageInfo pInfo = getContext().getPackageManager().getPackageInfo(getContext().getPackageName(), 0);
296
- versionCode = Integer.toString(pInfo.versionCode);
300
+ versionCode = Integer.toString((int) PackageInfoCompat.getLongVersionCode(pInfo));
297
301
  versionName = pInfo.versionName;
298
302
  } catch (Exception ex) {
299
303
  Logger.error("Unable to get package info", ex);
@@ -421,7 +425,6 @@ public class Bridge {
421
425
  settings.setDomStorageEnabled(true);
422
426
  settings.setGeolocationEnabled(true);
423
427
  settings.setDatabaseEnabled(true);
424
- settings.setAppCacheEnabled(true);
425
428
  settings.setMediaPlaybackRequiresUserGesture(false);
426
429
  settings.setJavaScriptCanOpenWindowsAutomatically(true);
427
430
  if (this.config.isMixedContentAllowed()) {
@@ -447,7 +450,10 @@ public class Bridge {
447
450
  Logger.debug("WebView background color not applied");
448
451
  }
449
452
 
450
- webView.requestFocusFromTouch();
453
+ if (config.isInitialFocus()) {
454
+ webView.requestFocusFromTouch();
455
+ }
456
+
451
457
  WebView.setWebContentsDebuggingEnabled(this.config.isWebContentsDebuggingEnabled());
452
458
  }
453
459
 
@@ -472,6 +478,17 @@ public class Bridge {
472
478
  }
473
479
  }
474
480
 
481
+ @SuppressWarnings("deprecation")
482
+ private String getLegacyPluginName(Class<? extends Plugin> pluginClass) {
483
+ NativePlugin legacyPluginAnnotation = pluginClass.getAnnotation(NativePlugin.class);
484
+ if (legacyPluginAnnotation == null) {
485
+ Logger.error("Plugin doesn't have the @CapacitorPlugin annotation. Please add it");
486
+ return null;
487
+ }
488
+
489
+ return legacyPluginAnnotation.name();
490
+ }
491
+
475
492
  /**
476
493
  * Register a plugin class
477
494
  * @param pluginClass a class inheriting from Plugin
@@ -481,14 +498,10 @@ public class Bridge {
481
498
 
482
499
  CapacitorPlugin pluginAnnotation = pluginClass.getAnnotation(CapacitorPlugin.class);
483
500
  if (pluginAnnotation == null) {
484
- NativePlugin legacyPluginAnnotation = pluginClass.getAnnotation(NativePlugin.class);
485
-
486
- if (legacyPluginAnnotation == null) {
487
- Logger.error("Plugin doesn't have the @CapacitorPlugin annotation. Please add it");
501
+ pluginName = this.getLegacyPluginName(pluginClass);
502
+ if (pluginName == null) {
488
503
  return;
489
504
  }
490
-
491
- pluginName = legacyPluginAnnotation.name();
492
505
  } else {
493
506
  pluginName = pluginAnnotation.name();
494
507
  }
@@ -527,6 +540,7 @@ public class Bridge {
527
540
  * @return
528
541
  */
529
542
  @Deprecated
543
+ @SuppressWarnings("deprecation")
530
544
  public PluginHandle getPluginWithRequestCode(int requestCode) {
531
545
  for (PluginHandle handle : this.plugins.values()) {
532
546
  int[] requestCodes;
@@ -842,6 +856,7 @@ public class Bridge {
842
856
  }
843
857
 
844
858
  @Deprecated
859
+ @SuppressWarnings("deprecation")
845
860
  public void startActivityForPluginWithResult(PluginCall call, Intent intent, int requestCode) {
846
861
  Logger.debug("Starting activity for result");
847
862
 
@@ -859,6 +874,7 @@ public class Bridge {
859
874
  * @param grantResults the set of granted/denied permissions
860
875
  * @return true if permission code was handled by a plugin explicitly, false if not
861
876
  */
877
+ @SuppressWarnings("deprecation")
862
878
  boolean onRequestPermissionsResult(int requestCode, String[] permissions, int[] grantResults) {
863
879
  PluginHandle plugin = getPluginWithRequestCode(requestCode);
864
880
 
@@ -998,6 +1014,7 @@ public class Bridge {
998
1014
  * @param resultCode
999
1015
  * @param data
1000
1016
  */
1017
+ @SuppressWarnings("deprecation")
1001
1018
  boolean onActivityResult(int requestCode, int resultCode, Intent data) {
1002
1019
  PluginHandle plugin = getPluginWithRequestCode(requestCode);
1003
1020
 
@@ -1193,6 +1210,14 @@ public class Bridge {
1193
1210
  this.webViewListeners = webViewListeners;
1194
1211
  }
1195
1212
 
1213
+ RouteProcessor getRouteProcessor() {
1214
+ return routeProcessor;
1215
+ }
1216
+
1217
+ void setRouteProcessor(RouteProcessor routeProcessor) {
1218
+ this.routeProcessor = routeProcessor;
1219
+ }
1220
+
1196
1221
  /**
1197
1222
  * Add a listener that the WebViewClient can trigger on certain events.
1198
1223
  * @param webViewListener A {@link WebViewListener} to add.
@@ -1216,6 +1241,7 @@ public class Bridge {
1216
1241
  private List<Class<? extends Plugin>> plugins = new ArrayList<>();
1217
1242
  private AppCompatActivity activity;
1218
1243
  private Fragment fragment;
1244
+ private RouteProcessor routeProcessor;
1219
1245
  private final List<WebViewListener> webViewListeners = new ArrayList<>();
1220
1246
 
1221
1247
  public Builder(AppCompatActivity activity) {
@@ -1268,6 +1294,11 @@ public class Bridge {
1268
1294
  return this;
1269
1295
  }
1270
1296
 
1297
+ public Builder setRouteProcessor(RouteProcessor routeProcessor) {
1298
+ this.routeProcessor = routeProcessor;
1299
+ return this;
1300
+ }
1301
+
1271
1302
  public Bridge create() {
1272
1303
  // Cordova initialization
1273
1304
  ConfigXmlParser parser = new ConfigXmlParser();
@@ -1291,6 +1322,7 @@ public class Bridge {
1291
1322
  Bridge bridge = new Bridge(activity, fragment, webView, plugins, cordovaInterface, pluginManager, preferences, config);
1292
1323
  bridge.setCordovaWebView(mockWebView);
1293
1324
  bridge.setWebViewListeners(webViewListeners);
1325
+ bridge.setRouteProcessor(routeProcessor);
1294
1326
 
1295
1327
  if (instanceState != null) {
1296
1328
  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) {
@@ -26,47 +26,18 @@ public class BridgeActivity extends AppCompatActivity {
26
26
  setTheme(getResources().getIdentifier("AppTheme_NoActionBar", "style", getPackageName()));
27
27
  setTheme(R.style.AppTheme_NoActionBar);
28
28
  setContentView(R.layout.bridge_layout_main);
29
- }
30
-
31
- /**
32
- * Initializes the Capacitor Bridge with the Activity.
33
- * @deprecated It is preferred not to call this method. If it is not called, the bridge is
34
- * initialized automatically. If you need to add additional plugins during initialization,
35
- * use {@link #registerPlugin(Class)} or {@link #registerPlugins(List)}.
36
- *
37
- * @param plugins A list of plugins to initialize with Capacitor
38
- */
39
- @Deprecated
40
- protected void init(Bundle savedInstanceState, List<Class<? extends Plugin>> plugins) {
41
- this.init(savedInstanceState, plugins, null);
42
- }
43
-
44
- /**
45
- * Initializes the Capacitor Bridge with the Activity.
46
- * @deprecated It is preferred not to call this method. If it is not called, the bridge is
47
- * initialized automatically. If you need to add additional plugins during initialization,
48
- * use {@link #registerPlugin(Class)} or {@link #registerPlugins(List)}.
49
- *
50
- * @param plugins A list of plugins to initialize with Capacitor
51
- * @param config An instance of a Capacitor Configuration to use. If null, will load from file
52
- */
53
- @Deprecated
54
- protected void init(Bundle savedInstanceState, List<Class<? extends Plugin>> plugins, CapConfig config) {
55
- this.initialPlugins = plugins;
56
- this.config = config;
29
+ PluginManager loader = new PluginManager(getAssets());
57
30
 
58
- this.load();
59
- }
31
+ try {
32
+ bridgeBuilder.addPlugins(loader.loadPluginClasses());
33
+ } catch (PluginLoadException ex) {
34
+ Logger.error("Error loading plugins.", ex);
35
+ }
60
36
 
61
- /**
62
- * @deprecated This method should not be called manually.
63
- */
64
- @Deprecated
65
- protected void load(Bundle savedInstanceState) {
66
37
  this.load();
67
38
  }
68
39
 
69
- private void load() {
40
+ protected void load() {
70
41
  Logger.debug("Starting BridgeActivity");
71
42
 
72
43
  bridge = bridgeBuilder.addPlugins(initialPlugins).setConfig(config).create();
@@ -96,20 +67,6 @@ public class BridgeActivity extends AppCompatActivity {
96
67
  @Override
97
68
  public void onStart() {
98
69
  super.onStart();
99
-
100
- // Preferred behavior: init() was not called, so we construct the bridge with auto-loaded plugins.
101
- if (bridge == null) {
102
- PluginManager loader = new PluginManager(getAssets());
103
-
104
- try {
105
- bridgeBuilder.addPlugins(loader.loadPluginClasses());
106
- } catch (PluginLoadException ex) {
107
- Logger.error("Error loading plugins.", ex);
108
- }
109
-
110
- this.load();
111
- }
112
-
113
70
  activityDepth++;
114
71
  this.bridge.onStart();
115
72
  Logger.debug("App started");
@@ -147,7 +147,6 @@ public class BridgeWebChromeClient extends WebChromeClient {
147
147
  AlertDialog.Builder builder = new AlertDialog.Builder(view.getContext());
148
148
  builder
149
149
  .setMessage(message)
150
- .setTitle("Alert")
151
150
  .setPositiveButton(
152
151
  "OK",
153
152
  (dialog, buttonIndex) -> {
@@ -187,7 +186,6 @@ public class BridgeWebChromeClient extends WebChromeClient {
187
186
 
188
187
  builder
189
188
  .setMessage(message)
190
- .setTitle("Confirm")
191
189
  .setPositiveButton(
192
190
  "OK",
193
191
  (dialog, buttonIndex) -> {
@@ -236,7 +234,6 @@ public class BridgeWebChromeClient extends WebChromeClient {
236
234
 
237
235
  builder
238
236
  .setMessage(message)
239
- .setTitle("Prompt")
240
237
  .setView(input)
241
238
  .setPositiveButton(
242
239
  "OK",
@@ -28,6 +28,7 @@ public class BridgeWebViewClient extends WebViewClient {
28
28
  return bridge.launchIntent(url);
29
29
  }
30
30
 
31
+ @Deprecated
31
32
  @Override
32
33
  public boolean shouldOverrideUrlLoading(WebView view, String url) {
33
34
  return bridge.launchIntent(Uri.parse(url));
@@ -42,6 +42,7 @@ public class CapConfig {
42
42
  private boolean captureInput = false;
43
43
  private boolean webContentsDebuggingEnabled = false;
44
44
  private boolean loggingEnabled = true;
45
+ private boolean initialFocus = true;
45
46
 
46
47
  // Embedded
47
48
  private String startPath;
@@ -122,6 +123,7 @@ public class CapConfig {
122
123
  this.captureInput = builder.captureInput;
123
124
  this.webContentsDebuggingEnabled = builder.webContentsDebuggingEnabled;
124
125
  this.loggingEnabled = builder.loggingEnabled;
126
+ this.initialFocus = builder.initialFocus;
125
127
 
126
128
  // Embedded
127
129
  this.startPath = builder.startPath;
@@ -198,6 +200,8 @@ public class CapConfig {
198
200
  loggingEnabled = isDebug;
199
201
  }
200
202
 
203
+ initialFocus = JSONUtils.getBoolean(configJSON, "android.initialFocus", initialFocus);
204
+
201
205
  // Plugins
202
206
  pluginsConfiguration = deserializePluginsConfig(JSONUtils.getObject(configJSON, "plugins"));
203
207
  }
@@ -264,6 +268,10 @@ public class CapConfig {
264
268
  return loggingEnabled;
265
269
  }
266
270
 
271
+ public boolean isInitialFocus() {
272
+ return initialFocus;
273
+ }
274
+
267
275
  public PluginConfig getPluginConfiguration(String pluginId) {
268
276
  PluginConfig pluginConfig = pluginsConfiguration.get(pluginId);
269
277
  if (pluginConfig == null) {
@@ -419,6 +427,7 @@ public class CapConfig {
419
427
  private boolean captureInput = false;
420
428
  private Boolean webContentsDebuggingEnabled = null;
421
429
  private boolean loggingEnabled = true;
430
+ private boolean initialFocus = false;
422
431
 
423
432
  // Embedded
424
433
  private String startPath = null;
@@ -517,5 +526,10 @@ public class CapConfig {
517
526
  this.loggingEnabled = enabled;
518
527
  return this;
519
528
  }
529
+
530
+ public Builder setInitialFocus(boolean focus) {
531
+ this.initialFocus = focus;
532
+ return this;
533
+ }
520
534
  }
521
535
  }
@@ -30,6 +30,7 @@ public class CapacitorWebView extends WebView {
30
30
  }
31
31
 
32
32
  @Override
33
+ @SuppressWarnings("deprecation")
33
34
  public boolean dispatchKeyEvent(KeyEvent event) {
34
35
  if (event.getAction() == KeyEvent.ACTION_MULTIPLE) {
35
36
  evaluateJavascript("document.activeElement.value = document.activeElement.value + '" + event.getCharacters() + "';", null);
@@ -77,7 +77,7 @@ public class FileUtils {
77
77
  final String type = split[0];
78
78
 
79
79
  if ("primary".equalsIgnoreCase(type)) {
80
- return Environment.getExternalStorageDirectory() + "/" + split[1];
80
+ return legacyPrimaryPath(split[1]);
81
81
  } else {
82
82
  final int splitIndex = docId.indexOf(':', 1);
83
83
  final String tag = docId.substring(0, splitIndex);
@@ -136,6 +136,11 @@ public class FileUtils {
136
136
  return null;
137
137
  }
138
138
 
139
+ @SuppressWarnings("deprecation")
140
+ private static String legacyPrimaryPath(String pathPart) {
141
+ return Environment.getExternalStorageDirectory() + "/" + pathPart;
142
+ }
143
+
139
144
  /**
140
145
  * Read a plaintext file.
141
146
  *
@@ -789,15 +789,7 @@ public class Plugin {
789
789
  public void requestPermissions(PluginCall call) {
790
790
  CapacitorPlugin annotation = handle.getPluginAnnotation();
791
791
  if (annotation == null) {
792
- // handle permission requests for plugins defined with @NativePlugin (prior to 3.0.0)
793
- NativePlugin legacyAnnotation = this.handle.getLegacyPluginAnnotation();
794
- String[] perms = legacyAnnotation.permissions();
795
- if (perms.length > 0) {
796
- saveCall(call);
797
- pluginRequestPermissions(perms, legacyAnnotation.permissionRequestCode());
798
- } else {
799
- call.resolve();
800
- }
792
+ handleLegacyPermission(call);
801
793
  } else {
802
794
  // handle permission requests for plugins defined with @CapacitorPlugin (since 3.0.0)
803
795
  String[] permAliases = null;
@@ -863,6 +855,19 @@ public class Plugin {
863
855
  }
864
856
  }
865
857
 
858
+ @SuppressWarnings("deprecation")
859
+ private void handleLegacyPermission(PluginCall call) {
860
+ // handle permission requests for plugins defined with @NativePlugin (prior to 3.0.0)
861
+ NativePlugin legacyAnnotation = this.handle.getLegacyPluginAnnotation();
862
+ String[] perms = legacyAnnotation.permissions();
863
+ if (perms.length > 0) {
864
+ saveCall(call);
865
+ pluginRequestPermissions(perms, legacyAnnotation.permissionRequestCode());
866
+ } else {
867
+ call.resolve();
868
+ }
869
+ }
870
+
866
871
  /**
867
872
  * Handle request permissions result. A plugin using the deprecated {@link NativePlugin}
868
873
  * should override this to handle the result, or this method will handle the result
@@ -20,11 +20,14 @@ public class PluginHandle {
20
20
 
21
21
  private final String pluginId;
22
22
 
23
+ @SuppressWarnings("deprecation")
23
24
  private NativePlugin legacyPluginAnnotation;
25
+
24
26
  private CapacitorPlugin pluginAnnotation;
25
27
 
26
28
  private Plugin instance;
27
29
 
30
+ @SuppressWarnings("deprecation")
28
31
  public PluginHandle(Bridge bridge, Class<? extends Plugin> pluginClass) throws InvalidPluginException, PluginLoadException {
29
32
  this.bridge = bridge;
30
33
  this.pluginClass = pluginClass;
@@ -67,6 +70,7 @@ public class PluginHandle {
67
70
  return this.pluginId;
68
71
  }
69
72
 
73
+ @SuppressWarnings("deprecation")
70
74
  public NativePlugin getLegacyPluginAnnotation() {
71
75
  return this.legacyPluginAnnotation;
72
76
  }
@@ -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);
@@ -1,6 +1,6 @@
1
1
  <?xml version="1.0" encoding="utf-8"?>
2
- <resources>
3
- <color name="colorPrimary">#3F51B5</color>
4
- <color name="colorPrimaryDark">#303F9F</color>
5
- <color name="colorAccent">#FF4081</color>
2
+ <resources xmlns:tools="http://schemas.android.com/tools">
3
+ <color tools:ignore="UnusedResources" name="colorPrimary">#3F51B5</color>
4
+ <color tools:ignore="UnusedResources" name="colorPrimaryDark">#303F9F</color>
5
+ <color tools:ignore="UnusedResources" name="colorAccent">#FF4081</color>
6
6
  </resources>
@@ -1,7 +1,2 @@
1
1
  <resources>
2
- <string name="app_name">CapacitorAndroid</string>
3
- <string name="ok">OK</string>
4
- <string name="picture">Picture</string>
5
- <string name="request_permission">Allow this app to take pictures</string>
6
- <string name="camera_error">Unable to use camera</string>
7
2
  </resources>
@@ -1,13 +1,4 @@
1
1
  <resources>
2
-
3
- <!-- Base application theme. -->
4
- <style name="AppTheme" parent="Theme.AppCompat.Light.DarkActionBar">
5
- <!-- Customize your theme here. -->
6
- <item name="colorPrimary">@color/colorPrimary</item>
7
- <item name="colorPrimaryDark">@color/colorPrimaryDark</item>
8
- <item name="colorAccent">@color/colorAccent</item>
9
- </style>
10
-
11
2
  <style name="AppTheme.NoActionBar" parent="Theme.AppCompat.NoActionBar">
12
3
  <item name="windowActionBar">false</item>
13
4
  <item name="windowNoTitle">true</item>
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@capacitor/android",
3
- "version": "4.0.0-alpha.2",
3
+ "version": "4.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)",
@@ -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": "5c588d5bd15b2b939c6efc25b7db9d6af29afae0"
30
+ "gitHead": "d9e553f76fac74df6ab0f2bf5c3da18e51b2282b"
31
31
  }
@@ -1,12 +0,0 @@
1
- <?xml version="1.0" encoding="utf-8"?>
2
- <vector xmlns:android="http://schemas.android.com/apk/res/android"
3
- android:width="16dp"
4
- android:height="16dp"
5
- android:viewportHeight="108"
6
- android:viewportWidth="108">
7
-
8
- <path
9
- android:width="1dp"
10
- android:color="@android:color/transparent" />
11
-
12
- </vector>