Skip to main content
Version: v9

Updating Capacitor to 9.0 in your plugin

note

This guide covers plugin-author changes. If you're updating an app, see Updating to 9.0 instead.

note

Capacitor 9 hasn't reached general availability yet. Dependency versions below point at the next dist-tag / current alpha; once 9.0.0 ships, use a normal ^9.0.0 range instead.

Using @capacitor/plugin-migration-v8-to-v9

From the plugin folder, run npx @capacitor/plugin-migration-v8-to-v9@latest and it will perform most of the file changes automatically.

Updating the files manually

Updating Capacitor dependencies

Update @capacitor/cli, @capacitor/core, @capacitor/android and @capacitor/ios in devDependencies to next. Update @capacitor/core in peerDependencies to >=9.0.0-alpha.1 (check npm for the current alpha, since it moves forward regularly).

Cordova support is now optional

Capacitor's Cordova compatibility layer is now only wired into a consuming app when that app actually has a Cordova plugin installed, on both Android and iOS. If your plugin's own native code directly references symbols from Capacitor's Cordova compatibility layer (for example com.getcapacitor.cordova.CordovaPlugin on Android), be aware that layer may not be present in a consuming app that has no Cordova plugins. There is currently no configuration option to force it to be included.

If your plugin is SPM compatible, also remove the unconditional Cordova product dependency from your Package.swift — it's no longer guaranteed to be present in every consumer:

    dependencies: [
.product(name: "Capacitor", package: "capacitor-swift-pm"),
- .product(name: "Cordova", package: "capacitor-swift-pm"),
]

Update Android Plugin Variables

In your build.gradle file, update the following package versions:

ext {
// Note: Some of the following dependencies are optional - only add/update the ones your plugin actually uses.
// If you use any of these dependencies, update them to the versions shown below.
junitVersion = project.hasProperty('junitVersion') ? rootProject.ext.junitVersion : '4.13.2'
androidxAppCompatVersion = project.hasProperty('androidxAppCompatVersion') ? rootProject.ext.androidxAppCompatVersion : '1.7.1'
androidxJunitVersion = project.hasProperty('androidxJunitVersion') ? rootProject.ext.androidxJunitVersion : '1.3.0'
androidxEspressoCoreVersion = project.hasProperty('androidxEspressoCoreVersion') ? rootProject.ext.androidxEspressoCoreVersion : '3.7.0'
- androidxActivityVersion = project.hasProperty('androidxActivityVersion') ? rootProject.ext.androidxActivityVersion : '1.11.0'
+ androidxActivityVersion = project.hasProperty('androidxActivityVersion') ? rootProject.ext.androidxActivityVersion : '1.13.0'
androidxCoordinatorLayoutVersion = project.hasProperty('androidxCoordinatorLayoutVersion') ? rootProject.ext.androidxCoordinatorLayoutVersion : '1.3.0'
- androidxCoreVersion = project.hasProperty('androidxCoreVersion') ? rootProject.ext.androidxCoreVersion : '1.17.0'
+ androidxCoreVersion = project.hasProperty('androidxCoreVersion') ? rootProject.ext.androidxCoreVersion : '1.19.0'
androidxFragmentVersion = project.hasProperty('androidxFragmentVersion') ? rootProject.ext.androidxFragmentVersion : '1.8.9'
firebaseMessagingVersion = project.hasProperty('firebaseMessagingVersion') ? rootProject.ext.firebaseMessagingVersion : '25.0.1'
- playServicesLocationVersion = project.hasProperty('playServicesLocationVersion') ? rootProject.ext.playServicesLocationVersion : '21.3.0'
+ playServicesLocationVersion = project.hasProperty('playServicesLocationVersion') ? rootProject.ext.playServicesLocationVersion : '21.4.0'
- androidxBrowserVersion = project.hasProperty('androidxBrowserVersion') ? rootProject.ext.androidxBrowserVersion : '1.9.0'
+ androidxBrowserVersion = project.hasProperty('androidxBrowserVersion') ? rootProject.ext.androidxBrowserVersion : '1.10.0'
- androidxMaterialVersion = project.hasProperty('androidxMaterialVersion') ? rootProject.ext.androidxMaterialVersion : '1.13.0'
+ androidxMaterialVersion = project.hasProperty('androidxMaterialVersion') ? rootProject.ext.androidxMaterialVersion : '1.14.0'
- androidxExifInterfaceVersion = project.hasProperty('androidxExifInterfaceVersion') ? rootProject.ext.androidxExifInterfaceVersion : '1.4.1'
+ androidxExifInterfaceVersion = project.hasProperty('androidxExifInterfaceVersion') ? rootProject.ext.androidxExifInterfaceVersion : '1.4.2'
coreSplashScreenVersion = project.hasProperty('coreSplashScreenVersion') ? rootProject.ext.coreSplashScreenVersion : '1.2.0'
- androidxWebkitVersion = project.hasProperty('androidxWebkitVersion') ? rootProject.ext.androidxWebkitVersion : '1.14.0'
+ androidxWebkitVersion = project.hasProperty('androidxWebkitVersion') ? rootProject.ext.androidxWebkitVersion : '1.16.0'
- googleMapsPlayServicesVersion = project.hasProperty('googleMapsPlayServicesVersion') ? rootProject.ext.googleMapsPlayServicesVersion : '19.2.0'
+ googleMapsPlayServicesVersion = project.hasProperty('googleMapsPlayServicesVersion') ? rootProject.ext.googleMapsPlayServicesVersion : '20.0.0'
- googleMapsUtilsVersion = project.hasProperty('googleMapsUtilsVersion') ? rootProject.ext.googleMapsUtilsVersion : '3.19.1'
+ googleMapsUtilsVersion = project.hasProperty('googleMapsUtilsVersion') ? rootProject.ext.googleMapsUtilsVersion : '5.0.0'
- googleMapsKtxVersion = project.hasProperty('googleMapsKtxVersion') ? rootProject.ext.googleMapsKtxVersion : '5.2.1'
- googleMapsUtilsKtxVersion = project.hasProperty('googleMapsUtilsKtxVersion') ? rootProject.ext.googleMapsUtilsKtxVersion : '5.2.1'
+ googleMapsKtxVersion = project.hasProperty('googleMapsKtxVersion') ? rootProject.ext.googleMapsKtxVersion : '6.0.1'
+ googleMapsUtilsKtxVersion = project.hasProperty('googleMapsUtilsKtxVersion') ? rootProject.ext.googleMapsUtilsKtxVersion : '6.0.1'
- kotlinxCoroutinesVersion = project.hasProperty('kotlinxCoroutinesVersion') ? rootProject.ext.kotlinxCoroutinesVersion : '1.10.2'
+ kotlinxCoroutinesVersion = project.hasProperty('kotlinxCoroutinesVersion') ? rootProject.ext.kotlinxCoroutinesVersion : '1.11.0'
}

googleMapsUtilsVersion 5.0.0 includes upstream breaking changes to the Google Maps Utils API; check your usage against the Google Maps Android Utility Library release notes if your plugin depends on it directly.

Migrate core-ktx to core

androidx.core:core 1.19.0 merges every extension function previously shipped in core-ktx into core itself, turning core-ktx into an empty compatibility artifact. Drop the separate androidxCoreKTXVersion variable (reuse androidxCoreVersion instead) and depend on core rather than core-ktx:

dependencies {
- implementation "androidx.core:core-ktx:$androidxCoreVersion"
+ implementation "androidx.core:core:$androidxCoreVersion"
}

Remove targetSdkVersion, update minSdk / compileSdk

AGP 9 infers targetSdkVersion from compileSdkVersion when it isn't set, and on a library module (which is what your plugin's android/build.gradle is) targetSdkVersion has no runtime effect anyway, so drop it entirely:

# build.gradle

android {
- compileSdk project.hasProperty('compileSdkVersion') ? rootProject.ext.compileSdkVersion : 36
+ compileSdk = project.hasProperty('compileSdkVersion') ? rootProject.ext.compileSdkVersion : 37
defaultConfig {
- minSdkVersion project.hasProperty('minSdkVersion') ? rootProject.ext.minSdkVersion : 24
+ minSdkVersion = project.hasProperty('minSdkVersion') ? rootProject.ext.minSdkVersion : 26
- targetSdkVersion project.hasProperty('targetSdkVersion') ? rootProject.ext.targetSdkVersion : 36
}
}

Remove the standalone Kotlin plugin

AGP 9 bundles the Kotlin Gradle Plugin natively (Kotlin 2.2.10) instead of requiring it to be applied separately. If your plugin still applies kotlin-android (or org.jetbrains.kotlin.android) and declares its own kotlin_version/kotlin-stdlib/kotlin-gradle-plugin, remove them, otherwise you'll hit a duplicate-plugin build failure:

buildscript {
- ext.kotlin_version = project.hasProperty("kotlin_version") ? rootProject.ext.kotlin_version : '2.2.20'
repositories {
google()
mavenCentral()
}
dependencies {
classpath 'com.android.tools.build:gradle:9.2.1'
- classpath "org.jetbrains.kotlin:kotlin-gradle-plugin:$kotlin_version"
}
}
-apply plugin: 'kotlin-android'

dependencies {
- implementation "org.jetbrains.kotlin:kotlin-stdlib:$kotlin_version"
}

Give your plugin a unique Android namespace

AGP 9 defaults android.uniquePackageNames to true: if your plugin's Android namespace collides with another library module in the same app (most commonly a leftover scaffold default, or a fork that kept the original plugin's namespace), the build now fails instead of silently working. Make sure your namespace in build.gradle is unique to your plugin.

Remove jcenter()

Gradle 9 fully removes the jcenter() repository helper (redirected to Maven Central since 2024). Any build.gradle that still calls it fails at Gradle configuration time:

repositories {
google()
- jcenter()
+ mavenCentral()
}

Update gradle plugin to 9.2.1

    dependencies {
- classpath 'com.android.tools.build:gradle:8.13.0'
+ classpath 'com.android.tools.build:gradle:9.2.1'
}

Update gradle wrapper to 9.5.1

# gradle-wrapper.properties

distributionBase=GRADLE_USER_HOME
distributionPath=wrapper/dists
- distributionUrl=https\://services.gradle.org/distributions/gradle-8.14.3-all.zip
+ distributionUrl=https\://services.gradle.org/distributions/gradle-9.5.1-all.zip
zipStoreBase=GRADLE_USER_HOME
zipStorePath=wrapper/dists

Update google services plugin

# build.gradle

dependencies {
classpath 'com.android.tools.build:gradle:9.2.1'
- classpath 'com.google.gms:google-services:4.4.4'
+ classpath 'com.google.gms:google-services:4.5.0'

Raise iOS Deployment Target to 16

Update your plugin's .podspec file:

-  s.ios.deployment_target = '15.0'
+ s.ios.deployment_target = '16.0'

SPM compatible plugins

Update Package.swift file:

-    platforms: [.iOS(.v15)],
+ platforms: [.iOS(.v16)],

Plugins with old structure

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 16.0. Repeat the same steps for any app Targets.

Then, open ios/Podfile and update the iOS version to 16.0:

-platform :ios, '15.0'
+platform :ios, '16.0'

Update Capacitor SPM dependency

In SPM compatible plugins, update Package.swift file to point at the current Capacitor 9 alpha (Capacitor 9 hasn't shipped a stable release yet, so this isn't a plain 9.0.0 version):

    dependencies: [
- .package(url: "https://github.com/ionic-team/capacitor-swift-pm.git", from: "8.0.0")
+ .package(url: "https://github.com/ionic-team/capacitor-swift-pm.git", from: "9.0.0-alpha.1")
],