doc: update 12.x 2025.01 snapshot (#1447)
diff --git a/www/docs/en/12.x-2025.01/config_ref/images.md b/www/docs/en/12.x-2025.01/config_ref/images.md
index 311bc8c..6b71913 100644
--- a/www/docs/en/12.x-2025.01/config_ref/images.md
+++ b/www/docs/en/12.x-2025.01/config_ref/images.md
@@ -45,19 +45,11 @@
height | *Optional* <br/> Icon height in pixels
target | *Optional* <br/> {% cdv_platform electron %} <br/> Set target to supply unique icons for `app` and `installer`
-The following configuration can be used to define a single default icon
-which will be used for all platforms.
-```xml
- <icon src="res/icon.png" />
-```
-For each platform, you can also define a pixel-perfect icon set to fit
-different screen resolutions.
-
## Android
-Instead of using a single image for an icon, you can use two images (background and foreground) to create an **Adaptive Icon**. To use Adaptive Icons in Cordova, at minimum **Cordova CLI** 9.0.0 and **Cordova-Android** 8.0.0 is required.
+Android's **Adaptive Icons** feature enables you to create separate foreground and background layers for your App Icons. To use Adaptive Icons in Cordova, you need at least **Cordova CLI** 9.0.0 and **Cordova-Android** 8.0.0.
-Android 13 has introduced themed icons which are monochrome images appended to the existing **Adaptive Icons**. To use Themed Icon in Cordova, at minimum **Cordova CLI** 12.0.0 and **Cordova-Android** 12.0.0 is required.
+With Android 13, Google introduced **Themed Icons**, which are monochrome variations of **Adaptive Icons** that integrate seamlessly with the system's color scheme. To use **Themed Icons** in Cordova, you'll need at least **Cordova CLI** 12.0.0 and **Cordova-Android** 12.0.0.
Attributes | Description
--------------|--------------------------------------------------------------------------------
@@ -71,6 +63,7 @@
To use the adaptive icons the `background`, `foreground` and optionally `monochrome` attributes must be defined in place of the `src` attribute. The `src` attribute is not used for adaptive icons.
#### Adaptive Icon with Images:
+
```xml
<platform name="android">
<icon monochrome="res/icon/android/ldpi-monochrome.png" background="res/icon/android/ldpi-background.png" density="ldpi" foreground="res/icon/android/ldpi-foreground.png" />
@@ -85,6 +78,7 @@
**Note:** In this example, the foreground image will also be used as the fallback icon for Android devices that do not support the adaptive icons. The fallback icon can be overridden by setting the src attribute.
#### Adaptive Icon with Vectors:
+
```xml
<platform name="android">
<icon monochrome="res/icon/android/ldpi-monochrome.png" background="res/icon/android/ldpi-background.xml" density="ldpi" foreground="res/icon/android/ldpi-foreground.xml" src="res/android/ldpi.png" />
@@ -99,6 +93,7 @@
**Note:** In this example, the src attribute must be defined when then foreground attribute is defined with a vector or color.
#### Adaptive Icon with Colors:
+
Create a `res/values/colors.xml` resource file in your project directory to store the app's color definitions.
```xml
<?xml version="1.0" encoding="utf-8"?>
@@ -143,7 +138,8 @@
</platform>
```
-### See Also
+**See Also:**
+
- [Android icon guide](https://developer.android.com/guide/practices/ui_guidelines/icon_design_adaptive)
- [Android Adaptive icons - User theming](https://developer.android.com/develop/ui/views/launch/icon_design_adaptive#user-theming)
- [Android - Supporting multiple screens](https://developer.android.com/guide/practices/screens_support.html)
@@ -152,43 +148,54 @@
Icons are not applicable to the Browser platform.
## iOS
+
```xml
<platform name="ios">
- <!-- iOS 8.0+ -->
- <!-- iPhone 6 Plus -->
- <icon src="res/ios/icon-60@3x.png" width="180" height="180" />
- <!-- iOS 7.0+ -->
- <!-- iPhone / iPod Touch -->
- <icon src="res/ios/icon-60.png" width="60" height="60" />
- <icon src="res/ios/icon-60@2x.png" width="120" height="120" />
- <!-- iPad -->
- <icon src="res/ios/icon-76.png" width="76" height="76" />
- <icon src="res/ios/icon-76@2x.png" width="152" height="152" />
- <!-- Spotlight Icon -->
- <icon src="res/ios/icon-40.png" width="40" height="40" />
+ <!-- Notifications on iPhone, iPad Pro, iPad, iPad mini -->
+ <icon src="res/ios/icon-38@2x.png" width="76" height="76" />
+ <icon src="res/ios/icon-38@3x.png" width="114" height="114" />
+
+ <!-- Settings on iPhone, iPad Pro, iPad, iPad mini -->
+ <icon src="res/ios/icon-29@1x.png" width="29" height="29" />
+ <icon src="res/ios/icon-29@2x.png" width="58" height="58" />
+ <icon src="res/ios/icon-29@3x.png" width="87" height="87" />
+
+ <!-- Spotlight on iPhone, iPad Pro, iPad, iPad mini -->
+ <icon src="res/ios/icon-40@1x.png" width="40" height="40" />
<icon src="res/ios/icon-40@2x.png" width="80" height="80" />
- <!-- iOS 6.1 -->
- <!-- iPhone / iPod Touch -->
- <icon src="res/ios/icon.png" width="57" height="57" />
- <icon src="res/ios/icon@2x.png" width="114" height="114" />
- <!-- iPad -->
- <icon src="res/ios/icon-72.png" width="72" height="72" />
- <icon src="res/ios/icon-72@2x.png" width="144" height="144" />
- <!-- iPad Pro -->
- <icon src="res/ios/icon-167.png" width="167" height="167" />
- <!-- iPhone Spotlight and Settings Icon -->
- <icon src="res/ios/icon-small.png" width="29" height="29" />
- <icon src="res/ios/icon-small@2x.png" width="58" height="58" />
- <icon src="res/ios/icon-small@3x.png" width="87" height="87" />
- <!-- iPad Spotlight and Settings Icon -->
- <icon src="res/ios/icon-50.png" width="50" height="50" />
- <icon src="res/ios/icon-50@2x.png" width="100" height="100" />
- <!-- iTunes Marketing Image -->
+
+ <!-- Home Screen on iPad, iPad mini -->
+ <icon src="res/ios/icon-76@2x.png" width="152" height="152" />
+
+ <!-- Home Screen on iPad Pro -->
+ <icon src="res/ios/icon-83.5@2x.png" width="167" height="167" />
+
+ <!-- Home Screen on iPhone -->
+ <icon src="res/ios/icon-60@1x.png" width="60" height="60" />
+ <icon src="res/ios/icon-60@2x.png" width="120" height="120" />
+ <icon src="res/ios/icon-60@3x.png" width="180" height="180" />
+
+ <!-- macOS app icons -->
+ <icon src="res/ios/icon-16.png" width="16" height="16" />
+ <icon src="res/ios/icon-32.png" width="32" height="32" />
+ <icon src="res/ios/icon-64.png" width="64" height="64" />
+ <icon src="res/ios/icon-128.png" width="128" height="128" />
+ <icon src="res/ios/icon-256.png" width="256" height="256" />
+ <icon src="res/ios/icon-512.png" width="512" height="512" />
+
+ <!-- App Store Icon and another macOS app icons -->
<icon src="res/ios/icon-1024.png" width="1024" height="1024" />
</platform>
```
-### See Also
-- [App Icons on iPad and iPhone](https://developer.apple.com/library/content/qa/qa1686/_index.html)
+
+**Notes:**
+
+- Alpha channel is not supported for any iOS icons.
+
+**References:**
+
+- [Apple Developer - Configuring your app icon](https://developer.apple.com/documentation/xcode/configuring-your-app-icon/)
+- [Apple Developer - Human Interface Guidelines > App icons](https://developer.apple.com/design/human-interface-guidelines/app-icons)
[splashscreen_plugin]: ../reference/cordova-plugin-splashscreen/
diff --git a/www/docs/en/12.x-2025.01/config_ref/index.md b/www/docs/en/12.x-2025.01/config_ref/index.md
index 21915df..df0dd92 100644
--- a/www/docs/en/12.x-2025.01/config_ref/index.md
+++ b/www/docs/en/12.x-2025.01/config_ref/index.md
@@ -325,12 +325,14 @@
android-buildToolsVersion<br/>{% cdv_vartype semver %} {% cdv_platform android %} | *Default: [Dependent on cordova-android Version][android-api-level-support]* <br/> Expects a full version string eg. "32.0.0". Changing this may also requires changing the PATH environment variable to find the proper build tools.<br/><br/>This preference is primarily for cordova development, for testing upcoming versions of the Android SDK. Changing this has a high risk of breaking builds as newer build tools frequently introduce breaking changes.
GradleVersion<br/>{% cdv_vartype string %} {% cdv_platform android %} | *Default: [Dependent on cordova-android Version][android-api-level-support]* <br/> Sets the gradle wrapper version to use.<br/> <br/>This preference is primarily for cordova development, for testing upcoming versions of the Android SDK. Changing this has a high risk of breaking builds as newer build tools frequently introduce breaking changes.
AndroidGradlePluginVersion<br/>{% cdv_vartype semver %} {% cdv_platform android %} | *Default: [Dependent on cordova-android Version][android-api-level-support]* <br/> Sets the Android Gradle Plugin version to use.<br/> <br/>This preference is primarily for cordova development, for testing upcoming versions of the Android SDK. Changing this has a high risk of breaking builds as newer build tools frequently introduce breaking changes.
+AndroidShowDeprecations<br />{% cdv_vartype boolean %} {% cdv_platform android %} | *Default: false* <br />Prints deprecation warnings for the android platform in the build output.<br /><br />This preference is primarily intended for cordova core and plugin development.
AndroidXAppCompatVersion<br/>{% cdv_vartype semver %} {% cdv_platform android %} | *Default: [Dependent on cordova-android Version][android-api-level-support]* <br/> Overrides Android App Compat library version.
AndroidXWebKitVersion<br/>{% cdv_vartype semver %} {% cdv_platform android %} | *Default: [Dependent on cordova-android Version][android-api-level-support]* <br/>Overrides Android WebKit library version.
AppendUserAgent<br/>{% cdv_vartype string %} {% cdv_platform android %} {% cdv_platform ios %} | If set, the value will append to the end of old UserAgent of webview. When using with OverrideUserAgent, this value will be ignored.
AutoHideSplashScreen<br/> {% cdv_vartype boolean %} {% cdv_platform android %} {% cdv_platform ios %} | *Default: true* <br/> Indicates whether to hide splash screen automatically or not. The splash screen is hidden after the amount of time specified in the `SplashScreenDelay` preference.
BackgroundColor<br/>{% cdv_vartype string %} {% cdv_platform android %} {% cdv_platform ios %} | Sets the app's background color. Supports a four-byte hex value, with the first byte representing the alpha channel, and standard RGB values for the following three bytes.
CordovaWebViewEngine<br/>{% cdv_vartype string %} {% cdv_platform ios %} | *Default: CDVWebViewEngine* <br/> This sets the WebView engine plugin to be used to render the host app. The plugin must conform to the CDVWebViewEngineProtocol protocol. The 'value' here should match the 'feature' name of the WebView engine plugin that is installed. This preference usually would be set by the WebView engine plugin that is installed, automatically.
+CrashRecoveryBehavior<br/>{% cdv_vartype string %} {% cdv_platform ios %} | *Default: refresh* <br/> Allowed values: refresh, reload <br/> Specifies the crash recovery behavior for the iOS web view. The `reload` option will cause the web view to reload the starting URL for the app, whereas `refresh` will attempt to restore the current URL state.
DefaultVolumeStream<br/>{% cdv_vartype string %} {% cdv_platform android %} | *Default: default* <br/> Added in cordova-android 3.7.0, This preference sets which volume the hardware volume buttons link to. By default this is "call" for phones and "media" for tablets. Set this to "media" to have your app's volume buttons always change the media volume. Note that when using Cordova's media plugin, the volume buttons will dynamically change to controlling the media volume when any Media objects are active.
DisallowOverscroll<br/>{% cdv_vartype boolean %} {% cdv_platform ios %} {% cdv_platform android %} | *Default: false* <br/> Set to **true** if you don't want the interface to display any feedback when users scroll past the beginning or end of content. On iOS, overscroll gestures cause content to bounce back to its original position. on Android, they produce a more subtle glowing effect along the top or bottom edge of the content. <br/>
EnableViewportScale<br/>{% cdv_vartype boolean %} {% cdv_platform ios %} | *Default: false* <br/> Set to true to allow a viewport meta tag to either disable or restrict the range of user scaling, which is enabled by default. Place a viewport such as the following in the HTML to disable scaling and fit content flexibly within the rendering WebView: <br/> ```<meta name='viewport' content='width=device-width, initial-scale=1, user-scalable=no' />```
diff --git a/www/docs/en/12.x-2025.01/guide/appdev/allowlist/index.md b/www/docs/en/12.x-2025.01/guide/appdev/allowlist/index.md
index d3145d0..885e8c3 100644
--- a/www/docs/en/12.x-2025.01/guide/appdev/allowlist/index.md
+++ b/www/docs/en/12.x-2025.01/guide/appdev/allowlist/index.md
@@ -85,7 +85,7 @@
to the host, or as a suffix to the path -->
<allow-navigation href="*://*.example.com/*" />
-<!--
+<!--
A wildcard can be used to allow the entire network, over HTTP and HTTPS.
This is *NOT RECOMMENDED*
-->
@@ -141,10 +141,54 @@
## Content Security Policy (CSP)
-Controls which network requests (images, XHRs, etc) are allowed to be made (via webview directly).
+The [**Content Security Policy (CSP)**](https://developer.mozilla.org/en-US/docs/Web/HTTP/CSP) `<meta>` tag is a very powerful mechanism that allows you to control trusted sources of content. You can restrict various content types and domains from which content can be loaded from. Unsafe and risky HTML and JavaScript can also be disabled to further increase the security of your app.
+
+The CSP `<meta>` tag should be placed in your app's index.html file.
On Android and iOS, the network request allow list (see above) is not able to filter all types of requests (e.g. `<video>` & WebSockets are not blocked). So, in addition to the allow list, you should use a [Content Security Policy](http://content-security-policy.com/) `<meta>` tag on all of your pages.
+> **Note**: If your app has multiple HTML files and navigates between them using the browser's navigation features, you should include the CSP in each file. If your app is a single-page application, you only need to include the CSP on `index.html`.
+
+### Cordova's Default Template Content Security Policy
+
+The CSP that Cordova's default template uses looks like this (indented for clarity):
+
+```html
+<meta http-equiv="Content-Security-Policy"
+ content="default-src 'self' data: https://ssl.gstatic.com 'unsafe-eval';
+ style-src 'self' 'unsafe-inline';
+ media-src *;
+ img-src 'self' data: content:;">
+```
+
+The above snippet enforces the following:
+
+**Default Source (`default-src`):**
+
+As a fallback, all other network requests are restricted to:
+
+* The same origin as the app itself (`'self'`).
+* Resources loaded via `data:` URIs.
+* Resources from the specified external domain `https://ssl.gstatic.com`.
+* JavaScript methods such as `eval()` (and similar) are permitted with `'unsafe-eval'`.
+
+**Style Source (`style-src`):**
+
+* Styles can only be loaded from the same origin (`'self'`).
+* Inline styles (`'unsafe-inline'`) are also allowed, meaning styles can be directly applied using the `style` attribute on elements or within `<style>` tags.
+
+**Media Source (`media-src`):**
+
+* Media can be loaded from any source.
+
+**Image Source (`img-src`):**
+
+* Images can only be loaded from the same origin (`'self'`).
+* Allows loading images from `data:` URIs.
+* Allows loading images from `content:` URIs, typically used within the Android ecosystem.
+
+### Example Content Security Policy Declarations
+
Here are some example CSP declarations for your `.html` pages:
```html
@@ -159,7 +203,7 @@
<!-- Allow everything but only from the same origin and foo.com -->
<meta http-equiv="Content-Security-Policy" content="default-src 'self' foo.com">
-<!-- This policy allows everything (eg CSS, AJAX, object, frame, media, etc) except that
+<!-- This policy allows everything (eg CSS, AJAX, object, frame, media, etc) except that
* CSS only from the same origin and inline styles,
* scripts only from the same origin and inline styles, and eval()
-->
@@ -172,6 +216,14 @@
<meta http-equiv="Content-Security-Policy" content="default-src 'self'; frame-src 'self' https://cordova.apache.org">
```
+You should fully understand the CSP tag and the various directives that can be specified. More documentation is available at [Content Security Policy](https://web.dev/articles/csp) (via Google Developers) and Mozilla's [Content Security Policy (CSP)](https://developer.mozilla.org/en-US/docs/Web/HTTP/CSP) article.
+
+> **Tip**: If you're using web sockets, include `ws:` (`wss:` if using SSL) in the `connect-src` directive.
+
+### Debugging Content Security Policy
+
+When adding a CSP to your app, it's likely you'll encounter some issues. Fortunately, both Google Chrome's Developer Tools and Safari's Web Inspector make it very clear when a CSP violation occurs. Watch the console for any violation messages, which are typically quite detailed, specifying exactly which resource was blocked and why. Address each violation as they appear to ensure your CSP is properly configured.
+
## Other Notes
[Application Transport Security (ATS)](https://developer.apple.com/library/prerelease/ios/documentation/General/Reference/InfoPlistKeyReference/Articles/CocoaKeys.html#//apple_ref/doc/uid/TP40009251-SW33) is new in iOS 9 (Xcode 7). This new feature acts as an allow list for your app. Cordova CLI will automatically convert the `<access>` and `<allow-navigation>` tags to the appropriate ATS directives.
diff --git a/www/docs/en/12.x-2025.01/guide/appdev/security/index.md b/www/docs/en/12.x-2025.01/guide/appdev/security/index.md
index 29671e9..1ffa557 100644
--- a/www/docs/en/12.x-2025.01/guide/appdev/security/index.md
+++ b/www/docs/en/12.x-2025.01/guide/appdev/security/index.md
@@ -28,27 +28,78 @@
## This guide discusses the following topics:
-* Allow List
-* Iframes and the Callback Id Mechanism
-* Certificate Pinning
-* Self-signed Certificates
-* Encrypted storage
* General Tips
+* Plugins and Security
+* Allow List
+* Content Security Policy
+* Certificate Pinning
+* Using TLS/SSL
+* Avoid Self-signed Certificates
+* Wrapping external sites and hot code push
+* Encrypted storage
* Recommended Articles and Other Resources
+## General Tips
+
+### Use InAppBrowser for outside links
+
+Use the [InAppBrowser](https://www.npmjs.com/package/cordova-plugin-inappbrowser) when opening links to any outside website. This is much safer than allow listing a domain name and including the content directly in your application because the InAppBrowser will use the native browser's security features and will not give the website access to your Cordova environment. Even if you trust the third party website and include it directly in your application, that third party website could link to malicious web content.
+
+### Validate all user input
+
+Always validate any and all input that your application accepts. This includes usernames, passwords, dates, uploaded media, etc. Because an attacker could manipulate your HTML and JS assets (either by decompiling your application or using debugging tools like `chrome://inspect`), this validation should also be performed on your server, especially before handing the data off to any backend service.
+
+> **Tip**: Other sources where data should be validated: user documents, contacts, push notifications
+
+### Do not store sensitive data
+
+If usernames, password, geolocation information, and other sensitive data is stored, then it could potentially be retrieved later by an unauthorized user or application.
+
+### Don't use `eval()`
+
+The JavaScript function `eval()` has a long history of being abused. Using it incorrectly can open your code up for injection attacks, debugging difficulties, and slower code execution.
+
+### Do not assume that your source code is secure
+
+Since a Cordova application is built from HTML and JavaScript assets that get packaged in a native container, you should not consider your code to be secure. It is possible for an iOS or Android application to be unpacked and unzipped to reveal its web assets such as HTML and JS.
+
+A sampling of what you should not include in your code:
+
+* Authentication information (usernames, passwords, keys, etc.)
+* Encryption keys
+* Trade secrets
+
+### Do not assume storage containers are secure
+
+Even if a device itself is encrypted, if someone has access to the device and can unlock it, you should not assume that data stored in various formats and containers is safe. Even SQLite databases are easily human readable once access is gained.
+
+As long as you're storing non-sensitive information, this isn't a big deal. But if you were storing passwords, keys, and other sensitive information, the data could be easily extracted, and depending on what was stored, could be used against your app and remote servers.
+
+For example, on iOS, if you store data in `localStorage`, the data itself is easily readable to anyone who has access to the device. This is because `localStorage` is backed by an unencrypted SQLite database. The underlying storage of the device may in fact be encrypted (and so it would be inaccessible while the device is locked), but once the device decrypts the file, the contents themselves are mostly in the clear. As such, the contents of `localStorage` can be easily read and even changed.
+
+## Plugins and Security
+
+Due to the way the native portion of Cordova communicates with your web code, it is possible for any code executing within the main webview context to communicate with any installed plugins. This means that you should _never_ permit untrusted content within the primary webview. This can include third-party advertisements, sites within an `iframe`, and even content injected via `innerHTML`.
+
+If you must inject content into the primary webview, be certain that it has been properly sanitized so that no JavaScript can be executed. _Do not try to sanitize content on your own; use a vetted third-party library instead!_
+
+> **Tip**: If you need to include advertising, use any of the many third-party plugins for Cordova. These are safer than executing arbitrary JavaScript from advertisers.
+
## Allow List
By default the app's navigation is unrestricted. It's recommended to restrict the navigation only to trusted domains. Learn more by reading the [Allow List Guide](../allowlist/index.html)
-## Iframes and the Callback Id Mechanism
+## Content Security Policy (CSP)
-If content is served in an iframe from a allow listed domain, that domain will have access to the native Cordova bridge. This means that if you allow a third-party advertising network and serve those ads through an iframe, it is possible that a malicious ad will be able to break out of the iframe and perform malicious actions. Because of this, you should generally not use iframes unless you control the server that hosts the iframe content. Also note that there are third party plugins available to support advertising networks. Note that this statement is not true for iOS, which intercepts everything including iframe connections.
+Cordova’s default template includes a basic Content Security Policy (CSP). It’s recommended to review and customize this CSP to fit your app's specific needs. For more information, refer to the [Allow List Guide - Content Security Policy (CSP)](../allowlist/index.html#content-security-policy-csp).
## Certificate Pinning
-Cordova does not support true certificate pinning. The main barrier to this is a lack of native APIs in Android for intercepting SSL connections to perform the check of the server's certificate. (Although it is possible to do certificate pinning on Android in Java using JSSE, the webview on Android is written in C++, and server connections are handled for you by the webview, so it is not possible to use Java and JSSE there.) Since Apache Cordova is meant to offer consistent APIs across multiple platforms, not having a capability in a major platform breaks that consistency.
+It is important to ensure that you trust any hosts with which there are communications. Typically, one would do this using certificate pinning. The app would double check any certificates and only communicate over channels where the certificate check passed. This helps mitigate man-in-the-middle attacks.
-There are ways to approximate certificate pinning, such as checking the server's public key (fingerprint) is the expected value when your application starts or at other various times during your application's lifetime. There are third-party plugins available for Cordova that can do that. However, this is not the same as true certificate pinning which automatically verifies the expected value on every connection to the server.
+Unfortunately, Cordova does not support true certificate pinning. The main barrier to this is a lack of native APIs in Android for intercepting SSL connections to perform the check of the server's certificate. (Although it is possible to do certificate pinning on Android in Java using JSSE, the webview on Android is written in C++, and server connections are handled for you by the webview, so it is not possible to use Java and JSSE there.) Since Apache Cordova is meant to offer consistent APIs across multiple platforms, not having a capability in a major platform breaks that consistency.
+
+There are ways to approximate certificate pinning, such as checking that the server's public key (fingerprint) is the expected value when your application starts or at other various times during your application's lifetime. There are third-party plugins available for Cordova that can do that. However, this is not the same as true certificate pinning which automatically verifies the expected value on every connection to the server.
There are also plugins that can do true certificate pinning for some platforms, assuming your app is able to do all of its network requests using the plugin (i.e.: no traditional XHR/AJAX requests, etc).
@@ -56,51 +107,64 @@
If your app communicates to an external server, it should be communicating using modern encryption standards. Use `https` protocol whenever possible.
-[Let's Encrypt](https://letsencrypt.org/) is a free, automated, and open certificate authority provided by the nonprofit [Internet Security Research Group](https://www.abetterinternet.org/). Let's Encrypt will offer free standard certificates, which will be sufficient for most developers. Enterprise organizations may still want to use a traditional certificate authority that offers more advanced features such as [Organization Validation](https://en.wikipedia.org/wiki/Public_key_certificate#Organization_validation) certificates.
+[Let's Encrypt](https://letsencrypt.org/) is a free, automated, and open certificate authority provided by the nonprofit [Internet Security Research Group](https://www.abetterinternet.org/). Let's Encrypt will offer free standard certificates, which will be sufficient for most developers. Enterprise organizations may still want to use a traditional certificate authority that offers more advanced features such as [Organization validation](https://en.wikipedia.org/wiki/Public_key_certificate#Organization_validation) certificates.
It is also important to keep up to date with security standards as they change over time. What might be acceptable SSL/TLS configuration today may not be acceptable years in the future. Using tools to test your certificate and SSL/TLS configuration should be done regularly. [SSL Labs](https://www.ssllabs.com/ssltest/) is a free online service provided by Qualys, Inc to test your server's SSL/TLS configuration and encryption strength, in addition to supported platforms.
-## Self-signed Certificates
+## Avoid Self-signed Certificates
-Using self-signed certificates on your server is not recommended. If you desire SSL, then it is highly recommended that your server have a certificate that has been properly signed by a well-known CA (certificate authority). The inability to do true certificate pinning makes this important.
+Using self-signed certificates on your server is not recommended. If you desire SSL, then it is highly recommended that your server have a certificate that has been properly signed by a well-known CA (certificate authority). The inability to do true certificate pinning makes this even more important.
-The reason is that accepting self-signed certificates bypasses the certificate chain validation, which allows any server certificate to be considered valid by the device. This opens up the communication to man-in-the-middle attacks. It becomes very easy for a hacker to not only intercept and read all communication between the device and the server, but also to modify the communication. The device will never know this is happening because it doesn't verify that the server's certificate is signed by a trusted CA. The device has no proof that the server is who it expects. Because of the ease of doing a man-in-the-middle attack, accepting self-signed certificates is only marginally better than just running http instead of https on an untrusted network. Yes, the traffic would be encrypted, but it could be encrypted with the key from a man-in-the-middle, so the man-in-the-middle can access everything, so encryption is useless except to passive observers. Users trust SSL to be secure, and this would be deliberately making it insecure, so the SSL use becomes misleading.
+The reason is that accepting self-signed certificates bypasses the certificate chain validation, which allows any server certificate to be considered valid by the device. This opens up the communication to man-in-the-middle attacks. It becomes very easy for a hacker to not only intercept and read all communication between the device and the server, but also to modify the communication. The device will never know this is happening because it doesn't verify that the server's certificate is signed by a trusted CA. The device has no proof that the server is who it expects.
-If the application is to be used only within a trusted network, such as an internal corporate network. Using self-signed certificates may be acceptable, however the public certificate should be pre-installed on the device(s) that will be running the application. A trusted third-party certificate authority will always be preferable.
+Because of the ease of doing a man-in-the-middle attack, accepting self-signed certificates is only marginally better than just running `http` instead of `https` on an untrusted network. While the traffic would be encrypted, it could be encrypted with the key from a man-in-the-middle, so the man-in-the-middle would have access everything, making the encryption useless except to passive observers. Users trust SSL to be secure, and this would be deliberately making it insecure, so the SSL use becomes misleading.
-The principles described here are not specific to Apache Cordova, they apply to all client-server communication.
+If the app will be used on a trusted network (i.e., you are entirely inside a controlled enterprise), then self-signed certs are still not recommended. The two recommendations in a trusted network are to just use http because the network itself is trusted, or to get a certificate signed by a trusted CA (not self-signed). Either the network is trusted or it is not.
-When running Cordova on Android, using `android:debuggable="true"` in the application manifest will permit SSL errors such as certificate chain validation errors on self-signed certs. So you can use self-signed certs in this configuration, but this is not a configuration that should be used when your application is in production. It is meant to be used only during application development.
+> **Note**: The principles described here are not specific to Apache Cordova, they apply to all client-server communication.
+> **Android Tip**: When running Cordova on Android, using `android:debuggable="true"` in the application manifest will permit SSL errors such as certificate chain validation errors on self-signed certs. So you can use self-signed certs in this configuration, but this is not a configuration that should be used when your application is in production. It is meant to be used only during application development.
-## Encrypted storage
+## Wrapping external sites and hot code push
-(TBD)
+Cordova's implementation allows you to redirect to an external site instead of using local content. This is **not** suggested for most apps, even though it might avoid a rewrite of the app or can make code updates faster. You should avoid this for any apps destined to any app store, but in general, it's risky regardless, for many reasons:
-## General Tips
+* No local code to detect no route to host. Apple _requires_ apps to detect no network connection (and other connectivity issues) and display a user-friendly error message. If there's no local code to detect this, the app will generally remain blank, and Apple will reject it.
+* No local code to verify the downloaded content. The content could be incomplete or corrupted, especially if being downloaded over a poor network connection. Incomplete or corrupt content is not going to render particularly well, leaving your user frustrated.
+* No local code to detect and remove malicious intent. Local code has a chance to sanitize content and verify that there are no spurious or unexpected `script` tags or event handlers. Without local code, the app is at the server's mercy.
+* No local code to check certificates. See **Certificate Pinning** above.
-### Do not use Android Gingerbread!
-* Set your min-target-sdk level higher than 10. API 10 is Gingerbread, and Gingerbread is no longer supported by Google or device manufacturers, and is therefore not recommend by the Cordova team.
-* Gingerbread has been shown to be insecure and one of the most targeted mobile OSs [https://www.mobilemag.com/2012/11/06/andriod-2-3-gingerbread-security/](https://bgr.com/2012/11/06/android-security-gingerbread-malware/).
-* The Allowlist on Android does not work with Gingerbread or lower. This means an attacker can load malicious code in an iframe that would then have access to all of the Cordova APIs and could use that access to steal personal data, send SMS messages to premium-rate numbers, and perform other malicious acts.
+Hot code push solutions improve matters a bit, since they will download code and store it locally on the device. This means that in the event of a network failure, the code still has a chance to run and display any appropriate messages, and that same code can verify any future downloads. You should, however, verify that any hot code push service you use does the following:
-### Use InAppBrowser for outside links
-* Use the InAppBrowser when opening links to any outside website. This is much safer than allow listing a domain name and including the content directly in your application because the InAppBrowser will use the native browser's security features and will not give the website access to your Cordova environment. Even if you trust the third party website and include it directly in your application, that third party website could link to malicious web content.
+* Validate checksums to ensure complete and accurate downloads
+* Certificate checking to ensure that the download is from a trusted server
+* Falls back to last downloaded code in the event something goes wrong
-### Validate all user input
-* Always validate any and all input that your application accepts. This includes usernames, passwords, dates, uploaded media, etc. Because an attacker could manipulate your HTML and JS assets (either by decompiling your application or using debugging tools like chrome://inspect), this validation should also be performed on your server, especially before handing the data off to any backend service.
-* Other sources where data should be validated: user documents, contacts, push notifications
+## Encrypted Storage
-### Do not cache sensitive data
-* If usernames, password, geolocation information, and other sensitive data is cached, then it could potentially be retrieved later by an unauthorized user or application.
+Both **Android** and **iOS** offer various secure storage options. While **Apache Cordova** does not provide these mechanisms natively at the platform core or plugin level, third-party plugins may be available or can be created to implement such features.
-### Don't use eval() unless you know what you're doing
-* The JavaScript function eval() has a long history of being abused. Using it incorrectly can open your code up for injection attacks, debugging difficulties, and slower code execution.
+**Android:**
-### Do not assume that your source code is secure
-* Since a Cordova application is built from HTML and JavaScript assets that get packaged in a native container, you should not consider your code to be secure. It is possible to reverse engineer a Cordova application.
+* [**Encrypted Shared Preferences**](https://developer.android.com/reference/androidx/security/crypto/EncryptedSharedPreferences)
+
+ **Encrypted SharedPreferences** is an encrypted version of SharedPreferences, where both the keys and values are encrypted. This is ideal for storing small amounts of data, such as user settings, preferences, or other sensitive information.
+
+* [**Encrypted File Storage**](https://developer.android.com/reference/androidx/security/crypto/EncryptedFile)
+
+ **Encrypted File Storage** is suitable for securely storing files, perfect for large data. By using the `EncryptedFile` class, you can create and read encrypted files, ensuring that the file contents remain protected.
+
+**iOS:**
+
+* **File Protection**
+
+ Using [`NSFileManager`](https://developer.apple.com/documentation/foundation/nsfilemanager), which provides an interface for managing the file system, you can define a file's protection level with the [`NSFileProtectionType`](https://developer.apple.com/documentation/foundation/nsfileprotectiontype) attribute. This allows you to store files on disk with protection based on the device's lock state. Files are encrypted and accessible only when the device is unlocked.
+
+* [**Keychain Services**](https://developer.apple.com/documentation/security/keychain-services?language=objc)
+
+ **Keychain Services** is a secure method for storing small pieces of sensitive data, such as passwords or tokens. Data in the keychain is encrypted and protected by the device's security mechanisms.
## Recommended Articles and Other Resources
-* [HTML5 Security cheat sheet, detailing how to secure your HTML5 application](https://www.owasp.org/index.php/HTML5_Security_Cheat_Sheet)
-* [Whitepaper about well known security flaws in Webview based hybrid applications](http://www.cis.syr.edu/~wedu/Research/paper/webview_acsac2011.pdf)
+* [OWASP Cheat Sheet Series - HTML5 Security Cheat Sheet](https://cheatsheetseries.owasp.org/cheatsheets/HTML5_Security_Cheat_Sheet.html)
+* [Research Paper - Attacks on WebView in the Android System](https://www.cs.ucr.edu/~heng/pubs/webview_acsac2011.pdf)
diff --git a/www/docs/en/12.x-2025.01/guide/hybrid/plugins/index.md b/www/docs/en/12.x-2025.01/guide/hybrid/plugins/index.md
index ab8c58f..50f025f 100644
--- a/www/docs/en/12.x-2025.01/guide/hybrid/plugins/index.md
+++ b/www/docs/en/12.x-2025.01/guide/hybrid/plugins/index.md
@@ -24,268 +24,100 @@
# Create a Plugin
-A _plugin_ is a package of injected code that allows the Cordova webview within
-which the app renders to communicate with the native platform on
-which it runs. Plugins provide access to device and platform
-functionality that is ordinarily unavailable to web-based apps. All
-the main Cordova API features are implemented as plugins, and many
-others are available that enable features such as bar code scanners,
-NFC communication, or to tailor calendar interfaces. You can search for available plugins
-on [Cordova Plugin Search page](/plugins/).
+- [Create a Plugin](#create-a-plugin)
+ - [Creating an npm Package](#creating-an-npm-package)
+ - [Updating the npm Package for Cordova](#updating-the-npm-package-for-cordova)
+ - [Adding the plugin's `id`](#adding-the-plugins-id)
+ - [Specifying supported platforms](#specifying-supported-platforms)
+ - [Adding keywords for discoverability](#adding-keywords-for-discoverability)
+ - [Adding engine requirements](#adding-engine-requirements)
+ - [Upper Bounds](#upper-bounds)
+ - [Creating the `plugin.xml` file](#creating-the-pluginxml-file)
+ - [Adding a Front-End JavaScript API](#adding-a-front-end-javascript-api)
+ - [`cordova.exec` Command Syntax](#cordovaexec-command-syntax)
+ - [Creating the `www/api.js` File](#creating-the-wwwapijs-file)
+ - [Injecting the JavaScript API to the `window` Object](#injecting-the-javascript-api-to-the-window-object)
+ - [Implementing Native Interfaces](#implementing-native-interfaces)
+ - [Testing a Plugin during development](#testing-a-plugin-during-development)
+ - [Publishing Plugins](#publishing-plugins)
-Plugins comprise a single JavaScript interface along with
-corresponding native code libraries for each supported platform. In essence
-this hides the various native code implementations behind a common
-JavaScript interface.
+A Cordova _plugin_ is a package that enables the Cordova apps to access native device features and functionality that is ordinarily unavailable to web-based apps. All of the core Cordova API features are implemented as plugins. Many third-party plugins are also available to provide additional capabilities such as barcode scanning, near-field communication (NFC), push notification, or even customizing interfaces.
-This section steps through a simple _echo_ plugin that passes a string from
-JavaScript to the native platform and back, one that you can use as a
-model to build far more complex features. This section discusses the
-basic plugin structure and the outward-facing JavaScript interface.
-For each corresponding native interface, see the list at the end of
-this section.
+Check out these locations for Cordova plugins:
-In addition to these instructions, when preparing to write a plugin it
-is best to look over [existing plugins](https://cordova.apache.org/contribute)
-for guidance.
+- Official Apache Cordova plugins on the [Cordova Plugin page](/plugins/).
+- Third-party plugins on the [npmjs registry](https://www.npmjs.com/search?q=keywords:ecosystem:cordova).
-## Building a Plugin
+Plugins usually consist of a JavaScript interface paired with corresponding platform-native code. In essence, this hides the platform-specific native implementations behind a common JavaScript interface.
-Application developers use the CLI's [plugin add command][cdv_plugin] to add a plugin to a project. The
-command takes the URL for a _git_ repository containing
-the plugin code as an argument. This example implements Cordova's Device API:
+This page will walk through the steps to create a basic _echo_ plugin that passes a string from the front-end JavaScript to the native platform and back. The purpose of this guide is to provide a model for how to build and publish a Cordova plugin. It focuses on the fundamentals of plugin structure and the outward-facing JavaScript interface.
-```bash
-cordova plugin add https://github.com/apache/cordova-plugin-device
+For the corresponding native implementations, see the list at the end of this section.
+
+In addition to following these instructions, it is recommended to review [existing plugins](https://cordova.apache.org/contribute) for further guidance.
+
+## Creating an npm Package
+
+In essence, a Cordova plugin is an extension of an npm package. By leveraging the npm ecosystem, plugin developers can easily publish their plugins to the npm registry, allowing app developers to install them into their Cordova apps using the Cordova CLI.
+
+Even if you don't plan to publish your plugin publicly, you still need to structure it as an npm package for installation purposes. The [`cordova plugin add`][cdv_plugin] command relies on npm under the hood to fetch and install plugins.
+
+First, we'll create the directory for our `echo` plugin and change to this newly created directory:
+
+```zsh
+mkdir cordova-plugin-echo
+cd cordova-plugin-echo
```
-If the plugin is published to _npm_, the command can also receive the package name as the argument:
+Next, we'll initialize it as an npm package using the `npm init` command. In this example, we'll accept all default values for the initialization process by appending the `-y` flag. If you want to customize the values, you can omit the flag or change the values later by editing the `package.json` file.
-```bash
-cordova plugin add cordova-plugin-device
+```zsh
+npm init -y
```
-The plugin repository must feature a top-level `plugin.xml` manifest
-file. There are many ways to configure this file, details for which
-are available in the [Plugin Specification](../../../plugin_ref/spec.html).
+**One important note:** the directory name `cordova-plugin-echo` will be used as the default package name and will be published as such to the npm registry. If the name is already taken, you'll need to choose a different name or use [scoped packages](https://docs.npmjs.com/cli/v10/using-npm/scope).
-This abbreviated version of the `Device` plugin provides a simple example to use as a model:
+### Updating the npm Package for Cordova
-```xml
-<?xml version="1.0" encoding="UTF-8"?>
-<plugin xmlns="http://apache.org/cordova/ns/plugins/1.0"
- id="cordova-plugin-device" version="0.2.3">
- <name>Device</name>
- <description>Cordova Device Plugin</description>
- <license>Apache 2.0</license>
- <keywords>cordova,device</keywords>
- <js-module src="www/device.js" name="device">
- <clobbers target="device" />
- </js-module>
- <platform name="ios">
- <config-file target="config.xml" parent="/*">
- <feature name="Device">
- <param name="ios-package" value="CDVDevice"/>
- </feature>
- </config-file>
- <header-file src="src/ios/CDVDevice.h" />
- <source-file src="src/ios/CDVDevice.m" />
- </platform>
-</plugin>
+In addition to the standard properties that the `package.json` file includes for npm, Cordova-specific properties will also be added. These are necessary to define the plugin's ID, supported platforms, relevant keywords for discoverability, and engine requirements.
+
+#### Adding the plugin's `id`
+
+This uniquely identifies your plugin within the Cordova ecosystem. It's generally recommended to match the plugin ID with the npm package name so that when a Cordova project is restored using the `cordova prepare` command, the package can be easily located in the npm registry.
+
+```zsh
+npm pkg set cordova.id=cordova-plugin-echo
```
-- The top-level `plugin` tag's `id` attribute usually follows the `cordova-plugin-{plugin name}` schema and matches the plugin's npm package name.
-- The `js-module` tag specifies the path to the [common
-JavaScript interface](#the-javascript-interface).
-- The `platform` tag specifies a corresponding
-set of native code, for the `ios` platform in this case.
-- The `config-file` tag encapsulates a `feature` tag that is injected into
-the platform-specific `config.xml` file to make the platform aware of
-the additional code library.
-- The `header-file` and `source-file` tags
-specify the path to the library's component files.
+#### Specifying supported platforms
-## The JavaScript Interface
+The following example shows how to add support for both Android and iOS. You can modify this to include only the platforms your plugin supports.
-The JavaScript interface provides the front-facing interface, making it perhaps
-the most important part of the plugin. You can structure your
-plugin's JavaScript however you like, but you need to call
-`cordova.exec` to communicate with the native platform, using the
-following syntax:
-
-```javascript
-cordova.exec(function(winParam) {},
- function(error) {},
- "service",
- "action",
- ["firstArgument", "secondArgument", 42, false]);
+```zsh
+npm pkg set "cordova.platforms[]=android"
+npm pkg set "cordova.platforms[]=ios"
```
-Here is how each parameter works:
+#### Adding keywords for discoverability
-- `function(winParam) {}`: A success callback function. Assuming your
- `exec` call completes successfully, this function executes along
- with any parameters you pass to it.
+Keywords help others find your plugin via search.
-- `function(error) {}`: An error callback function. If the operation
- does not complete successfully, this function executes with an
- optional error parameter.
-
-- `"service"`: The service name to call on the native side. This
- corresponds to a native class, for which more information is
- available in the native guides listed below.
-
-- `"action"`: The action name to call on the native side. This
- generally corresponds to the native class method. See the native
- guides listed below.
-
-- `[/* arguments */]`: An array of arguments to pass into the native
- environment.
-
-## Sample JavaScript
-
-This example shows one way to implement the plugin's JavaScript
-interface:
-
-```javascript
-window.echo = function(str, callback) {
- cordova.exec(callback, function(err) {
- callback('Nothing to echo.');
- }, "Echo", "echo", [str]);
-};
+```zsh
+npm pkg set "keywords[]=cordova"
+npm pkg set "keywords[]=echosystem:cordova"
+npm pkg set "keywords[]=cordova-android"
+npm pkg set "keywords[]=cordova-ios"
```
-In this example, the plugin attaches itself to the `window` object as
-the `echo` function, which plugin users would call as follows:
+#### Adding engine requirements
-```javascript
-window.echo("echome", function(echoValue) {
- alert(echoValue == "echome"); // should alert true.
-});
-```
+**Cordova 6.1.0** added support for specifying the Cordova-related dependencies of a plugin as part of the plugin's `package.json` file. Plugins may list the dependencies for multiple releases to provide guidance to the Cordova CLI when it is selecting the version of a plugin to fetch from npm. The CLI will choose the latest release of a plugin that is compatible with the local project's installed platforms and plugins as well as the the local Cordova CLI version. If no releases of the plugin are compatible, the CLI will warn the user about the failed requirements and fall back to the old behavior of fetching the latest release.
-Look at the last three arguments passed to the `cordova.exec` function. The
-first calls the `Echo` _service_, a class name. The second requests
-the `echo` _action_, a method within that class. The third is an array
-of arguments containing the echo string, which is the `window.echo`
-function's first parameter.
+This feature is intended to eventually replace the [engines element](../../../plugin_ref/spec.html#engines-and-engine) in `plugin.xml`.
-The success callback passed into `exec` is simply a reference to the
-callback function of `window.echo`. If the native platform fires
-the error callback, it simply calls the success callback and passes it
-a default string.
+Listing dependencies is a good way to ensure that your plugin will not appear broken or cause build errors when fetched from npm. If the latest release of the plugin is not compatible with a project, the CLI will give the app developer a list of unmet project requirements so that they are aware of incompatibilites and can update their project to support your plugin. This allows your plugin to respond to breaking changes without fear of confusing devlopers who are building against old platforms and plugins.
-## Native Interfaces
-
-Once you define JavaScript for your plugin, you need to complement it
-with at least one native implementation. Details for each platform are
-listed below, and each builds on the simple Echo Plugin example above:
-
-- [Android Plugins](../../platforms/android/plugin.html)
-- [iOS Plugins](../../platforms/ios/plugin.html)
-
-## Testing a Plugin during development
-
-The simplest way to manually test a plugin during development is to create a
-Cordova app as usual and add the plugin with the `--link` option:
-
-```bash
-cordova plugin add ../path/to/my/plugin/relative/to/project --link
-```
-
-This creates a symbolic link instead of copying the plugin files, which enables you to work on your plugin and then simply rebuild the app to use your changes. The plugin should be added after the platform, or the link will not work. The link will also be lost if you re-add the platform or [restore the project](../../../platform_plugin_versioning_ref/index.md) with `cordova prepare`. In that case, you'll need to re-add the plugin to restore the link.
-
-## Validating a Plugin using Plugman
-
-You can use the `plugman` utility to check whether the plugin installs
-correctly for each platform. Install `plugman` with the following
-[node](https://nodejs.org/) command:
-
-```bash
-npm install -g plugman
-```
-
-You need a valid app source directory, such as the top-level `www`
-directory included in a default CLI-generated project, as described in the
-[Create your first app](../../cli/index.html) guide.
-
-Then run a command such as the following to test whether iOS
-dependencies load properly:
-
-```bash
-plugman install --platform ios --project /path/to/my/project/www --plugin /path/to/my/plugin
-```
-
-For details on `plugman` options, see [Using Plugman to Manage Plugins](../../../plugin_ref/plugman.html). For information on how to actually _debug_ plugins, see [each platform's native interface listed above](#native-interfaces).
-
-## Publishing Plugins
-
-You can publish your plugin to any `npmjs`-based registry, but the recommended one is the [npm registry](https://www.npmjs.com). Other developers can install your plugin automatically using either `plugman` or the Cordova CLI.
-
-To publish a plugin to npm you need to follow these steps:
-
- * install the `plugman` CLI:
-
- ```bash
- $ npm install -g plugman
- ```
-
- * create a `package.json` file for your plugin:
-
- ```bash
- $ plugman createpackagejson /path/to/your/plugin
- ```
-
- * publish it:
-
- ```bash
- $ npm adduser # that is if you don't have an account yet
- $ npm publish /path/to/your/plugin
- ```
-
-For more details on npm usage, refer to [Publishing npm Packages](https://docs.npmjs.com/getting-started/publishing-npm-packages) on the npm documentation site.
-
-## Integrating with Plugin Search
-
-To surface the plugin in [Cordova Plugin Search](/plugins/), add the `ecosystem:cordova` keyword to the `package.json` file of your plugin before publishing.
-
-To indicate support for a particular platform, add a keyword in the format `cordova-<platformName>` to the list of keywords in `package.json`.
-Plugman's `createpackagejson` command does this for you, but if you did not use it to generate your `package.json`, you should manually edit it as shown below.
-
-For example, for a plugin that supports Android & iOS the keywords in `package.json` should include:
-
-```json
-"keywords": [
- "ecosystem:cordova",
- "cordova-android",
- "cordova-ios"
-]
-```
-
-For a more detailed example of a package.json, review the [package.json file of cordova-plugin-device](https://github.com/apache/cordova-plugin-device/blob/master/package.json).
-
-## Specifying Cordova Dependencies
-
-**Cordova 6.1.0** added support for specifying the Cordova-related dependencies of a plugin
-as part of the plugin's `package.json` file. Plugins may list the dependencies for multiple
-releases to provide guidance to the Cordova CLI when it is selecting the version of a
-plugin to fetch from npm. The CLI will choose the latest release of a plugin that is
-compatible with the local project's installed platforms and plugins as well as the
-the local Cordova CLI version. If no releases of the plugin are compatible, the CLI will warn
-the user about the failed requirements and fall back to the old behavior of fetching the
-latest release.
-
-This feature is intended to eventually replace the [engines element](../../../plugin_ref/spec.html#engines-and-engine) in plugin.xml.
-Listing dependencies is a good way to ensure that your plugin will not appear broken or cause
-build errors when fetched from npm. If the latest release of the plugin is not compatible with
-a project, the CLI will give the app developer a list of unmet project requirements so that
-they are aware of incompatibilites and can update their project to support your plugin. This
-allows your plugin to respond to breaking changes without fear of confusing devlopers who
-are building against old platforms and plugins.
-
-To specify Cordova-related dependencies for a plugin, alter the `engines` element in
-`package.json` to include a `cordovaDependencies` object with the following
-structure:
+To specify Cordova-related dependencies for a plugin, alter the `engines` element in `package.json` to include a `cordovaDependencies` object with the following structure:
```javascript
"engines": {
@@ -307,14 +139,9 @@
* Another Cordova plugin: `"cordova-plugin-camera"`, etc.
* `SEMVER_RANGE` should adhere to the syntax for a range as defined by [npm's semver package][npm-semver]
-**NOTE:** A Cordova platform `DEPENDENCY` refers to the Cordova platform and not
-the OS, i.e. `cordova-android` rather than the Android OS.
+**NOTE:** A Cordova platform `DEPENDENCY` refers to the Cordova platform and not the OS, i.e. `cordova-android` rather than the Android OS.
-Your `cordovaDependencies` may list any number of `PLUGIN_VERSION` requirements
-and any number of `DEPENDENCY` constraints. Versions of your plugin
-that do not have their dependencies listed will be assumed to have the same
-dependency information as the highest `PLUGIN_VERSION` listed below them. For
-example, consider the following entry:
+Your `cordovaDependencies` may list any number of `PLUGIN_VERSION` requirements and any number of `DEPENDENCY` constraints. Versions of your plugin that do not have their dependencies listed will be assumed to have the same dependency information as the highest `PLUGIN_VERSION` listed below them. For example, consider the following entry:
```javascript
"engines": {
@@ -324,22 +151,12 @@
}
}
```
-All plugin versions below the lowest entry (1.0.0 in this example) are assumed
-to have no dependencies. Any version of the plugin between 1.0.0 and 2.1.0 is
-assumed to have the same dependencies as version 1.0.0 (a cordova-android
-version less than 3.0.0). This lets you only update your `cordovaDependencies`
+All plugin versions below the lowest entry (1.0.0 in this example) are assumed to have no dependencies. Any version of the plugin between 1.0.0 and 2.1.0 is assumed to have the same dependencies as version 1.0.0 (a cordova-android version less than 3.0.0). This lets you only update your `cordovaDependencies`
information when there are breaking changes.
-### Upper Bounds
+##### Upper Bounds
-In addition to a single version, a `PLUGIN_VERSION` in `cordovaDependencies`
-may also specify an upper bound to amend entries for older releases
-of your plugin. This is useful when a breaking change occurs in a `DEPENDENCY`
-and a new constraint must be added for all older versions of a plugin that do
-not support it. These bounds should be written as a `<` followed by a single
-[semver][npm-semver] version (**Not an arbitrary range!**). This will apply
-whatever `DEPENDENCY` values are given to all versions of the plugin below the
-specified version. For example, consider the following entry:
+In addition to a single version, a `PLUGIN_VERSION` in `cordovaDependencies` may also specify an upper bound to amend entries for older releases of your plugin. This is useful when a breaking change occurs in a `DEPENDENCY` and a new constraint must be added for all older versions of a plugin that do not support it. These bounds should be written as a `<` followed by a single [semver][npm-semver] version (**Not an arbitrary range!**). This will apply whatever `DEPENDENCY` values are given to all versions of the plugin below the specified version. For example, consider the following entry:
```javascript
"engines": {
@@ -351,18 +168,134 @@
}
```
-Here we specify one plugin version (0.0.1) and two upper bounds (<1.0.0 and <2.0.0)
-that constrain cordova-ios. The two upper bounds do not override the constraint
-of 0.0.1, they are combined via AND at evaluation time. When the CLI checks the
-cordova-ios version of the project, the constraint that will be evaluated for
-plugin version 0.0.1 will be the combination of these three:
+Here we specify one plugin version (0.0.1) and two upper bounds (<1.0.0 and <2.0.0) that constrain cordova-ios. The two upper bounds do not override the constraint of 0.0.1, they are combined via AND at evaluation time. When the CLI checks the cordova-ios version of the project, the constraint that will be evaluated for plugin version 0.0.1 will be the combination of these three:
-```
- cordova-ios >1.0.0 AND cordova-ios <2.0.0 AND cordova-ios <5.0.0
+> cordova-ios >1.0.0 AND cordova-ios <2.0.0 AND cordova-ios <5.0.0
+
+Please note that the only `PLUGIN_VERSION` values allowed are single versions or upper bounds; no other semver ranges are supported.
+
+## Creating the `plugin.xml` file
+
+Plugins must also be paired with a top-level `plugin.xml` manifest file. This file is used for configuring the plugin. See the [Plugin.xml Specification](../../../plugin_ref/spec.html) for more information of the elements that can be defined.
+
+Below is a simple example of the `plugin.xml` file that will be used for the `Echo` plugin and a model to follow for creating your own plugins.
+
+```xml
+<?xml version="1.0" encoding="utf-8"?>
+<plugin xmlns="http://apache.org/cordova/ns/plugins/1.0"
+ id="cordova-plugin-echo"
+ version="1.0.0">
+ <name>Echo</name>
+ <description>Cordova Echo Plugin</description>
+ <license>Apache 2.0</license>
+ <keywords>cordova,plugin,echo</keywords>
+</plugin>
```
-Please note that the only `PLUGIN_VERSION` values allowed are single versions or
-upper bounds; no other semver ranges are supported.
+> Note: The top-level `plugin` tag's `id` attribute usually follows the `cordova-plugin-{plugin name}` schema and matches the plugin's npm package name.
+
+## Adding a Front-End JavaScript API
+
+Plugin developers typically include a front-end JavaScript API. The primary purpose is to abstract away Cordova's internal APIs, eliminate the need for app developers to understand the specific naming of your plugin's service or methods, and simplify the overall usage of the plugin.
+
+### `cordova.exec` Command Syntax
+
+```javascript
+exec(<successFunction>, <failFunction>, <service>, <action>, [<args>]);
+```
+
+The `cordova.exec` method is what triggeres the request from the front-end WebView to the native side of the platform, invoking an action method on the specified service class with the provided arguments. Depending on the outcome, either the success or failure callback will be triggered.
+
+- **`successCallback`**: The first argument is the success callback. If the native operation completes successfully, this function is invoked with any returned data.
+- **`failCallback`**: The second argument is the error callback. If the operation fails, this function is called with an error object or message.
+- **`service`**: A string representing the service name on the native side. This typically matches a native class defined in your plugin.
+- **`action`**: A string representing the method name to invoke on the native service.
+- **`[arguments]`**: An array of arguments to be passed to the native method.
+
+### Creating the `www/api.js` File
+
+In this example, we'll create a folder named `www` in the plugin's root directory and add a file named `api.js`.
+
+> Note: The directory and file names are customizable and do not need to follow this exact structure. However, if you choose to rename the directory or file, be sure to update the corresponding `js-module` path in the `plugin.xml` file accordingly.
+
+The `www/api.js` file will contain the front-end JavaScript API. For this example, the contents of the Echo plugin will be as follows:
+
+```javascript
+const exec = require('cordova/exec');
+const serviceName = 'Echo';
+
+const Echo = function () { };
+
+Echo.prototype.echo = function (message) {
+ return new Promise((resolve, reject) => {
+ const _successCb = function (result) {
+ resolve(result);
+ };
+
+ const _errorCb = function (err) {
+ reject(new Error(err));
+ };
+
+ exec(_successCb, _errorCb, serviceName, 'echo', [message]);
+ });
+};
+
+module.exports = new Echo();
+```
+
+This example demonstrates how to build a front-end plugin API that returns a Promise, offering a modern and user-friendly interface for app developers.
+
+### Injecting the JavaScript API to the `window` Object
+
+To make the Echo JavaScript API available on the WebView's `window` object, we need to update the `plugin.xml` to add the injection our API using the `<js-module>` element.
+
+```xml
+<js-module src="www/api.js" name="Echo">
+ <clobbers target="Echo" />
+</js-module>
+```
+
+The above wil take the `www/api.js` and clobber it onto the `window` object as `window.Echo`.
+
+Usually, when supporting multiple platforms, all platforms has the same JavaScript API. In this case, the above XML does not need to be posted inside the `<platform>` element. If there was a case where each platform has their own own JavaScript file, then the `<js-module>` should be added to the `<platform>` element.
+
+## Implementing Native Interfaces
+
+Once you created the core structure of the plugin with the above section, we can how complement it with at least one native implementation.
+
+Details for each platform are listed below, and each section is a continuation of the simple Echo Plugin:
+
+- [Android Plugin Development Guide](../../platforms/android/plugin.html)
+- [iOS Plugin Development Guide](../../platforms/ios/plugin.html)
+
+## Testing a Plugin during development
+
+Usually, the simplest way to manually test a plugin during development is to create a Cordova app and add the plugin with the `--link` option:
+
+```zsh
+cordova plugin add ../path/to/my/plugin/relative/to/project --link
+```
+
+This will creates a symbolic link instead of copying the plugin files, which enables you to work on your plugin and then simply rebuild the app to use your changes. The plugin should be added after the platform, or the link will not work. The link will also be lost if you re-add the platform or [restore the project](../../../platform_plugin_versioning_ref/index.md) with `cordova prepare`. In that case, you'll need to re-add the plugin to restore the link.
+
+## Publishing Plugins
+
+You can publish your plugin to any `npmjs`-based registry, but the recommended one is the [npm registry](https://www.npmjs.com). This allows other developers to easily install your plugin using the Cordova CLI.
+
+To publish,
+
+```zsh
+$ npm adduser # that is if you don't have an account yet
+$ npm publish /path/to/your/plugin
+```
+
+If you do not plan to publish your plugin publicly, it is recommended to set the `private` flag in the `package.json` to `true` to prevent accidental publication.
+
+```zsh
+npm pkg set private=true --json
+```
+
+For more details on npm usage, refer to [Contributing packages to the registry](https://docs.npmjs.com/packages-and-modules/contributing-packages-to-the-registry) on the npm documentation site.
[cdv_plugin]: ../../../reference/cordova-cli/index.html#cordova-plugin-command
[npm-semver]: https://www.npmjs.com/package/semver
diff --git a/www/docs/en/12.x-2025.01/guide/platforms/android/index.md b/www/docs/en/12.x-2025.01/guide/platforms/android/index.md
index a74c673..4374b70 100644
--- a/www/docs/en/12.x-2025.01/guide/platforms/android/index.md
+++ b/www/docs/en/12.x-2025.01/guide/platforms/android/index.md
@@ -41,6 +41,24 @@
</thead>
<tbody>
<tr>
+ <td>14.0.x</td>
+ <td>24 (7.0) - 35 (15.0)</td>
+ <td>
+ <ul>
+ <li>Build Tools: ^35.0.0</li>
+ <li>Kotlin: 1.9.24</li>
+ <li>Gradle: 8.13</li>
+ <li>Android Gradle Plugin: 8.7.3</li>
+ <li>AndroidX Compat Library: 1.7.0</li>
+ <li>AndroidX WebKit Library: 1.12.1</li>
+ <li>AndroidX Core SplashScreen: 1.0.1</li>
+ <li>Google Services Gradle Plugin: 4.4.2</li>
+ <li>Java Development Kit (JDK): 17</li>
+ <li>Node.js: >=20.5.0</li>
+ </ul>
+ </td>
+ </tr>
+ <tr>
<td>13.0.x</td>
<td>24 (7.0) - 34 (14.0)</td>
<td>
@@ -459,7 +477,7 @@
cdvMinSdkVersion=20
```
-- [Extending `build.gradle`](#extending-buildgradle) with the `build-extras.gradle file
+- [Extending `build.gradle`](#extending-buildgradle) with the `build-extras.gradle` file
Create a file named `build-extras.gradle` in the directory `<project-root>/platforms/android/app` with the contents such as:
@@ -469,14 +487,31 @@
The latter two options both involve including an extra file in your Android platform folder. In general, it is discouraged to edit the contents of this folder because it is easy for those changes to be lost or overwritten. Instead, these files should be copied into the folder as part of the build command by using the `before_build` [hook script](../../appdev/hooks/index.html).
-#### Extending build.gradle
+#### Extending `build.gradle`
-If you need to customize the `build.gradle` file, rather than edit it directly, it is recommended to create a sibling file named `build-extras.gradle`. This file will be included by the main `build.gradle` script when present. This file must be placed in the `app` folder of the Android's platform directory (`<your-project>/platforms/android/app`). It is recommended to use the `before_build` [hook script](../../appdev/hooks/index.html) to copy this file over.
+To customize the `app/build.gradle` file without modifying it directly, create a sibling file named `build-extras.gradle`.
-Here's an example:
+If this file exists in the `<your-project>/platforms/android/app` directory during the build process, it will be automatically applied by the app's `build.gradle` script.
+
+To automate placing `build-extras.gradle` in the correct location, use the `<resource-file>` element in `config.xml`.
+
+In the example below, the source `build-extras.gradle` is saved in a `res/` directory in the project root. It is then declared in `config.xml` to copy it to the appropriate target location:
+
+```xml
+<resource-file src="res/build-extras.gradle" target="app/build-extras.gradle"/>
+```
+
+**Note:** The `res/` directory name is just an example. You can use any directory and file name you prefer. However, it's recommended not to place the file inside the `platforms`, `plugins`, or `www` directories. Also, make sure the `target` path matches exactly as shown in the example.
+
+**Note:** Plugin developers can also include a `build-extras.gradle` file, but should use the `<framework>` element in `plugin.xml` instead of `<resource-file>`:
+
+```xml
+<framework src="build-extras.gradle" custom="true" type="gradleReference" />
+```
+
+**Example `build-extras.gradle`:**
```groovy
-// Example build-extras.gradle
// This file is included at the beginning of `build.gradle`
// special properties (see `build.gradle`) can be set and overwrite the defaults
@@ -500,12 +535,6 @@
}
```
-Note that plugins can also include `build-extras.gradle` files via:
-
-```xml
-<framework src="some.gradle" custom="true" type="gradleReference" />
-```
-
#### Configuring Gradle JVM Args
To change the Gradle JVM args, the `--jvmargs` flag can be used with both Cordova's `build` and `run` commands. This is mostly useful for controlling how much memory gradle is allowed to use during the build process. It is recommended to allow at least 2048 MB.
diff --git a/www/docs/en/12.x-2025.01/guide/platforms/android/webview.md b/www/docs/en/12.x-2025.01/guide/platforms/android/webview.md
index de9e299..0fc2c38 100644
--- a/www/docs/en/12.x-2025.01/guide/platforms/android/webview.md
+++ b/www/docs/en/12.x-2025.01/guide/platforms/android/webview.md
@@ -33,102 +33,227 @@
platform relies on a `CordovaWebView` component, which builds on a
legacy `CordovaActivity` component that pre-dates the 1.9 release.
-1. To follow these instructions, make sure you have the latest Cordova
- distribution. Download it from
- [cordova.apache.org](https://cordova.apache.org) and unzip its
- Android package.
+1. Create a new or open an exisiting native application.
-1. Navigate to the Android package's `/framework` directory and run
- `ant jar`. It creates the Cordova `.jar` file, formed as
- `/framework/cordova-x.x.x.jar`.
+2. Add the Cordova-Android framework dependency to your app module's build configuration.
-1. Copy the `.jar` file into the Android project's `/libs` directory.
+ If your build configuration uses Groovy DSL, update `app/build.gradle` with the following:
-1. Add the following to the application's `/res/xml/main.xml` file,
- with the `layout_height`, `layout_width` and `id` modified to suit
- the application:
+ ```groovy
+ dependencies {
+ implementation 'org.apache.cordova:framework:14.0.1'
+ }
+ ```
- <org.apache.cordova.CordovaWebView
- android:id="@+id/tutorialView"
+ If your build configuration uses Kotlin DSL, update `app/build.gradle.kts` with the following:
+
+ ```kotlin
+ dependencies {
+ implementation("org.apache.cordova:framework:14.0.1")
+ }
+ ```
+
+ After making any changes to your build configuration file, make sure to "**Sync Project with Gradle Files**" so it will checkout the framework.
+
+ **Note:** Your build configuration may already includes a `dependencies` block, so simply add the `implementation` line within the existing block.
+
+ **Note:** You can find a list of available versions of released Cordova-Android framework on [Sonatype Maven Central Repository](https://central.sonatype.com/artifact/org.apache.cordova/framework/versions) or any other mirror of the Maven Central Repository.
+
+ 3. Modify the layout file of the activity that shall host the Cordova view e.g.
+
+ ```xml
+ <?xml version="1.0" encoding="utf-8"?>
+ <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
+ android:orientation="vertical"
+ android:layout_width="match_parent"
+ android:layout_height="match_parent">
+
+ <org.apache.cordova.engine.SystemWebView
+ android:id="@+id/cordovaWebView"
android:layout_width="match_parent"
android:layout_height="match_parent" />
+ </LinearLayout>
+ ```
-1. Modify the activity so that it implements the `CordovaInterface`.
- It should implement the included methods. You may wish to copy
- them from `/framework/src/org/apache/cordova/CordovaActivity.java`,
- or else implement them on your own. The following code fragment
- shows a basic application that relies on the interface. Note how
- the referenced view id matches the `id` attribute specified in the
- XML fragment shown above:
+ 4. Modify your activity to extend `CordovaActivity` and override the `onCreate`, `makeWebView` and `createViews` to use your defined layout:
- public class CordovaViewTestActivity extends Activity implements CordovaInterface {
- CordovaWebView cwv;
- /* Called when the activity is first created. */
- @Override
- public void onCreate(Bundle savedInstanceState) {
- super.onCreate(savedInstanceState);
- setContentView(R.layout.main);
- cwv = (CordovaWebView) findViewById(R.id.tutorialView);
- Config.init(this);
- cwv.loadUrl(Config.getStartUrl());
- }
+ **Kotlin Example:**
-1. If the application needs to use the camera, implement the
- following:
+ ```kotlin
+ package org.apache.cordova.testapp
- @Override
- public void setActivityResultCallback(CordovaPlugin plugin) {
- this.activityResultCallback = plugin;
+ import android.os.Bundle
+ import android.view.View
+ import androidx.activity.enableEdgeToEdge
+ import org.apache.cordova.CordovaActivity
+ import org.apache.cordova.CordovaWebView
+ import org.apache.cordova.CordovaWebViewImpl
+ import org.apache.cordova.engine.SystemWebView
+ import org.apache.cordova.engine.SystemWebViewEngine
+
+ class TestActivity : CordovaActivity() {
+ override fun onCreate(savedInstanceState: Bundle?) {
+ super.onCreate(savedInstanceState)
+ enableEdgeToEdge()
+ setContentView(R.layout.activity_test)
}
- /**
- * Launch an activity for which you would like a result when it finished. When this activity exits,
- * your onActivityResult() method is called.
- *
- * @param command The command object
- * @param intent The intent to start
- * @param requestCode The request code that is passed to callback to identify the activity
- */
- public void startActivityForResult(CordovaPlugin command, Intent intent, int requestCode) {
- this.activityResultCallback = command;
- this.activityResultKeepRunning = this.keepRunning;
- // If multitasking turned on, then disable it for activities that return results
- if (command != null) {
- this.keepRunning = false;
- }
+ override fun makeWebView(): CordovaWebView {
+ val appView = findViewById<View>(R.id.cordovaWebView) as SystemWebView
+ return CordovaWebViewImpl(SystemWebViewEngine(appView))
+ }
- // Start activity
- super.startActivityForResult(intent, requestCode);
+ override fun createViews() {
+ // leave empty so the layout is used
+ }
+ }
+ ```
+
+ **Java Example:**
+
+ ```java
+ package org.apache.cordova.testapp;
+
+ import android.os.Bundle;
+ import android.view.View;
+ import androidx.activity.enableEdgeToEdge;
+ import org.apache.cordova.CordovaActivity;
+ import org.apache.cordova.CordovaWebView;
+ import org.apache.cordova.CordovaWebViewImpl;
+ import org.apache.cordova.engine.SystemWebView;
+ import org.apache.cordova.engine.SystemWebViewEngine;
+
+ public class TestActivity extends CordovaActivity {
+ @Override
+ public void onCreate(Bundle savedInstanceState) {
+ super.onCreate(savedInstanceState);
+ setContentView(R.layout.activity_test); // layout file for your activity
+ super.init();
+ loadUrl(launchUrl);
}
@Override
- /**
- * Called when an activity you launched exits, giving you the requestCode you started it with,
- * the resultCode it returned, and any additional data from it.
- *
- * @param requestCode The request code originally supplied to startActivityForResult(),
- * allowing you to identify who this result came from.
- * @param resultCode The integer result code returned by the child activity through its setResult().
- * @param data An Intent, which can return result data to the caller (various data can be attached to Intent "extras").
- */
- protected void onActivityResult(int requestCode, int resultCode, Intent intent) {
- super.onActivityResult(requestCode, resultCode, intent);
- CordovaPlugin callback = this.activityResultCallback;
- if (callback != null) {
- callback.onActivityResult(requestCode, resultCode, intent);
+ protected CordovaWebView makeWebView() {
+ SystemWebView appView = (SystemWebView) findViewById(R.id.cordovaWebView); // id for the SystemWebView in previous step
+ return new CordovaWebViewImpl(new SystemWebViewEngine(appView));
+ }
+
+ @Override
+ protected void createViews() {
+ // leave empty so the layout is used
+ }
+ }
+ ```
+
+3. Set up your activity's style to comply with Cordova
+
+ By default, `CordovaActivity` shows an initial splash screen. If this is the desired behavior, your custom activity should define a style in the `android:theme` attribute that inherits from `Theme.SplashScreen.IconBackground`.
+
+ Below is an example of what your `<activity>` might look like in `AndroidManifest.xml`:
+
+ **Sample `AndroidManifest.xml` `<activity>`:**
+
+ ```xml
+ <activity
+ android:name=".TestActivity"
+ android:exported="false"
+ android:theme="@style/Theme.MyCordovaAppSplashScreen" />
+ ```
+
+ Here's the corresponding style in `themes.xml` to match the `android:theme` value. Feel free to rename the style to suit your app.
+
+ **Sample `themes.xml` `<style>`:**
+
+ ```xml
+ <?xml version="1.0" encoding="utf-8"?>
+ <resources xmlns:tools="http://schemas.android.com/tools">
+ <!-- Theme for the activity that hosts Cordova -->
+ <style name="Theme.MyCordovaAppSplashScreen" parent="Theme.SplashScreen.IconBackground">
+ <item name="windowSplashScreenBackground">@color/black</item>
+ <item name="windowSplashScreenAnimatedIcon">@drawable/ic_launcher_foreground</item>
+ <item name="windowSplashScreenAnimationDuration">200</item>
+ <item name="postSplashScreenTheme">@style/Theme.MyCordovaApp</item>
+ </style>
+
+ <!-- Theme applied after the splash screen -->
+ <style name="Theme.MyCordovaApp" parent="Theme.AppCompat.DayNight.NoActionBar" />
+ </resources>
+ ```
+
+ > **Note:** Since `CordovaActivity` extends `AppCompatActivity`, the `postSplashScreenTheme` must inherit from a `Theme.AppCompat.*` style (e.g., `Theme.AppCompat.DayNight.NoActionBar` or a custom variant).
+
+ If you **don't** want the initial splash screen to appear, override the `showInitialSplashScreen` method in your activity:
+
+ **Kotlin example:**
+
+ ```kotlin
+ override fun showInitialSplashScreen(): Boolean {
+ return false
+ }
+ ```
+
+ > **Note:** If the splash screen is disabled, make sure the `android:theme` points directly to a theme based on `Theme.AppCompat.*`. Avoid using `Theme.SplashScreen.*`.
+
+4. Copy your application's web assets (HTML, CSS, JavaScript) to the Android project's `<app-root-directory>/app/src/main/assets/www/` directory.
+
+5. Copy your `config.xml` file to your Android project's `<app-root-directory>/app/src/main/res/xml/` directory.
+
+## Bonus: Jetpack Compose
+
+If your native Android application uses Jetpack Compose instead of XML layouts, you can still integrate the Cordova WebView by writing your Activity like this:
+
+```kotlin
+package org.apache.cordova.testapp
+
+import android.os.Bundle
+import androidx.activity.compose.setContent
+import androidx.activity.enableEdgeToEdge
+import androidx.compose.foundation.layout.fillMaxSize
+import androidx.compose.runtime.Composable
+import androidx.compose.ui.Modifier
+import androidx.compose.ui.viewinterop.AndroidView
+import org.apache.cordova.testapp.ui.theme.TestAppTheme
+import org.apache.cordova.CordovaActivity
+import org.apache.cordova.CordovaWebView
+import org.apache.cordova.CordovaWebViewImpl
+import org.apache.cordova.engine.SystemWebView
+import org.apache.cordova.engine.SystemWebViewEngine
+
+class TestActivity : CordovaActivity() {
+ private lateinit var cordovaWebView: CordovaWebView
+
+ override fun onCreate(savedInstanceState: Bundle?) {
+ super.onCreate(savedInstanceState)
+ enableEdgeToEdge()
+
+ // Set up the Cordova WebView manually
+ val systemWebView = SystemWebView(this)
+ cordovaWebView = CordovaWebViewImpl(SystemWebViewEngine(systemWebView))
+
+ setContent {
+ // Make sure to change "TestAppTheme" with your app's custom Jetpack Compose theme function.
+ TestAppTheme {
+ CordovaWebViewContainer(systemWebView = systemWebView)
}
}
-1. Finally, remember to add the thread pool, otherwise plugins
- have no threads on which to run:
+ loadUrl(launchUrl)
+ }
- @Override
- public ExecutorService getThreadPool() {
- return threadPool;
- }
+ override fun makeWebView(): CordovaWebView {
+ return cordovaWebView
+ }
-1. Copy the application's HTML and JavaScript files to the Android
- project's `/assets/www` directory.
+ override fun createViews() {
+ // leave empty so the layout is used
+ }
+}
-1. Copy the `config.xml` file from `/framework/res/xml` to the
- project's `/res/xml` directory.
+@Composable
+fun CordovaWebViewContainer(systemWebView: SystemWebView) {
+ AndroidView(
+ factory = { systemWebView },
+ modifier = Modifier.fillMaxSize()
+ )
+}
+```
diff --git a/www/docs/en/12.x-2025.01/guide/platforms/ios/index.md b/www/docs/en/12.x-2025.01/guide/platforms/ios/index.md
index bc1e960..97f02ee 100644
--- a/www/docs/en/12.x-2025.01/guide/platforms/ios/index.md
+++ b/www/docs/en/12.x-2025.01/guide/platforms/ios/index.md
@@ -50,6 +50,18 @@
</thead>
<tbody>
<tr>
+ <td>8.x</td>
+ <td>13.0</td>
+ <td>
+ <ul>
+ <li>Cocoapods: >=1.16.0</li>
+ <li>ios-deploy: >=1.12.2</li>
+ <li>Node: >=20.17.0</li>
+ <li>Xcode (xcodebuild): >=15.0.0</li>
+ </ul>
+ </td>
+ </tr>
+ <tr>
<td>7.x</td>
<td>11.0</td>
<td>
@@ -102,7 +114,7 @@
Once Xcode is installed, several command-line tools need to be enabled
for Cordova to run. From the command line, run:
-```bash
+```zsh
$ xcode-select --install
```
@@ -113,7 +125,7 @@
Install ios-deploy via [Homebrew](https://brew.sh/) by running:
-```bash
+```zsh
$ brew install ios-deploy
```
@@ -123,7 +135,7 @@
To install CocoaPods, run the following from command-line terminal:
-```bash
+```zsh
$ brew install cocoapods
```
@@ -137,15 +149,15 @@
To preview the app in the iOS simulator:
-1. Open the workspace file (`platforms/ios/HelloWorld.xcworkspace`) from Xcode, _or_ from the command line:
+1. Open the workspace file (`platforms/ios/App.xcworkspace`) from Xcode, _or_ from the command line:
- ```bash
- $ open ./platforms/ios/HelloWorld.xcworkspace/
+ ```zsh
+ $ open ./platforms/ios/App.xcworkspace/
```
2. Make sure the `HelloWorld` project is selected in the left panel (1).
- 
+ 
3. Select the intended device from the toolbar's __Scheme__ menu, such
as the iPhone XR Simulator as highlighted in (2)
@@ -155,7 +167,7 @@
application in the simulator. A separate simulator application opens
to display the app:
- 
+ <img src="{{ site.baseurl }}/static/img/guide/platforms/ios/xcode26-helloworld-running-simulator.png" alt="iOS Simulator" width="400"/>
Only one simulator may run at a time, so if you want to test the app
in a different simulator, you need to quit the simulator application
@@ -278,8 +290,10 @@
If you have a custom situation where you need to pass additional build flags to Xcode you would use one or more `--buildFlag` options to pass these flags to `xcodebuild`. If you use an `xcodebuild` built-in flag, it will show a warning.
- cordova build --device --buildFlag="MYSETTING=myvalue" --buildFlag="MY_OTHER_SETTING=othervalue"
- cordova run --device --buildFlag="DEVELOPMENT_TEAM=FG35JLLMXX4A" --buildFlag="-scheme TestSchemeFlag"
+```zsh
+cordova build --device --buildFlag="MYSETTING=myvalue" --buildFlag="MY_OTHER_SETTING=othervalue"
+cordova run --device --buildFlag="DEVELOPMENT_TEAM=FG35JLLMXX4A" --buildFlag="-scheme TestSchemeFlag"
+```
You can also specify a `buildFlag` option in [`build.json` above](#using-buildjson) (the value for the `buildFlag` key is a string or an array of strings).
@@ -294,69 +308,29 @@
you wish to use Xcode built in debugging/profiling tools or if you are
developing iOS plugins. Please note that when opening your project in Xcode,
it is recommended that you do NOT edit your code in the IDE. This will edit the code
-in the ```platforms``` folder of your project (not ```www```), and changes are liable to be overwritten.
-Instead, edit the ```www``` folder and copy over your changes by running ```cordova build```.
+in the `platforms` folder of your project (not `www`), and changes are liable to be overwritten.
+Instead, edit the `www` folder and copy over your changes by running `cordova build`.
-Plugin developers wishing to edit their native code in the IDE should use the ```--link``` flag when adding their
+Plugin developers wishing to edit their native code in the IDE should use the `--link` flag when adding their
plugin to the project via cordova plugin add. This will link the files so that changes to the plugin files in the
platforms folder are reflected in your plugin's source folder (and vice versa).
-Once the ios platform is added to your project and built using ```cordova build```, you can open it from
-within Xcode. Double-click to open the `${PROJECT_NAME}/platforms/ios/${PROJECT_NAME}.xcworkspace`
+Once the ios platform is added to your project and built using `cordova build`, you can open it from
+within Xcode. Double-click to open the `${PROJECT_NAME}/platforms/ios/App.xcworkspace`
file or open Xcode from your terminal:
-```bash
-$ open -a Xcode platforms/ios
+```zsh
+$ open -a Xcode platforms/ios/App.xcworkspace
```
The screen should look like this:
-
-
-## Platform Centered Workflow
-
-cordova-ios includes a number of scripts that allow the platform to be used
-without the full Cordova CLI. This development path may offer you a greater
-range of development options in certain situations than the cross-platform cordova CLI.
-For example, you need to use shell tools when deploying a custom
-Cordova WebView alongside native components. Before using this
-development path, you must still configure the SDK environment
-as described in [Requirements and Support](#link-requirements-and-support)
-above.
-
-For each of the scripts discussed below, refer to
- [Cordova CLI Reference][cli] for more information on their
-arguments and usage. Each script has a name that matches the corresponding CLI
-command. For example, `cordova-ios/bin/create` is equivalent to
-`cordova create`.
-
-To get started, either download the cordova-ios package from
-[npm](https://www.npmjs.com/package/cordova-ios) or
-[Github](https://github.com/apache/cordova-ios).
-
-To create a project using this package, run the `create` script in the `bin`
-folder:
-
-```bash
-$ cordova-ios/bin/create ...
-```
-
-To run the app, use the `run` script in the `bin` folder:
-
-```bash
-$ cordova-ios/bin/run
-```
-
-The created project will have a folder named `cordova` inside that contains
-scripts for the project-specific Cordova commands (e.g. `run`, `build`, etc.).
-
-To install plugins in this project, use the [Cordova Plugman Utility](../../../plugin_ref/plugman.html).
+
## Upgrading
Refer to [this](./upgrade.html) article for instructions to upgrade your ```cordova-ios``` version.
-
-(Mac®, OS X®, Apple®, Xcode®, App Store℠, iPad®, iPhone®, iPod® and Finder® are Trademarks of Apple Inc.)
+(macOS®, Mac®, OS X®, Apple®, Xcode®, App Store℠, iPad®, iPhone®, iPod® and Finder® are Trademarks of Apple Inc.)
[cli]: ../../../reference/cordova-cli/index.html
diff --git a/www/docs/en/12.x-2025.01/guide/platforms/ios/plugin.md b/www/docs/en/12.x-2025.01/guide/platforms/ios/plugin.md
index f1ba5c1..e81f299 100644
--- a/www/docs/en/12.x-2025.01/guide/platforms/ios/plugin.md
+++ b/www/docs/en/12.x-2025.01/guide/platforms/ios/plugin.md
@@ -23,134 +23,180 @@
# iOS Plugin Development Guide
-This section provides details for how to implement native plugin code
-on the iOS platform.
+- [iOS Plugin Development Guide](#ios-plugin-development-guide)
+ - [Creating an Cordova Plugin for iOS](#creating-an-cordova-plugin-for-ios)
+ - [Adding Native Source Code](#adding-native-source-code)
+ - [Configuring the `plugin.xml`](#configuring-the-pluginxml)
+ - [Adding Plugin Code to iOS Project](#adding-plugin-code-to-ios-project)
+ - [Setting Class Mapping for WebView-to-Native Communication](#setting-class-mapping-for-webview-to-native-communication)
+ - [Configuring Plugin Initialization Timing](#configuring-plugin-initialization-timing)
+ - [Supporting Swift Package Manager (SPM)](#supporting-swift-package-manager-spm)
+ - [Creating SPM's `Package.swift` File](#creating-spms-packageswift-file)
+ - [Additional Native Side Implementation](#additional-native-side-implementation)
+ - [Executing Plugin Initialization Logic](#executing-plugin-initialization-logic)
+ - [Handeling Long-running \& Background Activities](#handeling-long-running--background-activities)
+ - [Hooking into WKURLSchemeTask](#hooking-into-wkurlschemetask)
+ - [Using Background Threads](#using-background-threads)
+ - [Adding a Privacy Manifest File](#adding-a-privacy-manifest-file)
+ - [CDVPluginResult Message Types](#cdvpluginresult-message-types)
+ - [Other Supported `CDVPlugin` Features](#other-supported-cdvplugin-features)
+ - [Debugging Plugins for iOS](#debugging-plugins-for-ios)
+ - [Common Pitfalls](#common-pitfalls)
-Before reading this, see [Plugin Development Guide][plugin-dev] for
-an overview of the plugin's structure and its common JavaScript
-interface. This section continues to demonstrate the sample _echo_
-plugin that communicates from the Cordova webview to the native
-platform and back.
+This guide provides details on implementing native plugin code for the iOS platform. The plugin's platform-native code can be written in either Objective-C or Swift.
-An iOS plugin is implemented as an Objective-C class that extends the
-`CDVPlugin` class. For JavaScript's `exec` method's `service`
-parameter to map to an Objective-C class, each plugin class must be
-registered as a `<feature>` tag in the named application directory's
-`config.xml` file.
+Before proceeding, refer to the [Plugin Development Guide][plugin-dev] for an overview of plugin structure, plugin core files, and its common JavaScript interface. This guide will continue to use the _echo_ plugin, as an exmaple, which enables communication between the Cordova WebView and the native platform.
-## Plugin Class Mapping
+## Creating an Cordova Plugin for iOS
-The JavaScript portion of a plugin uses the `cordova.exec` method as
-follows:
+In this section we will cover:
-```javascript
-exec(<successFunction>, <failFunction>, <service>, <action>, [<args>]);
-```
+1. Adding Native Source Code
+2. Configuring `plugin.xml`
+ - Adding Plugin Code to iOS Project
+ - Setting Class Mapping for WebView-to-Native Communication
+3. Adding Swift Package Manager Support
+4. Additional Native Side Implementation
-This marshals a request from the `UIWebView` to the iOS native side,
-effectively calling the `action` method on the `service` class, with
-the arguments passed in the `args` array.
+### Adding Native Source Code
-Specify the plugin as a `<feature>` tag in your Cordova-iOS
-application's project's `config.xml` file, using the `plugin.xml` file
-to inject this markup automatically, as described in [Plugin Development Guide][plugin-dev]:
+In the following example, we will place all files in the `src/ios/` directory. This directory will be located inside the Cordova plugin's project root directory. The name and path of the directory are not strict and can be customized as you prefer. However, this is the typical pattern used by official Apache Cordova plugins to separate platform-specific source code and resources.
-```xml
-<feature name="LocalStorage">
- <param name="ios-package" value="CDVLocalStorage" />
-</feature>
-```
+- **Swift**
-The feature's `name` attribute should match what you specify as the
-JavaScript `exec` call's `service` parameter. The `value` attribute
-should match the name of the plugin's Objective-C class. The `<param>`
-element's `name` should always be `ios-package`. If you do not follow
-these guidelines, the plugin may compile, but Cordova may still not be
-able to access it.
+ In Swift, the implementation source code is written inside a `.swift` file. This is where the business logic is performed.
-## Plugin Initialization and Lifetime
+ To expose methods written in Swift to Objective-C, the `@objc` annotation needs to be added. When the `@objc` annotation is used, those methods are automatically included in the `-Swift.h` header file. This is required so that Cordova can locate and invoke them.
-One instance of a plugin object is created for the life of each
-`UIWebView`. Plugins are not instantiated until they are first
-referenced by a call from JavaScript, unless `<param>` with an `onload`
-`name` attribute is set to `"true"` in `config.xml`. For example,
+ **Echo.swift (Source File):**
-```xml
-<feature name="Echo">
- <param name="ios-package" value="Echo" />
- <param name="onload" value="true" />
-</feature>
-```
+ In this example, when the `echo` method is invoked, an `.ok` response with the provided message is returned if the message exists; otherwise, an `.error` is returned.
-Plugins should use the `pluginInitialize` method for their startup logic.
+ ```swift
+ #if canImport(Cordova)
+ import Cordova
+ #endif
-Plugins with long-running requests or background activities such as media
-playback, listeners, or that maintain internal state should implement
-the `onReset` method to cancel those long-running requests or to clean up
-after those activities.
-The method runs when the `UIWebView` navigates to a new page or refreshes, which
-reloads the JavaScript.
+ @objc(Echo)
+ class Echo : CDVPlugin {
+ @objc func sample(_ command : CDVInvokedUrlCommand) {
+ let myarg = command.arguments[0];
+ let pluginResult;
-## Writing an iOS Cordova Plugin
+ if (myarg != nil) {
+ pluginResult = CDVPluginResult(status: .ok, messageAs: myarg)
+ } else {
+ pluginResult = CDVPluginResult(status: .error)
+ }
-A JavaScript call fires off a plugin request to the native side, and
-the corresponding iOS Objective-C plugin is mapped properly in the
-`config.xml` file, but what does the final iOS Objective-C plugin
-class look like? Whatever is dispatched to the plugin with
-JavaScript's `exec` function is passed into the corresponding plugin
-class's `action` method. A plugin method has this signature:
-
-```objective_c
-- (void)myMethod:(CDVInvokedUrlCommand*)command
-{
- CDVPluginResult* pluginResult = nil;
- NSString* myarg = [command.arguments objectAtIndex:0];
-
- if (myarg != nil) {
- pluginResult = [CDVPluginResult resultWithStatus:CDVCommandStatus_OK];
- } else {
- pluginResult = [CDVPluginResult resultWithStatus:CDVCommandStatus_ERROR messageAsString:@"Arg was null"];
+ self.commandDelegate.send(pluginResult, callbackId: command.callbackId)
+ }
}
- [self.commandDelegate sendPluginResult:pluginResult callbackId:command.callbackId];
-}
+ ```
+
+- **Objective-C**
+
+ **Echo.h (Header File):**
+
+ The header file defines the methods and properties that are exposed to other native classes. We also expose the methods that the front-end WebView requests so that Cordova can locate and invoke them.
+
+ In this example, we are exposing the `echo` method:
+
+ ```objc
+ #import <Cordova/Cordova.h>
+
+ @interface Echo : CDVPlugin
+
+ - (void)echo:(CDVInvokedUrlCommand*)command;
+
+ @end
+ ```
+
+ **Echo.m (Source File):**
+
+ The implementation source code (.m files) is where the business logic is performed.
+
+ In this example, when the `echo` method is invoked, it examines the contents of the first argument to determine if there is something to echo back to the front-end WebView. If there is content, a `OK` result is returned with the message; otherwise, an `ERROR` is returned.
+
+ ```objc
+ #import "Echo.h"
+ #import <Cordova/Cordova.h>
+
+ @implementation Echo
+
+ - (void)echo:(CDVInvokedUrlCommand*)command
+ {
+ CDVPluginResult* pluginResult = nil;
+ NSString* echo = [command.arguments objectAtIndex:0];
+
+ if (echo != nil && [echo length] > 0) {
+ pluginResult = [CDVPluginResult resultWithStatus:CDVCommandStatus_OK messageAsString:echo];
+ } else {
+ pluginResult = [CDVPluginResult resultWithStatus:CDVCommandStatus_ERROR];
+ }
+
+ [self.commandDelegate sendPluginResult:pluginResult callbackId:command.callbackId];
+ }
+
+ @end
+ ```
+
+**Additional Notes:**
+
+- Plugin entry classes must extend `CDVPlugin`.
+- Supporting classes does not extend `CDVPlugin`.
+- The following `import` statements are required to be added to the top of the plugin entry classes.
+
+ Swift based project will added the following to the source file:
+
+ ```swift
+ #if canImport(Cordova)
+ import Cordova
+ #endif
+ ```
+
+ Objective-C based projects will added the following to the header & source files:
+
+ ```objc
+ #import <Cordova/Cordova.h>
+ ```
+
+**Additional References:**
+
+For more details, see the following class headers:
+
+- [CDVInvokedUrlCommand][CDVInvokedUrlCommand]
+- [CDVPluginResult][CDVPluginResult]
+- [CDVCommandDelegate][CDVCommandDelegate]
+
+### Configuring the `plugin.xml`
+
+#### Adding Plugin Code to iOS Project
+
+Now that we have our native source code written in our plugin project, we need to add these resource files to the application's directory. This ensures that the source code is available and used by the app. This can be achieved by defining the `<source-file>` and `<header-file>` elements in the `plugin.xml`.
+
+Below is an example of what this should look like inside the `plugin.xml`:
+
+```xml
+<platform name="ios">
+ <!-- If your plugin uses Swift -->
+ <source-file src="src/ios/Echo.swift" />
+
+ <!-- If your plugin uses Objective-C -->
+ <!-- <header-file src="src/ios/Echo.h" /> -->
+ <!-- <source-file src="src/ios/Echo.m" /> -->
+</platform>
```
-For more details, see
- [CDVInvokedUrlCommand.h][CDVInvokedUrlCommand.h], [CDVPluginResult.h][CDVPluginResult.h],
-and [CDVCommandDelegate.h][CDVCommandDelegate.h].
+_Note:_ If you are following along with **Objective-C**, be sure to update the above accordingly. In the example above, we are using **Swift**.
-## iOS CDVPluginResult Message Types
+What the above configuration does is for the iOS platform, it places the header file and source file in the appropriate location within the application. It also creates the necessary references in the Xcode project so that the application will recognize and use these files.
-You can use `CDVPluginResult` to return a variety of result types back to
-the JavaScript callbacks, using class methods that follow this pattern:
+#### Setting Class Mapping for WebView-to-Native Communication
-```objective_c
-+ (CDVPluginResult*)resultWithStatus:(CDVCommandStatus)statusOrdinal messageAs...
-```
+To be able to trigger native functionality in JavaScript, the native classes needs to be mapped within `plugin.xml` by using the `<feature>` element.
-You can create `String`, `Int`, `Double`, `Bool`, `Array`,
-`Dictionary`, `ArrayBuffer`, and `Multipart` types. You can also leave
-out any arguments to send a status, or return an error, or even choose
-not to send any plugin result, in which case neither callback fires.
-
-Note the following for complex return values:
-
-- `messageAsArrayBuffer` expects `NSData*` and converts to an
- `ArrayBuffer` in the JavaScript callback. Likewise, any
- `ArrayBuffer` the JavaScript sends to a plugin are converted to
- `NSData*`.
-
-- `messageAsMultipart` expects an `NSArray*` containing any of the
- other supported types, and sends the entire array as the `arguments`
- to your JavaScript callback. This way, all of the arguments are
- serialized or deserialized as necessary, so it is safe to return
- `NSData*` as multipart, but not as `Array`/`Dictionary`.
-
-## Echo iOS Plugin Example
-
-To match the JavaScript interface's _echo_ feature described in
-Application Plugins, use the `plugin.xml` to inject a `feature`
-specification to the local platform's `config.xml` file:
+Below is an example of what this should look like once the feature is added to the `plugin.xml` from the previous steps, combined:
```xml
<platform name="ios">
@@ -159,84 +205,130 @@
<param name="ios-package" value="Echo" />
</feature>
</config-file>
+
+ <!-- If your plugin uses Swift -->
+ <source-file src="src/ios/Echo.swift" />
+
+ <!-- If your plugin uses Objective-C -->
+ <!-- <header-file src="src/ios/Echo.h" /> -->
+ <!-- <source-file src="src/ios/Echo.m" /> -->
</platform>
```
+Specify the plugin's `<feature>` tag ensures that the necessary configuration is automatically injected into the Cordova-iOS project, as described in the [Plugin Development Guide][plugin-dev].
-Then we would add the following `Echo.h` and `Echo.m` files to the
-`Plugins` folder within the Cordova-iOS application directory:
+Lets break down what each element and attribute means.
+- `<feature>`
+ - The `name` attribute should match with the `service` parameter' value that is used in the JavaScript `cordova.exec` method call.
+- `<param>`
+ - The `value` attribute should match the name of the plugin'sObjective-C or Swift class name.
+ - The `name` attribute should always have the value of `ios-package` for iOS plugins.
-```objective_c
-/********* Echo.h Cordova Plugin Header *******/
+If the follow guidelines are not met, the plugin may compile but Cordova will not be able to access it.
-#import <Cordova/CDVPlugin.h>
+**IMPORTANT NOTE:** During the platform preparation for building the app, an auto-generated merged `config.xml` file is created. This file contains all platform-specific application configurations and plugin data gathered from the application's `config.xml` and the plugin's `plugin.xml`. The `config-file` block, as shown in the example above, ensures that the plugin's feature is injected into the merged `config.xml`, allowing the plugin to function properly. This `config.xml` is separate from the application's root `config.xml`.
-@interface Echo : CDVPlugin
+#### Configuring Plugin Initialization Timing
-- (void)echo:(CDVInvokedUrlCommand*)command;
+A single instance of a plugin object is typically created for the lifecycle of each `WKWebView`, though the instantiation timing depends on the plugin's implementation.
-@end
+By default, plugins are instantiated when they are first referenced by a call from JavaScript. However, plugins can be configured to instantiate when the app loads by defining the `onload` attribute within a `<param>` element in the plugin's `plugin.xml` configuration file. This `<param>` should be added to the plugin's `<feature>` element.
-/********* Echo.m Cordova Plugin Implementation *******/
+For example:
-#import "Echo.h"
-#import <Cordova/CDVPlugin.h>
-
-@implementation Echo
-
-- (void)echo:(CDVInvokedUrlCommand*)command
-{
- CDVPluginResult* pluginResult = nil;
- NSString* echo = [command.arguments objectAtIndex:0];
-
- if (echo != nil && [echo length] > 0) {
- pluginResult = [CDVPluginResult resultWithStatus:CDVCommandStatus_OK messageAsString:echo];
- } else {
- pluginResult = [CDVPluginResult resultWithStatus:CDVCommandStatus_ERROR];
- }
-
- [self.commandDelegate sendPluginResult:pluginResult callbackId:command.callbackId];
-}
-
-@end
+```xml
+<feature name="Echo">
+ <param name="ios-package" value="Echo" />
+ <param name="onload" value="true" /> <!-- Initialize plugin on app load -->
+</feature>
```
-The necessary imports at the top of the file extends the class from
-`CDVPlugin`. In this case, the plugin only supports a single `echo`
-action. It obtains the echo string by calling the `objectAtIndex`
-method get the first parameter of the `arguments` array, which
-corresponds to the arguments passed in by the JavaScript `exec()`
-function.
+### Supporting Swift Package Manager (SPM)
-It checks the parameter to make sure it is not `nil` or an empty
-string, returning a `PluginResult` with an `ERROR` status if so. If
-the parameter passes the check, it returns a `PluginResult` with an
-`OK` status, passing in the original `echo` string. Finally, it sends
-the result to `self.commandDelegate`, which executes the `exec`
-method's success or failure callbacks on the JavaScript side. If the
-success callback is called, it passes in the `echo` parameter.
+Starting from Cordova-iOS 8 and greater, support for the Swift Package Manager (SPM) has been implemented. To start using SPM with your plugin, a `Package.swift` file will need to be created in the plugin's root directory and add the `package="swift"` attribute to the iOS `<platform>` element in your `plugin.xml` file.
-## iOS Integration
+#### Creating SPM's `Package.swift` File
-The `CDVPlugin` class features other methods that your plugin can
-override. For example, you can capture the [pause][PauseEvent], [resume][ResumeEvent], app
-terminate and `handleOpenURL` events. See the
-[CDVPlugin.h][CDVPlugin.h] and [CDVPlugin.m][CDVPlugin.m]
-classes for guidance.
+In the plugin's root directory, create a new file called `Package.swift` with the following content:
-### WKURLSchemeTask Hook
+```swift
+// swift-tools-version:5.5
-The [WKURLSchemeTask](https://developer.apple.com/documentation/webkit/wkurlschemetask) is an interface Cordova's main WKWebView uses to load files from your app's bundle. You can create your own custom schemes or custom loading code for the webview by implementing the `- (BOOL) overrideSchemeTask: (id <WKURLSchemeTask>)urlSchemeTask` method in a plugin.
+import PackageDescription
-## Threading
+let package = Package(
+ name: "cordova-plugin-echo",
+ platforms: [.iOS(.v13)],
+ products: [
+ .library(name: "cordova-plugin-echo", targets: ["cordova-plugin-echo"])
+ ],
+ dependencies: [
+ // This must be included as a dependency, with this format for it to work.
+ .package(url: "https://github.com/apache/cordova-ios.git", branch: "master")
+ ],
+ targets: [
+ .target(
+ name: "cordova-plugin-echo",
+ dependencies: [
+ .product(name: "Cordova", package: "cordova-ios")
+ ],
+ path: "src/ios",
+ resources: [],
+ publicHeadersPath: "."
+ )
+ ]
+)
+```
-Plugin methods ordinarily execute in the same thread as the main
-interface. If your plugin requires a great deal of processing or
-requires a blocking call, you should use a background thread. For
-example:
+If the plugin is required to provide a privacy manifest file, the following line should be added to the `resources` element of the `cordova-plugin-echo` target: `.copy("Resources/PrivacyInfo.xcprivacy")`.
+On top of the SPM declaration, be sure to also refer to the section titled [Adding a Privacy Manifest File](#adding-a-privacy-manifest-file) to ensure that the actual resource file is properly declared in the `plugin.xml` so it is correctly injected into the app.
-```objective_c
+If the plugin requires for any third-party dependencies, it should be added to the `dependencies` element, and the `target`'s `dependencies`.
+
+For example:
+
+```swift
+dependencies: [
+ ...
+ .package(name: "SomePackageName", url: "...", from: "1.0.0"),
+],
+targets: [
+ .target(
+ ...
+ dependencies: [
+ .product(name: "Cordova", package: "cordova-ios"),
+ .product(name: "SomePackageLibraryName", package: "SomePackageName")
+ ],
+ )
+]
+```
+
+### Additional Native Side Implementation
+
+#### Executing Plugin Initialization Logic
+
+If the plugin has any logic that should execute on the during the plugin's initialization process, the `pluginInitialize` method should be defined in the plugin's class.
+
+For example, if the plugin has defined `onload` as `true`, when the app loads, the `pluginInitialize` method will be executed. Because this is triggered during app load, there is no `callbackID` so the `pluginInitialize` method can not return any results to the WebView. If results matter, they would need to be stored in some manar and later fetched with a JavaScript API call.
+
+#### Handeling Long-running & Background Activities
+
+Plugins with long-running requests or background activities, such as media playback, listeners, or those that maintain internal state, should implement the `onReset` method to cancel these requests or clean up after those activities.
+
+The `onReset` method is called when the `WKWebView` navigates to a new page or refreshes, triggering a reload of the JavaScript.
+
+#### Hooking into WKURLSchemeTask
+
+The [WKURLSchemeTask](https://developer.apple.com/documentation/webkit/wkurlschemetask) is an interface Cordova's main WKWebView uses to load files from your app's bundle. You can create your own custom schemes or custom loading code for the WebView by implementing the `- (BOOL) overrideSchemeTask: (id <WKURLSchemeTask>)urlSchemeTask` method in a plugin.
+
+#### Using Background Threads
+
+Plugin methods ordinarily execute in the same thread as the main interface. If your plugin requires a great deal of processing or requires a blocking call, you should use a background thread. It is important to note that any operations involving the UI, such as displaying alerts, changing colors, or performing other visual updates, must be executed on the main thread.
+
+For example:
+
+```objc
- (void)myPluginMethod:(CDVInvokedUrlCommand*)command
{
// Check command.arguments here.
@@ -250,25 +342,121 @@
}
```
-## Debugging iOS Plugins
+#### Adding a Privacy Manifest File
-To debug on the Objective-C side, you need Xcode's built-in debugger.
-For JavaScript, you can attach Safari to the app running within the iOS Simulator/Device.
+As of May 1, 2024, Apple requires a privacy manifest file to be created for apps and third-party SDKs. The purpose of the privacy manifest file is to explain the data being collected and the reasons for the required APIs it uses.
+
+Plugins can include a pre-bundled `PrivacyInfo.xcprivacy` file that lists any privacy-sensitive APIs they use, along with the reasons for their usage.
+
+It is recommended to review the following Apple Developer document, "[Describing data use in privacy manifests](https://developer.apple.com/documentation/bundleresources/privacy_manifest_files/describing_data_use_in_privacy_manifests)", to understand the list of known `NSPrivacyCollectedDataTypes` and `NSPrivacyCollectedDataTypePurposes`.
+
+Ensure all four keys—`NSPrivacyTracking`, `NSPrivacyTrackingDomains`, `NSPrivacyAccessedAPITypes`, and `NSPrivacyCollectedDataTypes`—are defined, even if you are not making an addition to the other items. Apple requires all to be defined.
+
+Once you've identified what the contents of the `PrivacyInfo.xcprivacy` will look like, lets start creating the bundle and loading it as a resource.
+
+1. Create a directory named `CDVEcho.bundle` inside the `src/ios` directory. Make sure the bundle name is unique enough to avoid conflicts with other plugins.
+
+2. Inside the new `CDVEcho.bundle` directory, create a privacy manifest file named `PrivacyInfo.xcprivacy`.
+
+3. Add the contents you've identified for this file. Here's an example:
+
+ ```xml
+ <!-- Example PrivacyInfo.xcprivacy Contents -->
+ <?xml version="1.0" encoding="UTF-8"?>
+ <!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
+ <plist version="1.0">
+ <dict>
+ <key>NSPrivacyTracking</key>
+ <false/>
+ <key>NSPrivacyTrackingDomains</key>
+ <array/>
+ <key>NSPrivacyAccessedAPITypes</key>
+ <array/>
+ <key>NSPrivacyCollectedDataTypes</key>
+ <array/>
+ </dict>
+ </plist>
+ ```
+
+4. Update your `plugin.xml` to load the `CDVEcho.bundle` into the app's resources.
+
+ Inside the iOS `<platform>` element, add a `<resource-file>` element pointing to the `CDVEcho.bundle` directory:
+
+ ```xml
+ <platform name="ios">
+ <resource-file src="src/ios/CDVEcho.bundle" target="CDVEcho.bundle" />
+ </platform>
+ ```
+
+5. **Optional:** If your plugin supports Swift Package Manager, refer to the section [Creating SPM's `Package.swift` File](#creating-spms-packageswift-file) to ensure the privacy manifest is also included as a resource file.
+
+## CDVPluginResult Message Types
+
+You can use [`CDVPluginResult`][CDVPluginResult] to return a variety of result types back to the JavaScript callbacks, using class methods that follow this pattern:
+
+```objc
++ (CDVPluginResult*)resultWithStatus:(CDVCommandStatus)statusOrdinal messageAs...
+```
+
+The following types can be used:
+
+- `String`
+- `Int`
+- `Double`
+- `Bool`
+- `Array`
+- `Dictionary`
+- `ArrayBuffer`
+- `Multipart`
+
+You can also leave out any arguments to send a status, or return an error, or even choose not to send any plugin result, in which case neither callback fires.
+
+Note the following for complex return values:
+
+- `messageAsArrayBuffer` expects `NSData*` and will convert it to an `ArrayBuffer` in the JavaScript callback. Likewise, any `ArrayBuffer` the JavaScript sends to a native side will be converted to `NSData*`.
+
+- `messageAsMultipart` expects an `NSArray*` containing any of the other supported types, and sends the entire array as the `arguments` to your JavaScript callback. This way, all of the arguments are serialized or deserialized as necessary, so it is safe to return `NSData*` as multipart, but not as `Array`/`Dictionary`.
+
+## Other Supported `CDVPlugin` Features
+
+The `CDVPlugin` class features other methods that a plugin can override.
+
+For example, the plugin can capture:
+- [`pause`][PauseEvent] Event
+- [`resume`][ResumeEvent] Event
+- App Terminate Event
+- `handleOpenURL` events
+
+For additional reference, see the following class documentation:
+
+- [CDVPlugin][CDVPlugin]
+
+## Debugging Plugins for iOS
+
+To debug the native side, you will need to use Xcode's built-in debugger.
+
+For JavaScript, you can launch the Safari Web Inspector and attach it to the running application process. The app can be running on either an iOS Simulator or device.
+
+Generally, its recommended to use a debug build for testing as it should already allow the WebView to be inspectable. If for any reason you need to test on a release build, you can enable WebView Inspector by setting the `InspectableWebview` config preference to `true` in the application's `config.xml`.
+
+E.g.
+
+```xml
+<preference name="InspectableWebview" value="true" />
+```
+
+For security purpose, its highly unrecommended to enable the `InspectableWebview` for release builds. If you do set it, remove the setting before deploy the app to the app store.
## Common Pitfalls
-- Don't forget to add your plugin's mapping to `config.xml`. If you
- forget, an error is logged in the Xcode console.
+- Don't forget to add your plugin's mapping to `plugin.xml`. If you forget, an error is logged in the Xcode console.
-- Don't forget to add any hosts you connect to in the allow list, as
- described in Domain [Allow List Guide](../../appdev/allowlist/index.html). If you forget, an error is
- logged in the Xcode console.
+- Don't forget to add any hosts you connect to in the allow list, as described in Domain [Allow List Guide](../../appdev/allowlist/index.html). If you forget, an error is logged in the Xcode console.
[plugin-dev]: ../../hybrid/plugins/index.html
-[CDVInvokedUrlCommand.h]: https://github.com/apache/cordova-ios/blob/master/CordovaLib/Classes/Public/CDVInvokedUrlCommand.h
-[CDVPluginResult.h]: https://github.com/apache/cordova-ios/blob/master/CordovaLib/Classes/Public/CDVPluginResult.h
-[CDVCommandDelegate.h]: https://github.com/apache/cordova-ios/blob/master/CordovaLib/Classes/Public/CDVCommandDelegate.h
-[CDVPlugin.h]: https://github.com/apache/cordova-ios/blob/master/CordovaLib/Classes/Public/CDVPlugin.h
-[CDVPlugin.m]: https://github.com/apache/cordova-ios/blob/master/CordovaLib/Classes/Public/CDVPlugin.m
[ResumeEvent]: ../../../cordova/events/events.html#resume
[PauseEvent]: ../../../cordova/events/events.html#pause
+[CDVCommandDelegate]: https://apache.github.io/cordova-ios/documentation/cordova/cdvcommanddelegate
+[CDVInvokedUrlCommand]: https://apache.github.io/cordova-ios/documentation/cordova/cdvinvokedurlcommand
+[CDVPlugin]: https://apache.github.io/cordova-ios/documentation/cordova/cdvplugin
+[CDVPluginResult]: https://apache.github.io/cordova-ios/documentation/cordova/cdvpluginresult
diff --git a/www/docs/en/12.x-2025.01/platform_plugin_versioning_ref/index.md b/www/docs/en/12.x-2025.01/platform_plugin_versioning_ref/index.md
index e9c65ee..7bab969 100644
--- a/www/docs/en/12.x-2025.01/platform_plugin_versioning_ref/index.md
+++ b/www/docs/en/12.x-2025.01/platform_plugin_versioning_ref/index.md
@@ -24,333 +24,264 @@
# Version Management
-Cordova provides the ability to save and restore platforms and plugins.
+Cordova allows developers to **save** and **restore** platforms and plugins, eliminating the need to check in platform and plugin source code.
-This feature allows developers to save and restore their app to a known state without having to check in all of the platform and plugin source code.
+When a platform or plugin is added, its version details are automatically saved to the `package.json` file.
-When adding a platform or plugin, details about the app's platform and plugin versions are automatically saved to the `package.json` file. It is also possible to add a platform or plugin by editing the `package.json` file directly, assuming you know the right tags and syntax. It is not possible to remove plugins or platforms in this manner. The recommended method of adding and removing plugins and platforms is with the Cordova CLI commands `cordova plugin add|remove ...` and `cordova platform add|remove ...` to avoid any out of sync issues.
+The recommended way to add or remove platforms and plugins is by using the Cordova CLI commands:
-The **restore** step happens automatically when a **`cordova prepare`** is issued, making use of information previously saved in the `package.json` and `config.xml` files.
+- `cordova platform add|remove ...`
+- `cordova plugin add|remove ...`
+
+Using these commands helps prevent out-of-sync issues.
+
+While it is technically possible to add a platform or plugin by editing `package.json` directly, this is **strongly discouraged**.
+
+The restore process runs automatically when executing `cordova prepare`, using the information stored in `package.json` and `config.xml`. This applies to both platforms and plugins. If a platform or plugin is defined in both files, `package.json` takes priority.
One scenario where save/restore capabilities come in handy is in large teams that work on an app, with each team member focusing on a platform or plugin. This feature makes it easier to share the project and reduce the amount of redundant code that is checked in the repository.
-## Platform Versioning
+The adding and removing mechanisim that Cordova CLI uses for platforms and plugins is controlled by npm CLI. Below we will take a look at the command syntax and examples.
-### Saving Platforms
+## Adding Platforms and Plugins
-To save a platform, issue the following command:
+**Command Syntax:**
```bash
-cordova platform add <platform[@<version>] | directory | git_url>
+cordova <platform | plugin> add [<package-spec> ...]
```
-After running the above command, the **`package.json`** should update with the platform dependency and cordova related information.
+The `package-spec` argument supports most formats accepted by the npm CLI.
-Example:
+Examples include:
-```json
-"cordova": {
- "platforms": [
- "android"
- ]
-},
-"dependencies": {
- "cordova-android": "^8.0.0",
-}
-```
+- Scoped and non-scoped npm packages
+- Local directory paths
+- Git remote URLs
+- Tarball archives
+- [Cordova Resolved Names](#Cordova-Resolved-Names) for official Cordova platforms
-The `--nosave` flag prevents adding and deleting the specified platform from the `package.json` file.
-
-Example:
-
-```bash
-cordova platform add <platform[@<version>] | directory | git_url> --nosave
-```
-
-The examples below fetch the package, extract it to `node_modules` and update the `package.json` file accordingly. Under the covers, this process is controlled by the npm CLI. Here are various ways to add platforms.
-
-*Adding with Cordova resolved name:*
-
-Example:
-
-```bash
-cordova platform add android
-```
-
-The avaialble Cordova resolved names are:
-
-| Cordova Resolved Name | NPM Package Name |
-| --- | --- |
-| `android` | `cordova-android` |
-| `electron` | `cordova-electron` |
-| `ios` | `cordova-ios` |
-| `browser` | `cordova-browser` |
-
-*Adding with Cordova resolved name and pinned version:*
-
-Example:
-
-```bash
-cordova platform add android@7.1.4
-```
-
-This command will explicitly fetch for version `7.1.4`.
-
-*Adding with npm package name:*
-
-Example:
-
-```bash
-cordova platform add cordova-android
-```
-
-*Adding with Git URL:*
-
-Example:
-
-```bash
-cordova platform add https://github.com/apache/cordova-android.git
-```
-
-or
-
-```bash
-cordova platform add https://github.com/apache/cordova-android
-```
-
-or
-
-```bash
-cordova platform add github:apache/cordova-android
-```
-
-* **`cordova platform add C:/path/to/android/platform`**
-
- Retrieves the Android platform from the specified directory, adds it to the project, and updates the `package.json` file.
-
-* **`cordova platform add android --nosave`**
-
- Retrieves the pinned version of `cordova-android` platform from npm, adds it to the project, but does not add it to the `package.json` file.
-
-### Updating or Removing Platforms
-
-It is possible to update and delete a platform from `config.xml` and `package.json`.
-
-To update a platform, execute the following command:
-
-```bash
-cordova platform update <platform[@<version>] | directory | git_url>
-```
-
-To remove a platform, execute one of the following commands:
-
-```bash
-cordova platform remove <platform>
-cordova platform rm <platform>
-```
-
-Some Examples:
-
-* **`cordova platform update android`**
-
- In addition to updating the `cordova-android` platform to the pinned version, it updates the `package.json` file.
-
-* **`cordova platform update android@3.8.0`**
-
- In addition to updating the `cordova-android` platform to version `3.8.0` it updates the `package.json` file.
-
-* **`cordova platform update /path/to/android/platform`**
-
- In addition to updating the `cordova-android` platform to version found in the provided folder, it updates the `package.json` file.
-
-* **`cordova platform remove android`**
-
- Removes the `cordova-android` platform from the project and removes it from the `package.json` file.
-
- _Note: If the platform definition existed in `config.xml` from a previous version of Cordova CLI, it will also be removed from `config.xml`._
-
-* **`cordova platform remove android --nosave`**
-
- Removes the `cordova-android` platform from the project, but does not remove it from the `package.json` file.
-
-### Restoring Platforms
-
-Platforms are automatically restored from the `package.json` (and `config.xml`) when executing the **`cordova prepare`** command.
-
-If a platform is defined in both files, the information defined in `package.json` is used as the source of truth.
-
-After `prepare`, any platforms restored from `config.xml` will update the `package.json` file to reflect the values taken from `config.xml`.
-
-If you add a platform without specifying a `<version | folder | git_url>`, the version that will be installed is taken from `package.json` or `config.xml`.
-
-**If discovered** in both files, `package.json` is given higher priority over `config.xml`.
-
-Example:
-
-Suppose your `config.xml` file contains the following entry:
-
-```xml
-<?xml version='1.0' encoding='utf-8'?>
- ...
- <engine name="android" spec="7.1.4" />
- ...
-</xml>
-```
-
-If you run the command **`cordova platform add android`** with no `<version | folder | git_url>` specified, the platform `android@7.1.4` will be retrieved and installed.
-
-**Example Order of Priority for Restoring Platforms:**
-
-Suppose you have defined in `config.xml` and `package.json` a platform and version as follows:
-
-**`config.xml`**:
-
-```xml
-<engine name="android" spec=“7.4.1” />
-```
-
-**`package.json`**:
-
-```json
-"cordova": {
- "platforms": [
- "android"
- ]
-},
-"dependencies": {
- "cordova-android": "^8.0.0"
-}
-```
-
-When `prepare` is executed, the version from `package.json` has higher priority over `config.xml` and version `^8.0.0` will be installed.
+Additionally, the `--nosave` flag could be appended to the command to prevent adding of specified platform and plugins from the `package.json` file.
---
-## Plugin Versioning
+**Quick Overview:**
-The plugin commands are a mirror of the platform commands:
+When you add a platform or plugin, `package.json` is updated with its dependencies and Cordova-specific metadata.
-### Saving Plugins
-
-To save a plugin, you issue the following command:
+For example, running the following commands in a Cordova project:
```bash
-cordova plugin add <plugin[@<version>] | directory | git_url>
+cordova platform add android@13.0.0
+cordova plugin add cordova-plugin-device@3.0.0
```
-After running the above command, the **`package.json`** should contain something as seen below:
+Would result in `package.json` containing the following entries:
```json
+"devDependencies": {
+ "cordova-android": "^13.0.0",
+ "cordova-plugin-device": "^3.0.0"
+},
"cordova": {
+ "platforms": [
+ "android"
+ ],
"plugins": {
"cordova-plugin-device": {}
}
-},
-"devDependencies": {
- "cordova-plugin-device": "^1.0.0"
}
```
-The `--nosave` flag prevents adding and deleting specified plugins from `package.json`. To prevent saving a plugin, you issue the following command:
+When restoring a Cordova project, this metadata determines which platforms and plugins will be installed.
+
+---
+
+### Various `add` Examples
+
+- **Cordova Resolved Names for Platforms:**
+
+ ```bash
+ cordova platform add android
+ ```
+
+ If no tag or version is specified, the Cordova CLI will fetch the latest release.
+
+ ```bash
+ cordova platform add electron@latest
+ ```
+
+ NPM tags are supported and can be appended to the end of the package specification.
+
+ ```bash
+ cordova platform add ios@7.1.1
+ ```
+
+ Exact release versions published to the npm registry are also supported and can be appended to the end of the package specification.
+
+- **npm Package:**
+
+ ```bash
+ cordova platform add cordova-android
+ cordova platform add cordova-android@latest
+ cordova platform add cordova-android@13.0.0
+
+ cordova platform add @cordova/some-platform
+ cordova platform add @cordova/some-platform@latest
+ cordova platform add @cordova/some-platform@1.0.0
+
+ cordova plugin some-cordova-plugin
+ cordova plugin some-cordova-plugin@latest
+
+ cordova plugin add @cordova/some-plugin
+ cordova plugin add @cordova/some-plugin@latest
+ cordova plugin add @cordova/some-plugin@1.0.0
+ ```
+
+ Scoped and non-scope npm packages are supported for both platforms and plugins. Optionally, npm package tags or released versions can be targeted by appending to the end of the package name. (e.g. `package-name@latest`).
+
+ Please note that the scoped packages shown above are only examples and do not exist.
+
+- **Git remote URL:**
+
+ ```bash
+ cordova platform add git://github.com/apache/cordova-android.git
+ cordova platform add git://github.com/apache/cordova-android.git#feature-branch
+ cordova platform add git://github.com/apache/cordova-android.git#rel/13.0.0
+
+ cordova platform add https://github.com/apache/cordova-android.git
+ cordova platform add https://github.com/apache/cordova-android.git#feature-branch
+ cordova platform add https://github.com/apache/cordova-android.git#rel/13.0.0
+
+ cordova platform add https://github.com/apache/cordova-android
+ cordova platform add https://github.com/apache/cordova-android#feature-branch
+ cordova platform add https://github.com/apache/cordova-android#rel/13.0.0
+ ```
+
+ Various Git URL formats are supported for installing platforms and plugins. Optionally, a treeish (branch name, tag, or commit ID) can be specified by appending `#<treeish>` to the URL.
+
+ When targeting a treeish, ensure it is production-ready before using it in a production environment. This functionality is useful for testing and reviewing pull requests, future releases, or release votes.
+
+- **Git service short hand:**
+
+ ```bash
+ cordova platform add github:apache/cordova-android
+ cordova platform add github:apache/cordova-android#feature-branch
+ cordova platform add github:apache/cordova-android#rel/13.0.0
+ ```
+
+ Platforms and plugins can also be checked out from Git repositories using a shorthand format.
+
+ If your repository is hosted on another Git service, such as Bitbucket or GitLab, you can modify the command to target these services.
+
+ Branches and tags can also be targeted using the shorthand format. However, ensure that the specified branch or version is production-ready before using it in production.
+
+- **Tarball Archive:**
+
+ ```bash
+ cordova platform add ~/path/to/a/tarbal.tgz
+ ```
+
+ Currently, **only platforms** support installation from a tarball package. The supported archive formats are `.tar.gz`, `.tgz,` and `.tar`.
+
+- **Local Directory Path:**
+
+ ```bash
+ cordova platform add ~/path/to/a/cordova-platform
+ cordova plugin add ~/path/to/a/cordova-plugin
+
+ cordova platform add C:/Path/to/a/cordova-platform
+ cordova plugin add C:/Path/to/a/cordova-plugin
+ ```
+
+ Platforms and plugins can be installed from a local directory path.
+
+## Removing Platforms and Plugins
+
+**Command Syntax:**
```bash
-cordova plugin add <plugin[@<version>] | directory | git_url> --nosave
+cordova <platform | plugin> remove <package-name>
```
-Some Examples:
+The `remove` command also has an alias of `rm`.
-* **`cordova plugin add cordova-plugin-device`**
+The `package-name` argument must be the name of the platform or plugin you want to remove.
- Retrieves the pinned version of the `cordova-plugin-device` plugin from npm, adds it to the project and updates the `package.json` file.
+For Apache Cordova's platforms, you **MUST** use the [Cordova Resolved Names](#Cordova-Resolved-Names) when removing them.
-* **`cordova plugin add cordova-plugin-device@2.0.1`**
+The `--nosave` flag could be appended to the command to prevent removal of specified platform and plugins from the `package.json` file.
- Retrieves the `cordova-plugin-device` plugin at version `2.0.1` from npm, adds it to the project and updates the `package.json` file.
+---
-* **`cordova plugin add https://github.com/apache/cordova-plugin-device.git`**
-
- **`cordova plugin add https://github.com/apache/cordova-plugin-device`**
-
- **`cordova plugin add github:apache/cordova-plugin-device`**
+### Various `remove` Examples
- npm retrieves the `cordova-plugin-device` plugin from the git repository, adds it to the project and updates the `package.json`.
+- **Removing platforms:**
-* **`cordova plugin add C:/path/to/console/plugin`**
+ ```bash
+ cordova platform remove android
+ ```
- Retrieves the `cordova-plugin-device` plugin from the specified directory, adds it to the project, and updates the `package.json` file.
+ The above command will remove the `cordova-android` platform from the project and `package.json` file.
-### Mass Saving of Plugins on an Existing Project
+ _Note: If the platform definition existed in `config.xml` from older version's of Cordova CLI, it will also be removed from `config.xml`._
-If you have a pre-existing project and you want to save all currently added plugins in the project, you can use:
+- **Removing plugins:**
-```bash
-cordova plugin save
-```
+ ```bash
+ cordova plugin remove cordova-plugin-device
+ ```
-### Removing Plugins
+ The above command will remove the `cordova-plugin-device` plugin from the project and `package.json` file.
-It is possible to delete a plugin from `config.xml` and `package.json` with one of the following commands:
+ _Note: If the plugin definition existed in `config.xml` from older version's of Cordova CLI, it will also be removed from `config.xml`._
-```bash
-cordova plugin remove <plugin>
-cordova plugin rm <plugin>
-```
+## Important Notes on Platform Restoration
-For Example:
+1. What version is installed when using `cordova platform add android` and the platform is defined in `config.xml`?
-* **`cordova plugin remove cordova-plugin-device`**
+ If the `config.xml` file contains the following entry:
- Removes the `cordova-plugin-device` plugin from the project and deletes its entry from `package.json`.
+ ```xml
+ <?xml version='1.0' encoding='utf-8'?>
+ ...
+ <engine name="android" spec="13.0.0" />
+ ...
+ </xml>
+ ```
- _Note: If the plugin definition existed in `config.xml` from a previous version of Cordova CLI, it will also be removed from `config.xml`._
+ When running the **`cordova platform add android`** command with no version provided, it will use the `spec` version defined in `config.xml`. In this example it would be `13.0.0`.
-### Restoring Plugins
+2. What version is restored if a platform is defined in both `config.xml` and `package.json`?
-Plugins are automatically restored from `package.json` and `config.xml` when executing the **`cordova prepare`** command.
+ Suppose your project has the following configurations:
-If a plugin is defined in both files, the information defined in `package.json` is used as the source of truth.
+ **`config.xml`**:
-After `prepare`, any plugins restored from `config.xml` will update the `package.json` file to reflect the values taken from `config.xml`.
+ ```xml
+ <engine name="android" spec=“12.0.0” />
+ ```
-If you add a plugin without specifying a `<version | folder | git_url>`, the version that will be installed is taken from `package.json` or `config.xml`.
+ **`package.json`**:
-**If discovered** in both files, `package.json` is given higher priority over `config.xml`.
+ ```json
+ "cordova": {
+ "platforms": [
+ "android"
+ ]
+ },
+ "dependencies": {
+ "cordova-android": "^13.0.0"
+ }
+ ```
-Example:
+ When `cordova prepare` is executed, the version from `package.json` has higher priority over `config.xml`. It will install version `^13.0.0`.
-Suppose your `config.xml` file contains the following entry:
+## Cordova Resolved Names
-```xml
-<?xml version='1.0' encoding='utf-8'?>
- ...
- <plugin name="cordova-plugin-device" spec="2.0.1" />
- ...
-</ xml>
-```
-
-If you run the command **`cordova plugin add cordova-plugin-device`** with no `<version | folder | git_url>` specified, the platform `cordova-plugin-device@2.0.1` will be retrieved and installed.
-
-**Example Order of Priority for Restoring Plugins:**
-
-Suppose you have defined in `config.xml` and `package.json` a plugin and version as follows:
-
-**`config.xml`**:
-
-```xml
-<plugin name="cordova-plugin-splashscreen"/>
-```
-
-**`package.json`**:
-
-```json
-"cordova": {
- "plugins": {
- "cordova-plugin-splashscreen": {}
- }
-},
-"devDependencies": {
- "cordova-plugin-splashscreen": "1.0.0"
-}
-```
-
-When `prepare` is executed, the version from `package.json` has higher priority over `config.xml` and version `1.0.0` will be installed.
+| Cordova Resolved Name | NPM Package Name |
+ | --- | --- |
+ | `android` | `cordova-android` |
+ | `electron` | `cordova-electron` |
+ | `ios` | `cordova-ios` |
+ | `browser` | `cordova-browser` |
diff --git a/www/docs/en/12.x-2025.01/plugin_ref/spec.md b/www/docs/en/12.x-2025.01/plugin_ref/spec.md
index adb22cc..de64f58 100644
--- a/www/docs/en/12.x-2025.01/plugin_ref/spec.md
+++ b/www/docs/en/12.x-2025.01/plugin_ref/spec.md
@@ -273,8 +273,8 @@
<source-file src="src/android/Foo.java" target-dir="src/com/alunny/foo" />
<!-- ios -->
<source-file src="src/ios/CDVFoo.m" />
+<source-file src="src/ios/CDVFoo.m" compiler-flags="-fno-objc-arc" />
<source-file src="src/ios/someLib.a" framework="true" />
-<source-file src="src/ios/someLib.a" compiler-flags="-fno-objc-arc" />
```
## header-file
diff --git a/www/docs/en/12.x-2025.01/reference/cordova-plugin-dialogs/index.md b/www/docs/en/12.x-2025.01/reference/cordova-plugin-dialogs/index.md
index 352fae1..8889780 100644
--- a/www/docs/en/12.x-2025.01/reference/cordova-plugin-dialogs/index.md
+++ b/www/docs/en/12.x-2025.01/reference/cordova-plugin-dialogs/index.md
@@ -89,7 +89,6 @@
- Android
- Browser
- iOS
-- Windows
## navigator.notification.confirm
@@ -133,7 +132,6 @@
- Android
- Browser
- iOS
-- Windows
### Android Quirks
@@ -141,12 +139,6 @@
- Android dialog title cannot exceed 2 lines of content, it will ignore any more than this.
-### Windows Quirks
-
-- On Windows8/8.1 it is not possible to add more than three buttons to MessageDialog instance.
-
-- On Windows Phone 8.1 it's not possible to show dialog with more than two buttons.
-
## navigator.notification.prompt
Displays a native dialog box that is more customizable than the browser's `prompt` function.
@@ -194,7 +186,6 @@
- Android
- Browser
- iOS
-- Windows
### Android Quirks
@@ -202,10 +193,6 @@
- On Android 3.0 and later, buttons are displayed in reverse order for devices that use the Holo theme.
-### Windows Quirks
-
-- On Windows prompt dialog is html-based due to lack of such native api.
-
## navigator.notification.beep
The device plays a beep sound.
@@ -224,7 +211,6 @@
- Android
- Browser
- iOS
-- Windows 8
### Android Quirks
diff --git a/www/docs/en/12.x-2025.01/reference/cordova-plugin-vibration/index.md b/www/docs/en/12.x-2025.01/reference/cordova-plugin-vibration/index.md
index a887490..639fc1b 100644
--- a/www/docs/en/12.x-2025.01/reference/cordova-plugin-vibration/index.md
+++ b/www/docs/en/12.x-2025.01/reference/cordova-plugin-vibration/index.md
@@ -51,7 +51,6 @@
## Supported Platforms
- iOS
-- Windows Phone
- Android
The Android webview (API level 19 and up) supports the [W3C Vibration API](https://www.w3.org/TR/vibration/) natively, so no Android specific implementation in this plugin is necessary.
@@ -93,14 +92,6 @@
navigator.vibrate(3000); // 3000 is ignored
```
-##### Windows Phone Quirks
-
-- __time__: Max time is 5000ms (5s) and min time is 1ms
-
- ```javascript
- navigator.vibrate(8000); // will be truncated to 5000
- ```
-
##### Android Quirks
> Calls to `navigator.vibrate` will immediately return `false` if user hasn't tapped on the frame or any embedded frame yet.