Flutter 3.41 is live! Check out theFlutter 3.41 blog post!
Swift Package Manager for plugin authors
How to add Swift Package Manager compatibility to iOS and macOS plugins
Flutter is migrating toSwift Package Manager to manage iOS and macOS native dependencies. Flutter's support of Swift Package Manager is under development. If you find a bug in Flutter's Swift Package Manager support,open an issue. Swift Package Manager support isoff by default. Flutter continues to support CocoaPods.
Flutter's Swift Package Manager integration has several benefits:
- Provides access to the Swift package ecosystem. Flutter plugins can use the growing ecosystem ofSwift packages!
- Simplifies Flutter installation. Swift Package Manager is bundled with Xcode. In the future, you won’t need to install Ruby and CocoaPods to target iOS or macOS.
How to turn on Swift Package Manager
#Flutter's Swift Package Manager support is turned off by default. To turn it on:
Upgrade to the latest Flutter SDK:
shflutter upgradeTurn on the Swift Package Manager feature:
shflutter config --enable-swift-package-manager
Using the Flutter CLI to run an appmigrates the project to add Swift Package Manager integration. This makes your project download the Swift packages that your Flutter plugins depend on. An app with Swift Package Manager integration requires Flutter version 3.24 or higher. To use an older Flutter version, you will need toremove Swift Package Manager integration from the app.
Flutter falls back to CocoaPods for dependencies that do not support Swift Package Manager yet.
How to turn off Swift Package Manager
#Plugin authors need to turn on and off Flutter's Swift Package Manager support for testing. App developers do not need to disable Swift Package Manager support, unless they are running into issues.
If you find a bug in Flutter's Swift Package Manager support,open an issue.
Disabling Swift Package Manager causes Flutter to use CocoaPods for all dependencies. However, Swift Package Manager remains integrated with your project. To remove Swift Package Manager integration completely from your project, follow theHow to remove Swift Package Manager integration instructions.
Turn off for a single project
# In the project'spubspec.yaml file, under theflutter section, setenable-swift-package-manager tofalse in theconfig subsection.
# The following section is specific to Flutter packages.flutter:config:enable-swift-package-manager:falseThis turns off Swift Package Manager for all contributors to this project.
If you were previously usingdisable-swift-package-manager: true, update yourpubspec.yaml to use the newconfig section format shown above. The old syntax is deprecated and will produce an error in Flutter 3.38 and later.
Turn off globally for all projects
#Run the following command:
flutter config --no-enable-swift-package-managerThis turns off Swift Package Manager for the current user.
If a project is incompatible with Swift Package Manager, all contributors need to run this command.
How to add Swift Package Manager support to an existing Flutter plugin
#This guide shows how to add Swift Package Manager support to a plugin that already supports CocoaPods. This ensures the plugin is usable by all Flutter projects.
Flutter plugins should supportboth Swift Package Manager and CocoaPods until further notice.
Swift Package Manager adoption will be gradual. Plugins that don't support CocoaPods won't be usable by projects that haven't migrated to Swift Package Manager yet. Plugins that don't support Swift Package Manager can cause problems for projects that have migrated.
Replaceplugin_name throughout this guide with the name of your plugin. The example below usesios, replaceios withmacos/darwin as applicable.
Start by creating a directory under the
ios,macos, and/ordarwindirectories. Name this new directory the name of the platform package.plugin_name/
ios/
- …
- plugin_name/
Within this new directory, create the following files/directories:
Package.swift(file)Sources(directory)Sources/plugin_name(directory)
Your plugin should look like:
plugin_name/
ios/
- …
plugin_name/
- Package.swift
Sources/
- plugin_name/
Use the following template in the
Package.swiftfile:Package.swiftswift// swift-tools-version: 5.9// The swift-tools-version declares the minimum version of Swift required to build this package.importPackageDescriptionletpackage=Package(// TODO: Update your plugin name.name:"plugin_name",platforms:[// TODO: Update the platforms your plugin supports.// If your plugin only supports iOS, remove `.macOS(...)`.// If your plugin only supports macOS, remove `.iOS(...)`..iOS("13.0"),.macOS("10.15")],products:[// TODO: Update your library and target names.// If the plugin name contains "_", replace with "-" for the library name..library(name:"plugin-name",targets:["plugin_name"])],dependencies:[],targets:[.target(// TODO: Update your target name.name:"plugin_name",dependencies:[],resources:[// TODO: If your plugin requires a privacy manifest// (e.g. if it uses any required reason APIs), update the PrivacyInfo.xcprivacy file// to describe your plugin's privacy impact, and then uncomment this line.// For more information, see:// https://developer.apple.com/documentation/bundleresources/privacy_manifest_files// .process("PrivacyInfo.xcprivacy"),// TODO: If you have other resources that need to be bundled with your plugin, refer to// the following instructions to add them:// https://developer.apple.com/documentation/xcode/bundling-resources-with-a-swift-package])])Update thesupported platforms in your
Package.swiftfile.Package.swiftswiftplatforms:[// TODO: Update the platforms your plugin supports.// If your plugin only supports iOS, remove `.macOS(...)`.// If your plugin only supports macOS, remove `.iOS(...)`..iOS("13.0"),.macOS("10.15")],Update the package, library, and target names in your
Package.swiftfile.Package.swiftswiftletpackage=Package(// TODO: Update your plugin name.name:"plugin_name",platforms:[.iOS("13.0"),.macOS("10.15")],products:[// TODO: Update your library and target names.// If the plugin name contains "_", replace with "-" for the library name.library(name:"plugin-name",targets:["plugin_name"])],dependencies:[],targets:[.target(// TODO: Update your target name.name:"plugin_name",dependencies:[],resources:[// TODO: If your plugin requires a privacy manifest// (e.g. if it uses any required reason APIs), update the PrivacyInfo.xcprivacy file// to describe your plugin's privacy impact, and then uncomment this line.// For more information, see:// https://developer.apple.com/documentation/bundleresources/privacy_manifest_files// .process("PrivacyInfo.xcprivacy"),// TODO: If you have other resources that need to be bundled with your plugin, refer to// the following instructions to add them:// https://developer.apple.com/documentation/xcode/bundling-resources-with-a-swift-package])])NoteIf the plugin name contains
_, the library name must be a-separated version of the plugin name.If your plugin has a
PrivacyInfo.xcprivacyfile, move it toios/plugin_name/Sources/plugin_name/PrivacyInfo.xcprivacyand uncomment the resource in thePackage.swiftfile.Package.swiftswiftresources:[// TODO: If your plugin requires a privacy manifest// (e.g. if it uses any required reason APIs), update the PrivacyInfo.xcprivacy file// to describe your plugin's privacy impact, and then uncomment this line.// For more information, see:// https://developer.apple.com/documentation/bundleresources/privacy_manifest_files.process("PrivacyInfo.xcprivacy"),// TODO: If you have other resources that need to be bundled with your plugin, refer to// the following instructions to add them:// https://developer.apple.com/documentation/xcode/bundling-resources-with-a-swift-package],Move any resource files from
ios/Assetstoios/plugin_name/Sources/plugin_name(or a subdirectory). Add the resource files to yourPackage.swiftfile, if applicable. For more instructions, seehttps://developer.apple.com/documentation/xcode/bundling-resources-with-a-swift-package.Move all files from
ios/Classestoios/plugin_name/Sources/plugin_name.The
ios/Assets,ios/Resources, andios/Classesdirectories should now be empty and can be deleted.If your plugin usesPigeon, update your Pigeon input file.
pigeons/messages.dartdartkotlinOptions:KotlinOptions(),javaOut:'android/app/src/main/java/io/flutter/plugins/Messages.java',javaOptions:JavaOptions(),swiftOut:'ios/Classes/messages.g.swift',swiftOut:'ios/plugin_name/Sources/plugin_name/messages.g.swift',swiftOptions:SwiftOptions(),Update your
Package.swiftfile with any customizations you might need.Open the
ios/plugin_name/directory in Xcode.In Xcode, open your
Package.swiftfile. Verify Xcode doesn't produce any warnings or errors for this file.TipIf Xcode doesn't show any files, quit Xcode (Xcode > Quit Xcode) and reopen.
If Xcode doesn't update after you make a change, try clickingFile > Packages > Reset Package Caches.
If your
ios/plugin_name.podspecfile hasCocoaPodsdependencys, add the correspondingSwift Package Manager dependencies to yourPackage.swiftfile.If your package must be linked explicitly
staticordynamic(not recommended by Apple), update theProduct to define the type:Package.swiftswiftproducts:[.library(name:"plugin-name",type:.static,targets:["plugin_name"])],Make any other customizations. For more information on how to write a
Package.swiftfile, seehttps://developer.apple.com/documentation/packagedescription.TipIf you add targets to your
Package.swiftfile, use unique names. This avoids conflicts with targets from other packages.
Update your
ios/plugin_name.podspecto point to new paths.ios/plugin_name.podspecrubys.source_files='Classes/**/*.swift's.resource_bundles={'plugin_name_privacy'=>['Resources/PrivacyInfo.xcprivacy']}s.source_files='plugin_name/Sources/plugin_name/**/*.swift's.resource_bundles={'plugin_name_privacy'=>['plugin_name/Sources/plugin_name/PrivacyInfo.xcprivacy']}Update loading of resources from bundle to use
Bundle.module.swift#ifSWIFT_PACKAGEletsettingsURL=Bundle.module.url(forResource:"image",withExtension:"jpg")#elseletsettingsURL=Bundle(for:Self.self).url(forResource:"image",withExtension:"jpg")#endifNoteBundle.moduleonly works if there are resourcesdefined in thePackage.swiftfile orautomatically included by Xcode). Otherwise, usingBundle.moduleresults in an error.If your
.gitignoredoesn't include.build/and.swiftpm/directories, you'll want to update your.gitignoreto include:.gitignore.build/.swiftpm/Commit your plugin's changes to your version control system.
Verify the plugin still works with CocoaPods.
Turn off Swift Package Manager.
shflutter config --no-enable-swift-package-managerNavigate to the plugin's example app.
shcd path/to/plugin/example/Ensure the plugin's example app builds and runs.
shflutter runNavigate to the plugin's top-level directory.
shcd path/to/plugin/Run CocoaPods validation lints.
shpod lib lint ios/plugin_name.podspec --configuration=Debug --skip-tests --use-modular-headers --use-librariesshpod lib lint ios/plugin_name.podspec --configuration=Debug --skip-tests --use-modular-headers
Verify the plugin works with Swift Package Manager.
Turn on Swift Package Manager.
shflutter config --enable-swift-package-managerNavigate to the plugin's example app.
shcd path/to/plugin/example/Ensure the plugin's example app builds and runs.
shflutter runNoteUsing the Flutter CLI to run the plugin's example app with the Swift Package Manager feature turned on migrates the project to add Swift Package Manager integration.
This raises the example app's Flutter SDK requirement to version 3.24 or higher.
If you'd like to run the example app using an older Flutter SDK version, do not commit the migration's changes to your version control system. If needed, you can alwaysundo the Swift Package Manager migration.
Open the plugin's example app in Xcode. Ensure thatPackage Dependencies shows in the leftProject Navigator.
Verify tests pass.
If your plugin has native unit tests (XCTest), make sure you alsoupdate unit tests in the plugin's example app.
Follow instructions fortesting plugins.
Replaceplugin_name throughout this guide with the name of your plugin. The example below usesios, replaceios withmacos/darwin as applicable.
Start by creating a directory under the
ios,macos, and/ordarwindirectories. Name this new directory the name of the platform package.plugin_name/
ios/
- …
- plugin_name/
Within this new directory, create the following files/directories:
Package.swift(file)Sources(directory)Sources/plugin_name(directory)Sources/plugin_name/include(directory)Sources/plugin_name/include/plugin_name(directory)Sources/plugin_name/include/plugin_name/.gitkeep(file)- This file ensures the directory is committed. You can remove the
.gitkeepfile if other files are added to the directory.
- This file ensures the directory is committed. You can remove the
Your plugin should look like:
plugin_name/
ios/
- …
plugin_name/
- Package.swift
Sources/plugin_name/include/plugin_name/
- .gitkeep/
Use the following template in the
Package.swiftfile:Package.swiftswift// swift-tools-version: 5.9// The swift-tools-version declares the minimum version of Swift required to build this package.importPackageDescriptionletpackage=Package(// TODO: Update your plugin name.name:"plugin_name",platforms:[// TODO: Update the platforms your plugin supports.// If your plugin only supports iOS, remove `.macOS(...)`.// If your plugin only supports macOS, remove `.iOS(...)`..iOS("13.0"),.macOS("10.15")],products:[// TODO: Update your library and target names.// If the plugin name contains "_", replace with "-" for the library name.library(name:"plugin-name",targets:["plugin_name"])],dependencies:[],targets:[.target(// TODO: Update your target name.name:"plugin_name",dependencies:[],resources:[// TODO: If your plugin requires a privacy manifest// (e.g. if it uses any required reason APIs), update the PrivacyInfo.xcprivacy file// to describe your plugin's privacy impact, and then uncomment this line.// For more information, see:// https://developer.apple.com/documentation/bundleresources/privacy_manifest_files// .process("PrivacyInfo.xcprivacy"),// TODO: If you have other resources that need to be bundled with your plugin, refer to// the following instructions to add them:// https://developer.apple.com/documentation/xcode/bundling-resources-with-a-swift-package],cSettings:[// TODO: Update your plugin name..headerSearchPath("include/plugin_name")])])Update thesupported platforms in your
Package.swiftfile.Package.swiftswiftplatforms:[// TODO: Update the platforms your plugin supports.// If your plugin only supports iOS, remove `.macOS(...)`.// If your plugin only supports macOS, remove `.iOS(...)`..iOS("13.0"),.macOS("10.15")],Update the package, library, and target names in your
Package.swiftfile.Package.swiftswiftletpackage=Package(// TODO: Update your plugin name.name:"plugin_name",platforms:[.iOS("13.0"),.macOS("10.15")],products:[// TODO: Update your library and target names.// If the plugin name contains "_", replace with "-" for the library name.library(name:"plugin-name",targets:["plugin_name"])],dependencies:[],targets:[.target(// TODO: Update your target name.name:"plugin_name",dependencies:[],resources:[// TODO: If your plugin requires a privacy manifest// (e.g. if it uses any required reason APIs), update the PrivacyInfo.xcprivacy file// to describe your plugin's privacy impact, and then uncomment this line.// For more information, see:// https://developer.apple.com/documentation/bundleresources/privacy_manifest_files// .process("PrivacyInfo.xcprivacy"),// TODO: If you have other resources that need to be bundled with your plugin, refer to// the following instructions to add them:// https://developer.apple.com/documentation/xcode/bundling-resources-with-a-swift-package],cSettings:[// TODO: Update your plugin name..headerSearchPath("include/plugin_name")])])NoteIf the plugin name contains
_, the library name must be a-separated version of the plugin name.If your plugin has a
PrivacyInfo.xcprivacyfile, move it toios/plugin_name/Sources/plugin_name/PrivacyInfo.xcprivacyand uncomment the resource in thePackage.swiftfile.Package.swiftswiftresources:[// TODO: If your plugin requires a privacy manifest// (e.g. if it uses any required reason APIs), update the PrivacyInfo.xcprivacy file// to describe your plugin's privacy impact, and then uncomment this line.// For more information, see:// https://developer.apple.com/documentation/bundleresources/privacy_manifest_files.process("PrivacyInfo.xcprivacy"),// TODO: If you have other resources that need to be bundled with your plugin, refer to// the following instructions to add them:// https://developer.apple.com/documentation/xcode/bundling-resources-with-a-swift-package],Move any resource files from
ios/Assetstoios/plugin_name/Sources/plugin_name(or a subdirectory). Add the resource files to yourPackage.swiftfile, if applicable. For more instructions, seehttps://developer.apple.com/documentation/xcode/bundling-resources-with-a-swift-package.Move any public headers from
ios/Classestoios/plugin_name/Sources/plugin_name/include/plugin_name.If you're unsure which headers are public, check your
podspecfile'spublic_header_filesattribute. If this attribute isn't specified, all of your headers were public. You should consider whether you want all of your headers to be public.The
pluginClassdefined in yourpubspec.yamlfile must be public and within this directory.
Handling
modulemap.Skip this step if your plugin does not have a
modulemap.If you're using a
modulemapfor CocoaPods to create a Test submodule, consider removing it for Swift Package Manager. Note that this makes all public headers available through the module.To remove the
modulemapfor Swift Package Manager but keep it for CocoaPods, exclude themodulemapand umbrella header in the plugin'sPackage.swiftfile.The example below assumes the
modulemapand umbrella header are located in theios/plugin_name/Sources/plugin_name/includedirectory.Package.swiftswift.target(name:"plugin_name",dependencies:[],exclude:["include/cocoapods_plugin_name.modulemap","include/plugin_name-umbrella.h"],If you want to keep your unit tests compatible with both CocoaPods and Swift Package Manager, you can try the following:
Tests/TestFile.mobjc@importplugin_name;@importplugin_name.Test;#if __has_include(<plugin_name/plugin_name-umbrella.h>)@importplugin_name.Test;#endifIf you would like to use a custom
modulemapwith your Swift package, refer toSwift Package Manager's documentation.Move all remaining files from
ios/Classestoios/plugin_name/Sources/plugin_name.The
ios/Assets,ios/Resources, andios/Classesdirectories should now be empty and can be deleted.If your header files are no longer in the same directory as your implementation files, you should update your import statements.
For example, imagine the following migration:
Before:
ios/Classes/├── PublicHeaderFile.h└── ImplementationFile.mAfter:
ios/plugin_name/Sources/plugin_name/└── include/plugin_name/ └── PublicHeaderFile.h└── ImplementationFile.m
In this example, the import statements in
ImplementationFile.mshould be updated:Sources/plugin_name/ImplementationFile.mobjc#import "PublicHeaderFile.h"#import "./include/plugin_name/PublicHeaderFile.h"If your plugin usesPigeon, update your Pigeon input file.
pigeons/messages.dartdartjavaOptions:JavaOptions(),objcHeaderOut:'ios/Classes/messages.g.h',objcSourceOut:'ios/Classes/messages.g.m',objcHeaderOut:'ios/plugin_name/Sources/plugin_name/messages.g.h',objcSourceOut:'ios/plugin_name/Sources/plugin_name/messages.g.m',copyrightHeader:'pigeons/copyright.txt',If your
objcHeaderOutfile is no longer within the same directory as theobjcSourceOut, you can change the#importusingObjcOptions.headerIncludePath:pigeons/messages.dartdartjavaOptions:JavaOptions(),objcHeaderOut:'ios/Classes/messages.g.h',objcSourceOut:'ios/Classes/messages.g.m',objcHeaderOut:'ios/plugin_name/Sources/plugin_name/include/plugin_name/messages.g.h',objcSourceOut:'ios/plugin_name/Sources/plugin_name/messages.g.m',objcOptions:ObjcOptions(headerIncludePath:'./include/plugin_name/messages.g.h',),copyrightHeader:'pigeons/copyright.txt',Run Pigeon to re-generate its code with the latest configuration.
Update your
Package.swiftfile with any customizations you might need.Open the
ios/plugin_name/directory in Xcode.In Xcode, open your
Package.swiftfile. Verify Xcode doesn't produce any warnings or errors for this file.TipIf Xcode doesn't show any files, quit Xcode (Xcode > Quit Xcode) and reopen.
If Xcode doesn't update after you make a change, try clickingFile > Packages > Reset Package Caches.
If your
ios/plugin_name.podspecfile hasCocoaPodsdependencys, add the correspondingSwift Package Manager dependencies to yourPackage.swiftfile.If your package must be linked explicitly
staticordynamic(not recommended by Apple), update theProduct to define the type:Package.swiftswiftproducts:[.library(name:"plugin-name",type:.static,targets:["plugin_name"])],Make any other customizations. For more information on how to write a
Package.swiftfile, seehttps://developer.apple.com/documentation/packagedescription.TipIf you add targets to your
Package.swiftfile, use unique names. This avoids conflicts with targets from other packages.
Update your
ios/plugin_name.podspecto point to new paths.ios/plugin_name.podspecrubys.source_files='Classes/**/*.{h,m}'s.public_header_files='Classes/**/*.h's.module_map='Classes/cocoapods_plugin_name.modulemap's.resource_bundles={'plugin_name_privacy'=>['Resources/PrivacyInfo.xcprivacy']}s.source_files='plugin_name/Sources/plugin_name/**/*.{h,m}'s.public_header_files='plugin_name/Sources/plugin_name/include/**/*.h's.module_map='plugin_name/Sources/plugin_name/include/cocoapods_plugin_name.modulemap's.resource_bundles={'plugin_name_privacy'=>['plugin_name/Sources/plugin_name/PrivacyInfo.xcprivacy']}Update loading of resources from bundle to use
SWIFTPM_MODULE_BUNDLE:objc#if SWIFT_PACKAGENSBundle*bundle=SWIFTPM_MODULE_BUNDLE;#elseNSBundle*bundle=[NSBundlebundleForClass:[selfclass]];#endifNSURL*imageURL=[bundleURLForResource:@"image"withExtension:@"jpg"];NoteSWIFTPM_MODULE_BUNDLEonly works if there are actual resources (eitherdefined in thePackage.swiftfile orautomatically included by Xcode). Otherwise, usingSWIFTPM_MODULE_BUNDLEresults in an error.If your
ios/plugin_name/Sources/plugin_name/includedirectory only contains a.gitkeep, you'll want update your.gitignoreto include the following:.gitignore!.gitkeepRun
flutter pub publish --dry-runto ensure theincludedirectory is published.Commit your plugin's changes to your version control system.
Verify the plugin still works with CocoaPods.
Turn off Swift Package Manager:
shflutter config --no-enable-swift-package-managerNavigate to the plugin's example app.
shcd path/to/plugin/example/Ensure the plugin's example app builds and runs.
shflutter runNavigate to the plugin's top-level directory.
shcd path/to/plugin/Run CocoaPods validation lints:
shpod lib lint ios/plugin_name.podspec --configuration=Debug --skip-tests --use-modular-headers --use-librariesshpod lib lint ios/plugin_name.podspec --configuration=Debug --skip-tests --use-modular-headers
Verify the plugin works with Swift Package Manager.
Turn on Swift Package Manager:
shflutter config --enable-swift-package-managerNavigate to the plugin's example app.
shcd path/to/plugin/example/Ensure the plugin's example app builds and runs.
shflutter runNoteUsing the Flutter CLI to run the plugin's example app with the Swift Package Manager feature turned on migrates the project to add Swift Package Manager integration.
This raises the example app's Flutter SDK requirement to version 3.24 or higher.
If you'd like to run the example app using an older Flutter SDK version, do not commit the migration's changes to your version control system. If needed, you can alwaysundo the Swift Package Manager migration.
Open the plugin's example app in Xcode. Ensure thatPackage Dependencies shows in the leftProject Navigator.
Verify tests pass.
If your plugin has native unit tests (XCTest), make sure you alsoupdate unit tests in the plugin's example app.
Follow instructions fortesting plugins.
How to update unit tests in a plugin's example app
#If your plugin has native XCTests, you might need to update them to work with Swift Package Manager if one of the following is true:
- You're using a CocoaPod dependency for the test.
- Your plugin is explicitly set to
type: .dynamicin itsPackage.swiftfile.
To update your unit tests:
Open your
example/ios/Runner.xcworkspacein Xcode.If you were using a CocoaPod dependency for tests, such as
OCMock, you'll want to remove it from yourPodfilefile.ios/Podfilerubytarget'RunnerTests'doinherit!:search_pathspod'OCMock','3.5'endThen in the terminal, run
pod installin theplugin_name_ios/example/iosdirectory.Navigate toPackage Dependencies for the project.

The project's package dependencies
Click the+ button and add any test-only dependencies by searching for them in the top right search bar.

Search for test-only dependencies
NoteOCMock uses unsafe build flags and can only be used if targeted by commit.
fe1661a3efed11831a6452f4b1a0c5e6ddc08c3dis the commit for the 3.9.3 version.Ensure the dependency is added to the
RunnerTestsTarget.
Ensure the dependency is added to the
RunnerTeststargetClick theAdd Package button.
If you've explicitly set your plugin's library type to
.dynamicin itsPackage.swiftfile (not recommended by Apple), you'll also need to add it as a dependency to theRunnerTeststarget.Ensure
RunnerTestsBuild Phases has aLink Binary With Libraries build phase:
The
Link Binary With LibrariesBuild Phase in theRunnerTeststargetIf the build phase doesn't exist already, create one. Click theadd button and then clickNew Link Binary With Libraries Phase.

Add
Link Binary With LibrariesBuild PhaseNavigate toPackage Dependencies for the project.
Click theadd button.
In the dialog that opens, click theAdd Local... button.
Navigate to
plugin_name/plugin_name_ios/ios/plugin_name_iosand click theAdd Package button.Ensure that it's added to the
RunnerTeststarget and click theAdd Package button.
Ensure tests passProduct > Test.
Unless stated otherwise, the documentation on this site reflects Flutter 3.38.6. Page last updated on 2025-12-08.View source orreport an issue.