diff --git a/.github/workflows/capacitor-bot.yml b/.github/workflows-disabled/capacitor-bot.yml
similarity index 100%
rename from .github/workflows/capacitor-bot.yml
rename to .github/workflows-disabled/capacitor-bot.yml
diff --git a/.github/workflows/ci.yml b/.github/workflows-disabled/ci.yml
similarity index 100%
rename from .github/workflows/ci.yml
rename to .github/workflows-disabled/ci.yml
diff --git a/.github/workflows/needs-reply.yml b/.github/workflows-disabled/needs-reply.yml
similarity index 100%
rename from .github/workflows/needs-reply.yml
rename to .github/workflows-disabled/needs-reply.yml
diff --git a/README.md b/README.md
index e76f0dfd..1b3c3ca4 100644
--- a/README.md
+++ b/README.md
@@ -1,3 +1,91 @@
+# Deprecation Notice
+
+This package is deprecated in favor of https://ionic.io/portals.
+"Portals" provides a better dev-experience and is actively supported by Ionic and newer Capacitor-versions.
+__________
+
+# Embedded Capacitor
+
+This project enables an "embedded usage" of https://capacitorjs.com/ within existing native apps.
+It exists because of the following frustrating situation:
+
+- Capacitor 2.X provides only bad support for "embedded usage", but promised to deliver with Capacitor 3.X [[3405](https://github.com/ionic-team/capacitor/pull/3405)]
+- Capacitor 3.X deliberately destroyed "embedded usage", but promised to deliver an embedded closed-source-solution [[4343](https://github.com/ionic-team/capacitor/issues/4343), [4370](https://github.com/ionic-team/capacitor/issues/4370)]
+
+For the time being, I consider Capacitor 2.X as more stable for embedded usage.
+Therefore, this project only works with Capacitor 2.X.
+
+## Improvements over Ionic's Capacitor
+
+With only minimal changes, this project provides the following improvements over Ionic's Capacitor 2.X:
+
+- Configure custom URL-paths for Android/iOS: [3405](https://github.com/ionic-team/capacitor/pull/3405), [3106](https://github.com/ionic-team/capacitor/issues/3106)
+- Make iOS `CAPBridgeViewController` extensible to better support embedded usage: [1972](https://github.com/ionic-team/capacitor/pull/1972)
+- Fix Android-crashes related to unneeded plugins: [4379](https://github.com/ionic-team/capacitor/issues/4379)
+- Disable splashscreen-plugin by default to speedup launches (you can still enable it).
+
+To convince yourself, here are the differences between this project and Ionic's Capacitor: https://github.com/fkirc/embedded-capacitor/pull/1/files
+
+## Installation
+
+Before you install this project, ensure that regular Capacitor 2.X is working with your project (e.g. it should work in "fullscreen-mode").
+Once you finished a regular Capacitor 2.X setup, replace your `@capacitor/android` or `@capacitor/ios` packages as follows:
+
+`npm uninstall @capacitor/android`
+`npm install capacitor-embedded-android`
+
+`npm uninstall @capacitor/ios`
+`npm install capacitor-embedded-ios`
+
+Next, create symlinks from the original package-locations to the new package-locations:
+
+`ln -s "$PWD/node_modules/capacitor-embedded-android/" node_modules/@capacitor/android`
+`ln -s "$PWD/node_modules/capacitor-embedded-ios/" node_modules/@capacitor/ios`
+
+Those symlinks need to be created every time when `node_modules` is created.
+Therefore, I recommend adding a `postinstall`-script to your `package.json`:
+
+````
+ "scripts": {
+ "postinstall": "ln -s \"$PWD/node_modules/capacitor-embedded-android/\" node_modules/@capacitor/android && ln -s \"$PWD/node_modules/capacitor-embedded-ios/\" node_modules/@capacitor/ios"
+ },
+````
+
+Optionally, I recommend the [capsafe](https://github.com/fkirc/capacitor-build-safety) tool to increase safety and traceability of your Capacitor-apps.
+
+Finally, follow the Android/iOS-specific instructions below.
+
+### Embedded Android
+
+For Android, I recommend to subclass `BridgeFragment` for embedded usage:
+
+````Kotlin
+import android.os.Bundle
+import com.getcapacitor.BridgeFragment
+
+class MyBridgeFragment : BridgeFragment() {
+ override fun onCreate(savedInstanceState: Bundle?) {
+ super.onCreate(savedInstanceState)
+ super.setUrlPath("/#embedded_feature_1") // Set an URL-path for your embedded usage
+ }
+}
+````
+
+### Embedded iOS
+
+For iOS, I recommend to subclass `CAPBridgeViewController` for embedded usage:
+
+````Swift
+public class MyCAPBridgeViewController: CAPBridgeViewController {
+ public override func loadView() {
+ super.setUrlPath(path: "/#embedded_feature_1") // Set an URL-path for your embedded usage
+ super.loadView()
+ }
+}
+````
+
+---
+

diff --git a/android/capacitor/src/main/AndroidManifest.xml b/android/capacitor/src/main/AndroidManifest.xml
index cf142882..94585f59 100644
--- a/android/capacitor/src/main/AndroidManifest.xml
+++ b/android/capacitor/src/main/AndroidManifest.xml
@@ -1,28 +1,4 @@
(https://ionicframework.com) ",
diff --git a/capacitor-cordova-android-plugins/build.gradle b/capacitor-cordova-android-plugins/build.gradle
index 9d81326d..7d72ca94 100644
--- a/capacitor-cordova-android-plugins/build.gradle
+++ b/capacitor-cordova-android-plugins/build.gradle
@@ -18,7 +18,7 @@ android {
compileSdkVersion project.hasProperty('compileSdkVersion') ? rootProject.ext.compileSdkVersion : 29
defaultConfig {
minSdkVersion project.hasProperty('minSdkVersion') ? rootProject.ext.minSdkVersion : 21
- targetSdkVersion targetSdkVersion = project.hasProperty('targetSdkVersion') ? rootProject.ext.targetSdkVersion : 29
+ targetSdkVersion project.hasProperty('targetSdkVersion') ? rootProject.ext.targetSdkVersion : 29
versionCode 1
versionName "1.0"
}
diff --git a/ios/Capacitor/Capacitor/CAPBridgeViewController.swift b/ios/Capacitor/Capacitor/CAPBridgeViewController.swift
index 95abcb00..1aa2f503 100644
--- a/ios/Capacitor/Capacitor/CAPBridgeViewController.swift
+++ b/ios/Capacitor/Capacitor/CAPBridgeViewController.swift
@@ -7,7 +7,7 @@ import UIKit
import WebKit
import Cordova
-public class CAPBridgeViewController: UIViewController, CAPBridgeDelegate, WKScriptMessageHandler, WKUIDelegate, WKNavigationDelegate {
+open class CAPBridgeViewController: UIViewController, CAPBridgeDelegate, WKScriptMessageHandler, WKUIDelegate, WKNavigationDelegate {
private var webView: WKWebView?
@@ -42,8 +42,13 @@ public class CAPBridgeViewController: UIViewController, CAPBridgeDelegate, WKScr
// Construct the Capacitor runtime
public var bridge: CAPBridge?
private var handler: CAPAssetHandler?
-
- override public func loadView() {
+
+ private var urlPath: String?
+ open func setUrlPath(path: String) {
+ self.urlPath = path
+ }
+
+ override open func loadView() {
let configUrl = Bundle.main.url(forResource: "config", withExtension: "xml")
let configParser = XMLParser(contentsOf: configUrl!)!;
configParser.delegate = cordovaParser
@@ -164,7 +169,7 @@ public class CAPBridgeViewController: UIViewController, CAPBridgeDelegate, WKScr
return false
}
- override public func viewDidLoad() {
+ override open func viewDidLoad() {
super.viewDidLoad()
self.becomeFirstResponder()
loadWebView()
@@ -202,6 +207,9 @@ public class CAPBridgeViewController: UIViewController, CAPBridgeDelegate, WKScr
hostname = bridge!.config.getString("server.url") ?? "\(bridge!.getLocalUrl())"
allowNavigationConfig = bridge!.config.getValue("server.allowNavigation") as? Array
+ if let urlPath = self.urlPath {
+ hostname! += urlPath
+ }
if bridge!.isDevMode() && bridge!.config.getString("server.url") != nil {
let toastPlugin = bridge!.getOrLoadPlugin(pluginName: "Toast") as? CAPToastPlugin
@@ -218,7 +226,7 @@ public class CAPBridgeViewController: UIViewController, CAPBridgeDelegate, WKScr
self.handler?.setAssetPath(path)
}
- public func setStatusBarDefaults() {
+ open func setStatusBarDefaults() {
if let plist = Bundle.main.infoDictionary {
if let statusBarHidden = plist["UIStatusBarHidden"] as? Bool {
if (statusBarHidden) {
@@ -239,7 +247,7 @@ public class CAPBridgeViewController: UIViewController, CAPBridgeDelegate, WKScr
}
}
- public func setScreenOrientationDefaults() {
+ open func setScreenOrientationDefaults() {
if let plist = Bundle.main.infoDictionary {
if let orientations = plist["UISupportedInterfaceOrientations"] as? Array {
for orientation in orientations {
@@ -263,19 +271,19 @@ public class CAPBridgeViewController: UIViewController, CAPBridgeDelegate, WKScr
}
}
- public func configureWebView(configuration: WKWebViewConfiguration) {
+ open func configureWebView(configuration: WKWebViewConfiguration) {
configuration.allowsInlineMediaPlayback = true
configuration.suppressesIncrementalRendering = false
configuration.allowsAirPlayForMediaPlayback = true
configuration.mediaTypesRequiringUserActionForPlayback = []
}
- public func webView(_ webView: WKWebView, didStartProvisionalNavigation navigation: WKNavigation!) {
+ open func webView(_ webView: WKWebView, didStartProvisionalNavigation navigation: WKNavigation!) {
// Reset the bridge on each navigation
bridge!.reset()
}
- public func webView(_ webView: WKWebView, decidePolicyFor navigationAction: WKNavigationAction, decisionHandler: @escaping (WKNavigationActionPolicy) -> Void) {
+ open func webView(_ webView: WKWebView, decidePolicyFor navigationAction: WKNavigationAction, decisionHandler: @escaping (WKNavigationActionPolicy) -> Void) {
NotificationCenter.default.post(name: Notification.Name(CAPNotifications.DecidePolicyForNavigationAction.name()), object: navigationAction)
let navUrl = navigationAction.request.url!
@@ -321,7 +329,7 @@ public class CAPBridgeViewController: UIViewController, CAPBridgeDelegate, WKScr
decisionHandler(.allow)
}
- public func webView(_ webView: WKWebView, didFinish navigation: WKNavigation!) {
+ open func webView(_ webView: WKWebView, didFinish navigation: WKNavigation!) {
if case .initialLoad(let isOpaque) = webViewLoadingState {
webView.isOpaque = isOpaque
webViewLoadingState = .subsequentLoad
@@ -329,7 +337,7 @@ public class CAPBridgeViewController: UIViewController, CAPBridgeDelegate, WKScr
CAPLog.print("⚡️ WebView loaded")
}
- public func webView(_ webView: WKWebView, didFail navigation: WKNavigation!, withError error: Error) {
+ open func webView(_ webView: WKWebView, didFail navigation: WKNavigation!, withError error: Error) {
if case .initialLoad(let isOpaque) = webViewLoadingState {
webView.isOpaque = isOpaque
webViewLoadingState = .subsequentLoad
@@ -338,20 +346,20 @@ public class CAPBridgeViewController: UIViewController, CAPBridgeDelegate, WKScr
CAPLog.print("⚡️ Error: " + error.localizedDescription)
}
- public func webView(_ webView: WKWebView, didFailProvisionalNavigation navigation: WKNavigation!, withError error: Error) {
+ open func webView(_ webView: WKWebView, didFailProvisionalNavigation navigation: WKNavigation!, withError error: Error) {
CAPLog.print("⚡️ WebView failed provisional navigation")
CAPLog.print("⚡️ Error: " + error.localizedDescription)
}
- public func webViewWebContentProcessDidTerminate(_ webView: WKWebView) {
+ open func webViewWebContentProcessDidTerminate(_ webView: WKWebView) {
webView.reload()
}
- public override func canPerformUnwindSegueAction(_ action: Selector, from fromViewController: UIViewController, withSender sender: Any) -> Bool {
+ open override func canPerformUnwindSegueAction(_ action: Selector, from fromViewController: UIViewController, withSender sender: Any) -> Bool {
return false
}
- public func userContentController(_ userContentController: WKUserContentController, didReceive message: WKScriptMessage) {
+ open func userContentController(_ userContentController: WKUserContentController, didReceive message: WKScriptMessage) {
guard let bridge = bridge else {
return
}
@@ -448,48 +456,48 @@ public class CAPBridgeViewController: UIViewController, CAPBridgeDelegate, WKScr
return host == pattern
}
- override public func didReceiveMemoryWarning() {
+ override open func didReceiveMemoryWarning() {
super.didReceiveMemoryWarning()
// Dispose of any resources that can be recreated.
}
- override public var prefersStatusBarHidden: Bool {
+ override open var prefersStatusBarHidden: Bool {
get {
return !isStatusBarVisible
}
}
- override public var preferredStatusBarStyle: UIStatusBarStyle {
+ override open var preferredStatusBarStyle: UIStatusBarStyle {
get {
return statusBarStyle
}
}
- override public var preferredStatusBarUpdateAnimation: UIStatusBarAnimation {
+ override open var preferredStatusBarUpdateAnimation: UIStatusBarAnimation {
get {
return statusBarAnimation
}
}
- public func setStatusBarVisible(_ isStatusBarVisible: Bool) {
+ open func setStatusBarVisible(_ isStatusBarVisible: Bool) {
self.isStatusBarVisible = isStatusBarVisible
UIView.animate(withDuration: 0.2, animations: {
self.setNeedsStatusBarAppearanceUpdate()
})
}
- public func setStatusBarStyle(_ statusBarStyle: UIStatusBarStyle) {
+ open func setStatusBarStyle(_ statusBarStyle: UIStatusBarStyle) {
self.statusBarStyle = statusBarStyle
UIView.animate(withDuration: 0.2, animations: {
self.setNeedsStatusBarAppearanceUpdate()
})
}
- public func setStatusBarAnimation(_ statusBarAnimation: UIStatusBarAnimation) {
+ open func setStatusBarAnimation(_ statusBarAnimation: UIStatusBarAnimation) {
self.statusBarAnimation = statusBarAnimation
}
- public func webView(_ webView: WKWebView, runJavaScriptAlertPanelWithMessage message: String, initiatedByFrame frame: WKFrameInfo, completionHandler: @escaping () -> Void) {
+ open func webView(_ webView: WKWebView, runJavaScriptAlertPanelWithMessage message: String, initiatedByFrame frame: WKFrameInfo, completionHandler: @escaping () -> Void) {
let alertController = UIAlertController(title: nil, message: message, preferredStyle: .alert)
@@ -500,7 +508,7 @@ public class CAPBridgeViewController: UIViewController, CAPBridgeDelegate, WKScr
self.present(alertController, animated: true, completion: nil)
}
- public func webView(_ webView: WKWebView, runJavaScriptConfirmPanelWithMessage message: String, initiatedByFrame frame: WKFrameInfo, completionHandler: @escaping (Bool) -> Void) {
+ open func webView(_ webView: WKWebView, runJavaScriptConfirmPanelWithMessage message: String, initiatedByFrame frame: WKFrameInfo, completionHandler: @escaping (Bool) -> Void) {
let alertController = UIAlertController(title: nil, message: message, preferredStyle: .alert)
@@ -515,7 +523,7 @@ public class CAPBridgeViewController: UIViewController, CAPBridgeDelegate, WKScr
self.present(alertController, animated: true, completion: nil)
}
- public func webView(_ webView: WKWebView, runJavaScriptTextInputPanelWithPrompt prompt: String, defaultText: String?, initiatedByFrame frame: WKFrameInfo, completionHandler: @escaping (String?) -> Void) {
+ open func webView(_ webView: WKWebView, runJavaScriptTextInputPanelWithPrompt prompt: String, defaultText: String?, initiatedByFrame frame: WKFrameInfo, completionHandler: @escaping (String?) -> Void) {
let alertController = UIAlertController(title: nil, message: prompt, preferredStyle: .alert)
@@ -541,22 +549,22 @@ public class CAPBridgeViewController: UIViewController, CAPBridgeDelegate, WKScr
self.present(alertController, animated: true, completion: nil)
}
- public func webView(_ webView: WKWebView, createWebViewWith configuration: WKWebViewConfiguration, for navigationAction: WKNavigationAction, windowFeatures: WKWindowFeatures) -> WKWebView? {
+ open func webView(_ webView: WKWebView, createWebViewWith configuration: WKWebViewConfiguration, for navigationAction: WKNavigationAction, windowFeatures: WKWindowFeatures) -> WKWebView? {
if (navigationAction.request.url != nil) {
UIApplication.shared.open(navigationAction.request.url!, options: [:], completionHandler: nil)
}
return nil
}
- public func getWebView() -> WKWebView {
+ open func getWebView() -> WKWebView {
return self.webView!
}
- public func getServerBasePath() -> String {
+ open func getServerBasePath() -> String {
return self.basePath
}
- public func setServerBasePath(path: String) {
+ open func setServerBasePath(path: String) {
setServerPath(path: path)
let request = URLRequest(url: URL(string: hostname!)!)
DispatchQueue.main.async {
@@ -564,7 +572,7 @@ public class CAPBridgeViewController: UIViewController, CAPBridgeDelegate, WKScr
}
}
- override public var supportedInterfaceOrientations: UIInterfaceOrientationMask {
+ override open var supportedInterfaceOrientations: UIInterfaceOrientationMask {
var ret = 0
if self.supportedOrientations.contains(UIInterfaceOrientation.portrait.rawValue) {
ret = ret | (1 << UIInterfaceOrientation.portrait.rawValue)
diff --git a/ios/Capacitor/Capacitor/Plugins/DefaultPlugins.m b/ios/Capacitor/Capacitor/Plugins/DefaultPlugins.m
index b6d36d6f..31c32184 100644
--- a/ios/Capacitor/Capacitor/Plugins/DefaultPlugins.m
+++ b/ios/Capacitor/Capacitor/Plugins/DefaultPlugins.m
@@ -139,10 +139,10 @@
CAP_PLUGIN_METHOD(share, CAPPluginReturnPromise);
)
-CAP_PLUGIN(CAPSplashScreenPlugin, "SplashScreen",
+/*CAP_PLUGIN(CAPSplashScreenPlugin, "SplashScreen",
CAP_PLUGIN_METHOD(show, CAPPluginReturnPromise);
CAP_PLUGIN_METHOD(hide, CAPPluginReturnPromise);
-)
+)*/
CAP_PLUGIN(CAPStatusBarPlugin, "StatusBar",
CAP_PLUGIN_METHOD(setStyle, CAPPluginReturnPromise);
diff --git a/ios/package.json b/ios/package.json
index 1f30986b..2d568b3e 100644
--- a/ios/package.json
+++ b/ios/package.json
@@ -1,6 +1,6 @@
{
- "name": "@capacitor/ios",
- "version": "2.4.7",
+ "name": "capacitor-embedded-ios",
+ "version": "2.4.7-1",
"description": "Capacitor: cross-platform mobile apps with the web",
"homepage": "https://capacitor.ionicframework.com/",
"author": "Ionic Team