# Table of Contents - [Capacitor - Cross-platform Native Runtime for Web Apps | Capacitor Documentation](#capacitor-cross-platform-native-runtime-for-web-apps-capacitor-documentation) - [Search the documentation | Capacitor Documentation](#search-the-documentation-capacitor-documentation) - [Managing Android Dependencies in Capacitor | Capacitor Documentation](#managing-android-dependencies-in-capacitor-capacitor-documentation) - [Android Lifecycle | Capacitor Documentation](#android-lifecycle-capacitor-documentation) - [Browser | Capacitor Documentation](#browser-capacitor-documentation) - [Managing Deployment Platforms | Capacitor Documentation](#managing-deployment-platforms-capacitor-documentation) - [Capacitor Basics | Capacitor Documentation](#capacitor-basics-capacitor-documentation) - [Building your App | Capacitor Documentation](#building-your-app-capacitor-documentation) - [Opening Native Projects | Capacitor Documentation](#opening-native-projects-capacitor-documentation) - [Running your App | Capacitor Documentation](#running-your-app-capacitor-documentation) - [Building Progressive Web Apps | Capacitor Documentation](#building-progressive-web-apps-capacitor-documentation) - [Known Incompatible Cordova Plugins | Capacitor Documentation](#known-incompatible-cordova-plugins-capacitor-documentation) - [Building an Ionic Framework Photo Gallery App | Capacitor Documentation](#building-an-ionic-framework-photo-gallery-app-capacitor-documentation) - [Using Cordova Plugins and Ionic Native | Capacitor Documentation](#using-cordova-plugins-and-ionic-native-capacitor-documentation) - [Android Lifecycle | Capacitor Documentation](#android-lifecycle-capacitor-documentation) - [Building an Ionic Framework Photo Gallery App | Capacitor Documentation](#building-an-ionic-framework-photo-gallery-app-capacitor-documentation) - [Managing Android Dependencies in Capacitor | Capacitor Documentation](#managing-android-dependencies-in-capacitor-capacitor-documentation) - [Managing Deployment Platforms | Capacitor Documentation](#managing-deployment-platforms-capacitor-documentation) - [Building a Capacitor Plugin | Capacitor Documentation](#building-a-capacitor-plugin-capacitor-documentation) - [Building a Capacitor Plugin | Capacitor Documentation](#building-a-capacitor-plugin-capacitor-documentation) - [Building a Capacitor Plugin | Capacitor Documentation](#building-a-capacitor-plugin-capacitor-documentation) - [Building a Capacitor Plugin | Capacitor Documentation](#building-a-capacitor-plugin-capacitor-documentation) - [Building a Capacitor Plugin | Capacitor Documentation](#building-a-capacitor-plugin-capacitor-documentation) - [Capacitor Web/PWA Plugin Guide | Capacitor Documentation](#capacitor-web-pwa-plugin-guide-capacitor-documentation) - [Plugin Development Workflow | Capacitor Documentation](#plugin-development-workflow-capacitor-documentation) - [Updating to 1.1 | Capacitor Documentation](#updating-to-1-1-capacitor-documentation) - [Updating to 2.0 | Capacitor Documentation](#updating-to-2-0-capacitor-documentation) - [Updating to 3.0 | Capacitor Documentation](#updating-to-3-0-capacitor-documentation) - [Updating to 4.0 | Capacitor Documentation](#updating-to-4-0-capacitor-documentation) - [Updating to 5.0 | Capacitor Documentation](#updating-to-5-0-capacitor-documentation) - [Updating plugins to 3.0 | Capacitor Documentation](#updating-plugins-to-3-0-capacitor-documentation) - [Updating plugins to 5.0 | Capacitor Documentation](#updating-plugins-to-5-0-capacitor-documentation) - [Advanced Topics | Capacitor Documentation](#advanced-topics-capacitor-documentation) - [Build and Run | Capacitor Documentation](#build-and-run-capacitor-documentation) - [Bundle Analysis | Capacitor Documentation](#bundle-analysis-capacitor-documentation) - [Migrate from Cordova | Capacitor Documentation](#migrate-from-cordova-capacitor-documentation) - [Debugging | Capacitor Documentation](#debugging-capacitor-documentation) - [Dependencies | Capacitor Documentation](#dependencies-capacitor-documentation) - [Framework Features | Capacitor Documentation](#framework-features-capacitor-documentation) - [Monorepos | Capacitor Documentation](#monorepos-capacitor-documentation) - [Getting Started | Capacitor Documentation](#getting-started-capacitor-documentation) - [Native Settings | Capacitor Documentation](#native-settings-capacitor-documentation) - [New Project | Capacitor Documentation](#new-project-capacitor-documentation) - [Plugins | Capacitor Documentation](#plugins-capacitor-documentation) - [Android Lifecycle | Capacitor Documentation](#android-lifecycle-capacitor-documentation) - [Recommendations | Capacitor Documentation](#recommendations-capacitor-documentation) - [Release to the Store | Capacitor Documentation](#release-to-the-store-capacitor-documentation) - [Running Scripts | Capacitor Documentation](#running-scripts-capacitor-documentation) - [VS Code Extension | Capacitor Documentation](#vs-code-extension-capacitor-documentation) - [Building an Ionic Framework Photo Gallery App | Capacitor Documentation](#building-an-ionic-framework-photo-gallery-app-capacitor-documentation) - [Managing Android Dependencies in Capacitor | Capacitor Documentation](#managing-android-dependencies-in-capacitor-capacitor-documentation) - [Splash Screen & Icon | Capacitor Documentation](#splash-screen-icon-capacitor-documentation) - [Capacitor APIs | Capacitor Documentation](#capacitor-apis-capacitor-documentation) - [Android Lifecycle | Capacitor Documentation](#android-lifecycle-capacitor-documentation) - [Building an Ionic Framework Photo Gallery App | Capacitor Documentation](#building-an-ionic-framework-photo-gallery-app-capacitor-documentation) - [Managing Android Dependencies in Capacitor | Capacitor Documentation](#managing-android-dependencies-in-capacitor-capacitor-documentation) - [Capacitor APIs | Capacitor Documentation](#capacitor-apis-capacitor-documentation) - [CLI Command - cap open | Capacitor Documentation](#cli-command-cap-open-capacitor-documentation) - [CLI Command - cap run | Capacitor Documentation](#cli-command-cap-run-capacitor-documentation) - [CLI Command - cap sync | Capacitor Documentation](#cli-command-cap-sync-capacitor-documentation) - [CLI Command - cap update | Capacitor Documentation](#cli-command-cap-update-capacitor-documentation) - [CLI Hooks | Capacitor Documentation](#cli-hooks-capacitor-documentation) - [CLI Command - cap ls | Capacitor Documentation](#cli-command-cap-ls-capacitor-documentation) - [Telemetry | Capacitor Documentation](#telemetry-capacitor-documentation) - [Plugin Hooks | Capacitor Documentation](#plugin-hooks-capacitor-documentation) - [Building a Capacitor Plugin | Capacitor Documentation](#building-a-capacitor-plugin-capacitor-documentation) - [Building a Capacitor Plugin | Capacitor Documentation](#building-a-capacitor-plugin-capacitor-documentation) - [Building a Capacitor Plugin | Capacitor Documentation](#building-a-capacitor-plugin-capacitor-documentation) - [Building a Capacitor Plugin | Capacitor Documentation](#building-a-capacitor-plugin-capacitor-documentation) - [Building a Capacitor Plugin | Capacitor Documentation](#building-a-capacitor-plugin-capacitor-documentation) - [Capacitor Web/PWA Plugin Guide | Capacitor Documentation](#capacitor-web-pwa-plugin-guide-capacitor-documentation) - [Building a Capacitor Plugin | Capacitor Documentation](#building-a-capacitor-plugin-capacitor-documentation) - [Plugin Development Workflow | Capacitor Documentation](#plugin-development-workflow-capacitor-documentation) - [Building a Capacitor Plugin | Capacitor Documentation](#building-a-capacitor-plugin-capacitor-documentation) - [Building a Capacitor Plugin | Capacitor Documentation](#building-a-capacitor-plugin-capacitor-documentation) - [Updating to 1.1 | Capacitor Documentation](#updating-to-1-1-capacitor-documentation) - [Capacitor Web Documentation | Capacitor Documentation](#capacitor-web-documentation-capacitor-documentation) - [Updating plugins to 6.0 | Capacitor Documentation](#updating-plugins-to-6-0-capacitor-documentation) - [Updating to 7.0 | Capacitor Documentation](#updating-to-7-0-capacitor-documentation) - [Building Progressive Web Apps | Capacitor Documentation](#building-progressive-web-apps-capacitor-documentation) - [Updating to 5.0 | Capacitor Documentation](#updating-to-5-0-capacitor-documentation) - [Updating to 6.0 | Capacitor Documentation](#updating-to-6-0-capacitor-documentation) - [PWA Elements | Capacitor Documentation](#pwa-elements-capacitor-documentation) - [Updating to 2.0 | Capacitor Documentation](#updating-to-2-0-capacitor-documentation) - [Updating plugins to 5.0 | Capacitor Documentation](#updating-plugins-to-5-0-capacitor-documentation) - [Updating plugins to 7.0 | Capacitor Documentation](#updating-plugins-to-7-0-capacitor-documentation) - [Updating to 4.0 | Capacitor Documentation](#updating-to-4-0-capacitor-documentation) - [Updating plugins to 3.0 | Capacitor Documentation](#updating-plugins-to-3-0-capacitor-documentation) - [Updating to 3.0 | Capacitor Documentation](#updating-to-3-0-capacitor-documentation) --- # Capacitor - Cross-platform Native Runtime for Web Apps | Capacitor Documentation [Skip to main content](https://capacitorjs.com/docs#__docusaurus_skipToContent_fallback) [An **OutSystems** Company →](https://www.outsystems.com/?utm_source=ionic&utm_medium=referral&utm_campaign=ionic-referral&utm_term=none&utm_content=other&utm_campaignteam=digital-mktg&utm_partner=none) Version: v7 Capacitor is a cross-platform native runtime that makes it easy to build performant mobile applications that run natively on iOS, Android, and more using modern web tooling. Representing the next evolution of Hybrid apps, Capacitor creates **Web Native apps**, providing a modern native container approach for teams who want to build web-first without sacrificing full access to native SDKs when they need it. ![Capacitor Logo and background](https://capacitorjs.com/docs/assets/images/capacitor-index-51336ba21d2a831d216e4d8f6a2ccb9c.png) Introduction[​](https://capacitorjs.com/docs#introduction "Direct link to Introduction") ----------------------------------------------------------------------------------------- Capacitor provides a consistent, web-focused set of APIs that enable an app to stay as close to web standards as possible, while accessing rich native device features on platforms that support them. If it works in the browser, it probably works in a mobile app when using Capacitor. Adding native functionality is straightforward with a Plugin API for Swift on iOS, Java on Android, and JavaScript for the web. Get Started[​](https://capacitorjs.com/docs#get-started "Direct link to Get Started") -------------------------------------------------------------------------------------- Getting started with Capacitor is easy! Capacitor can be dropped into any existing modern JavaScript project, or a fresh Capacitor project can be created from scratch. Follow the [Installation guide](https://capacitorjs.com/docs/getting-started) to get started building your app. --- # Search the documentation | Capacitor Documentation [Skip to main content](https://capacitorjs.com/docs/search#__docusaurus_skipToContent_fallback) [An **OutSystems** Company →](https://www.outsystems.com/?utm_source=ionic&utm_medium=referral&utm_campaign=ionic-referral&utm_term=none&utm_content=other&utm_campaignteam=digital-mktg&utm_partner=none) Search the documentation ======================== [](https://www.algolia.com/) --- # Managing Android Dependencies in Capacitor | Capacitor Documentation [Skip to main content](https://capacitorjs.com/docs/v2/android/managing-dependencies#__docusaurus_skipToContent_fallback) [An **OutSystems** Company →](https://www.outsystems.com/?utm_source=ionic&utm_medium=referral&utm_campaign=ionic-referral&utm_term=none&utm_content=other&utm_campaignteam=digital-mktg&utm_partner=none) This is documentation for Capacitor Documentation **v2**, which is no longer actively maintained. For up-to-date documentation, see the **[latest version](https://capacitorjs.com/docs/) ** (v7). Version: v2 Coming soon. --- # Android Lifecycle | Capacitor Documentation [Skip to main content](https://capacitorjs.com/docs/v2/android/lifecycle#__docusaurus_skipToContent_fallback) [An **OutSystems** Company →](https://www.outsystems.com/?utm_source=ionic&utm_medium=referral&utm_campaign=ionic-referral&utm_term=none&utm_content=other&utm_campaignteam=digital-mktg&utm_partner=none) This is documentation for Capacitor Documentation **v2**, which is no longer actively maintained. For up-to-date documentation, see the **[latest version](https://capacitorjs.com/docs/) ** (v7). Version: v2 On this page Understanding the Android Activity Lifecycle is crucial for building apps that act the way Android users expect. This document attempts to explain the lifecycle as it pertains to Capacitor. For more information, the [Activity Lifecycle](https://developer.android.com/guide/components/activities/activity-lifecycle.html) reference on the official Android docs is the best resource out there. Handling App Restarts[​](https://capacitorjs.com/docs/v2/android/lifecycle#handling-app-restarts "Direct link to Handling App Restarts") ----------------------------------------------------------------------------------------------------------------------------------------- Android apps often utilize other apps (or Activities) for features that are too complicated to include in their own app, such as camera or browser features. In some cases, when a device is low on memory, launching a new Activity may cause your app to be killed in order to free up memory. In this case, when the new Activity returns data back to your app, your app will want to show the user a state of the app that resumes what the user was just doing. Contents -------- * [Handling App Restarts](https://capacitorjs.com/docs/v2/android/lifecycle#handling-app-restarts) * * * [Edit this page](https://github.com/ionic-team/capacitor-docs/edit/main/versioned_docs/version-v2/android/lifecycle.md) --- # Browser | Capacitor Documentation [Skip to main content](https://capacitorjs.com/docs/v2/apis/browser#__docusaurus_skipToContent_fallback) [An **OutSystems** Company →](https://www.outsystems.com/?utm_source=ionic&utm_medium=referral&utm_campaign=ionic-referral&utm_term=none&utm_content=other&utm_campaignteam=digital-mktg&utm_partner=none) This is documentation for Capacitor Documentation **v2**, which is no longer actively maintained. For up-to-date documentation, see the **[latest version](https://capacitorjs.com/docs/apis/browser) ** (v7). Version: v2 On this page * [`open(...)`](https://capacitorjs.com/docs/v2/apis/browser#open) * [`prefetch(...)`](https://capacitorjs.com/docs/v2/apis/browser#prefetch) * [`close()`](https://capacitorjs.com/docs/v2/apis/browser#close) * [`addListener(...)`](https://capacitorjs.com/docs/v2/apis/browser#addlistener) * [`addListener(...)`](https://capacitorjs.com/docs/v2/apis/browser#addlistener) * [`removeAllListeners()`](https://capacitorjs.com/docs/v2/apis/browser#removealllisteners) * [Interfaces](https://capacitorjs.com/docs/v2/apis/browser#interfaces) The Browser API makes it easy to open an in-app browser session to show external web content, handle authentication flows, and more. On iOS this uses `SFSafariViewController` and is compliant with leading oAuth service in-app-browser requirements. import { Plugins } from '@capacitor/core';const { Browser } = Plugins;await Browser.open({ url: 'http://capacitorjs.com/' }); API[​](https://capacitorjs.com/docs/v2/apis/browser#api "Direct link to API") ------------------------------------------------------------------------------ ### open(...)[​](https://capacitorjs.com/docs/v2/apis/browser#open "Direct link to open(...)") open(options: BrowserOpenOptions) => Promise Open a page with the given URL | Param | Type | | --- | --- | | **`options`** | BrowserOpenOptions | * * * ### prefetch(...)[​](https://capacitorjs.com/docs/v2/apis/browser#prefetch "Direct link to prefetch(...)") prefetch(options: BrowserPrefetchOptions) => Promise Hint to the browser that the given URLs will be accessed to improve initial loading times. Only functional on Android, is a no-op on iOS | Param | Type | | --- | --- | | **`options`** | BrowserPrefetchOptions | * * * ### close()[​](https://capacitorjs.com/docs/v2/apis/browser#close "Direct link to close()") close() => Promise Close an open browser. Only works on iOS and Web environment, otherwise is a no-op * * * ### addListener(...)[​](https://capacitorjs.com/docs/v2/apis/browser#addlistener "Direct link to addListener(...)") addListener(eventName: 'browserFinished', listenerFunc: (info: any) => void) => PluginListenerHandle | Param | Type | | --- | --- | | **`eventName`** | `"browserFinished"` | | **`listenerFunc`** | `(info: any) => void` | **Returns:** PluginListenerHandle * * * ### addListener(...)[​](https://capacitorjs.com/docs/v2/apis/browser#addlistener-1 "Direct link to addListener(...)") addListener(eventName: 'browserPageLoaded', listenerFunc: (info: any) => void) => PluginListenerHandle | Param | Type | | --- | --- | | **`eventName`** | `"browserPageLoaded"` | | **`listenerFunc`** | `(info: any) => void` | **Returns:** PluginListenerHandle * * * ### removeAllListeners()[​](https://capacitorjs.com/docs/v2/apis/browser#removealllisteners "Direct link to removeAllListeners()") removeAllListeners() => void Remove all native listeners for this plugin * * * ### Interfaces[​](https://capacitorjs.com/docs/v2/apis/browser#interfaces "Direct link to Interfaces") #### BrowserOpenOptions[​](https://capacitorjs.com/docs/v2/apis/browser#browseropenoptions "Direct link to BrowserOpenOptions") | Prop | Type | Description | | --- | --- | --- | | **`url`** | `string` | The URL to open the browser to | | **`windowName`** | `string` | Web only: Optional target for browser open. Follows the `target` property for window.open. Defaults to \_blank | | **`toolbarColor`** | `string` | A hex color to set the toolbar color to. | | **`presentationStyle`** | `"fullscreen" \| "popover"` | iOS only: The presentation style of the browser. Defaults to fullscreen. | #### BrowserPrefetchOptions[​](https://capacitorjs.com/docs/v2/apis/browser#browserprefetchoptions "Direct link to BrowserPrefetchOptions") | Prop | Type | | --- | --- | | **`urls`** | `string[]` | #### PluginListenerHandle[​](https://capacitorjs.com/docs/v2/apis/browser#pluginlistenerhandle "Direct link to PluginListenerHandle") | Prop | Type | | --- | --- | | **`remove`** | `() => void` | Contents -------- * [API](https://capacitorjs.com/docs/v2/apis/browser#api) * [open(...)](https://capacitorjs.com/docs/v2/apis/browser#open) * [prefetch(...)](https://capacitorjs.com/docs/v2/apis/browser#prefetch) * [close()](https://capacitorjs.com/docs/v2/apis/browser#close) * [addListener(...)](https://capacitorjs.com/docs/v2/apis/browser#addlistener) * [addListener(...)](https://capacitorjs.com/docs/v2/apis/browser#addlistener-1) * [removeAllListeners()](https://capacitorjs.com/docs/v2/apis/browser#removealllisteners) * [Interfaces](https://capacitorjs.com/docs/v2/apis/browser#interfaces) * * * [Edit this page](https://github.com/ionic-team/capacitor-docs/edit/main/versioned_docs/version-v2/apis/browser.md) --- # Managing Deployment Platforms | Capacitor Documentation [Skip to main content](https://capacitorjs.com/docs/v2/basics/managing-platforms#__docusaurus_skipToContent_fallback) [An **OutSystems** Company →](https://www.outsystems.com/?utm_source=ionic&utm_medium=referral&utm_campaign=ionic-referral&utm_term=none&utm_content=other&utm_campaignteam=digital-mktg&utm_partner=none) This is documentation for Capacitor Documentation **v2**, which is no longer actively maintained. For up-to-date documentation, see the **[latest version](https://capacitorjs.com/docs/) ** (v7). Version: v2 Capacitor supports iOS, Android, and PWA. --- # Capacitor Basics | Capacitor Documentation [Skip to main content](https://capacitorjs.com/docs/v2/basics#__docusaurus_skipToContent_fallback) [An **OutSystems** Company →](https://www.outsystems.com/?utm_source=ionic&utm_medium=referral&utm_campaign=ionic-referral&utm_term=none&utm_content=other&utm_campaignteam=digital-mktg&utm_partner=none) This is documentation for Capacitor Documentation **v2**, which is no longer actively maintained. For up-to-date documentation, see the **[latest version](https://capacitorjs.com/docs/) ** (v7). Version: v2 Follow the links on the left to learn the basics of using and developing with Capacitor. --- # Building your App | Capacitor Documentation [Skip to main content](https://capacitorjs.com/docs/v2/basics/building-your-app#__docusaurus_skipToContent_fallback) [An **OutSystems** Company →](https://www.outsystems.com/?utm_source=ionic&utm_medium=referral&utm_campaign=ionic-referral&utm_term=none&utm_content=other&utm_campaignteam=digital-mktg&utm_partner=none) This is documentation for Capacitor Documentation **v2**, which is no longer actively maintained. For up-to-date documentation, see the **[latest version](https://capacitorjs.com/docs/) ** (v7). Version: v2 On this page Capacitor works on a three-step build process: First, your web code is built (if necessary). Next, the built web code is copied to each platform. Finally, the app is compiled using the platform-specific tooling. 1\. Building web code[​](https://capacitorjs.com/docs/v2/basics/building-your-app#1-building-web-code "Direct link to 1. Building web code") --------------------------------------------------------------------------------------------------------------------------------------------- Capacitor does not have any built-in feature to build web code. Instead, you will use your framework's build process of choice. Regardless of your build process, we recommend adding a `build` script to your `package.json` to enable the standard frontend build command: { "scripts": { "build": "command-to-build (ex: webpack, tsc, babel, etc.)" }} npm run build This builds your Progressive Web App if you've configured [Progressive Web App](https://capacitorjs.com/docs/v2/basics/progressive-web-app) support already. 2\. Copying Web Code[​](https://capacitorjs.com/docs/v2/basics/building-your-app#2-copying-web-code "Direct link to 2. Copying Web Code") ------------------------------------------------------------------------------------------------------------------------------------------ Once your web code is built, it needs to be copied into each native project: npx cap copy Run this command each time you perform a build and consider adding it to the end of your build script in `package.json`. 3\. Building Native Project[​](https://capacitorjs.com/docs/v2/basics/building-your-app#3-building-native-project "Direct link to 3. Building Native Project") --------------------------------------------------------------------------------------------------------------------------------------------------------------- ### iOS[​](https://capacitorjs.com/docs/v2/basics/building-your-app#ios "Direct link to iOS") iOS relies on Xcode to do the final app compile: npx cap copy iosnpx cap open ios Once Xcode launches, you can build your app binary through the standard Xcode workflow. ### Android[​](https://capacitorjs.com/docs/v2/basics/building-your-app#android "Direct link to Android") Android relies on Android Studio (or, optionally, the Android CLI tools) to build the app: npx cap copy androidnpx cap open android Once Android Studio launches, you can build your app through the standard Android Studio workflow. Contents -------- * [1\. Building web code](https://capacitorjs.com/docs/v2/basics/building-your-app#1-building-web-code) * [2\. Copying Web Code](https://capacitorjs.com/docs/v2/basics/building-your-app#2-copying-web-code) * [3\. Building Native Project](https://capacitorjs.com/docs/v2/basics/building-your-app#3-building-native-project) * [iOS](https://capacitorjs.com/docs/v2/basics/building-your-app#ios) * [Android](https://capacitorjs.com/docs/v2/basics/building-your-app#android) * * * [Edit this page](https://github.com/ionic-team/capacitor-docs/edit/main/versioned_docs/version-v2/basics/building-your-app.md) --- # Opening Native Projects | Capacitor Documentation [Skip to main content](https://capacitorjs.com/docs/v2/basics/opening-native-projects#__docusaurus_skipToContent_fallback) [An **OutSystems** Company →](https://www.outsystems.com/?utm_source=ionic&utm_medium=referral&utm_campaign=ionic-referral&utm_term=none&utm_content=other&utm_campaignteam=digital-mktg&utm_partner=none) This is documentation for Capacitor Documentation **v2**, which is no longer actively maintained. For up-to-date documentation, see the **[latest version](https://capacitorjs.com/docs/) ** (v7). Version: v2 On this page Capacitor uses the native IDE for each platform in order to provide required configuration, and to build, test, and deploy apps. For iOS development, that means you must have [Xcode 11](https://developer.apple.com/xcode/) or above installed. For Android, [Android Studio](https://developer.android.com/studio/index.html) 3 or above. Both IDEs can be opened manually or using the `npx cap open` command: Opening Xcode[​](https://capacitorjs.com/docs/v2/basics/opening-native-projects#opening-xcode "Direct link to Opening Xcode") ------------------------------------------------------------------------------------------------------------------------------ npx cap open ios Alternatively, you can open Xcode manually: open ios/App/App.xcworkspace Opening Android Studio[​](https://capacitorjs.com/docs/v2/basics/opening-native-projects#opening-android-studio "Direct link to Opening Android Studio") --------------------------------------------------------------------------------------------------------------------------------------------------------- npx cap open android Alternatively, you can open Android Studio and import the `android/` directory as an Android Studio project. Contents -------- * [Opening Xcode](https://capacitorjs.com/docs/v2/basics/opening-native-projects#opening-xcode) * [Opening Android Studio](https://capacitorjs.com/docs/v2/basics/opening-native-projects#opening-android-studio) * * * [Edit this page](https://github.com/ionic-team/capacitor-docs/edit/main/versioned_docs/version-v2/basics/opening-native-projects.md) --- # Running your App | Capacitor Documentation [Skip to main content](https://capacitorjs.com/docs/v2/basics/running-your-app#__docusaurus_skipToContent_fallback) [An **OutSystems** Company →](https://www.outsystems.com/?utm_source=ionic&utm_medium=referral&utm_campaign=ionic-referral&utm_term=none&utm_content=other&utm_campaignteam=digital-mktg&utm_partner=none) This is documentation for Capacitor Documentation **v2**, which is no longer actively maintained. For up-to-date documentation, see the **[latest version](https://capacitorjs.com/docs/) ** (v7). Version: v2 On this page Capacitor relies on each platform's IDE of choice to run and test your app. iOS[​](https://capacitorjs.com/docs/v2/basics/running-your-app#ios "Direct link to iOS") ----------------------------------------------------------------------------------------- iOS requires using Xcode to run your app. npx cap open ios Once Xcode launches, you can build/simulate/run your app through the standard Xcode workflow. Android[​](https://capacitorjs.com/docs/v2/basics/running-your-app#android "Direct link to Android") ----------------------------------------------------------------------------------------------------- npx cap open android Once Android Studio launches, you can build/emulate/run your app through the standard Android Studio workflow. Progressive Web App[​](https://capacitorjs.com/docs/v2/basics/running-your-app#progressive-web-app "Direct link to Progressive Web App") ----------------------------------------------------------------------------------------------------------------------------------------- Capacitor has a tiny development web server for local testing, but it's recommended to run your web app using your framework of choice's server tools. npx cap serve This will open your web app in a local web server instance in the browser. Contents -------- * [iOS](https://capacitorjs.com/docs/v2/basics/running-your-app#ios) * [Android](https://capacitorjs.com/docs/v2/basics/running-your-app#android) * [Progressive Web App](https://capacitorjs.com/docs/v2/basics/running-your-app#progressive-web-app) * * * [Edit this page](https://github.com/ionic-team/capacitor-docs/edit/main/versioned_docs/version-v2/basics/running-your-app.md) --- # Building Progressive Web Apps | Capacitor Documentation [Skip to main content](https://capacitorjs.com/docs/v2/basics/progressive-web-app#__docusaurus_skipToContent_fallback) [An **OutSystems** Company →](https://www.outsystems.com/?utm_source=ionic&utm_medium=referral&utm_campaign=ionic-referral&utm_term=none&utm_content=other&utm_campaignteam=digital-mktg&utm_partner=none) This is documentation for Capacitor Documentation **v2**, which is no longer actively maintained. For up-to-date documentation, see the **[latest version](https://capacitorjs.com/docs/) ** (v7). Version: v2 On this page Capacitor has first-class support for Progressive Web Apps, making it easy to build an app that runs natively on iOS and Android, but also on the web as a mobile web app or "Progressive Web App." What is a Progressive Web App?[​](https://capacitorjs.com/docs/v2/basics/progressive-web-app#what-is-a-progressive-web-app "Direct link to What is a Progressive Web App?") ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------- Put simply, a Progressive Web App (PWA) is a web app that uses modern web capabilities to deliver an app-like experience to users. These apps are deployed to traditional web servers, are accessible through URLs, and can be indexed by search engines. A Progressive Web App is, for all practical purposes, just another term for a website that has been optimized for mobile performance and that utilizes newly available Web APIs to deliver features that are similar to a traditional native app, such as push notifications and offline storage. Capacitor and Progressive Web Apps[​](https://capacitorjs.com/docs/v2/basics/progressive-web-app#capacitor-and-progressive-web-apps "Direct link to Capacitor and Progressive Web Apps") ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- Capacitor has first-class support for Progressive Web Apps _and_ native apps. That means that Capacitor's plugin bridge supports running in either a native context or in the web, with many core plugins available _in both contexts_ with the exact same API and calling conventions. This means you use `@capacitor/core` as a dependency for both your native app _and_ your Progressive Web App, and Capacitor seamlessly calls web code when required and native code when available. Additionally, Capacitor offers a number of utilities for querying the current platform to provide customized experiences when running natively or on the web. Adding Progressive Web App Support to your app[​](https://capacitorjs.com/docs/v2/basics/progressive-web-app#adding-progressive-web-app-support-to-your-app "Direct link to Adding Progressive Web App Support to your app") ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- Adding PWA support to any existing frontend project is easy. Just add an App Manifest file and configure a service worker: ### App Manifest[​](https://capacitorjs.com/docs/v2/basics/progressive-web-app#app-manifest "Direct link to App Manifest") First, you'll need an [App Manifest](https://developer.mozilla.org/en-US/docs/Web/Manifest) file ([manifest.json](https://developer.mozilla.org/en-US/Add-ons/WebExtensions/manifest.json) ) that sits alongside your `index.html` file and provides metadata about your app, such as its name, theme colors, and icons. This information will be used when your app is installed on the home screen, for example. ### Service Worker[​](https://capacitorjs.com/docs/v2/basics/progressive-web-app#service-worker "Direct link to Service Worker") Next, in order to send push notifications and store data offline, a [Service Worker](https://developer.mozilla.org/en-US/docs/Web/API/Service_Worker_API) will enable your web app to proxy network requests and perform background tasks needed to process and sync data. Service Workers are powerful, but complicated. Generally, writing them from scratch is not recommended. Instead, take a look at tools like [Workbox](https://developers.google.com/web/tools/workbox/) that provide common Service Worker recipes that you can easily incorporate into your app. Read more about using Service Workers, including how to register them, on the [Using Service Workers](https://developer.mozilla.org/en-US/docs/Web/API/Service_Worker_API/Using_Service_Workers) page on MDN. Progressive Web App Performance[​](https://capacitorjs.com/docs/v2/basics/progressive-web-app#progressive-web-app-performance "Direct link to Progressive Web App Performance") -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- Progressive Web Apps are judged by several performance standards, including [Time to Interactive](https://developers.google.com/web/tools/lighthouse/audits/time-to-interactive) and [First Meaningful Paint](https://developers.google.com/web/tools/lighthouse/audits/first-meaningful-paint) . Follow the [Progressive Web App Checklist](https://developers.google.com/web/progressive-web-apps/checklist) before going live, and use [Lighthouse](https://developers.google.com/web/tools/lighthouse/) to audit and test your app. If you're struggling to meet Progressive Web App performance standards with your existing frontend stack, take a look at [Ionic Framework](https://ionicframework.com/) version 4 or greater as an option for getting fast PWA support with nearly zero configuration. Ionic 4.x or above is a web component library that works in several popular frontend frameworks, not just Angular. Running Natively and on the Web[​](https://capacitorjs.com/docs/v2/basics/progressive-web-app#running-natively-and-on-the-web "Direct link to Running Natively and on the Web") -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- One of the key features of Capacitor is the ability to build one app that runs both natively (in the app stores), _and_ on the web. Capacitor does this by providing a layer between the underlying platform and the APIs/Plugins you'd like to use. If your app makes native plugin calls that don't have a web substitute, such as `SplashScreen.show()`, the app will allow those calls without crashing. Calls that return a promise will return a rejected promise, which you should be handling in your app anyways. Additionally, Capacitor's JavaScript API has a number of utilities that make it possible to programmatically check whether certain APIs are available. For example, if your app would normally rely on the Camera app being used to take a photo, you could check if the Camera is available, and if not, ask the user to upload a file instead: import { Capacitor } from '@capacitor/core';const isAvailable = Capacitor.isPluginAvailable('Camera');if (!isAvailable) { // Have the user upload a file instead} else { // Otherwise, make the call: Camera.getPhoto();} Contents -------- * [What is a Progressive Web App?](https://capacitorjs.com/docs/v2/basics/progressive-web-app#what-is-a-progressive-web-app) * [Capacitor and Progressive Web Apps](https://capacitorjs.com/docs/v2/basics/progressive-web-app#capacitor-and-progressive-web-apps) * [Adding Progressive Web App Support to your app](https://capacitorjs.com/docs/v2/basics/progressive-web-app#adding-progressive-web-app-support-to-your-app) * [App Manifest](https://capacitorjs.com/docs/v2/basics/progressive-web-app#app-manifest) * [Service Worker](https://capacitorjs.com/docs/v2/basics/progressive-web-app#service-worker) * [Progressive Web App Performance](https://capacitorjs.com/docs/v2/basics/progressive-web-app#progressive-web-app-performance) * [Running Natively and on the Web](https://capacitorjs.com/docs/v2/basics/progressive-web-app#running-natively-and-on-the-web) * * * [Edit this page](https://github.com/ionic-team/capacitor-docs/edit/main/versioned_docs/version-v2/basics/progressive-web-app.md) --- # Known Incompatible Cordova Plugins | Capacitor Documentation [Skip to main content](https://capacitorjs.com/docs/v2/cordova/known-incompatible-plugins#__docusaurus_skipToContent_fallback) [An **OutSystems** Company →](https://www.outsystems.com/?utm_source=ionic&utm_medium=referral&utm_campaign=ionic-referral&utm_term=none&utm_content=other&utm_campaignteam=digital-mktg&utm_partner=none) This is documentation for Capacitor Documentation **v2**, which is no longer actively maintained. For up-to-date documentation, see the **[latest version](https://capacitorjs.com/docs/) ** (v7). Version: v2 On this page While we've tested a number of popular Cordova plugins, it's possible Capacitor doesn't support every Cordova plugin. Some don't work with Capacitor or Capacitor provides a conflicting alternative. If it's known that the plugin is conflicting or causes build issues, it will be skipped when running `npx cap update`. If you find an issue with an existing Cordova plugin, please [let us know](https://github.com/ionic-team/capacitor/issues/new) by providing the issue's details and plugin information. Known incompatible plugins (Subject to change)[​](https://capacitorjs.com/docs/v2/cordova/known-incompatible-plugins#known-incompatible-plugins-subject-to-change "Direct link to Known incompatible plugins (Subject to change)") ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- * cordova-plugin-add-swift-support (not needed, Capacitor has built in Swift support) * cordova-plugin-admobpro ([see details](https://github.com/ionic-team/capacitor/issues/1101) ) * cordova-plugin-braintree ([see details](https://github.com/ionic-team/capacitor/issues/1415) ) * cordova-plugin-code-push ([see details](https://github.com/microsoft/code-push/issues/615) ) * cordova-plugin-compat (not needed) * cordova-plugin-console (not needed, Capacitor has its own) * cordova-plugin-crosswalk-webview (Capacitor doesn't allow to change the webview) * cordova-plugin-fcm ([see details](https://github.com/ionic-team/capacitor/issues/584) ) * cordova-plugin-firebase ([see details](https://github.com/ionic-team/capacitor/issues/815) ) * cordova-plugin-ionic-keyboard (not needed, Capacitor has it's own) * cordova-plugin-ionic-webview (not needed, Capacitor uses WKWebView) * cordova-plugin-music-controls (causes build failures, skipped) * cordova-plugin-qrscanner ([see details](https://github.com/ionic-team/capacitor/issues/1213) ) * cordova-plugin-splashscreen (not needed, Capacitor has its own) * cordova-plugin-statusbar (not needed, Capacitor has its own) * cordova-plugin-wkwebview-engine (not needed, Capacitor uses WKWebView) * cordova-plugin-googlemaps (causes build failures on iOS, skipped for iOS only) * cordova-plugin-lottie-splashscreen (it's incompatible and some further work is needed) Contents -------- * [Known incompatible plugins (Subject to change)](https://capacitorjs.com/docs/v2/cordova/known-incompatible-plugins#known-incompatible-plugins-subject-to-change) * * * [Edit this page](https://github.com/ionic-team/capacitor-docs/edit/main/versioned_docs/version-v2/cordova/known-incompatible-plugins.md) --- # Building an Ionic Framework Photo Gallery App | Capacitor Documentation [Skip to main content](https://capacitorjs.com/docs/v2/guides/ionic-framework-app#__docusaurus_skipToContent_fallback) [An **OutSystems** Company →](https://www.outsystems.com/?utm_source=ionic&utm_medium=referral&utm_campaign=ionic-referral&utm_term=none&utm_content=other&utm_campaignteam=digital-mktg&utm_partner=none) This is documentation for Capacitor Documentation **v2**, which is no longer actively maintained. For up-to-date documentation, see the **[latest version](https://capacitorjs.com/docs/) ** (v7). Version: v2 **Platforms**: Web, iOS, Android Capacitor makes it easy to build web apps that run natively on iOS, Android, desktop, and the web. In this guide, we'll build a complete Photo Gallery app that works on all platforms. > This guide is now maintained over in the Ionic docs. The [latest version](https://ionicframework.com/docs/intro/next) > contains tutorials for Angular, React, and Vue. --- # Using Cordova Plugins and Ionic Native | Capacitor Documentation [Skip to main content](https://capacitorjs.com/docs/v2/cordova/using-cordova-plugins#__docusaurus_skipToContent_fallback) [An **OutSystems** Company →](https://www.outsystems.com/?utm_source=ionic&utm_medium=referral&utm_campaign=ionic-referral&utm_term=none&utm_content=other&utm_campaignteam=digital-mktg&utm_partner=none) This is documentation for Capacitor Documentation **v2**, which is no longer actively maintained. For up-to-date documentation, see the **[latest version](https://capacitorjs.com/docs/) ** (v7). Version: v2 On this page When developing an app that uses Capacitor, it's possible to use both Cordova and Ionic Native plugins. Installing Cordova Plugins[​](https://capacitorjs.com/docs/v2/cordova/using-cordova-plugins#installing-cordova-plugins "Direct link to Installing Cordova Plugins") -------------------------------------------------------------------------------------------------------------------------------------------------------------------- Simply install your plugin of choice, sync your project, finish any required native project configuration, and you're ready to go: npm install cordova-plugin-namenpx cap sync Updating Cordova Plugins[​](https://capacitorjs.com/docs/v2/cordova/using-cordova-plugins#updating-cordova-plugins "Direct link to Updating Cordova Plugins") -------------------------------------------------------------------------------------------------------------------------------------------------------------- Similar to the installation steps. Simply update the cordova plugin to the latest version then Capacitor will pick up the changes: npm install cordova-plugin-name@2npx cap update If you don't want to risk to introduce breaking changes, use `npm update cordova-plugin-name` instead of `@2` as `update` respects semver. Installing Ionic Native Plugins[​](https://capacitorjs.com/docs/v2/cordova/using-cordova-plugins#installing-ionic-native-plugins "Direct link to Installing Ionic Native Plugins") ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- [Ionic Native](https://ionicframework.com/docs/native) provides TypeScript wrappers and a consistent API and naming convention for easier development with Cordova plugins. It's supported in Capacitor, so whenever you find an Ionic Native wrapper you'd like to use, install the JavaScript code, install the corresponding Cordova plugin, then sync your project: npm install @ionic-native/javascript-package-namenpm install cordova-plugin-namenpx cap sync Updating Ionic Native Plugins[​](https://capacitorjs.com/docs/v2/cordova/using-cordova-plugins#updating-ionic-native-plugins "Direct link to Updating Ionic Native Plugins") ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------- Similiar to the installation steps. Update the Ionic Native JavaScript library, remove then re-add the Cordova plugin, then update your project: npm install @ionic-native/javascript-package-name@2npm install cordova-plugin-name@2npx cap update Determining Installed Plugin Version[​](https://capacitorjs.com/docs/v2/cordova/using-cordova-plugins#determining-installed-plugin-version "Direct link to Determining Installed Plugin Version") -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- See the list of Capacitor and Cordova plugins (and their exact version numbers) installed in your project with: npx cap ls Important: Configuration[​](https://capacitorjs.com/docs/v2/cordova/using-cordova-plugins#important-configuration "Direct link to Important: Configuration") ------------------------------------------------------------------------------------------------------------------------------------------------------------- Capacitor does not support Cordova install variables, auto configuration, or hooks, due to our philosophy of letting you control your native project source code (meaning things like hooks are unnecessary). If your plugin requires variables or settings to be set, you'll need to apply those configuration settings manually by mapping between the plugin's `plugin.xml` and required settings on iOS and Android. Consult the [iOS](https://capacitorjs.com/docs/v2/ios/configuration) and [Android](https://capacitorjs.com/docs/v2/android/configuration) configuration guides for info on how to configure each platform. Compatibility Issues[​](https://capacitorjs.com/docs/v2/cordova/using-cordova-plugins#compatibility-issues "Direct link to Compatibility Issues") -------------------------------------------------------------------------------------------------------------------------------------------------- Some Cordova plugins don't work with Capacitor or Capacitor provides a conflicting alternative. [See here](https://capacitorjs.com/docs/v2/cordova/known-incompatible-plugins) for details and a known incompatibility list. Contents -------- * [Installing Cordova Plugins](https://capacitorjs.com/docs/v2/cordova/using-cordova-plugins#installing-cordova-plugins) * [Updating Cordova Plugins](https://capacitorjs.com/docs/v2/cordova/using-cordova-plugins#updating-cordova-plugins) * [Installing Ionic Native Plugins](https://capacitorjs.com/docs/v2/cordova/using-cordova-plugins#installing-ionic-native-plugins) * [Updating Ionic Native Plugins](https://capacitorjs.com/docs/v2/cordova/using-cordova-plugins#updating-ionic-native-plugins) * [Determining Installed Plugin Version](https://capacitorjs.com/docs/v2/cordova/using-cordova-plugins#determining-installed-plugin-version) * [Important: Configuration](https://capacitorjs.com/docs/v2/cordova/using-cordova-plugins#important-configuration) * [Compatibility Issues](https://capacitorjs.com/docs/v2/cordova/using-cordova-plugins#compatibility-issues) * * * [Edit this page](https://github.com/ionic-team/capacitor-docs/edit/main/versioned_docs/version-v2/cordova/using-cordova-plugins.md) --- # Android Lifecycle | Capacitor Documentation [Skip to main content](https://capacitorjs.com/docs/v3/android/lifecycle#__docusaurus_skipToContent_fallback) [An **OutSystems** Company →](https://www.outsystems.com/?utm_source=ionic&utm_medium=referral&utm_campaign=ionic-referral&utm_term=none&utm_content=other&utm_campaignteam=digital-mktg&utm_partner=none) This is documentation for Capacitor Documentation **v3**, which is no longer actively maintained. For up-to-date documentation, see the **[latest version](https://capacitorjs.com/docs/android/lifecycle) ** (v7). Version: v3 On this page Understanding the Android Activity Lifecycle is crucial for building apps that act the way Android users expect. This document attempts to explain the lifecycle as it pertains to Capacitor. For more information, the [Activity Lifecycle](https://developer.android.com/guide/components/activities/activity-lifecycle.html) reference on the official Android docs is the best resource out there. Handling App Restarts[​](https://capacitorjs.com/docs/v3/android/lifecycle#handling-app-restarts "Direct link to Handling App Restarts") ----------------------------------------------------------------------------------------------------------------------------------------- Android apps often utilize other apps (or Activities) for features that are too complicated to include in their own app, such as camera or browser features. In some cases, when a device is low on memory, launching a new Activity may cause your app to be killed in order to free up memory. In this case, when the new Activity returns data back to your app, your app will want to show the user a state of the app that resumes what the user was just doing. Contents -------- * [Handling App Restarts](https://capacitorjs.com/docs/v3/android/lifecycle#handling-app-restarts) * * * [Edit this page](https://github.com/ionic-team/capacitor-docs/edit/main/versioned_docs/version-v3/main/android/lifecycle.md) --- # Building an Ionic Framework Photo Gallery App | Capacitor Documentation [Skip to main content](https://capacitorjs.com/docs/v3/guides/ionic-framework-app#__docusaurus_skipToContent_fallback) [An **OutSystems** Company →](https://www.outsystems.com/?utm_source=ionic&utm_medium=referral&utm_campaign=ionic-referral&utm_term=none&utm_content=other&utm_campaignteam=digital-mktg&utm_partner=none) This is documentation for Capacitor Documentation **v3**, which is no longer actively maintained. For up-to-date documentation, see the **[latest version](https://capacitorjs.com/docs/guides/ionic-framework-app) ** (v7). Version: v3 **Platforms**: Web, iOS, Android Capacitor makes it easy to build web apps that run natively on iOS, Android, desktop, and the web. In this guide, we'll build a complete Photo Gallery app that works on all platforms. > This guide is now maintained over in the Ionic docs. The [latest version](https://ionicframework.com/docs/v3/intro/next) > contains tutorials for Angular, React, and Vue. --- # Managing Android Dependencies in Capacitor | Capacitor Documentation [Skip to main content](https://capacitorjs.com/docs/v3/main/android/managing-dependencies#__docusaurus_skipToContent_fallback) [An **OutSystems** Company →](https://www.outsystems.com/?utm_source=ionic&utm_medium=referral&utm_campaign=ionic-referral&utm_term=none&utm_content=other&utm_campaignteam=digital-mktg&utm_partner=none) This is documentation for Capacitor Documentation **v3**, which is no longer actively maintained. For up-to-date documentation, see the **[latest version](https://capacitorjs.com/docs/main/android/managing-dependencies) ** (v7). Version: v3 Coming soon. --- # Managing Deployment Platforms | Capacitor Documentation [Skip to main content](https://capacitorjs.com/docs/v3/main/basics/managing-platforms#__docusaurus_skipToContent_fallback) [An **OutSystems** Company →](https://www.outsystems.com/?utm_source=ionic&utm_medium=referral&utm_campaign=ionic-referral&utm_term=none&utm_content=other&utm_campaignteam=digital-mktg&utm_partner=none) This is documentation for Capacitor Documentation **v3**, which is no longer actively maintained. For up-to-date documentation, see the **[latest version](https://capacitorjs.com/docs/) ** (v7). Version: v3 Capacitor supports iOS, Android, and PWA. --- # Building a Capacitor Plugin | Capacitor Documentation [Skip to main content](https://capacitorjs.com/docs/v5/plugins/tutorial/introduction#__docusaurus_skipToContent_fallback) [An **OutSystems** Company →](https://www.outsystems.com/?utm_source=ionic&utm_medium=referral&utm_campaign=ionic-referral&utm_term=none&utm_content=other&utm_campaignteam=digital-mktg&utm_partner=none) This is documentation for Capacitor Documentation **v5**, which is no longer actively maintained. For up-to-date documentation, see the **[latest version](https://capacitorjs.com/docs/plugins/tutorial/introduction) ** (v7). Version: v5 On this page Capacitor provides a comprehensive Plugin API to use when adding native functionality to a Capacitor app. There are two types of Capacitor plugins: a _local plugin_ is custom native code isolated to a particular Capacitor application, residing within the native projects committed as part of source control. A _global plugin_ is a published npm package that developers can add to any Capacitor application. In this tutorial, we will start with a blank Capacitor application and add native code to it to build a local plugin. Then we will package it up into a global plugin, ready to be published. So, what are we going to build?[​](https://capacitorjs.com/docs/v5/plugins/tutorial/introduction#so-what-are-we-going-to-build "Direct link to So, what are we going to build?") --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- Pretend that you work for a delivery carrier, and the application you wrote lets drivers obtain signatures from customers, confirming they have received their deliveries. The legal team noticed customer signatures were of poor quality because drivers had customers sign in portrait mode. They’ve tasked you to force the app into landscape mode when capturing signatures. The plugin we build will implement **screen orientation** features to accommodate this request: * The device’s current **orientation** will be detected, with differing UIs for portrait and landscape mode. * Users will be given the option to rotate and **lock** their screen orientation to landscape mode. * After a signature has been confirmed, the app will **unlock** screen orientation rotation. For this tutorial, we will mock up a signature pad but only build out screen orientation functionality. This `ScreenOrientation` plugin will work across the web, iOS, and Android platforms. Getting started[​](https://capacitorjs.com/docs/v5/plugins/tutorial/introduction#getting-started "Direct link to Getting started") ----------------------------------------------------------------------------------------------------------------------------------- Clone [this repository](https://github.com/ionic-enterprise/capacitor-plugin-tutorial) and check out the `start` branch. Run `npm install` at the root of the project. > This tutorial uses `@ionic/react` to build the user interface. If you are not familiar with React or the Ionic Framework, that’s OK! The concepts covered apply to Capacitor apps using any TypeScript-enabled web framework. Add both the iOS and Android platforms to the Capacitor app: npm run buildnpm install @capacitor/ios @capacitor/androidnpx cap add iosnpx cap add androidnpx cap sync Now that we have a Capacitor app in place with native platforms added, we’re ready to move on to the first step of building a plugin: designing the API. Contents -------- * [So, what are we going to build?](https://capacitorjs.com/docs/v5/plugins/tutorial/introduction#so-what-are-we-going-to-build) * [Getting started](https://capacitorjs.com/docs/v5/plugins/tutorial/introduction#getting-started) * * * [Edit this page](https://github.com/ionic-team/capacitor-docs/edit/main/versioned_docs/version-v5/plugins/tutorial/getting-started.md) --- # Building a Capacitor Plugin | Capacitor Documentation [Skip to main content](https://capacitorjs.com/docs/v5/plugins/tutorial/ios-implementation#__docusaurus_skipToContent_fallback) [An **OutSystems** Company →](https://www.outsystems.com/?utm_source=ionic&utm_medium=referral&utm_campaign=ionic-referral&utm_term=none&utm_content=other&utm_campaignteam=digital-mktg&utm_partner=none) This is documentation for Capacitor Documentation **v5**, which is no longer actively maintained. For up-to-date documentation, see the **[latest version](https://capacitorjs.com/docs/plugins/tutorial/ios-implementation) ** (v7). Version: v5 On this page The decision to implement iOS before Android is arbitrary - in all honesty, you could have written the Android implementation first, then iOS, then web. Or any combination of the three. It just so happens that this tutorial implements iOS before Android. You may want to implement the web first because it sits closer to the plugin’s API definition. If any tweaks need to be made to the API, it’s far easier to uncover them while working in the web layer. Register the plugin with Capacitor[​](https://capacitorjs.com/docs/v5/plugins/tutorial/ios-implementation#register-the-plugin-with-capacitor "Direct link to Register the plugin with Capacitor") -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- > **Prerequisite:** Familiarize yourself with the [Capacitor Custom Native iOS Code documentation](https://capacitorjs.com/docs/ios/custom-code) > before continuing. Open up the Capacitor application’s iOS project in Xcode by running `npx cap open ios`. Right-click the **App** group (under the **App** target) and select **New Group** from the context menu. Name this new group **plugins**. Add a new group to **plugins** and name it **ScreenOrientation**. Once complete, you'll have a path `/App/App/plugins/ScreenOrientation/`. Add the following files by right-clicking the **ScreenOrientation** group and selecting **New File…** from the context menu: `ScreenOrientation.swift` `ScreenOrientationPlugin.swift` `ScreenOrientationPlugin.m` If prompted by Xcode to create a Bridging Header, click **Create Bridging Header**. Copy the following code into `ScreenOrientationPlugin.m`: #import #import CAP_PLUGIN(ScreenOrientationPlugin, "ScreenOrientation", CAP_PLUGIN_METHOD(orientation, CAPPluginReturnPromise); CAP_PLUGIN_METHOD(lock, CAPPluginReturnPromise); CAP_PLUGIN_METHOD(unlock, CAPPluginReturnPromise);) These Objective-C macros register the plugin with Capacitor, making `ScreenOrientationPlugin` and its methods available to JavaScript. Copy the following code into `ScreenOrientationPlugin.swift`: import Foundationimport Capacitor@objc(ScreenOrientationPlugin)public class ScreenOrientationPlugin: CAPPlugin { @objc public func orientation(_ call: CAPPluginCall) { call.resolve() } @objc public func lock(_ call: CAPPluginCall) { call.resolve() } @objc public func unlock(_ call: CAPPluginCall) { call.resolve(); }} Note the use of `@objc` decorators; these are required to make sure Capacitor can see the class and its methods at runtime. Getting the current screen orientation[​](https://capacitorjs.com/docs/v5/plugins/tutorial/ios-implementation#getting-the-current-screen-orientation "Direct link to Getting the current screen orientation") -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- Let’s tackle the task of getting the current screen orientation first. Open up `ScreenOrientation.swift` to set up the class and write a method to get the current orientation: import Foundationimport UIKitpublic class ScreenOrientation: NSObject { public func getCurrentOrientationType() -> String { let currentOrientation: UIDeviceOrientation = UIDevice.current.orientation return fromDeviceOrientationToOrientationType(currentOrientation) } private func fromDeviceOrientationToOrientationType(_ orientation: UIDeviceOrientation) -> String { switch orientation { case .landscapeLeft: return "landscape-primary" case .landscapeRight: return "landscape-secondary" case .portraitUpsideDown: return "portrait-secondary" default: // Case: portrait return "portrait-primary" } }} Next, wire up the `orientation` method in `ScreenOrientationPlugin.swift` to call the implementation class’s method: @objc(ScreenOrientationPlugin)public class ScreenOrientationPlugin: CAPPlugin { private let implementation = ScreenOrientation() @objc public func orientation(_ call: CAPPluginCall) { let orientationType = implementation.getCurrentOrientationType(); call.resolve(["type": orientationType]) } /* Remaining code omitted for brevity */} Go ahead and run the app from Xcode, either on an actual device or an iOS simulator. Once it finishes loading, you should see the following logs printed to the console: ⚡️ To Native -> ScreenOrientation orientation 115962915⚡️ TO JS {"type":"portrait-primary"} > **Note:** The exact value of the logs will be different for you. In this example, `115962915` is an arbitrary ID assigned to the method call made from the plugin. You’ve successfully bridged native iOS code to the web application! 🎉 Listening for screen orientation changes[​](https://capacitorjs.com/docs/v5/plugins/tutorial/ios-implementation#listening-for-screen-orientation-changes "Direct link to Listening for screen orientation changes") -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- iOS will let us know when a user rotates their device through the [NotificationCenter](https://developer.apple.com/documentation/foundation/notificationcenter) , when UIDevice fires the `orientationDidChangeNotification` event. The `load()` method is the proper place to register an observer for this event. Likewise, the `deinit()` method is the appropriate place to remove the observer. Within the observer registration, we need to provide a method to return the changed orientation to our plugin’s listeners listening for the `screenOrientationChange` event we defined as part of our plugin’s API. We can reuse the `getCurrentOrientationType()` method to obtain the changed screen orientation. Add the following methods to the `ScreenOrientationPlugin` class: override public func load() { NotificationCenter.default.addObserver( self, selector: #selector(self.orientationDidChange), name: UIDevice.orientationDidChangeNotification, object: nil)}deinit { NotificationCenter.default.removeObserver(self)}@objc private func orientationDidChange() { // Ignore changes in orientation if unknown, face up, or face down if(UIDevice.current.orientation.isValidInterfaceOrientation) { let orientation = implementation.getCurrentOrientationType() notifyListeners("screenOrientationChange", data: ["type": orientation]) }} iOS will detect changes in orientation in three dimensions. As the code comment mentions, we’ll ignore notifying listeners when orientation changes don’t reference landscape or portrait orientations. Locking and unlocking the screen orientation[​](https://capacitorjs.com/docs/v5/plugins/tutorial/ios-implementation#locking-and-unlocking-the-screen-orientation "Direct link to Locking and unlocking the screen orientation") -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- iOS doesn’t exactly provide a mechanism to “lock” or “unlock” a screen orientation. Instead, it allows you to set which orientations are allowed programmatically. To achieve this, we need to add a method to the `AppDelegate` class in `AppDelegate.swift`: func application(_ application: UIApplication, supportedInterfaceOrientationsFor window: UIWindow?) -> UIInterfaceOrientationMask { return ScreenOrientationPlugin.supportedOrientations } Notice that the function returns `ScreenOrientationPlugin.supportedOrientations`. This property doesn’t exist yet, so let’s add it to the `ScreenOrientationPlugin` class as a private static class member: public static var supportedOrientations = UIInterfaceOrientationMask.all By setting up the code above, we tell iOS that we only want to support orientations defined by the value of `ScreenOrientationPlugin.supportedOrientations`. As you might imagine, the `UIInterfaceOrientationMask.all` enumeration value supports all orientations. We will pick a more restrictive enumeration value when we write code to lock the screen orientation. We’ll need a function that maps an OrientationType to its corresponding UIInterfaceOrientationMask enumeration value. Add the following method to the `ScreenOrientation` class: private func fromOrientationTypeToMask(_ orientationType: String) -> UIInterfaceOrientationMask { switch orientationType { case "landscape-primary": return UIInterfaceOrientationMask.landscapeLeft case "landscape-secondary": return UIInterfaceOrientationMask.landscapeRight case "portrait-secondary": return UIInterfaceOrientationMask.portraitUpsideDown default: // Case: portrait-primary return UIInterfaceOrientationMask.portrait }} Forecasting into the future, we will also need a method that maps an OrientationType to an `Int`, so we’ll add it now into the `ScreenOrientation` class: private func fromOrientationTypeToInt(_ orientationType: String) -> Int { switch orientationType { case "landscape-primary": return UIInterfaceOrientation.landscapeLeft.rawValue case "landscape-secondary": return UIInterfaceOrientation.landscapeRight.rawValue case "portrait-secondary": return UIInterfaceOrientation.portraitUpsideDown.rawValue default: // Case: portrait-primary return UIInterfaceOrientation.portrait.rawValue }} Now that all the setup is out of the way, we can implement the `lock()` method. Add the following method to the `ScreenOrientation` class: public func lock(_ orientationType: String, completion: @escaping (UIInterfaceOrientationMask) -> Void) { DispatchQueue.main.async { let mask = self.fromOrientationTypeToMask(orientationType) let orientation = self.fromOrientationTypeToInt(orientationType) UIDevice.current.setValue(orientation, forKey: "orientation") UINavigationController.attemptRotationToDeviceOrientation() completion(mask) }} This is a complicated method; let’s walk through essential parts of it: 1. `completion: @escaping (UIInterfaceOrientationMask) -> Void` tells callers of this method that they must provide a function that will be called when the method finishes execution, and we will pass the function an `UIInterfaceOrientationMask` value, by way of `completion(mask)`. 2. `UIDevice.current.setValue(orientation, forKey: "orientation")` sets a screen orientation for the device, but does not rotate the screen to it. 3. `UINavigationController.attemptRotationToDeviceOrientation()` will attempt to rotate the application to the screen orientation set in the previous line of code. 4. We wrap the code in `DispatchQueue.main.async` to prevent blocking the UI thread. This method needs to get called from the `ScreenOrientationPlugin` class, and afterward, update `ScreenOrientationPlugin.supportedOrientations` so iOS knows we only want to support one specific screen orientation at this time: ​​@objc public func lock(_ call: CAPPluginCall) { guard let lockToOrientation = call.getString("orientation") else { call.reject("Input option 'orientation' must be provided.") return } implementation.lock(lockToOrientation, completion: { (mask) -> Void in ScreenOrientationPlugin.supportedOrientations = mask; call.resolve() })} The `lock()` method also introduces a guard to prevent anyone from calling it without an `orientation` input parameter. It’s best practice to reject any calls to plugin methods that are missing any required input parameters. To unlock the screen orientation, we walk back the steps we took the lock it. Add the following method to the `ScreenOrientation` class: public func unlock(completion: @escaping () -> Void) { DispatchQueue.main.async { let unknownOrientation = UIInterfaceOrientation.unknown.rawValue UIDevice.current.setValue(unknownOrientation, forKey: "orientation") UINavigationController.attemptRotationToDeviceOrientation() completion() }} By setting the current orientation value to `UIInterfaceOrientation.unknown`, iOS attempts to auto-correct its orientation. In the `ScreenOrientationPlugin` class, we’ll revert `supportedOrientations` to `UIInterfaceOrientationMask.all`: @objc public func unlock(_ call: CAPPluginCall) { implementation.unlock { ScreenOrientationPlugin.supportedOrientations = UIInterfaceOrientationMask.all call.resolve() }} Give it a test drive![​](https://capacitorjs.com/docs/v5/plugins/tutorial/ios-implementation#give-it-a-test-drive "Direct link to Give it a test drive!") ---------------------------------------------------------------------------------------------------------------------------------------------------------- In Xcode, run the app on either a device or a simulator. The plugin functions as intended! Pressing the “Rotate My Device” button will rotate the screen orientation into landscape mode, and if you rotate further, you will see that the screen orientation is locked. Pressing “Confirm Signature“ will unlock the screen orientation. The penultimate step to this tutorial is: the Android implementation. Contents -------- * [Register the plugin with Capacitor](https://capacitorjs.com/docs/v5/plugins/tutorial/ios-implementation#register-the-plugin-with-capacitor) * [Getting the current screen orientation](https://capacitorjs.com/docs/v5/plugins/tutorial/ios-implementation#getting-the-current-screen-orientation) * [Listening for screen orientation changes](https://capacitorjs.com/docs/v5/plugins/tutorial/ios-implementation#listening-for-screen-orientation-changes) * [Locking and unlocking the screen orientation](https://capacitorjs.com/docs/v5/plugins/tutorial/ios-implementation#locking-and-unlocking-the-screen-orientation) * [Give it a test drive!](https://capacitorjs.com/docs/v5/plugins/tutorial/ios-implementation#give-it-a-test-drive) * * * [Edit this page](https://github.com/ionic-team/capacitor-docs/edit/main/versioned_docs/version-v5/plugins/tutorial/implementing-for-ios.md) --- # Building a Capacitor Plugin | Capacitor Documentation [Skip to main content](https://capacitorjs.com/docs/v5/plugins/tutorial/packaging-the-plugin#__docusaurus_skipToContent_fallback) [An **OutSystems** Company →](https://www.outsystems.com/?utm_source=ionic&utm_medium=referral&utm_campaign=ionic-referral&utm_term=none&utm_content=other&utm_campaignteam=digital-mktg&utm_partner=none) This is documentation for Capacitor Documentation **v5**, which is no longer actively maintained. For up-to-date documentation, see the **[latest version](https://capacitorjs.com/docs/plugins/tutorial/packaging-the-plugin) ** (v7). Version: v5 On this page The `ScreenOrientation` plugin is functionally complete and integrated into the Capacitor application as a local plugin. However, the `ScreenOrientation` plugin can’t be used by other Capacitor applications in its current state. Let’s go ahead and package the plugin for publishing to make the `ScreenOrientation` plugin globally available. > **Note:** This section references steps and procedures from the [Creating Capacitor Plugins](https://capacitorjs.com/docs/plugins/creating-plugins) > portion of the Capacitor documentation. Please refer to the documentation for details beyond the scope of this tutorial. Generating a new plugin project[​](https://capacitorjs.com/docs/v5/plugins/tutorial/packaging-the-plugin#generating-a-new-plugin-project "Direct link to Generating a new plugin project") ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- Capacitor has a [a plugin generator](https://github.com/ionic-team/create-capacitor-plugin) we can use to scaffold a project in a format suitable for publishing a global plugin. In a new terminal, run the following command: npx @capacitor/create-plugin \ --name @capacitor-community/screen-orientation \ --package-id io.ionic.plugins.screenorientation \ --class-name ScreenOrientation \ --repo "https://ionic.io" \ --license "MIT" \ --description "Work with the screen orientation in a common way for iOS, Android, and web" When prompted to provide a directory, use the default by pressing Enter. When asked for the author’s name, use your own! Port the plugin code[​](https://capacitorjs.com/docs/v5/plugins/tutorial/packaging-the-plugin#port-the-plugin-code "Direct link to Port the plugin code") ---------------------------------------------------------------------------------------------------------------------------------------------------------- Take a look at the generated project’s structure; it looks very similar to the structure built for the Capacitor application, doesn't it? 🤔 Obviously, this was intentional to easily port plugin code from the Capacitor application’s codebase into the generated plugin project. Copy the contents of the files in `src/plugins/screen-orientation` into their equivalent `web.ts`, `index.ts`, and `definitions.ts` files in the plugin project. Next, copy the contents of `ScreenOrientation.swift`, `ScreenOrientationPlugin.m`, and `ScreenOrientationPlugin.swift` from one codebase to the other. Then, do the same for `ScreenOrientation.java` and `ScreenOrientationPlugin.java`. Afterward, update the package of these files in the plugin project: package io.ionic.plugins.screenorientation The package name above was supplied when generating the plugin project, and any Android files in the project should use this package name. Finally, let’s verify that no issues occurred when porting over the code by running the following command: npm run verify > **Note:** You can test the plugin before publishing it by linking the plugin folder to a Capacitor project. See [Plugin Development Workflow](https://capacitorjs.com/docs/plugins/workflow#local-testing) > for details. Update the plugin documentation[​](https://capacitorjs.com/docs/v5/plugins/tutorial/packaging-the-plugin#update-the-plugin-documentation "Direct link to Update the plugin documentation") ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- Take a look at the plugin project’s `README.md` file; it was updated to document the plugin’s API. This update happened when we ran `npm run verify`. Any changes made to source file JSDoc comments can be reflected within the readme file’s API section by running `npm run docgen`. The plugin requires developers to modify their Capacitor application’s `AppDelegate.swift` file, so instructions on how to do so should be included in the plugin’s documentation. > **Note:** Always document any modifications developers will need to make when installing or configuring plugins you build. Replace the “Install” section of `README.md` with the following markdown: Install[​](https://capacitorjs.com/docs/v5/plugins/tutorial/packaging-the-plugin#install "Direct link to Install") ------------------------------------------------------------------------------------------------------------------- npm install @capacitor-community/screen-orientationnpx cap sync ### iOS[​](https://capacitorjs.com/docs/v5/plugins/tutorial/packaging-the-plugin#ios "Direct link to iOS") For iOS, you must make the following adjustments to your `AppDelegate.swift` file: import UIKit+ import CapacitorCommunityScreenOrientation@UIApplicationMainclass AppDelegate: UIResponder, UIApplicationDelegate {+ func application(_ application: UIApplication, supportedInterfaceOrientationsFor window: UIWindow?) -\> UIInterfaceOrientationMask {+ return ScreenOrientationPlugin.supportedOrientations+ }} Publishing the plugin[​](https://capacitorjs.com/docs/v5/plugins/tutorial/packaging-the-plugin#publishing-the-plugin "Direct link to Publishing the plugin") ------------------------------------------------------------------------------------------------------------------------------------------------------------- The plugin is in a state where it can be published to an npm registry. We won’t do that in this tutorial, but note that the command to publish a Capacitor plugin project is the same as publishing any other npm package: `npm publish`. You can publish a global Capacitor plugin to the public npm registry, a private registry, or just link it to a bunch of projects locally on your machine. Whatever fits your use-case. What’s more, there is a [Capacitor Community GitHub organization](https://github.com/capacitor-community/welcome) where you can get your plugin hosted and work closely with the community and Capacitor team as you continue development and maintenance on your plugin. Conclusion[​](https://capacitorjs.com/docs/v5/plugins/tutorial/packaging-the-plugin#conclusion "Direct link to Conclusion") ---------------------------------------------------------------------------------------------------------------------------- Capacitor’s Plugin API is a flexible and robust solution to supplement Capacitor applications with native functionality unavailable to the web, whether the need is to add custom native code to a specific application or reuse native code between a fleet of apps. Looking forward to the plugin you develop next! 🎉 Contents -------- * [Generating a new plugin project](https://capacitorjs.com/docs/v5/plugins/tutorial/packaging-the-plugin#generating-a-new-plugin-project) * [Port the plugin code](https://capacitorjs.com/docs/v5/plugins/tutorial/packaging-the-plugin#port-the-plugin-code) * [Update the plugin documentation](https://capacitorjs.com/docs/v5/plugins/tutorial/packaging-the-plugin#update-the-plugin-documentation) * [Install](https://capacitorjs.com/docs/v5/plugins/tutorial/packaging-the-plugin#install) * [iOS](https://capacitorjs.com/docs/v5/plugins/tutorial/packaging-the-plugin#ios) * [Publishing the plugin](https://capacitorjs.com/docs/v5/plugins/tutorial/packaging-the-plugin#publishing-the-plugin) * [Conclusion](https://capacitorjs.com/docs/v5/plugins/tutorial/packaging-the-plugin#conclusion) * * * [Edit this page](https://github.com/ionic-team/capacitor-docs/edit/main/versioned_docs/version-v5/plugins/tutorial/packaging.md) --- # Building a Capacitor Plugin | Capacitor Documentation [Skip to main content](https://capacitorjs.com/docs/v5/plugins/tutorial/using-the-plugin-api#__docusaurus_skipToContent_fallback) [An **OutSystems** Company →](https://www.outsystems.com/?utm_source=ionic&utm_medium=referral&utm_campaign=ionic-referral&utm_term=none&utm_content=other&utm_campaignteam=digital-mktg&utm_partner=none) This is documentation for Capacitor Documentation **v5**, which is no longer actively maintained. For up-to-date documentation, see the **[latest version](https://capacitorjs.com/docs/plugins/tutorial/using-the-plugin-api) ** (v7). Version: v5 On this page It makes sense to build out a user interface that exercises the plugin’s API before implementing screen orientation functionality. Essentially, we want to rig up a testing harness that allows us to test feature parity across platforms quickly. The focus of this walkthrough is how to build a Capacitor plugin, not how to build an Ionic Framework application, so you can just take the finished versions of the files needed and copy and paste their contents into your project: * [src/pages/Home.tsx](https://github.com/ionic-enterprise/capacitor-plugin-tutorial/blob/main/src/pages/Home.tsx) * [src/pages/Home.css](https://github.com/ionic-enterprise/capacitor-plugin-tutorial/blob/main/src/pages/Home.css) Once copied over, serve the Capacitor app using the `ionic serve` command. Open up the browser’s Developer Tools, and you should see the following error: Uncaught (in promise) ScreenOrientation does not have web implementation. That error checks out; we haven’t implemented code for any of the platforms yet. Keep the browser open. We will implement the web platform first. Before we do, let’s review relevant code from `Home.tsx`. How is the plugin being used?[​](https://capacitorjs.com/docs/v5/plugins/tutorial/using-the-plugin-api#how-is-the-plugin-being-used "Direct link to How is the plugin being used?") ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ **Tracking the screen orientation:** const [orientation, setOrientation] = useState(''); The `orientation` state variable is used to hold the value of the screen’s orientation. It can be updated by calling `setOrientation`. Since we don’t know the current screen orientation when the code starts executing, it’s defaulted to an empty string. A string type is used to make it easier to tell the UI which design to display. An event listener is established that updates `orientation` when `screenOrientationChange` is fired. ScreenOrientation.addListener('screenOrientationChange', res => setOrientation(res.type),); The current screen orientation is obtained when the UI loads, and any listeners created (like the one above) are removed when the UI is removed from the DOM. useEffect(() => { ScreenOrientation.orientation().then(res => setOrientation(res.type)); return () => { ScreenOrientation.removeAllListeners(); };}, []); Please don’t read too much into `useEffect` and the return function; those are React-specific syntax rules. **Showing the correct design:** The `OrientationType` has two values for portrait orientation: `portrait-primary` and `portrait-secondary`. The same goes for landscape orientation. Our UI doesn’t care about the difference between them, only if it is landscape or portrait. { orientation.includes('portrait') && { /* Provide a button that will rotate and lock the screen orientation to landscape mode. */ };}{ orientation.includes('landscape') && { /* Let the user "sign" and unlock screen orientation through a confirmation button. */ };} **Locking and unlocking screen orientation:** The portrait design contains a button that will change the screen orientation and lock it when pressed. onClick={() => ScreenOrientation.lock({ orientation: "landscape-primary" })} Conversely, the landscape design contains a button that will unlock the screen orientation when pressed. onClick={() => ScreenOrientation.unlock()} The rest of the code in `Home.tsx` and `Home.css` is purely cosmetic; we do not need to dig into that. Run `npm run build` so the new UI is used when we run the app on iOS or Android. We now have a user interface that exercises our plugin’s API, so let’s start implementing functionality! We will target the web first in our next step: the web implementation. Contents -------- * [How is the plugin being used?](https://capacitorjs.com/docs/v5/plugins/tutorial/using-the-plugin-api#how-is-the-plugin-being-used) * * * [Edit this page](https://github.com/ionic-team/capacitor-docs/edit/main/versioned_docs/version-v5/plugins/tutorial/using-api.md) --- # Building a Capacitor Plugin | Capacitor Documentation [Skip to main content](https://capacitorjs.com/docs/v5/plugins/tutorial/web#__docusaurus_skipToContent_fallback) [An **OutSystems** Company →](https://www.outsystems.com/?utm_source=ionic&utm_medium=referral&utm_campaign=ionic-referral&utm_term=none&utm_content=other&utm_campaignteam=digital-mktg&utm_partner=none) This is documentation for Capacitor Documentation **v5**, which is no longer actively maintained. For up-to-date documentation, see the **[latest version](https://capacitorjs.com/docs/plugins/tutorial/web) ** (v7). Version: v5 On this page While designing the plugin’s API, we found out that the web already supports screen orientation functionality (except on mobile devices, of course). You might be asking why what would be the purpose for our plugin to have a web implementation...couldn’t you programmatically detect if the user is on the web and use the [Screen Orientation Web API](https://whatwebcando.today/screen-orientation.html) , otherwise, use the plugin? The mantra behind Web Native applications is "write once, run anywhere." This applies to plugins as well; developers using Capacitor plugins ought to be able to use the same plugin class and methods and have them implemented for all platforms. Therefore, we will be good developer-citizens and wrap the Screen Orientation Web API inside the web implementation of the `ScreenOrientation` plugin. Extending Capacitor’s WebPlugin class[​](https://capacitorjs.com/docs/v5/plugins/tutorial/web#extending-capacitors-webplugin-class "Direct link to Extending Capacitor’s WebPlugin class") ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- Open a new file `src/plugins/screen-orientation/web.ts`. This file is where we will write the web implementation of the `ScreenOrientation` plugin. Start by declaring the `ScreenOrientationWeb` class, and have it extend `WebPlugin`: import { WebPlugin } from '@capacitor/core';import type { ScreenOrientationPlugin } from './definitions';export class ScreenOrientationWeb extends WebPlugin { constructor() { super(); }} Capacitor’s `WebPlugin` class contains logic to notify any plugin listeners, which we’ll use to tell them when the screen orientation has changed. Let’s notify any listeners when the Screen Orientation Web API’s change event fires. Update the constructor like so: constructor() { super(); window.screen.orientation.addEventListener("change", () => { const type = window.screen.orientation.type; this.notifyListeners("screenOrientationChange", { type }); }); } The `WebPlugin` class contains an implementation for the `addListener()` and `removeAllListeners()` methods defined in the `ScreenOrientationPlugin` interface. No additional work is needed to use those methods. Implement the remaining methods[​](https://capacitorjs.com/docs/v5/plugins/tutorial/web#implement-the-remaining-methods "Direct link to Implement the remaining methods") -------------------------------------------------------------------------------------------------------------------------------------------------------------------------- Let’s finish implementing the `ScreenOrientationPlugin` interface. Start by adjusting the class definition so that it _actually_ implements the interface: export class ScreenOrientationWeb extends WebPlugin implements ScreenOrientationPlugin{ Then implement the remaining methods as part of the `ScreenOrientationWeb` class: async orientation(): Promise<{ type: OrientationType }> { return { type: window.screen.orientation.type }; } async lock(opts: { orientation: OrientationLockType }): Promise { await window.screen.orientation.lock(opts.orientation); } async unlock(): Promise { window.screen.orientation.unlock(); } Registering the web implementation[​](https://capacitorjs.com/docs/v5/plugins/tutorial/web#registering-the-web-implementation "Direct link to Registering the web implementation") ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- To register `ScreenOrientationWeb` as our plugin’s web implementation, we need to use the second input parameter of `registerPlugin()`. Open `src/plugins/screen-orientation/index.ts` and update the declaration of the `ScreenOrientation` variable like so: const ScreenOrientation = registerPlugin( 'ScreenOrientation', { web: () => import('./web').then(m => new m.ScreenOrientationWeb()), },); Give it a test drive![​](https://capacitorjs.com/docs/v5/plugins/tutorial/web#give-it-a-test-drive "Direct link to Give it a test drive!") ------------------------------------------------------------------------------------------------------------------------------------------- Test out the web implementation. Serve your application using `ionic serve`, and you can use your browser’s Development Tools to emulate a mobile device in both portrait and landscape screen orientations. The “Rotate my Device” button doesn’t function as there is poor web support for `window.screen.orientation.lock()`, but you should be able to see the different designs if you manually rotate the orientation using the developer tooling. One platform implemented, two to go! Before diving into iOS and Android code, we should consider how to pattern and abstract it. Let’s review some patterns in the next step: code abstraction patterns. Contents -------- * [Extending Capacitor’s WebPlugin class](https://capacitorjs.com/docs/v5/plugins/tutorial/web#extending-capacitors-webplugin-class) * [Implement the remaining methods](https://capacitorjs.com/docs/v5/plugins/tutorial/web#implement-the-remaining-methods) * [Registering the web implementation](https://capacitorjs.com/docs/v5/plugins/tutorial/web#registering-the-web-implementation) * [Give it a test drive!](https://capacitorjs.com/docs/v5/plugins/tutorial/web#give-it-a-test-drive) * * * [Edit this page](https://github.com/ionic-team/capacitor-docs/edit/main/versioned_docs/version-v5/plugins/tutorial/implementing-for-web.md) --- # Capacitor Web/PWA Plugin Guide | Capacitor Documentation [Skip to main content](https://capacitorjs.com/docs/v5/plugins/web#__docusaurus_skipToContent_fallback) [An **OutSystems** Company →](https://www.outsystems.com/?utm_source=ionic&utm_medium=referral&utm_campaign=ionic-referral&utm_term=none&utm_content=other&utm_campaignteam=digital-mktg&utm_partner=none) This is documentation for Capacitor Documentation **v5**, which is no longer actively maintained. For up-to-date documentation, see the **[latest version](https://capacitorjs.com/docs/plugins/web) ** (v7). Version: v5 On this page Capacitor utilizes a web/native compatibility layer, making it easy to build plugins that have functionality when running natively as well as when running in a PWA on the Web. Getting Started[​](https://capacitorjs.com/docs/v5/plugins/web#getting-started "Direct link to Getting Started") ----------------------------------------------------------------------------------------------------------------- To get started, first generate a plugin as shown in the [Getting Started](https://capacitorjs.com/docs/v5/plugins/creating-plugins#plugin-generator) section of the Plugin guide. Next, open `echo/src/web.ts` in your editor of choice. Example[​](https://capacitorjs.com/docs/v5/plugins/web#example "Direct link to Example") ----------------------------------------------------------------------------------------- The basic structure of a web plugin for Capacitor looks like this: import { WebPlugin } from '@capacitor/core';import type { EchoPlugin } from './definitions';export class EchoWeb extends WebPlugin implements EchoPlugin { async echo(options: { value: string }) { console.log('ECHO', options); return options; }} The `EchoPlugin` interface defines the method signatures of your plugin. In TypeScript, we can ensure the web implementation (the `EchoWeb` class) correctly implements the interface. Permissions[​](https://capacitorjs.com/docs/v5/plugins/web#permissions "Direct link to Permissions") ----------------------------------------------------------------------------------------------------- If your plugin has functionality on web that requires permissions from the end user, then you will need to implement the permissions pattern. ### Aliases[​](https://capacitorjs.com/docs/v5/plugins/web#aliases "Direct link to Aliases") You will need to develop one or more aliases for abstracting and grouping permissions that your plugin requires. These aliases are used to convey permission state. By default, an alias can be in one of the following states: * `granted`: Every permission in this alias has been granted by the end user (or prompting is not necessary). * `denied`: One or more permissions in this alias have been denied by the end user. * `prompt`: The end user should be prompted for permission, because it has neither been granted nor denied. * `prompt-with-rationale`: The end user has denied permission before, but has not blocked the prompt yet. These are represented by the `PermissionState` type exported from `@capacitor/core`. It is also possible to define custom states for aliases, if need be. For example, the official [Camera plugin](https://capacitorjs.com/docs/v5/apis/camera) also defines a `limited` state for the `camera` and `photos` aliases. Aliases are cross-platform, so make sure to take iOS, Android, and web permissions into account when deciding on the aliases for your plugin. ### Permission Status Definitions[​](https://capacitorjs.com/docs/v5/plugins/web#permission-status-definitions "Direct link to Permission Status Definitions") In `src/definitions.ts`, import `PermissionState` from Capacitor and define a `PermissionStatus` interface which represents the status of permissions in your plugin, keyed by the alias(es) you came up with. In the example below, the permission status can be entirely represented by a `location` alias which can be `granted`, `denied`, etc. import type { PermissionState } from '@capacitor/core';export interface PermissionStatus { // TODO: change 'location' to the actual name of your alias! location: PermissionState;} Then, add the definitions for `checkPermissions()` and `requestPermissions()` in your plugin interface. Both of these methods will return the current status of permissions in your plugin as defined by `PermissionStatus`. export interface EchoPlugin { echo(options: { value: string }): Promise<{ value: string }>;+ checkPermissions(): Promise;+ requestPermissions(): Promise; } Because these methods are added to your plugin interface, they must be implemented on all platforms that your plugin supports. ### Implementing Permissions[​](https://capacitorjs.com/docs/v5/plugins/web#implementing-permissions "Direct link to Implementing Permissions") In `src/web.ts`, add the `checkPermissions()` and `requestPermissions()` methods to your web implementation. +import { PermissionStatus } from './definitions'; export class EchoWeb extends WebPlugin implements EchoPlugin { async echo(options: { value: string }) { ... }+ async checkPermissions(): Promise {+ // TODO+ }+ async requestPermissions(): Promise {+ // TODO+ } } #### `checkPermissions()`[​](https://capacitorjs.com/docs/v5/plugins/web#checkpermissions "Direct link to checkpermissions") This method should return the current status of permissions in your plugin. This information may be available on the specific web API directly, or from the [Permissions API](https://developer.mozilla.org/en-US/docs/Web/API/Permissions_API) . Remember, when working with web APIs with spotty browser adoption (such as the Permissions API), you should implement feature detection and throw an appropriate error when the end user's browser is not supported. async checkPermissions(): Promise {+ if (typeof navigator === 'undefined' || !navigator.permissions) {+ throw this.unavailable('Permissions API not available in this browser.');+ } const permission = await navigator.permissions.query( ... ); // TODO } #### `requestPermissions()`[​](https://capacitorjs.com/docs/v5/plugins/web#requestpermissions "Direct link to requestpermissions") This method should prompt the end user for permission to use the platform APIs that your plugin requires. Then, it should return the new state of permissions in your plugin after prompting (just like with the `checkPermissions()` method). On web, is it sometimes not possible to separate the requesting of permission from the actual call. For example, the Geolocation API only requests permission at the time a location is requested. For situations like this, we recommended throwing the unimplemented exception. async requestPermissions(): Promise { // TODO: does the web support requesting permissions for my plugin? throw this.unimplemented('Not implemented on web.');} Error Handling[​](https://capacitorjs.com/docs/v5/plugins/web#error-handling "Direct link to Error Handling") -------------------------------------------------------------------------------------------------------------- Capacitor plugins for web often work with APIs that haven't been adopted in some browsers or even remotely standardized. Despite this, it is common to take a best-effort approach for the web implementation of your plugin and gracefully fail when APIs are unavailable. This is why error handling is especially important on web! ### Unavailable[​](https://capacitorjs.com/docs/v5/plugins/web#unavailable "Direct link to Unavailable") This error should be thrown to indicate that the functionality can't be used right now. Reasons for this include: * It is currently missing a prerequisite, such as network connectivity. * It requires a browser that has implemented the underlying API. In the example below, we first check that `geolocation` is defined on `navigator`. If it does not, it means the browser does not support Geolocation and we should throw the "unavailable" error. Otherwise, we can proceed with the implementation. async getLocation(): Promise { if (typeof navigator === 'undefined' || !navigator.geolocation) { throw this.unavailable('Geolocation API not available in this browser.'); } // TODO: actual web implementation} ### Unimplemented[​](https://capacitorjs.com/docs/v5/plugins/web#unimplemented "Direct link to Unimplemented") This error can be thrown to indicate that the functionality is not implemented. You can use this to stub out your methods on web for a later implementation or use it to indicate the functionality can't be implemented on a certain platform. async getLocation(): Promise { throw this.unimplemented('Not implemented on web.');} Contents -------- * [Getting Started](https://capacitorjs.com/docs/v5/plugins/web#getting-started) * [Example](https://capacitorjs.com/docs/v5/plugins/web#example) * [Permissions](https://capacitorjs.com/docs/v5/plugins/web#permissions) * [Aliases](https://capacitorjs.com/docs/v5/plugins/web#aliases) * [Permission Status Definitions](https://capacitorjs.com/docs/v5/plugins/web#permission-status-definitions) * [Implementing Permissions](https://capacitorjs.com/docs/v5/plugins/web#implementing-permissions) * [Error Handling](https://capacitorjs.com/docs/v5/plugins/web#error-handling) * [Unavailable](https://capacitorjs.com/docs/v5/plugins/web#unavailable) * [Unimplemented](https://capacitorjs.com/docs/v5/plugins/web#unimplemented) * * * [Edit this page](https://github.com/ionic-team/capacitor-docs/edit/main/versioned_docs/version-v5/plugins/creating-plugins/web-guide.md) --- # Plugin Development Workflow | Capacitor Documentation [Skip to main content](https://capacitorjs.com/docs/v5/plugins/workflow#__docusaurus_skipToContent_fallback) [An **OutSystems** Company →](https://www.outsystems.com/?utm_source=ionic&utm_medium=referral&utm_campaign=ionic-referral&utm_term=none&utm_content=other&utm_campaignteam=digital-mktg&utm_partner=none) This is documentation for Capacitor Documentation **v5**, which is no longer actively maintained. For up-to-date documentation, see the **[latest version](https://capacitorjs.com/docs/plugins/workflow) ** (v7). Version: v5 On this page With the new plugin created, you can begin implementing functionality across a variety of platforms. Implementing a New Method[​](https://capacitorjs.com/docs/v5/plugins/workflow#implementing-a-new-method "Direct link to Implementing a New Method") ---------------------------------------------------------------------------------------------------------------------------------------------------- To implement new functionality in your plugin, begin by defining the method's signature in the exported TypeScript interface for your plugin in `src/definitions.ts`. In the example below, the `openMap()` method is added which takes a `latitude` and `longitude`. It is good practice to define interfaces for method parameters that can be imported and used in apps. export interface EchoPlugin { echo(options: { value: string }): Promise<{ value: string }>;+ openMap(options: OpenMapOptions): Promise; }+export interface OpenMapOptions {+ latitude: number;+ longitude: number;+} Implement the web implementation in `src/web.ts`: import type { EchoPlugin,+ OpenMapOptions, } from './definitions'; export class EchoWeb extends WebPlugin implements EchoPlugin { // other methods+ async openMap(location: OpenMapOptions): Promise {+ // logic here+ } } To compile the plugin, navigate into the plugin directory then run: npm run build Implement [Android functionality](https://capacitorjs.com/docs/v5/plugins/android) in `android/src/main/[nested folders]/EchoPlugin.java`: @PluginMethod()public void openMap(PluginCall call) { Double latitude = call.getDouble("latitude"); Double longitude = call.getDouble("longitude"); // more logic call.resolve();} Implement [iOS functionality](https://capacitorjs.com/docs/v5/plugins/ios) in `ios/Plugin/EchoPlugin.swift`: @objc func openMap(_ call: CAPPluginCall) { let latitude = call.getString("latitude") let longitude = call.getNumber("longitude") // more logic call.resolve()} > Remember to [register plugin methods](https://capacitorjs.com/docs/v5/plugins/ios#export-to-capacitor) > in your `.m` file. This example contains the most common type of method in plugins but details about all the supported types [can be found here.](https://capacitorjs.com/docs/v5/plugins/method-types) Local Testing[​](https://capacitorjs.com/docs/v5/plugins/workflow#local-testing "Direct link to Local Testing") ---------------------------------------------------------------------------------------------------------------- To test the plugin locally while developing it, link the plugin folder to your app using `npm install` with the path to your plugin. npm install ../path/to/echo The project's `package.json` file now shows the plugin package link in the dependencies list: "echo": "file:../path/to/echo", Finally, run `npx cap sync` to make the native projects aware of your plugin. If it was detected correctly, it will print something like this: [info] Found 1 Capacitor plugin for android: - echo (0.0.1) ### Unlinking the Plugin[​](https://capacitorjs.com/docs/v5/plugins/workflow#unlinking-the-plugin "Direct link to Unlinking the Plugin") To unlink the local plugin from your app, use `npm uninstall` with the package name of your plugin. npm uninstall echo Package Scripts[​](https://capacitorjs.com/docs/v5/plugins/workflow#package-scripts "Direct link to Package Scripts") ---------------------------------------------------------------------------------------------------------------------- The plugin template ships with a variety of scripts in `package.json`. * `verify`: builds and tests web and native code * `lint`: lints web and native code * `fmt`: autoformats web and native code * `docgen`: generates documentation from plugin interface (see [Documentation](https://capacitorjs.com/docs/v5/plugins/workflow#documentation) ) * `build`: builds web code into ESM and bundle distributions Documentation[​](https://capacitorjs.com/docs/v5/plugins/workflow#documentation "Direct link to Documentation") ---------------------------------------------------------------------------------------------------------------- To document plugin functionality, add [JSDoc](https://jsdoc.app/) comment blocks to methods and properties. > It is usually not necessary to include type information with the `@param` and `@returns` JSDoc tags in TypeScript files. Using our `openMap()` method as an example, open `src/definitions.ts` and start documenting! export interface EchoPlugin { echo(options: { value: string }): Promise<{ value: string }>;+ /**+ * Opens the map at a given location.+ *+ * @since 1.1.0+ */ openMap(options: OpenMapOptions): Promise; } export interface OpenMapOptions {+ /**+ * The latitude at which to open the map.+ */ latitude: number;+ /**+ * The longitude at which to open the map.+ */ longitude: number; } The plugin template ships with [`@capacitor/docgen`](https://github.com/ionic-team/capacitor-docgen) , which writes generated documentation to `README.md`. Documentation is generated during `npm run build`. You can also run it manually: npm run docgen Publishing[​](https://capacitorjs.com/docs/v5/plugins/workflow#publishing "Direct link to Publishing") ------------------------------------------------------------------------------------------------------- Whenever you are ready to publish your plugin, just use: npm publish This will build the JS portion of your plugin and publish the rest of your plugin files to npm. Your package can now be installed using `npm install echo` in any Capacitor app. Contents -------- * [Implementing a New Method](https://capacitorjs.com/docs/v5/plugins/workflow#implementing-a-new-method) * [Local Testing](https://capacitorjs.com/docs/v5/plugins/workflow#local-testing) * [Unlinking the Plugin](https://capacitorjs.com/docs/v5/plugins/workflow#unlinking-the-plugin) * [Package Scripts](https://capacitorjs.com/docs/v5/plugins/workflow#package-scripts) * [Documentation](https://capacitorjs.com/docs/v5/plugins/workflow#documentation) * [Publishing](https://capacitorjs.com/docs/v5/plugins/workflow#publishing) * * * [Edit this page](https://github.com/ionic-team/capacitor-docs/edit/main/versioned_docs/version-v5/plugins/creating-plugins/development-workflow.md) --- # Updating to 1.1 | Capacitor Documentation [Skip to main content](https://capacitorjs.com/docs/v5/updating/1-1#__docusaurus_skipToContent_fallback) [An **OutSystems** Company →](https://www.outsystems.com/?utm_source=ionic&utm_medium=referral&utm_campaign=ionic-referral&utm_term=none&utm_content=other&utm_campaignteam=digital-mktg&utm_partner=none) This is documentation for Capacitor Documentation **v5**, which is no longer actively maintained. For up-to-date documentation, see the **[latest version](https://capacitorjs.com/docs/updating/1-1) ** (v7). Version: v5 On this page If you are using an earlier version of Capacitor in your app, there are some recommended changes to make in your app for Capacitor 1.1.0. iOS[​](https://capacitorjs.com/docs/v5/updating/1-1#ios "Direct link to iOS") ------------------------------------------------------------------------------ Add `Podfile.lock` to the `ios/.gitignore` file: App/build App/Pods App/public+App/Podfile.lock xcuserdata # Cordova plugins for Capacitor Android[​](https://capacitorjs.com/docs/v5/updating/1-1#android "Direct link to Android") ------------------------------------------------------------------------------------------ Remove the `fileprovider_authority` string from the `android/app/src/main/res/values/strings.xml` file: My App My App com.getcapacitor.myapp- com.getcapacitor.myapp.fileprovider com.getcapacitor.myapp Contents -------- * [iOS](https://capacitorjs.com/docs/v5/updating/1-1#ios) * [Android](https://capacitorjs.com/docs/v5/updating/1-1#android) * * * [Edit this page](https://github.com/ionic-team/capacitor-docs/edit/main/versioned_docs/version-v5/main/updating/1-1.md) --- # Updating to 2.0 | Capacitor Documentation [Skip to main content](https://capacitorjs.com/docs/v5/updating/2-0#__docusaurus_skipToContent_fallback) [An **OutSystems** Company →](https://www.outsystems.com/?utm_source=ionic&utm_medium=referral&utm_campaign=ionic-referral&utm_term=none&utm_content=other&utm_campaignteam=digital-mktg&utm_partner=none) This is documentation for Capacitor Documentation **v5**, which is no longer actively maintained. For up-to-date documentation, see the **[latest version](https://capacitorjs.com/docs/updating/2-0) ** (v7). Version: v5 On this page Capacitor 2 makes some tooling updates including the adoption of Swift 5 in iOS and AndroidX for Android. [Read the Capacitor 2.0 announcement ›](https://ionicframework.com/blog/announcing-capacitor-2-0) Update Capacitor dependencies[​](https://capacitorjs.com/docs/v5/updating/2-0#update-capacitor-dependencies "Direct link to Update Capacitor dependencies") ------------------------------------------------------------------------------------------------------------------------------------------------------------ First, update Capacitor Core and the CLI: npm install @capacitor/cli@2 @capacitor/core@2 Next, update each Capacitor platform that you use: # iOSnpm install @capacitor/ios@2npx cap sync ios# Androidnpm install @capacitor/android@2npx cap sync android# Electroncd electronnpm install @capacitor/electron@2 Backward Incompatible Plugin Changes[​](https://capacitorjs.com/docs/v5/updating/2-0#backward-incompatible-plugin-changes "Direct link to Backward Incompatible Plugin Changes") --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- * **Camera** * `saveToGallery` default value is now `false` on all platforms * if `allowEditing` is `true` and the edit is canceled, the original image is returned * **Push Notifications** * permissions will no longer be requested when `register()` is called, use `requestPermission()` * `PushNotificationChannel` renamed to `NotificationChannel` * **Local Notifications** * permissions will no longer be requested when `register()` is called, use `requestPermission()` * `schedule()` now returns `LocalNotificationScheduleResult` * **Toast** * unify duration across platforms: short 2000ms, long 3500ms * **Geolocation** * use Fused Location Provider on Android * `requireAltitude` removed from `GeolocationOptions` * change native location accuracy values on iOS ([more info](https://github.com/ionic-team/capacitor/pull/2420) ) * **Filesystem** * `createIntermediateDirectories` was removed from `MkdirOptions` (use `recursive` instead) * `recursive` option added to writeFile, which changes behavior on Android and web ([more info](https://github.com/ionic-team/capacitor/pull/2487) ) * `Application` directory option removed because it was broken * **Device** * `batteryLevel` and `isCharging` removed from `getInfo()`, use `getBatteryInfo()` * **Modals** * `inputPlaceholder` sets a placeholder instead of text, use `inputText` instead * **App** * `AppRestoredResult` is optional now, returned only if succeeded, otherwise it returns an error * **Clipboard** * `ReadOptions` was removed iOS[​](https://capacitorjs.com/docs/v5/updating/2-0#ios "Direct link to iOS") ------------------------------------------------------------------------------ Capacitor 2 requires Xcode 11+. ### Update native project to Swift 5[​](https://capacitorjs.com/docs/v5/updating/2-0#update-native-project-to-swift-5 "Direct link to Update native project to Swift 5") Capacitor 2 uses Swift 5. It's recommended to update your native project to also use Swift 5. 1. From Xcode click **Edit** -> **Convert** -> **To Current Swift Syntax**. 2. **App.app** will appear selected, click **Next** button. 3. Then a message will say **No source changes necessary**. 4. Finally, click the **Update** button. Android[​](https://capacitorjs.com/docs/v5/updating/2-0#android "Direct link to Android") ------------------------------------------------------------------------------------------ ### AndroidX[​](https://capacitorjs.com/docs/v5/updating/2-0#androidx "Direct link to AndroidX") Capacitor 2 uses AndroidX for Android support library dependencies as recommended by Google, so the native project needs to be updated to use AndroidX as well. From Android Studio do **Refactor** -> **Migrate to AndroidX**. Then click on **Migrate** button and finally click on **Do Refactor**. If using Cordova or Capacitor plugins that don't use AndroidX yet, you can use [jetifier](https://www.npmjs.com/package/jetifier) tool to patch them. npm install jetifiernpx jetifier To run it automatically after every package install, add `"postinstall": "jetifier"` in the `package.json`. ### Create common variables[​](https://capacitorjs.com/docs/v5/updating/2-0#create-common-variables "Direct link to Create common variables") Create a `android/variables.gradle` file with this content: ext { minSdkVersion = 21 compileSdkVersion = 29 targetSdkVersion = 29 androidxAppCompatVersion = '1.1.0' androidxCoreVersion = '1.2.0' androidxMaterialVersion = '1.1.0-rc02' androidxBrowserVersion = '1.2.0' androidxLocalbroadcastmanagerVersion = '1.0.0' firebaseMessagingVersion = '20.1.2' playServicesLocationVersion = '17.0.0' junitVersion = '4.12' androidxJunitVersion = '1.1.1' androidxEspressoCoreVersion = '3.2.0' cordovaAndroidVersion = '7.0.0'} In `android/build.gradle` file, add `apply from: "variables.gradle"`: classpath 'com.android.tools.build:gradle:4.1.1' classpath 'com.google.gms:google-services:4.3.3' // NOTE: Do not place your application dependencies here; they belong // in the individual module build.gradle files } }+apply from: "variables.gradle" allprojects { repositories { google() jcenter() ### Use common variables[​](https://capacitorjs.com/docs/v5/updating/2-0#use-common-variables "Direct link to Use common variables") If you created the `variables.gradle` file, update your project to use them. In the `android/app/build.gradle` file, make the following updates: android {- compileSdkVersion 28+ compileSdkVersion rootProject.ext.compileSdkVersion defaultConfig { applicationId "com.example.app"- minSdkVersion 21- targetSdkVersion 28+ minSdkVersion rootProject.ext.minSdkVersion+ targetSdkVersion rootProject.ext.targetSdkVersion versionCode 1 versionName "1.0" testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner" dependencies { implementation fileTree(include: ['*.jar'], dir: 'libs')- implementation 'androidx.appcompat:appcompat:1.0.0'+ implementation "androidx.appcompat:appcompat:$androidxAppCompatVersion" implementation project(':capacitor-android')- testImplementation 'junit:junit:4.12'- androidTestImplementation 'androidx.test.ext:junit:1.1.1'- androidTestImplementation 'androidx.test.espresso:espresso-core:3.1.0'+ testImplementation "junit:junit:$junitVersion"+ androidTestImplementation "androidx.test.ext:junit:$androidxJunitVersion"+ androidTestImplementation "androidx.test.espresso:espresso-core:$androidxEspressoCoreVersion" implementation project(':capacitor-cordova-android-plugins') > Don't miss the change from single quotes to double quotes. Double quotes are required for variable interpolation. ### Android Studio plugin update recommended[​](https://capacitorjs.com/docs/v5/updating/2-0#android-studio-plugin-update-recommended "Direct link to Android Studio plugin update recommended") When you open the Android project in Android Studio, a **Plugin Update Recommended** message will appear. Click on **update**. It will tell you to update Gradle plugin and Gradle. Click **Update** button. You can also manually update the Gradle plugin and Gradle. To manually update Gradle plugin, in `android/build.gradle` file, update the `com.android.tool.build:gradle` version to 3.6.1. To manually update Gradle, in `android/gradle/wrapper/gradle-wrapper.properties`, change `gradle-4.10.1-all.zip` to `gradle-5.6.4-all.zip`. ### Update Google Services plugin[​](https://capacitorjs.com/docs/v5/updating/2-0#update-google-services-plugin "Direct link to Update Google Services plugin") In `android/build.gradle` file, update the `com.google.gms:google-services` dependency version to 4.3.3. dependencies { classpath 'com.android.tools.build:gradle:4.1.1'- classpath 'com.google.gms:google-services:4.2.0'+ classpath 'com.google.gms:google-services:4.3.3' // NOTE: Do not place your application dependencies here; they belong // in the individual module build.gradle files } ### Change `android:configChanges` to avoid app restarts[​](https://capacitorjs.com/docs/v5/updating/2-0#change-androidconfigchanges-to-avoid-app-restarts "Direct link to change-androidconfigchanges-to-avoid-app-restarts") In `android/app/src/main/AndroidManifest.xml`, add `|smallestScreenSize|screenLayout|uiMode` in the activity's `android:configChanges` attribute. ### Add caches folder to `FileProvider` file paths to avoid permission error when editing gallery images[​](https://capacitorjs.com/docs/v5/updating/2-0#add-caches-folder-to-fileprovider-file-paths-to-avoid-permission-error-when-editing-gallery-images "Direct link to add-caches-folder-to-fileprovider-file-paths-to-avoid-permission-error-when-editing-gallery-images") In `android/app/src/main/res/xml/file_paths.xml` add ``: + ### Remove `launch_splash.xml`[​](https://capacitorjs.com/docs/v5/updating/2-0#remove-launch_splashxml "Direct link to remove-launch_splashxml") The `android/app/src/main/res/drawable/launch_splash.xml` file can be removed because it is no longer used. ### Remove maven repository[​](https://capacitorjs.com/docs/v5/updating/2-0#remove-maven-repository "Direct link to Remove maven repository") Capacitor is distributed on npm, so having the maven repository entry on `android/app/build.gradle` is no longer needed and can cause problems. Remove it from `repositories` section: repositories {- maven {- url "https://dl.bintray.com/ionic-team/capacitor"- } flatDir { dirs '../capacitor-cordova-android-plugins/src/main/libs', 'libs' } } Contents -------- * [Update Capacitor dependencies](https://capacitorjs.com/docs/v5/updating/2-0#update-capacitor-dependencies) * [Backward Incompatible Plugin Changes](https://capacitorjs.com/docs/v5/updating/2-0#backward-incompatible-plugin-changes) * [iOS](https://capacitorjs.com/docs/v5/updating/2-0#ios) * [Update native project to Swift 5](https://capacitorjs.com/docs/v5/updating/2-0#update-native-project-to-swift-5) * [Android](https://capacitorjs.com/docs/v5/updating/2-0#android) * [AndroidX](https://capacitorjs.com/docs/v5/updating/2-0#androidx) * [Create common variables](https://capacitorjs.com/docs/v5/updating/2-0#create-common-variables) * [Use common variables](https://capacitorjs.com/docs/v5/updating/2-0#use-common-variables) * [Android Studio plugin update recommended](https://capacitorjs.com/docs/v5/updating/2-0#android-studio-plugin-update-recommended) * [Update Google Services plugin](https://capacitorjs.com/docs/v5/updating/2-0#update-google-services-plugin) * [Change `android:configChanges` to avoid app restarts](https://capacitorjs.com/docs/v5/updating/2-0#change-androidconfigchanges-to-avoid-app-restarts) * [Add caches folder to `FileProvider` file paths to avoid permission error when editing gallery images](https://capacitorjs.com/docs/v5/updating/2-0#add-caches-folder-to-fileprovider-file-paths-to-avoid-permission-error-when-editing-gallery-images) * [Remove `launch_splash.xml`](https://capacitorjs.com/docs/v5/updating/2-0#remove-launch_splashxml) * [Remove maven repository](https://capacitorjs.com/docs/v5/updating/2-0#remove-maven-repository) * * * [Edit this page](https://github.com/ionic-team/capacitor-docs/edit/main/versioned_docs/version-v5/main/updating/2-0.md) --- # Updating to 3.0 | Capacitor Documentation [Skip to main content](https://capacitorjs.com/docs/v5/updating/3-0#__docusaurus_skipToContent_fallback) [An **OutSystems** Company →](https://www.outsystems.com/?utm_source=ionic&utm_medium=referral&utm_campaign=ionic-referral&utm_term=none&utm_content=other&utm_campaignteam=digital-mktg&utm_partner=none) This is documentation for Capacitor Documentation **v5**, which is no longer actively maintained. For up-to-date documentation, see the **[latest version](https://capacitorjs.com/docs/updating/3-0) ** (v7). Version: v5 On this page Capacitor 3 brings crucial updates to the ecosystem and exciting new features. [Read the Capacitor 3.0 announcement ›](https://ionicframework.com/blog/announcing-capacitor-3-0/) > After upgrading your app to Capacitor 3, would you mind sharing any feedback you have in [this discussion](https://github.com/ionic-team/capacitor/discussions/3994) > ? We'd love to hear from you! 💖 If you're a plugin author looking to upgrade your plugins to newer Capacitor versions, see the [Upgrade Guide for Capacitor Plugins](https://capacitorjs.com/docs/v5/updating/plugins/3-0) . NodeJS 12+[​](https://capacitorjs.com/docs/v5/updating/3-0#nodejs-12 "Direct link to NodeJS 12+") -------------------------------------------------------------------------------------------------- Node 8 has reached end-of-life. Node 10 will reach end-of-life on April 30th, 2021. Capacitor 3 requires NodeJS 12 or greater. (Latest LTS version is recommended.) Ionic CLI[​](https://capacitorjs.com/docs/v5/updating/3-0#ionic-cli "Direct link to Ionic CLI") ------------------------------------------------------------------------------------------------ If you are using the Ionic CLI, official Capacitor 3 support starts at version 6.16.0. We suggest upgrading to the latest version at this time via `npm install -g @ionic/cli`. Update Capacitor CLI and Core[​](https://capacitorjs.com/docs/v5/updating/3-0#update-capacitor-cli-and-core "Direct link to Update Capacitor CLI and Core") ------------------------------------------------------------------------------------------------------------------------------------------------------------ npm install @capacitor/cli@latest-3 @capacitor/core@latest-3 ES2017+[​](https://capacitorjs.com/docs/v5/updating/3-0#es2017 "Direct link to ES2017+") ----------------------------------------------------------------------------------------- Capacitor 3 now builds for ES2017 environments, instead of ES5. The [plugin template has also been updated](https://github.com/ionic-team/capacitor/pull/3427/files#diff-b22b3d0cbb7d8f6fdfe1f6f1d9e84b7d) to target ES2017, and third-party plugins are encouraged to update their targets. This change should not affect your app unless you are supporting IE11, which Capacitor does not officially support. TypeScript 3.8+[​](https://capacitorjs.com/docs/v5/updating/3-0#typescript-38 "Direct link to TypeScript 3.8+") ---------------------------------------------------------------------------------------------------------------- Capacitor 3 uses a newer TypeScript syntax which can only be used in TS 3.8 or later. Capacitor Config changes[​](https://capacitorjs.com/docs/v5/updating/3-0#capacitor-config-changes "Direct link to Capacitor Config changes") --------------------------------------------------------------------------------------------------------------------------------------------- If you have TypeScript 3.8+ installed, you can migrate your `capacitor.config.json` to be a typed TypeScript config file named `capacitor.config.ts`. You can continue using a `.json` file, but a typescript config file may give a better developer experience for your team. Below is an example `capacitor.config.ts` file that is used in the [Capacitor Test App](https://github.com/ionic-team/capacitor-testapp) . /// /// /// import { CapacitorConfig } from '@capacitor/cli';const config: CapacitorConfig = { appId: 'com.capacitorjs.app.testapp', appName: 'capacitor-testapp', webDir: 'build', plugins: { SplashScreen: { launchAutoHide: false, }, LocalNotifications: { smallIcon: 'ic_stat_icon_config_sample', iconColor: '#CE0B7C', }, PushNotifications: { presentationOptions: ['alert', 'sound'], }, },};export default config; Official Plugins[​](https://capacitorjs.com/docs/v5/updating/3-0#official-plugins "Direct link to Official Plugins") --------------------------------------------------------------------------------------------------------------------- All plugins have been removed from Capacitor core and placed into their own npm packages. There are several reasons for this (see [#3227](https://github.com/ionic-team/capacitor/issues/3227) ) and the core team is confident this is the right way to go. You can import core plugins like so. import { Camera } from '@capacitor/camera'; ### Background Task, Permissions, and Photos plugins removed[​](https://capacitorjs.com/docs/v5/updating/3-0#background-task-permissions-and-photos-plugins-removed "Direct link to Background Task, Permissions, and Photos plugins removed") * **Background Task**: This plugin appeared to be rarely used and didn't quite work as most devs expected. The core team will readdress background functionality in the future. Subscribe to [#3032](https://github.com/ionic-team/capacitor/issues/3032) for updates. * **Permissions**: The core team has implemented an alternative to this centralized approach which community plugins may also adopt (see the [new Permissions API](https://capacitorjs.com/docs/v5/plugins/web#permissions) ). * **Photos**: This undocumented iOS-only plugin has been removed. Use [`@capacitor-community/media`](https://github.com/capacitor-community/media) . ### Accessibility, App, and Modals plugins split up[​](https://capacitorjs.com/docs/v5/updating/3-0#accessibility-app-and-modals-plugins-split-up "Direct link to Accessibility, App, and Modals plugins split up") * **Accessibility** * VoiceOver and TalkBack functionality moved into [**Screen Reader**](https://capacitorjs.com/docs/v5/apis/screen-reader) * **App** * App-related info and functionality remains in [**App**](https://capacitorjs.com/docs/v5/apis/app) * App URL handling (`openUrl()` and `canOpenUrl()`) moved into [**App Launcher**](https://capacitorjs.com/docs/v5/apis/app-launcher) * **Modals** * Action Sheet functionality (`showActions()`) moved into [**Action Sheet**](https://capacitorjs.com/docs/v5/apis/action-sheet) * Dialog window functionality (`alert()`, `prompt()`, and `confirm()`) moved into [**Dialog**](https://capacitorjs.com/docs/v5/apis/dialog) ### Migrating your app to use the new official plugin packages[​](https://capacitorjs.com/docs/v5/updating/3-0#migrating-your-app-to-use-the-new-official-plugin-packages "Direct link to Migrating your app to use the new official plugin packages") This change will require you to install each plugin that you were using individually. 1. Search your project for core plugins extracted from the `Plugins` object from `@capacitor/core` 2. Find the corresponding [plugin documentation](https://capacitorjs.com/docs/v5/apis) , keeping in mind that [some plugins have been split up](https://capacitorjs.com/docs/v5/updating/3-0#accessibility-app-and-modals-plugins-split-up) 3. Follow the installation instructions for each plugin in the documentation 4. Change the plugin import to import from the plugin's package instead (see [Plugin Imports](https://capacitorjs.com/docs/v5/updating/3-0#plugin-imports) ) 5. Follow any instructions in [Backward Incompatible Plugin Changes](https://capacitorjs.com/docs/v5/updating/3-0#backward-incompatible-plugin-changes) **Using Ionic Framework?** The Ionic Framework makes use of APIs in the following plugins: * [**App**](https://capacitorjs.com/docs/v5/apis/app) * [**Haptics**](https://capacitorjs.com/docs/v5/apis/haptics) * [**Keyboard**](https://capacitorjs.com/docs/v5/apis/keyboard) * [**StatusBar**](https://capacitorjs.com/docs/v5/apis/status-bar) For best user experience with Ionic Framework, you should make sure these plugins are installed even if you don't import them in your app: npm install @capacitor/app @capacitor/haptics @capacitor/keyboard @capacitor/status-bar Plugin Imports[​](https://capacitorjs.com/docs/v5/updating/3-0#plugin-imports "Direct link to Plugin Imports") --------------------------------------------------------------------------------------------------------------- The `Plugins` object is deprecated, but will continue to work in Capacitor 3. Capacitor plugins should be updated to use the new plugin registration APIs (see the [Upgrade Guide for plugins](https://capacitorjs.com/docs/v5/updating/plugins/3-0) ), which will allow them to be imported directly from the plugin's package. Going forward, the `Plugins` object from `@capacitor/core` should not be used. // OLDimport { Plugins } from '@capacitor/core';const { AnyPlugin } = Plugins; Importing the plugin directly from the plugin's package is preferred, but the plugin must be updated to work with Capacitor 3 for this to be possible. // NEWimport { AnyPlugin } from 'any-plugin'; Backward Incompatible Plugin Changes[​](https://capacitorjs.com/docs/v5/updating/3-0#backward-incompatible-plugin-changes "Direct link to Backward Incompatible Plugin Changes") --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- While many of the plugin APIs remain the same to ease the migration process to Capacitor 3, some will require code updates and manual migrations. * **Accessibility** / **Screen Reader** * `isScreenReaderEnabled()` method has been renamed to `isEnabled()` * `'accessibilityScreenReaderStateChange'` event has been renamed to `'stateChange'` * On Android and iOS, `speak()` will only work if a screen reader is currently active. For text-to-speech capabilities while screen readers are active or not, use [`@capacitor-community/text-to-speech`](https://github.com/capacitor-community/text-to-speech) . * **Browser** * `prefetch()` has been removed. * **Device** * App information has been removed from `getInfo()` (`appVersion`, `appBuild`, `appId` and `appName`). Use the App plugin's [`getInfo()`](https://capacitorjs.com/docs/v5/apis/app#getinfo) for this information. * `uuid` has been removed from `getInfo()`. Use the new `getId()` function. * **Haptics** * `HapticsNotificationType` enum keys have been switched from upper case to camel case to match other enums. * **Local Notifications** * This plugin is now using the new Permissions API. `requestPermission()` was removed, use `requestPermissions()`. * **Push Notifications** * This plugin is now using the new Permissions API. `requestPermission()` was removed, use `requestPermissions()`. * **Share** * `share()` method now returns `ShareResult` instead of `any` * The return value of `share()` will no longer include `completed`. If it was not completed, it will reject instead. * **Storage** * **Data migration required!** The internal storage mechanism has changed and requires data migration. A convenience method has been added: `migrate()`. To update your app without affecting end users, call `migrate()` before any other methods. * **Filesystem** * `stat()` method now returns ctime and mtime timestamps in milliseconds on all platforms. Previously, iOS returned timestamps in seconds. Logging Changes[​](https://capacitorjs.com/docs/v5/updating/3-0#logging-changes "Direct link to Logging Changes") ------------------------------------------------------------------------------------------------------------------ The `hideLogs` configuration option has been deprecated in Capacitor 3. It has been replaced by a new `loggingBehavior` configuration option. Details can be found [in the config documentation.](https://capacitorjs.com/docs/v5/config) iOS[​](https://capacitorjs.com/docs/v5/updating/3-0#ios "Direct link to iOS") ------------------------------------------------------------------------------ Capacitor 3 supports iOS 12+. Xcode 12+ is required. CocoaPods 1.8+ is recommended. ### Update CocoaPods[​](https://capacitorjs.com/docs/v5/updating/3-0#update-cocoapods "Direct link to Update CocoaPods") It's recommended to upgrade CocoaPods to the latest stable version. [CocoaPods 1.8](https://blog.cocoapods.org/CocoaPods-1.8.0-beta/) switches to using a CDN, which means running `pod repo update` periodically is no longer required. Check your version of CocoaPods with `pod --version` and visit [cocoapods.org](https://cocoapods.org/) for installation instructions. ### Set iOS deployment target to 12.0[​](https://capacitorjs.com/docs/v5/updating/3-0#set-ios-deployment-target-to-120 "Direct link to Set iOS deployment target to 12.0") Do the following for your Xcode project and app target: open the **Build Settings** tab. Under the **Deployment** section, change **iOS Deployment Target** to **iOS 12.0**. Then, open `ios/App/Podfile` and update the iOS version to 12.0: -platform :ios, '11.0'+platform :ios, '12.0' use_frameworks! ### Set Swift version to 5[​](https://capacitorjs.com/docs/v5/updating/3-0#set-swift-version-to-5 "Direct link to Set Swift version to 5") If your app is not already using Swift 5, open the **Build Settings** tab in your Xcode target, then change **Swift Language Version** to **Swift 5** under the **Swift Compiler - Language** section. ### Move `public` into the iOS target directory[​](https://capacitorjs.com/docs/v5/updating/3-0#move-public-into-the-ios-target-directory "Direct link to move-public-into-the-ios-target-directory") It is recommended in Capacitor 3 to move the `ios/App/public` directory into `ios/App/App/public`. This can be achieved in Xcode: **Remove existing `public` folder** 1. Expand the file tree under the `App` project, then the `App` group, and select the `public` folder. 2. Right-click on **Delete**. When prompted to delete the folder or just remove the reference, select **Move to Trash**. ![delete public folder](https://capacitorjs.com/docs/assets/images/xcode-public-delete-folder-10ef781aa05adc2642e975f616f87751.png) **Recreate `public` in the new location** 1. Right-click on the `App` group inside the `App` project and click **Add Files to "App"...** 2. Leave the default options (ensuring to create folder references, not groups and to add to the `App` target). 3. Click **New Folder**, name it "public". 4. Click **Create**, then **Add**. ![recreate public folder](https://capacitorjs.com/docs/assets/images/xcode-public-new-folder-5ada57e45172c7504f10966da2c3c847.png) It may look the same in Xcode, but the new `public` folder should now be relative to the `App` group, not the project root. **gitignore the new `public` folder** In `ios/.gitignore`, change the ignore path from `App/public` to `App/App/public`. This folder contains a copy of your web assets and should not be committed. App/build App/Pods-App/public+App/App/public App/Podfile.lock xcuserdata ### Update the Capacitor iOS platform[​](https://capacitorjs.com/docs/v5/updating/3-0#update-the-capacitor-ios-platform "Direct link to Update the Capacitor iOS platform") npm install @capacitor/ios@latest-3npx cap sync ios ### Switch from `CAPBridge` to `ApplicationDelegateProxy` in application events[​](https://capacitorjs.com/docs/v5/updating/3-0#switch-from-capbridge-to-applicationdelegateproxy-in-application-events "Direct link to switch-from-capbridge-to-applicationdelegateproxy-in-application-events") In `ios/App/App/AppDelegate.swift`, update the following: func application(_ app: UIApplication, open url: URL, options: [UIApplication.OpenURLOptionsKey: Any] = [:]) -> Bool { // Called when the app was launched with a url. Feel free to add additional processing here, // but if you want the App API to support tracking app url opens, make sure to keep this call- return CAPBridge.handleOpenUrl(url, options)+ return ApplicationDelegateProxy.shared.application(app, open: url, options: options) } func application(_ application: UIApplication, continue userActivity: NSUserActivity, restorationHandler: @escaping ([UIUserActivityRestoring]?) -> Void) -> Bool { // Called when the app was launched with an activity, including Universal Links. // Feel free to add additional processing here, but if you want the App API to support // tracking app url opens, make sure to keep this call- return CAPBridge.handleContinueActivity(userActivity, restorationHandler)+ return ApplicationDelegateProxy.shared.application(application, continue: userActivity, restorationHandler: restorationHandler) } ### Remove USE\_PUSH compilation condition[​](https://capacitorjs.com/docs/v5/updating/3-0#remove-use_push-compilation-condition "Direct link to Remove USE_PUSH compilation condition") If using the push notifications feature, in `ios/App/App/AppDelegate.swift`, update the following: - #if USE_PUSH func application(_ application: UIApplication, didRegisterForRemoteNotificationsWithDeviceToken deviceToken: Data) { NotificationCenter.default.post(name: Notification.Name(CAPNotifications.DidRegisterForRemoteNotificationsWithDeviceToken.name()), object: deviceToken) } func application(_ application: UIApplication, didFailToRegisterForRemoteNotificationsWithError error: Error) { NotificationCenter.default.post(name: Notification.Name(CAPNotifications.DidFailToRegisterForRemoteNotificationsWithError.name()), object: error) }-#endif If not using push notifications you can remove the whole block - #if USE_PUSH-- func application(_ application: UIApplication, didRegisterForRemoteNotificationsWithDeviceToken deviceToken: Data) {- NotificationCenter.default.post(name: Notification.Name(CAPNotifications.DidRegisterForRemoteNotificationsWithDeviceToken.name()), object: deviceToken)- }-- func application(_ application: UIApplication, didFailToRegisterForRemoteNotificationsWithError error: Error) {- NotificationCenter.default.post(name: Notification.Name(CAPNotifications.DidFailToRegisterForRemoteNotificationsWithError.name()), object: error)- }--#endif ### Switch from hard-coded `CAPNotifications` to `NSNotification` extensions[​](https://capacitorjs.com/docs/v5/updating/3-0#switch-from-hard-coded-capnotifications-to-nsnotification-extensions "Direct link to switch-from-hard-coded-capnotifications-to-nsnotification-extensions") In `ios/App/App/AppDelegate.swift`, update the following: override func touchesBegan(_ touches: Set, with event: UIEvent?) { super.touchesBegan(touches, with: event) let statusBarRect = UIApplication.shared.statusBarFrame guard let touchPoint = event?.allTouches?.first?.location(in: self.window) else { return } if statusBarRect.contains(touchPoint) {- NotificationCenter.default.post(CAPBridge.statusBarTappedNotification)+ NotificationCenter.default.post(name: .capacitorStatusBarTapped, object: nil) } } func application(_ application: UIApplication, didRegisterForRemoteNotificationsWithDeviceToken deviceToken: Data) {- NotificationCenter.default.post(name: Notification.Name(CAPNotifications.DidRegisterForRemoteNotificationsWithDeviceToken.name()), object: deviceToken)+ NotificationCenter.default.post(name: .capacitorDidRegisterForRemoteNotifications, object: deviceToken) } func application(_ application: UIApplication, didFailToRegisterForRemoteNotificationsWithError error: Error) {- NotificationCenter.default.post(name: Notification.Name(CAPNotifications.DidFailToRegisterForRemoteNotificationsWithError.name()), object: error)+ NotificationCenter.default.post(name: .capacitorDidFailToRegisterForRemoteNotifications, object: error) } ### Ignore `DerivedData`[​](https://capacitorjs.com/docs/v5/updating/3-0#ignore-deriveddata "Direct link to ignore-deriveddata") Add `DerivedData` to the `ios/.gitignore` file. This is where the Capacitor CLI places native iOS builds. App/Pods App/App/public App/Podfile.lock+DerivedData xcuserdata # Cordova plugins for Capacitor Android[​](https://capacitorjs.com/docs/v5/updating/3-0#android "Direct link to Android") ------------------------------------------------------------------------------------------ Capacitor 3 supports Android 5+ (and now supports Android 11). Android Studio 4+ is required. ### Update the Capacitor Android platform[​](https://capacitorjs.com/docs/v5/updating/3-0#update-the-capacitor-android-platform "Direct link to Update the Capacitor Android platform") npm install @capacitor/android@latest-3npx cap sync android ### Switch to automatic Android plugin loading[​](https://capacitorjs.com/docs/v5/updating/3-0#switch-to-automatic-android-plugin-loading "Direct link to Switch to automatic Android plugin loading") In Capacitor 3, it is preferred to automatically load the Android plugins. In `MainActivity.java`, the `onCreate` method can be removed. You no longer have to edit this file when adding or removing plugins installed via npm. public class MainActivity extends BridgeActivity {- @Override- public void onCreate(Bundle savedInstanceState) {- super.onCreate(savedInstanceState);-- // Initializes the Bridge- this.init(savedInstanceState, new ArrayList>() {{- // Additional plugins you've installed go here- add(Plugin1.class);- add(Plugin2.class);- }});- } } If your app includes custom plugins built specifically for your application, you do still have to register the plugins in `onCreate`: public class MainActivity extends BridgeActivity { @Override public void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState);+ registerPlugin(PluginInMyApp.class); } } ### Update Gradle to 7.0[​](https://capacitorjs.com/docs/v5/updating/3-0#update-gradle-to-70 "Direct link to Update Gradle to 7.0") We now recommend using Gradle 7.0 with Capacitor projects. In Android Studio, open the **File** menu, then click **Project Structure**. In the **Project** section, change **Gradle Version** to **7.0** and **Android Gradle Plugin Version** to **4.2.0**. Then, click **OK**. You may want to evaluate suggested updates to Android packages in the **Suggestions** section of the **Project Structure** dialog. ### Update Android variables[​](https://capacitorjs.com/docs/v5/updating/3-0#update-android-variables "Direct link to Update Android variables") In `android/variables.gradle` you can update the following variables: ext { minSdkVersion = 21- compileSdkVersion = 29- targetSdkVersion = 29+ compileSdkVersion = 30+ targetSdkVersion = 30+ androidxActivityVersion = '1.2.0'- androidxAppCompatVersion = '1.1.0'+ androidxAppCompatVersion = '1.2.0'+ androidxCoordinatorLayoutVersion = '1.1.0'- androidxCoreVersion = '1.2.0'- androidxMaterialVersion = '1.1.0-rc02'- androidxBrowserVersion = '1.2.0'- androidxLocalbroadcastmanagerVersion = '1.0.0'- androidxExifInterfaceVersion = '1.2.0'- firebaseMessagingVersion = '20.1.2'- playServicesLocationVersion = '17.0.0'+ androidxCoreVersion = '1.3.2'+ androidxFragmentVersion = '1.3.0'- junitVersion = '4.12'- androidxJunitVersion = '1.1.1'- androidxEspressoCoreVersion = '3.2.0'+ junitVersion = '4.13.1'+ androidxJunitVersion = '1.1.2'+ androidxEspressoCoreVersion = '3.3.0' cordovaAndroidVersion = '7.0.0' } Capacitor 3 supports Android 11 (API 30), so you can update your SDK target to 30. Change `compileSdkVersion` and `targetSdkVersion` to `30`. A new `androidxActivityVersion` variable is available, add it with value `1.2.0`. The `androidxAppCompatVersion` can be updated to `1.2.0`. A new `androidxCoordinatorLayoutVersion` variable is available, add it with value `1.1.0`. The `androidxCoreVersion` can be updated to `1.3.2`. The `androidxMaterialVersion` variable was used by Action Sheet and Camera plugins, can be removed if not using them. If using them, check [Camera docs](https://capacitorjs.com/docs/v3/apis/camera#variables) and [Action Sheet docs](https://capacitorjs.com/docs/v3/apis/action-sheet#variables) . The `androidxBrowserVersion` variable was used by Browser plugin, can be removed if not using the plugin. If using the plugin, check the [docs](https://capacitorjs.com/docs/v3/apis/browser#variables) . The `androidxLocalbroadcastmanagerVersion` variable can be removed. The `androidxExifInterfaceVersion` variable was used by Camera plugin, can be removed if not using the plugin. If using the plugin, check the [docs](https://capacitorjs.com/docs/v3/apis/camera#variables) . The `firebaseMessagingVersion` variable was used by Push Notifications plugin, can be removed if not using the plugin. If using the plugin, check the [docs](https://capacitorjs.com/docs/v3/apis/push-notifications#variables) . The `playServicesLocationVersion` variable was used by Geolocation plugin, can be removed if not using the plugin. If using the plugin, check the [docs](https://capacitorjs.com/docs/v3/apis/geolocation#variables) . A new `androidxFragmentVersion` variable is available, add it with value `1.3.0`. The `junitVersion` can be updated to `4.13.1`. The `androidxJunitVersion` can be updated to `1.1.2`. The `androidxEspressoCoreVersion` can be updated to `3.3.0`. ### Remove unused and redundant permissions[​](https://capacitorjs.com/docs/v5/updating/3-0#remove-unused-and-redundant-permissions "Direct link to Remove unused and redundant permissions") Depending on which plugins you are using, you can optionally remove unused permissions from your app's `AndroidManifest.xml` file. [The manifest in new Capacitor apps](https://github.com/ionic-team/capacitor/blob/5.x/android-template/app/src/main/AndroidManifest.xml) only includes `INTERNET` because permissions are now meant to be added when plugins are installed. Follow these steps to remove unused permissions: 1. Determine the plugins that your app uses 2. Read the installation instructions of each plugin [in these docs](https://capacitorjs.com/docs/v5/apis) , looking for permissions that each plugin requires 3. In your app's `AndroidManifest.xml` file, keep permissions that your plugins require, remove permissions that are unused The Haptics and Network plugins are examples of plugins that now include their install-time permissions in their own `AndroidManifest.xml` files, which end up [being merged](https://developer.android.com/studio/build/manifest-merge) with your app's. It is safe to remove their permissions from your app's `AndroidManifest.xml` file: - - - - Contents -------- * [NodeJS 12+](https://capacitorjs.com/docs/v5/updating/3-0#nodejs-12) * [Ionic CLI](https://capacitorjs.com/docs/v5/updating/3-0#ionic-cli) * [Update Capacitor CLI and Core](https://capacitorjs.com/docs/v5/updating/3-0#update-capacitor-cli-and-core) * [ES2017+](https://capacitorjs.com/docs/v5/updating/3-0#es2017) * [TypeScript 3.8+](https://capacitorjs.com/docs/v5/updating/3-0#typescript-38) * [Capacitor Config changes](https://capacitorjs.com/docs/v5/updating/3-0#capacitor-config-changes) * [Official Plugins](https://capacitorjs.com/docs/v5/updating/3-0#official-plugins) * [Background Task, Permissions, and Photos plugins removed](https://capacitorjs.com/docs/v5/updating/3-0#background-task-permissions-and-photos-plugins-removed) * [Accessibility, App, and Modals plugins split up](https://capacitorjs.com/docs/v5/updating/3-0#accessibility-app-and-modals-plugins-split-up) * [Migrating your app to use the new official plugin packages](https://capacitorjs.com/docs/v5/updating/3-0#migrating-your-app-to-use-the-new-official-plugin-packages) * [Plugin Imports](https://capacitorjs.com/docs/v5/updating/3-0#plugin-imports) * [Backward Incompatible Plugin Changes](https://capacitorjs.com/docs/v5/updating/3-0#backward-incompatible-plugin-changes) * [Logging Changes](https://capacitorjs.com/docs/v5/updating/3-0#logging-changes) * [iOS](https://capacitorjs.com/docs/v5/updating/3-0#ios) * [Update CocoaPods](https://capacitorjs.com/docs/v5/updating/3-0#update-cocoapods) * [Set iOS deployment target to 12.0](https://capacitorjs.com/docs/v5/updating/3-0#set-ios-deployment-target-to-120) * [Set Swift version to 5](https://capacitorjs.com/docs/v5/updating/3-0#set-swift-version-to-5) * [Move `public` into the iOS target directory](https://capacitorjs.com/docs/v5/updating/3-0#move-public-into-the-ios-target-directory) * [Update the Capacitor iOS platform](https://capacitorjs.com/docs/v5/updating/3-0#update-the-capacitor-ios-platform) * [Switch from `CAPBridge` to `ApplicationDelegateProxy` in application events](https://capacitorjs.com/docs/v5/updating/3-0#switch-from-capbridge-to-applicationdelegateproxy-in-application-events) * [Remove USE\_PUSH compilation condition](https://capacitorjs.com/docs/v5/updating/3-0#remove-use_push-compilation-condition) * [Switch from hard-coded `CAPNotifications` to `NSNotification` extensions](https://capacitorjs.com/docs/v5/updating/3-0#switch-from-hard-coded-capnotifications-to-nsnotification-extensions) * [Ignore `DerivedData`](https://capacitorjs.com/docs/v5/updating/3-0#ignore-deriveddata) * [Android](https://capacitorjs.com/docs/v5/updating/3-0#android) * [Update the Capacitor Android platform](https://capacitorjs.com/docs/v5/updating/3-0#update-the-capacitor-android-platform) * [Switch to automatic Android plugin loading](https://capacitorjs.com/docs/v5/updating/3-0#switch-to-automatic-android-plugin-loading) * [Update Gradle to 7.0](https://capacitorjs.com/docs/v5/updating/3-0#update-gradle-to-70) * [Update Android variables](https://capacitorjs.com/docs/v5/updating/3-0#update-android-variables) * [Remove unused and redundant permissions](https://capacitorjs.com/docs/v5/updating/3-0#remove-unused-and-redundant-permissions) * * * [Edit this page](https://github.com/ionic-team/capacitor-docs/edit/main/versioned_docs/version-v5/main/updating/3-0.md) --- # Updating to 4.0 | Capacitor Documentation [Skip to main content](https://capacitorjs.com/docs/v5/updating/4-0#__docusaurus_skipToContent_fallback) [An **OutSystems** Company →](https://www.outsystems.com/?utm_source=ionic&utm_medium=referral&utm_campaign=ionic-referral&utm_term=none&utm_content=other&utm_campaignteam=digital-mktg&utm_partner=none) This is documentation for Capacitor Documentation **v5**, which is no longer actively maintained. For up-to-date documentation, see the **[latest version](https://capacitorjs.com/docs/updating/4-0) ** (v7). Version: v5 On this page Compared to previous upgrades, the breaking changes between Capacitor 3 and 4 are fairly minimal. In this guide, you'll find steps to update your project to the current Capacitor 4 version as well as a list of breaking changes for our official plugins. Using the CLI to Migrate[​](https://capacitorjs.com/docs/v5/updating/4-0#using-the-cli-to-migrate "Direct link to Using the CLI to Migrate") --------------------------------------------------------------------------------------------------------------------------------------------- Install the latest version of the Capacitor CLI to your project using `npm i -D @capacitor/cli@latest-4`. Once installed, simply run `npx cap migrate` to have the CLI handle the migration for you. If any of the steps for the migration are not able to be completed, additional information will be made available in the output in the terminal. The steps for doing the migration manually are listed out below. iOS[​](https://capacitorjs.com/docs/v5/updating/4-0#ios "Direct link to iOS") ------------------------------------------------------------------------------ The following guide describes how to upgrade your Capacitor 3 iOS project to Capacitor 4. ### Raise iOS Deployment Target[​](https://capacitorjs.com/docs/v5/updating/4-0#raise-ios-deployment-target "Direct link to Raise iOS Deployment Target") Do the following for your Xcode project: select the **Project** within the project editor and open the **Build Settings** tab. Under the **Deployment** section, change **iOS Deployment Target** to **iOS 13.0**. Repeat the same steps for any app **Targets**. Then, open `ios/App/Podfile` and follow these steps: 1. Add this on the first line: require_relative '../../node_modules/@capacitor/ios/scripts/pods_helpers' 2. Update the iOS version to 13.0: platform :ios, '13.0' 3. Add this block on the last line: post_install do |installer| assertDeploymentTarget(installer)end ### Remove Unnecessary Code[​](https://capacitorjs.com/docs/v5/updating/4-0#remove-unnecessary-code "Direct link to Remove Unnecessary Code") Remove unused `touchesBegan` method from `AppDelegate.swift` -override func touchesBegan(_ touches: Set, with event: UIEvent?) {- super.touchesBegan(touches, with: event)-- let statusBarRect = UIApplication.shared.statusBarFrame- guard let touchPoint = event?.allTouches?.first?.location(in: self.window) else { return }-- if statusBarRect.contains(touchPoint) {- NotificationCenter.default.post(name: .capacitorStatusBarTapped, object: nil)- }-} ### Optional: Remove NSAppTransportSecurity entry from Info.plist[​](https://capacitorjs.com/docs/v5/updating/4-0#optional-remove-nsapptransportsecurity-entry-from-infoplist "Direct link to Optional: Remove NSAppTransportSecurity entry from Info.plist") `NSAppTransportSecurity` is only used for live reload, if you are not using live reload or you are using Ionic CLI for live reload you no longer need this entry. -NSAppTransportSecurity-- NSAllowsArbitraryLoads- - Android[​](https://capacitorjs.com/docs/v5/updating/4-0#android "Direct link to Android") ------------------------------------------------------------------------------------------ The following guide describes how to upgrade your Capacitor 3 Android project to Capacitor 4. ### Update Android Project Variables[​](https://capacitorjs.com/docs/v5/updating/4-0#update-android-project-variables "Direct link to Update Android Project Variables") In your `variables.gradle` file, update your values to the following new minimums and add the new `coreSplashScreenVersion` and `androidxWebkitVersion` minSdkVersion = 22compileSdkVersion = 32targetSdkVersion = 32androidxActivityVersion = '1.4.0'androidxAppCompatVersion = '1.4.2'androidxCoordinatorLayoutVersion = '1.2.0'androidxCoreVersion = '1.8.0'androidxFragmentVersion = '1.4.1'coreSplashScreenVersion = '1.0.0-rc01'androidxWebkitVersion = '1.4.0'junitVersion = '4.13.2'androidxJunitVersion = '1.1.3'androidxEspressoCoreVersion = '3.4.0'cordovaAndroidVersion = '10.1.1' ### Add `android:exported` tag to your Android Manifest[​](https://capacitorjs.com/docs/v5/updating/4-0#add-androidexported-tag-to-your-android-manifest "Direct link to add-androidexported-tag-to-your-android-manifest") In your `AndroidManifest.xml` file, you'll need to add the following line to the `` tag. android:exported="true" This tag ensures that you can open this "Activity," or screen, in your app. For more information on this and other tags, check out [Android's `` reference documentation](https://developer.android.com/guide/topics/manifest/activity-element?hl=en) . info By default, your `AndroidManifest.xml` will be located in `android/app/src/main/AndroidManifest.xml`. ### Update Gradle Google Services plugin[​](https://capacitorjs.com/docs/v5/updating/4-0#update-gradle-google-services-plugin "Direct link to Update Gradle Google Services plugin") In `android/build.gradle` file change `classpath 'com.google.gms:google-services:4.3.5'` to `classpath 'com.google.gms:google-services:4.3.13'` to update Google Services plugin. ### Update to Gradle 7[​](https://capacitorjs.com/docs/v5/updating/4-0#update-to-gradle-7 "Direct link to Update to Gradle 7") Adjust your Gradle project settings in `File > Project Structure > Project`. The Android Gradle Plugin Version should be 7.2.1 or later and the Gradle Version should be 7.4.2 or later. Apply these changes and run a gradle sync by clicking on the Elephant Icon in the top right of Android Studio info Android Studio may provide an automatic migration to Gradle 7. Go ahead and take them up on the offer! To upgrade, go to your `build.gradle` file, and click on the 💡 icon, and click "Upgrade Gradle. Once your project is migrated over, run a gradle sync as described above. Another alternative would be to use the Android Gradle Plugin Upgrade Assistant to handle the migration for you. Steps for this tool can be found in the [Android documentation](https://developer.android.com/studio/build/agp-upgrade-assistant) . ### Ensure you are using Java 11[​](https://capacitorjs.com/docs/v5/updating/4-0#ensure-you-are-using-java-11 "Direct link to Ensure you are using Java 11") Capacitor 3 works with both Java 8 and Java 11. Moving forward, Capacitor 4 will only support Java 11. You can change this in your project by going to the following menu in Android Studio: `Preferences > Build, Execution, Deployment > Build Tools > Gradle` ![Gradle preferences](https://capacitorjs.com/docs/assets/images/android-java-11-3a689fb5f10e972db655982aa0e8c0eb.png) From there, you can modify the "Gradle JDK" to be Java 11. info Java 11 ships with the latest version of Android Studio. No additional downloads needed! ### Switch to automatic Android plugin loading[​](https://capacitorjs.com/docs/v5/updating/4-0#switch-to-automatic-android-plugin-loading "Direct link to Switch to automatic Android plugin loading") This was an optional change in Capacitor 3, but it's now mandatory for the Capacitor 4 upgrade since the init method has been removed. In `MainActivity.java`, the `onCreate` method can be removed. You no longer have to edit this file when adding or removing plugins installed via npm. public class MainActivity extends BridgeActivity {- @Override- public void onCreate(Bundle savedInstanceState) {- super.onCreate(savedInstanceState);-- // Initializes the Bridge- this.init(savedInstanceState, new ArrayList>() {{- // Additional plugins you've installed go here- add(Plugin1.class);- add(Plugin2.class);- }});- } } ### Change registerPlugin order[​](https://capacitorjs.com/docs/v5/updating/4-0#change-registerplugin-order "Direct link to Change registerPlugin order") If your app includes custom plugins built specifically for your application, you have to register them before `super.onCreate`: public class MainActivity extends BridgeActivity { @Override public void onCreate(Bundle savedInstanceState) {+ registerPlugin(PluginInMyApp.class); super.onCreate(savedInstanceState);- registerPlugin(PluginInMyApp.class); } } ### Optional: Use the new Android 12 Splash Screen API[​](https://capacitorjs.com/docs/v5/updating/4-0#optional-use-the-new-android-12-splash-screen-api "Direct link to Optional: Use the new Android 12 Splash Screen API") To enable the new recommended **[Android 12 Splash Screen API](https://developer.android.com/guide/topics/ui/splash-screen) ** this change is required: * In `android/app/src/main/res/values/styles.xml`, edit the theme `parent` attribute on the `AppTheme.NoActionBarLaunch` Theme from `AppTheme.NoActionBar` to `Theme.SplashScreen` and add desired options to the theme. Not enabling the Android 12 Splash Screen will result in a double Splash Screen on Android 12+ devices and will use the old Splash Screen on older devices. This change is optional but recommended to prevent Android Studio from showing `Cannot resolve symbol 'Theme.SplashScreen'` message after the previous change. * Add `implementation "androidx.core:core-splashscreen:$coreSplashScreenVersion"` in the dependencies section of `android/app/build.gradle`. ### Optional: Use a DayNight theme[​](https://capacitorjs.com/docs/v5/updating/4-0#optional-use-a-daynight-theme "Direct link to Optional: Use a DayNight theme") To benefit from automatic theme change (Dark/Light themes) based on the user's device theme, change ` Not enabling the Android 12 Splash Screen will result in a double Splash Screen on Android 12+ devices and will use the old Splash Screen on older devices. This change is optional but recommended to prevent Android Studio from showing `Cannot resolve symbol 'Theme.SplashScreen'` message after the previous change. * Add `implementation "androidx.core:core-splashscreen:$coreSplashScreenVersion"` in the dependencies section of `android/app/build.gradle`. ### Optional: Use a DayNight theme[​](https://capacitorjs.com/docs/updating/4-0#optional-use-a-daynight-theme "Direct link to Optional: Use a DayNight theme") To benefit from automatic theme change (Dark/Light themes) based on the user's device theme, change `