diff --git a/android/capacitor/src/main/java/com/getcapacitor/Bridge.java b/android/capacitor/src/main/java/com/getcapacitor/Bridge.java index 0d5f0ad86..7115ebd31 100644 --- a/android/capacitor/src/main/java/com/getcapacitor/Bridge.java +++ b/android/capacitor/src/main/java/com/getcapacitor/Bridge.java @@ -1511,6 +1511,12 @@ public Bridge create() { preferences, config ); + + if (webView instanceof CapacitorWebView) { + CapacitorWebView capacitorWebView = (CapacitorWebView) webView; + capacitorWebView.setBridge(bridge); + } + bridge.setCordovaWebView(mockWebView); bridge.setWebViewListeners(webViewListeners); bridge.setRouteProcessor(routeProcessor); diff --git a/android/capacitor/src/main/java/com/getcapacitor/CapConfig.java b/android/capacitor/src/main/java/com/getcapacitor/CapConfig.java index 75e3ace0d..2f417a7f5 100644 --- a/android/capacitor/src/main/java/com/getcapacitor/CapConfig.java +++ b/android/capacitor/src/main/java/com/getcapacitor/CapConfig.java @@ -3,13 +3,14 @@ import static com.getcapacitor.Bridge.CAPACITOR_HTTP_SCHEME; import static com.getcapacitor.Bridge.DEFAULT_ANDROID_WEBVIEW_VERSION; import static com.getcapacitor.Bridge.MINIMUM_ANDROID_WEBVIEW_VERSION; -import static com.getcapacitor.FileUtils.readFile; +import static com.getcapacitor.FileUtils.readFileFromAssets; import android.content.Context; import android.content.pm.ApplicationInfo; import android.content.res.AssetManager; import androidx.annotation.Nullable; import com.getcapacitor.util.JSONUtils; +import java.io.File; import java.io.IOException; import java.util.Arrays; import java.util.HashMap; @@ -78,7 +79,7 @@ public CapConfig(AssetManager assetManager, JSONObject config) { this.configJSON = config; } else { // Load the capacitor.config.json - loadConfig(assetManager); + loadConfigFromAssets(assetManager, null); } deserializeConfig(null); @@ -98,7 +99,47 @@ public static CapConfig loadDefault(Context context) { return config; } - config.loadConfig(context.getAssets()); + config.loadConfigFromAssets(context.getAssets(), null); + config.deserializeConfig(context); + return config; + } + + /** + * Constructs a Capacitor Configuration from config.json file within the app assets. + * + * @param context The context. + * @param path A path relative to the root assets directory. + * @return A loaded config file, if successful. + */ + public static CapConfig loadFromAssets(Context context, String path) { + CapConfig config = new CapConfig(); + + if (context == null) { + Logger.error("Capacitor Config could not be created from file. Context must not be null."); + return config; + } + + config.loadConfigFromAssets(context.getAssets(), path); + config.deserializeConfig(context); + return config; + } + + /** + * Constructs a Capacitor Configuration from config.json file within the app file-space. + * + * @param context The context. + * @param path A path relative to the root of the app file-space. + * @return A loaded config file, if successful. + */ + public static CapConfig loadFromFile(Context context, String path) { + CapConfig config = new CapConfig(); + + if (context == null) { + Logger.error("Capacitor Config could not be created from file. Context must not be null."); + return config; + } + + config.loadConfigFromFile(path); config.deserializeConfig(context); return config; } @@ -142,10 +183,20 @@ private CapConfig(Builder builder) { /** * Loads a Capacitor Configuration JSON file into a Capacitor Configuration object. + * An optional path string can be provided to look for the config in a subdirectory path. */ - private void loadConfig(AssetManager assetManager) { + private void loadConfigFromAssets(AssetManager assetManager, String path) { + if (path == null) { + path = ""; + } else { + // Add slash at the end to form a proper file path if going deeper in assets dir + if (path.charAt(path.length() - 1) != '/') { + path = path + "/"; + } + } + try { - String jsonString = readFile(assetManager, "capacitor.config.json"); + String jsonString = readFileFromAssets(assetManager, path + "capacitor.config.json"); configJSON = new JSONObject(jsonString); } catch (IOException ex) { Logger.error("Unable to load capacitor.config.json. Run npx cap copy first", ex); @@ -154,6 +205,31 @@ private void loadConfig(AssetManager assetManager) { } } + /** + * Loads a Capacitor Configuration JSON file into a Capacitor Configuration object. + * An optional path string can be provided to look for the config in a subdirectory path. + */ + private void loadConfigFromFile(String path) { + if (path == null) { + path = ""; + } else { + // Add slash at the end to form a proper file path if going deeper in assets dir + if (path.charAt(path.length() - 1) != '/') { + path = path + "/"; + } + } + + try { + File configFile = new File(path + "capacitor.config.json"); + String jsonString = FileUtils.readFileFromDisk(configFile); + configJSON = new JSONObject(jsonString); + } catch (JSONException ex) { + Logger.error("Unable to parse capacitor.config.json. Make sure it's valid json", ex); + } catch (IOException ex) { + Logger.error("Unable to load capacitor.config.json.", ex); + } + } + /** * Deserializes the config from JSON into a Capacitor Configuration object. */ diff --git a/android/capacitor/src/main/java/com/getcapacitor/CapacitorWebView.java b/android/capacitor/src/main/java/com/getcapacitor/CapacitorWebView.java index 2320bdd09..e46b904a8 100644 --- a/android/capacitor/src/main/java/com/getcapacitor/CapacitorWebView.java +++ b/android/capacitor/src/main/java/com/getcapacitor/CapacitorWebView.java @@ -11,14 +11,25 @@ public class CapacitorWebView extends WebView { private BaseInputConnection capInputConnection; + private Bridge bridge; public CapacitorWebView(Context context, AttributeSet attrs) { super(context, attrs); } + public void setBridge(Bridge bridge) { + this.bridge = bridge; + } + @Override public InputConnection onCreateInputConnection(EditorInfo outAttrs) { - CapConfig config = CapConfig.loadDefault(getContext()); + CapConfig config; + if (bridge != null) { + config = bridge.getConfig(); + } else { + config = CapConfig.loadDefault(getContext()); + } + boolean captureInput = config.isInputCaptured(); if (captureInput) { if (capInputConnection == null) { diff --git a/android/capacitor/src/main/java/com/getcapacitor/FileUtils.java b/android/capacitor/src/main/java/com/getcapacitor/FileUtils.java index 4e5e2bd85..47add8cd0 100644 --- a/android/capacitor/src/main/java/com/getcapacitor/FileUtils.java +++ b/android/capacitor/src/main/java/com/getcapacitor/FileUtils.java @@ -37,6 +37,7 @@ import java.io.BufferedReader; import java.io.File; import java.io.FileOutputStream; +import java.io.FileReader; import java.io.IOException; import java.io.InputStream; import java.io.InputStreamReader; @@ -142,19 +143,38 @@ private static String legacyPrimaryPath(String pathPart) { } /** - * Read a plaintext file. + * Read a plaintext file from the assets directory. * * @param assetManager Used to open the file. * @param fileName The path of the file to read. * @return The contents of the file path. * @throws IOException Thrown if any issues reading the provided file path. */ - static String readFile(AssetManager assetManager, String fileName) throws IOException { + static String readFileFromAssets(AssetManager assetManager, String fileName) throws IOException { try (BufferedReader reader = new BufferedReader(new InputStreamReader(assetManager.open(fileName)))) { StringBuilder buffer = new StringBuilder(); String line; while ((line = reader.readLine()) != null) { - buffer.append(line + "\n"); + buffer.append(line).append("\n"); + } + + return buffer.toString(); + } + } + + /** + * Read a plaintext file from within the app disk space. + * + * @param file The file to read. + * @return The contents of the file path. + * @throws IOException Thrown if any issues reading the provided file path. + */ + static String readFileFromDisk(File file) throws IOException { + try (BufferedReader reader = new BufferedReader(new FileReader(file))) { + StringBuilder buffer = new StringBuilder(); + String line; + while ((line = reader.readLine()) != null) { + buffer.append(line).append("\n"); } return buffer.toString(); diff --git a/android/capacitor/src/main/java/com/getcapacitor/JSExport.java b/android/capacitor/src/main/java/com/getcapacitor/JSExport.java index 8d21f72c6..382f4b5d3 100644 --- a/android/capacitor/src/main/java/com/getcapacitor/JSExport.java +++ b/android/capacitor/src/main/java/com/getcapacitor/JSExport.java @@ -1,6 +1,6 @@ package com.getcapacitor; -import static com.getcapacitor.FileUtils.readFile; +import static com.getcapacitor.FileUtils.readFileFromAssets; import android.content.Context; import android.text.TextUtils; @@ -24,7 +24,7 @@ public static String getGlobalJS(Context context, boolean loggingEnabled, boolea public static String getCordovaJS(Context context) { String fileContent = ""; try { - fileContent = readFile(context.getAssets(), "public/cordova.js"); + fileContent = readFileFromAssets(context.getAssets(), "public/cordova.js"); } catch (IOException ex) { Logger.error("Unable to read public/cordova.js file, Cordova plugins will not work"); } @@ -34,7 +34,7 @@ public static String getCordovaJS(Context context) { public static String getCordovaPluginsFileJS(Context context) { String fileContent = ""; try { - fileContent = readFile(context.getAssets(), "public/cordova_plugins.js"); + fileContent = readFileFromAssets(context.getAssets(), "public/cordova_plugins.js"); } catch (IOException ex) { Logger.error("Unable to read public/cordova_plugins.js file, Cordova plugins will not work"); } @@ -91,7 +91,7 @@ public static String getFilesContent(Context context, String path) { } } } else { - return readFile(context.getAssets(), path); + return readFileFromAssets(context.getAssets(), path); } } catch (IOException ex) { Logger.warn("Unable to read file at path " + path);