Updating Capacitor to 9.0 in your plugin
This guide covers plugin-author changes. If you're updating an app, see Updating to 9.0 instead.
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")
],