In this Section, we provide an Android and iOS step-by-step guide to build your first Situm app using Flutter. For more advanced use cases, take a look at our Flutter sample app and at the Plugin Method Reference.
Pre-requisites: install Flutter #
First, you need to set up your Flutter development environment. To get started, please follow instructions under the Flutter installation guide.
After installing Flutter you can directly create an example app with the following command:
$ mkdir flutter_getting_started $ flutter create -t app --platform android,ios flutter_getting_started $ cd flutter_getting_started
Installing the plugin #
Alternative 1: package manager #
Run the following command from the root directory of your Flutter project:
$ flutter pub add situm_flutter
This will add the Situm dependency to your project. Specifically, in your pubspec.yaml file.
Alternative 2: git repository + flutter pub add #
Another way to add the Situm dependency to your Flutter project is by directly adding it using the Situm Github repository (https://github.com/situmtech/flutter.git) with the “flutter pub add” command:
$ flutter pub add situm_flutter_wayfinding --git-url=https://github.com/situmtech/flutter.git
Alternative 3: git repository + pubspec.yaml #
If you prefer to handle the dependencies manually, you can add them to your pubspec.yaml file. This file is located in the root directory of your project and it’s used to manage your project’s dependencies.
You will need to add the following lines under the dependencies section:
situm_flutter_wayfinding: git: url: https://github.com/situmtech/flutter.git
Save the pubspec.yaml file and run the command flutter pub get in the root directory of your project to download and install the package:
$ flutter pub get
Once the package is installed, you can start using it in your code.
Installing other dependencies #
To use Situm in your project, you’ll also need to install the following dependency to handle permissions (see this section for more information):
$ flutter pub add permission_handler
Remember to follow the setup guide for the permission_handler plugin. The plugin communicates directly with the operating system, which requires adding configurations to specific files in both Android and iOS.
Setup native projects (Android & iOS) #
You will also need to make some changes to the native projects of your Flutter application.
Android #
Add the ACCESS_FINE_LOCATION permission declaration to your AndroidManifest.xml.
<uses-permission android:name="android.permission.ACCESS_FINE_LOCATION" />
Finally, set the minSdkVersion to 21 (or later) and compileSdkVersion to 33 (needed by permission_handler) on your app’s build.gradle file.
Finally, add the following to your gradle.properties file:
android.useAndroidX=true android.enableJetifier=true
iOS #
Remove the “use_frameworks!” directive in the Podfile of your iOS project. This is needed because Situm SDK is a static library:
... target 'Runner' do # This line must be commented or removed: # use_frameworks! use_modular_headers! ...
Run the command pod install in the ios directory of your project so CocoaPods can install the necessary Situm SDK dependencies.
$ cd ios $ pod install $ cd ..
Add the required permissions (more info here) in your app’s Info.plist file:
<key>NSLocationWhenInUseUsageDescription</key> <string>Location is required to find out where you are</string> <key>NSLocationAlwaysAndWhenInUseUsageDescription</key> <string>Location is required to find out where you are</string> <key>NSMotionUsageDescription</key> <string>We use your phone sensors (giroscope, accelerometer and altimeter) to improve location quality</string>
And in your Podfile (required by the permission_handler library):
... post_install do |installer| installer.pods_project.targets.each do |target| ... #INCLUDE THIS SNIPPET IN YOUR PODFILE TO CONFIGURE PERMISSION HANDLER PLUGIN target.build_configurations.each do |config| config.build_settings['GCC_PREPROCESSOR_DEFINITIONS'] ||= [ '$(inherited)', 'PERMISSION_LOCATION=1', 'PERMISSION_SENSORS=1', ] #END OF SNIPPET TO INCLUDE ... end end end
Finally, you will need to add the underlying web application’s domain inside the entry WKAppBoundDomains, also on Info.plist as follows:
<key>WKAppBoundDomains</key> <array> <string>map-viewer.situm.com</string> </array>
If you have other webviews in your app this might affect them, you can learn more about this here.
Run your first app! #
The following code contains a fully functional Flutter app. You may copy & paste it in your main.dart file (you may obtain your credentials as explained here, and your building ID as explained here):
import "dart:io"; import 'package:flutter/material.dart'; import 'package:permission_handler/permission_handler.dart'; //Step 1 - Importing Situm import 'package:situm_flutter/sdk.dart'; import 'package:situm_flutter/wayfinding.dart'; //Step 2 - Setting credentials and building identifier //Input here your user credentials ... const situmApiKey = "YOUR-SITUM-API-KEY"; // ... and the building you want visualize const buildingIdentifier = "YOUR-SITUM-BUILDING-IDENTIFIER"; void main() { runApp(const MyApp()); } class MyApp extends StatelessWidget { const MyApp({super.key}); // This widget is the root of your application. @override Widget build(BuildContext context) { return MaterialApp( title: 'Situm Flutter', theme: ThemeData( colorScheme: ColorScheme.fromSeed(seedColor: Colors.deepPurple), useMaterial3: true, ), home: const MyHomePage(), ); } } class MyHomePage extends StatefulWidget { const MyHomePage({super.key}); @override State<MyHomePage> createState() => _MyHomePageState(); } class _MyHomePageState extends State<MyHomePage> { MapViewController? mapViewController; @override void initState() { super.initState(); // Initialize SitumSdk class _useSitum(); } @override Widget build(BuildContext context) { return Scaffold( appBar: AppBar( backgroundColor: Theme.of(context).colorScheme.inversePrimary, title: const Text('Situm Flutter'), ), //Step 3 - Showing the building cartography using the MapView body: Center( //MapView widget will visualize the building cartography child: MapView( key: const Key("situm_map"), configuration: MapViewConfiguration( situmApiKey: situmApiKey, buildingIdentifier: buildingIdentifier, ), onLoad: _onLoad, ), ), ); } void _onLoad(MapViewController controller) { // Map successfully loaded: now you can register callbacks and perform // actions over the map. mapViewController = controller; debugPrint("Situm> wayfinding> Map successfully loaded."); controller.onPoiSelected((poiSelectedResult) { debugPrint("Situm> wayfinding> Poi selected: ${poiSelectedResult.poi.name}"); }); } //Step 4 - Positioning void _useSitum() async { var situmSdk = SitumSdk(); // Set up your credentials situmSdk.init(); situmSdk.setApiKey(situmApiKey); // Set up location callbacks: situmSdk.onLocationUpdate((location) { debugPrint("Situm> sdk> Location updated: ${location.toMap().toString()}"); }); situmSdk.onLocationStatus((status) { debugPrint("Situm> sdk> Status: $status"); }); situmSdk.onLocationError((error) { debugPrint("Situm> sdk> Error: ${error.message}"); }); // Check permissions: var hasPermissions = await _requestPermissions(); if (hasPermissions) { // Happy path: start positioning using the default options. // The MapView will automatically draw the user location. situmSdk.requestLocationUpdates(LocationRequest()); } else { // Handle permissions denial. debugPrint("Situm> sdk> Permissions denied!"); } } // Requests positioning permissions Future<bool> _requestPermissions() async { var permissions = <Permission>[ Permission.locationWhenInUse, ]; if (Platform.isAndroid) { permissions.addAll([ Permission.bluetoothConnect, Permission.bluetoothScan, ]); } Map<Permission, PermissionStatus> statuses = await permissions.request(); return statuses.values.every((status) => status.isGranted); } }
You may run this app by using:
$ flutter run
You should see something like this:
Code explanation: step-by-step #
Step 1 – Importing Situm #
The 1st thing the example does is to import the situm_flutter package, which contains two libraries:
- Wayfinding: visual module for maps, routes, and navigation.
- Sdk: allows you to control the positioning system through the SitumSdk class.
Step 2 – Setting credentials and building identifier #
Right after the import, we set:
- User credentials (email and APIKEY).
- Building identifier. Identifier of the building whose cartography will be shown. It should be the same as the one where you’ll perform positioning.
You may obtain your credentials as explained here, and your building ID as explained here.
Step 3 – Showing the building cartography using the MapView #
Then, the example shows the cartography of the selected building. You may see that the wayfinding library exposes two main classes to this extent:
- MapView. The Flutter widget that you can add to your view hierarchy.
- MapViewController. Allows you to communicate with the map: methods and callbacks are available to perform actions and listen to events (e.g. listen to POI selections, intercept navigation options, etc.)
Note that you need need to wait until the MapViewController is properly loaded, using the onLoad callback as the example does.
Step 4 – Positioning #
You may perform positioning by using the function _useSitum() detailed in the example above.
Initializing SitumSdk #
First, you may initialize SitumSdk on your root stateful widget.
Setting up callbacks #
Then, by setting up callbacks (onLocationUpdate, onLocationStatus, onLocationError), you can listen for location updates, status and errors (after positioning is started).
Requesting permissions #
After that, your app must ask for the following permissions (check our documentation for more details):
- Android: Location and Bluetooth runtime permissions.
- iOS: Bluetooth permissions.
The example calls the function _requestPermissions(), that in turn uses the package permission_handler to do so.
Starting positioning #
Finally, start positioning with the Situm SDK, you will need to call the requestLocationUpdates() method. This method takes one argument of the type LocationRequest that will encapsulate the configuration parameters.
In this example, the LocationRequest is empty, meaning that positioning parameters will be drawn from the Remote Configuration, which you may configure in Situm Dashboard.
Visualize the user’s position on the map #
Once the positioning has started, the MapView will automatically start drawing the user’s position on the map. Otherwise, please check that you’ve configured the Remote Configuration properly in Situm Dashboard.
Advanced configuration #
To further configure the user experience see our Advanced Topics section that explains additional capabilities of both Situm SDK and MapView as well as how to configure them on your projects. Topics you can be interested in are: battery efficiency, location cache, working offline with cached data, foreground & background execution, external provider locations, listen to geofences entries & exits, how to provide your iOS app’s privacy manifest.
Legacy configuration #
Prior to version 3.16.0 of situm_flutter, it was also necessary to add the Situm repository to your project’s build.gradle file so Gradle can download the native Situm SDK dependency:
allprojects { repositories { maven { url "https://repo.situm.com/artifactory/libs-release-local" } } }