Adding iOS app extensions
iOS App extensions allow you to expand functionality outside your app. Your app could appear as a home screen widget, or you can make portions of your app available within other apps.
To learn more about app extensions, check out Apple’s documentation.
How do you add an app extension to your Flutter app?
To add an app extension to your Flutter app, add the extension point target to your Xcode project.
- Open the default Xcode workspace in your project by running
open ios/Runner.xcworkspace
in a terminal window from your Flutter project directory. -
In Xcode, select File -> New -> Target from the menu bar.
- Select the app extension you intend to add. This selection generates extension-specific code within a new folder in your project. To learn more about the generated code and the SDKs for each extension point, check out the resources in Apple’s documentation.
How do Flutter apps interact with App Extensions?
Flutter apps interact with app extensions using the same techniques as UIKit or SwiftUI apps. The containing app and the app extension don’t communicate directly. The containing app might not be running while the device user interacts with the extension. The app and your extension can read and write to shared resources or use higher-level APIs to communicate with each other.
Using higher-level APIs
Some extensions have APIs. For example, the Core Spotlight framework indexes your app allowing users to search from Spotlight and Safari. The WidgetKit framework can trigger an update of your home screen widget.
To simplify how your app communicates with extensions, Flutter plugins wrap these APIs. To find plugins that wrap extension APIs, check out Leveraging Apple’s System APIs and Frameworks or search pub.dev.
Sharing resources
To share resources between your Flutter app and your app extension, put
the Runner
app target and the extension target in the same
App Group.
To add a target to an App Group:
- Open the target settings in Xcode.
- Navigate to the Signing & Capabilities tab.
- Select + Capability then App Groups.
- Choose which App Group you want to add the target from one of two options:
- Select an App Group from the list.
- Click + to add a new App Group.
When two targets belong to the same App Group, they can read and write data to the same source. Choose one of the following sources for your data.
-
Key/value: Use the
shared_preference_app_group
plugin to read or write toUserDefaults
within the same App Group. -
File: Use the App Group container path from the
path_provider
plugin to read and write files. -
Database: Use the App Group container path from
the
path_provider
plugin to create a database with thesqflite
plugin.
Background updates
Background tasks provide a means to update your extension through code regardless of the status of your app.
To schedule background work from your Flutter app, use the
workmanager
plugin.
Deep linking
You might want to direct users from an app extension to a specific page in your Flutter app. To have a URL open a specified route in your app, you can use Deep Linking.
Creating app extension UIs with Flutter
Some app extensions display a user interface. For example, iMessage extensions allow users to access your app’s content directly from the Messages app.
Flutter does not support
building Flutter UI for app extensions.
To create the UI for
an app extension using Flutter, you must compile
a custom engine and embed the FlutterViewController
as described in the following section.
-
Create a custom build of the Flutter engine that removes uses of
sharedApplication
and corrects the path for the bundle. Check out an example from the community on GitHub. -
Open the Flutter app project settings in Xcode to share build configurations.
- Navigate to the Info tab.
- Expand the Configurations group.
- Expand the Debug, Profile, and Release entries.
- For each of these configurations, make sure the value in the Based on configuration file drop-down menu for your extension matches the one selected for the normal app target.
- (Optional) Replace any storyboard files with an extension class if needed.
- In the Info.plist file, delete the NSExtensionMainStoryboard property.
- Add the NSExtensionPrincipalClass property.
- Set this value for this property to the name of your
ViewController
. For example, in an iMessage extension you would useMessageViewController
.
-
Embed the
FlutterViewController
as described in Adding a Flutter Screen. For example, you can display a specific route in your Flutter app within an iMessage extension.//This attribute tells the compiler that this piece of Swift code can be accessed from Objective-C. @objc(MessagesViewController) class MessagesViewController: MSMessagesAppViewController { override func viewDidLoad() { super.viewDidLoad() showFlutter() } @objc func showFlutter() { // Create a FlutterViewController with an implicit FlutterEngine let flutterViewController = FlutterViewController(project: nil, initialRoute: "/ext", nibName: nil, bundle: nil) present(flutterViewController, animated: true, completion: nil) }