layout | title | sidebar | permalink |
---|---|---|---|
page |
Accessing Platform and Third-Party Services in Flutter |
home_sidebar |
/platform-services/ |
This guide describes how to connect your Flutter app to platform-specific or third-party services that are available on iOS and Android devices.
- TOC {:toc}
Mobile devices offer many capabilities to extend your app through platform-specific APIs, or APIs from third-party vendors. Flutter offers the following ways to integrate platform-specific services when building your app using the Flutter framework.
- First-party services for Flutter: For frequently used services, the Flutter SDK provides first-party APIs to access system services across platforms. You can call these APIs directly in your Flutter app by importing the 'flutter/services' package.
- Platform and Third-party Services for Flutter: Flutter provides the
HostMessages
class which allows your Flutter user interface (UI) code to asynchronously exchange application-specific messages with the portions of your app that run on iOS or Android devices. This flexible approach lets you invoke platform-specific and third-party APIs on iOS and Android devices, while keeping a common UI codebase.
You can use the HostMessages
class in the Flutter UI portion of your app to send messages to a host (that is, the iOS or
Android portion of your app that uses a shared UI codebase built with Flutter). The HostMessages
class lets you implement your own integrations with
platform-specific services; you can send a request message to the host to call a
platform API then asynchronously retrieve the service data via a response message
from that host.
Your message must consist of string value. Message passing with the
HostMessages
class is
asynchronous, bi-directional, and supports optional reply routing.
The services that you invoke using the
HostMessages
class must return
non-graphical, data-only information. Examples include:
- Geolocation
- Contacts
- File system
- Network information
- Sensors
You can also use the HostMessages
class to invoke APIs from third-party SDKs that run on iOS and Android devices.
To communicate between the
HostMessages
class and
platform-specific APIs in the host, you must add the following Flutter components into
the host's view hierarchy.
- On iOS: Add a
FlutterViewController
object to interact with aUIView
. - On Android: Add a
FlutterView
object to your app’sandroid.view.View
hierarchy.
To create additional platform-specific or third-party service integrations using message passing, follow these steps:
-
Download the hello_services example. If your app needs to access platform-specific APIs on iOS or Android, you can download the
hello_services
example and use it as the starter code to build your own service integration. This reference example demonstrates how to connect to the geolocation service within an iOS or Android application by using theHostMessages
class.The following diagram shows how the
hello_services
app accesses platform-specific services on iOS and Android.Fig 1. Architecture of the
hello_services
example.The Flutter UI and host-specific components are related as follows:
- In the Flutter UI portion of the app, the main app imports the
flutter/services.dart
package, which defines theHostMessages
class. In theState
class, the app makes a service request by calling the static methods of theHostMessages
class. If the service request is successful, the app updates the UI accordingly with the data that the service returns. - On the iOS portion of the app, the
AppDelagate
class sets an instance ofFlutterViewController
as the root view controller of itsUIWindow
. TheFlutterViewController
class provides a bridge connecting theUIKit
view hierarchy to the Flutter UI code. To use theFlutterViewController
class, the iOS portion of the app must import theFlutter.h
library. - On the Android portion of the app, the main activity sets as its
content view an instance of the
FlutterView
class, which provides a bridge connecting the Android view hierarchy to the Flutter UI code. To use theFlutterView
class, the Android portion of the app must specify the flutter gradle plugin dependency in itsbuild.gradle
file.
- In the Flutter UI portion of the app, the main app imports the
-
Establish the service bindings. The
HostMessages
class uses theMojoShell
class to establish connections with services. In order to set up theMojoShell
object, you must first invoke therunApp()
orWidgetsFlutterBinding.ensureInitialized()
method in yourmain()
function.After initializing the service bindings, you can register a callback for receiving messages through the
HostMessages
class by calling theaddJSONMessageHandler()
oraddMessageHandler()
static methods.For example, this snippet shows how you might initialize a service binding and register a message handler callback in the
main()
function.import 'dart:async'; import 'dart:math'; import 'package:flutter/material.dart'; import 'package:flutter/services.dart'; final Random random = new Random(); void main() { runApp(Null); HostMessages.addJSONMessageHandler('getRandom', handleGetRandom); } Future<dynamic> handleGetRandom(Map<String, dynamic> message) async { final double min = message['min'].toDouble(); final double max = message['max'].toDouble(); return <String, double>{ 'value': (random.nextDouble() * (max - min)) + min }; }
-
Add a service invocation call in the Flutter UI. In your
State
class, use theHostMessages
class to call a target service on the host. You'll typically peform this operation when the user performs a UI interaction.You can construct your service invocation call as a JSON-encoded string, then call the
sendJSON
method and pass this string as a parameter.For example, the following snippet shows how you might asynchronously invoke the geolocation service.
class HelloServices extends StatefulWidget { @override _HelloServicesState createState() => new _HelloServicesState(); } class _HelloServicesState extends State<HelloServices> { double _latitude; double _longitude; Future<Null> _getLocation() async { final Map<String, String> message = <String, String>{'provider': 'network'}; final Map<String, dynamic> reply = await HostMessages.sendJSON('getLocation', message); // If the widget was removed from the tree while the message was // in flight, we want to discard the reply rather than // calling setState to update our non-existant appearance. if (!mounted) return; setState(() { _latitude = reply['latitude'].toDouble(); _longitude = reply['longitude'].toDouble(); }); } @override Widget build(BuildContext context) { // ... return new Text('Latitude: $latitude, Longitude: $longitude'); } }
-
Add a service provider in the host (iOS). Follow these steps if your app needs to invoke a platform-specific or third-party API on iOS:
-
In the example project, the
ios/HelloServices
folder contains the Objective-C source files for the iOS-specific part of the app. In Xcode, open this folder as an iOS project. -
In your iOS project, create a service provider to handle the service request message, locally invoke the service, and return a response message to the Flutter UI portion of the app. Your service provider should conform to one of these protocols:
FlutterMessageListener
: Implement this protocol if the request message does not require a reply, or if the Flutter UI portion of your app can reply to the message synchronously.FlutterAsyncMessageListener
: Implement this protocol if the request message requires a reply and the code that creates the reply is asynchronous.
For an example of how to implement a service provider, see the
LocationProvider.m
andAppDelegate.m
classes from the example project. -
Create or modify a
Flutter/Generated.xcconfig
file to specify the configuration settings for building your iOS app. See the project README to learn more about the iOS-specific properties you can configure.
-
-
Add a service provider in the host (Android). Follow these steps if your app needs to invoke a platform-specific or third-party API on Android:
- In the example project, the
android/app
folder contains the Java source files for the Android-specific portion of the app. The file organization in this folder conforms to the Android app module format for Gradle. In Android Studio, open theapp
folder as an Android project. - In your Android project, create a service provider to handle the service request message,
locally invoke the service, and return a response message to the Flutter UI portion of the app.
For each service you want to invoke, attach a message listener to the
FlutterView
object and specify the service provider it calls when theonMessage()
event is triggered. For an example of how to implement a service provider, see theExampleActivity.java
class from the example project. - Modify the
AndroidManifest.xml
file to add any permissions necessary to invoke your target service (for example, the geolocation service needs theACCESS_FINE_LOCATION
permission). - Create or modify a
local.properties
file to specify the configuration settings for building your Android app. See the project README to learn more about the Android-specific properties you can configure.
- In the example project, the
-
Build your app. You should build your app directly from the platform-specific tools.
- On iOS: Build your app using Xcode.
- On Android: Build your app using Android Studio or Gradle from the command-line.
To learn how to build the app for a specific platform, see the
hello_services
README.The platform-specific build system creates the application package in the normal way. This approach eases the integration of third-party SDKs, which are designed to be integrated into the normal build process for each platform they support.