Skip to content
Developers Docs

Android getting started

This guide will take you through the process of integrating the Mapsted Android SDK.

Upgrading from 6.2.x?

Version 26.7.1 changes the Maven repository and module coordinates (com.mapsted:sdk-*com.mapsted:android-sdk-*), raises the minimum Android SDK version to 26, and removes the sdk-alerts module. Review the Migration Guide to v26.7.1 (Android) for the full list of breaking changes before you upgrade.

1. Minimum Requirements

To import the Mapsted SDK, your Android project must meet the following minimum requirements.

Library Version
Minimum Android SDK Version 26

You must be running jdk 11 or higher. In Android Studio, open Files > Settings. Under Gradle options, Choose Gradle JDK to use jdk 11 or higher.

2. Setup Permissions

The mobile sdk includes the permissions it requires in its respective AndroidManifest file. Note that different sdk modules may require additional permissions.

3. Include Licence Files

Place the Mapsted Android licence file in the assets folder located at $(ProjectPath)/app/src/main/assets. You will need to create the assets folder if it does not exist.

4. Import the Mapsted SDK

This section describes integrating the Mapsted SDK into your Android project.

If you are using the kotlin gradle build.gradle.kt, please refer to Migrating build logic from Groovy to Kotlin

Add the following code into your project's gradle file:

allprojects {
    repositories {
        google()
        mavenCentral()
        maven { url 'https://jitpack.io' }
        maven { url "https://mapstedhq.github.io/mapsted-android-maven" }
    }
}

Make sure you have all the below settings in the app level build.gradle file.

apply plugin: 'com.android.application'    

android {
    compileSdkVersion 34

    defaultConfig {
        applicationId "your.packagename"
        minSdkVersion 26
        targetSdkVersion 34
        versionCode = 1
        versionName = "1"
        testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner"

        // Required by the Mapsted SDK: it reads these manifest placeholders at build time.
        // Any integer for versionCode and any date string for dateString are accepted.
        manifestPlaceholders = [versionCode: "1", dateString: "2026-07-09"]
    }

    buildTypes {
        //...
    }

    buildFeatures {
        dataBinding true
        viewBinding true
    }

    compileOptions {
        sourceCompatibility JavaVersion.VERSION_11
        targetCompatibility JavaVersion.VERSION_11
    }
    tasks.withType(org.jetbrains.kotlin.gradle.tasks.KotlinCompile).all {
        kotlinOptions {
            jvmTarget = '11'
        }
    }

     configurations {
        implementation.exclude group: 'org.jetbrains', module: 'annotations'
    }

    packagingOptions {
        resources.excludes.add("META-INF/gradle/*")
        resources.excludes.add("META-INF/*")
    }
}

dependencies {
    implementation fileTree(dir: 'libs', include: ['*.jar'])

    // Import Mapsted SDKs.
    // The Mapsted SDK BOM pins every module below to one version (26.7.1),
    // so the individual module lines are declared without a version.
    // Order is important: top resources overwrite bottom, so keep the more "core" SDKs lower.
    implementation platform('com.mapsted:android-sdk-bom:26.7.1')

    // If using app-templates, import here.
    // NOTE: android-app-template ships its own <application> element. If you include it,
    // add xmlns:tools and tools:replace="android:label" to the <application> tag in your AndroidManifest.xml.
    implementation 'com.mapsted:android-app-template'      // Example app-template
    implementation 'com.mapsted:android-app-template-core' // Core/common functionality used by the app-template.

    // Optionally, if you want location marketing (depends on inapp-notification)
    implementation 'com.mapsted:android-sdk-loc-marketing'
    implementation 'com.mapsted:android-sdk-inapp-notification'

    // Optionally, if you want programmatic geofences
    implementation 'com.mapsted:android-sdk-geofence'
    implementation 'com.mapsted:android-sdk-geofence-offline'

    // Optionally, if you want prebuilt Mapsted UI/UX, include this dependency
    implementation 'com.mapsted:android-sdk-ui-components'

    // Optionally, if you want access to the Mapsted Map UI, include this dependency
    implementation 'com.mapsted:android-sdk-ui'

    // If you want access to the Mapsted map, include this dependency
    implementation 'com.mapsted:android-sdk-map'

    // This is always required to use the Mapsted SDK
    implementation 'com.mapsted:android-sdk-core'

    // If you want to use the Location share feature, include this module
    implementation 'com.mapsted:android-sdk-loc-share'

    // If you want to use Mapsted Top Bar Notifications feature, include this module
    implementation 'com.mapsted:android-sdk-topbar-notifications'
}

5. Proguard exclusion

If you have proguard enabled in your project, please keep all mapsted related public classes and interfaces.

Add the following in your proguard file.

-keep interface com.mapsted.** { *; }    
-keep public class com.mapsted.** { public protected *; }
-keep interface com.carto.** { *; }
-keep public class com.carto.** { public protected *; }

# Required for release/minified builds: joda-time (a transitive dependency) references
# optional compile-only annotations that are not present at runtime.
-dontwarn org.joda.convert.**

6. Initialization of Mapsted SDK

The Mapsted SDK is very flexible and allows for multiple levels of integration. We will outline several different recommendations below, and you can adjust based on your requirements and preferences.

Setting up Map Views

When you initialize the map-sdk and map-ui-sdk, you must supply a corresponding View (usually a FrameLayout), and the mobile sdk will inflate this view with the appropriate Map View or Map Ui View. Our recommendation for setting up your .xml when using map-sdk and map-ui-sdk is as follows:\

<!-- General container -->
<RelativeLayout
    android:id="@+id/rl_map_container"
    android:layout_width="match_parent"
    android:layout_height="0dp"
    android:background="@android:color/transparent"
    app:layout_constraintBottom_toBottomOf="parent"
    app:layout_constraintEnd_toEndOf="parent"
    app:layout_constraintStart_toStartOf="parent"
    app:layout_constraintTop_toTopOf="parent">

    <!-- View to be supplied to the map-sdk -->
    <FrameLayout
        android:id="@+id/fl_base_map"
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:visibility="gone" />

    <!-- View to be supplied to the map-ui-sdk -->
    <FrameLayout
        android:id="@+id/fl_map_ui"
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:visibility="gone" />
</RelativeLayout>

Integrating the Core SDK

The core-sdk is the most important module in the Mapsted Android SDK as it is a dependency for almost every other module. For example, initializing the map-sdk (and MapView) requires that the core-sdk already be initialized. As such, it is not recommended to continuously destroy and recreate the core-sdk. The main interface for the core-sdk is the CoreApi.

Note that it is very important to not create multiple instances of the CoreApi as this would lead to a major performance overhead and likely result in concurrency issues.

For some use-cases, you may wish to create a dedicated Activity for handling Mapsted-related functionality. Should you choose to create the CoreApi instance within this Activity, then the Mapsted SDK would be essentially shut down completely everytime the Activity is destroyed.

As such, it is recommended to maintain the CoreApi instance beyond the scope of a single Activity, allowing for the mobile SDK to be initialized just once and allowing for fast loading on subsequent map launches, etc. Note that this is also necessary if you intend to make use of the various CoreApi functionality while the MapView is not visible (e.g., triggering map data downloads or point-of-interest search/filterings).

We have provided a utility Application class, MapstedBaseApplication which provides getter/setters for creating and/or retrieving the coreApi instance. It is our strong recommendation that you create your Application class and extend the MapstedBaseApplication, which allows for the CoreApi to be shared between activities, if desired, but will also automatically handle the CoreApi destruction/clean-up.

A sample Application class is shown below, which provides access to application.getCoreApi(context), which can be accessed from any Activity.

public class MyApplication extends MapstedBaseApplication {
    // ...
}

public class MyActivity extends AppCompatActivity {
    // ...
    CoreApi coreApi = ((MapstedBaseApplication)getApplication()).getCoreApi(this);
    // ...
}

Integrating the Core, Map, and Map-Ui SDKs

You can create/obtain instances of the CoreApi, MapApi, and MapUiApi in one of two ways, as shown below:

// Recommended approach
CoreApi coreApi = ((MapstedBaseApplication)getApplication()).getCoreApi(this);

// Alternative appoach:
// CoreApi coreApi = MapstedCoreApi.newInstance(this);

MapApi mapApi = MapstedMapApi.newInstance(this, coreApi);
MapUiApi mapUiApi = MapstedMapUiApi.newInstance(getApplicationContext(), mapApi);

// Note:
// This gives you full control of each sdk
// You are managing the lifecycle of each Api, so you are responsible for calling the appropriate lifecycle().onDestroy()
// If you are using the MapstedBaseApplication, then you do not need to manage the coreApi lifecycle.

Customizable Parameters

When you initialize a mobile sdk module, you must supply it with the corresponding parameter object, which allows for customization options.

Sdk Params class Extends
sdk-core CoreParams --
sdk-map CustomMapParams CoreParams
sdk-map CustomParams CustomMapParams

As can be seen, due to the inheritance relationship, a single instance of CustomParams can be created and supplied for initializing each of the foundational sdks. A sample CustomParams creation is shown below.

// Some sample customization parameters
CustomParams params = CustomParams.newBuilder(this)
            .setBaseMapStyle(BaseMapStyle.DEVICE_DEFAULT)
            .setMapPanType(MapPanType.RESTRICT_TO_SELECTED_PROPERTY)
            .setMapZoomRange(new MapstedMapRange(6.0f, 25.0f))
            // Set whatever parameters you want
            .build();

// Note that you can also create a CoreParams or CustomMapParams (as necessary, if required)    

Initializing the SDK

Each module has its own initialize(...) method. For the map-sdk and map-ui-sdk, the initialization is related to UI views (i.e., MapView or MapUiView, respectively). Conversely, the core-sdk can be initialized independently of any UI views. There are two main ways in which the modules can be initialized. Either, each module can be initialized seprately, or, if you initialize a depdent module (e.g., map-ui-sdk), then it will automatically also initialize any modules that it is depedent on (i.e., map-sdk, core-sdk). Examples of this are shown below.

// Example initialization of coreApi
coreApi.setup().initialize(params, new CoreApi.CoreInitCallback() {
    @Override
    public void onSuccess() {
        // Core successfully initialized
    }

    @Override
    public void onStatusUpdate(SdkStatusUpdate sdkUpdate) {
        // Status updates (warnings or information about what is going on)
    }

    @Override
    public void onFailure(SdkError sdkError) {
        // Initialization failed
    }
});

// ...

// Example initialization of mapApi
// If coreApi is not yet initialized, this will internally do so.
// If coreApi is already inialized, the onCoreInitiated() callback will be immediate
mapApi.setup().initialize(params, new MapApi.MapInitCallback() {        

    @Override
    public void onCoreInitiated() {
        // Core initialized
    }

    @Override
    public void onSuccess() {
        // Map successfully initialized
    }        

    @Override
    public void onStatusUpdate(SdkStatusUpdate sdkUpdate) {
        // Status updates (warnings or information about what is going on)
    }

    @Override
    public void onFailure(SdkError sdkError) {
        // Initialization failed
    }
});

// ...

// Example initialization of mapUiApi
// If coreApi and/or mapApi are not yet initialized, this will internally do so.
// If coreApi and/or mapApi are already inialized, the corresponding callback method will be called immediately
mapUiApi.setup().initialize(params, new MapUiApi.MapUiInitCallback() {
                @Override
                public void onCoreInitialized() {
                     // Core initialized
                }

                @Override
                public void onMapInitialized() {
                    // Map initialized
                }

                @Override
                public void onSuccess() {
                   // MapUi initialized
                }

                @Override
                public void onStatusUpdate(SdkStatusUpdate sdkUpdate) {
                    // Status updates (warnings or information about what is going on)  
                }

                @Override
                public void onFailure(SdkError sdkError) {
                    // Initialization failed
                }
            },
            new MapUiApi.LocationServicesCallback() {
                @Override
                public void onLocationServicesStarted() {
                    // Location services has started
                }

                @Override
                public void onFailure(SdkError sdkError) {
                    // Location services failed to start
                    // e.g., no permissions
                }
            });

Note

Please be very careful not to create multiple instances of each module.

If you are using Location Marketing SDK, please note that you should initialize it only after the core-sdk is initialized.

// create an instance of the location marketing api (returns LocationMarketingApi)
LocationMarketingApi marketingApi = MapstedLocationMarketingApi.newInstance(
        getApplicationContext(),      // For showing dialogs, notifications, etc.
        coreApi,                      // Core SDK integration
        getSupportFragmentManager(),  // For handling dialog fragments
        getInAppNotificationApi(),    // To show in-app notifications
        entity -> {
            // Handle notification click or 'Navigate' button action here,
            // e.g. redirect to the given entity on the map.
            Logger.d("marketing entity: " + entity.getLongName());
        });

Not available on Android

The Mapsted Alerts module (sdk-alerts) was removed from the Android SDK in 26.7.1. Alerts is currently available on iOS only. See the Android migration guide.

If you are using Location Sharing SDK, please note that you should initialize it after the core-sdk is initialized.

 // Setup location share api instance instantiation, once CoreApi & MapUiApi are initialized
 LocationShareApi liveLocationShareAPI = new MapstedLocationShareApi(this.getApplicationContext(), coreApi, mapUiApi);
 liveLocationShareAPI.setup().initialize();

// Start location sharing
liveLocationShareAPI.events().shareLiveLocation(selectedPropertyId, position, liveLocationResponse -> {
    if (liveLocationResponse != null && liveLocationResponse.getSuccess()) {
        // location sharing started
    }
});

 // Stop location sharing
liveLocationShareAPI.events().deleteSharedLiveLocation(liveLocationResponse -> {
    // ...
});

 //Setting up location share callbacks
liveLocationShareAPI.addLiveLocationTriggerListener(status -> {
    //If status is true, location sharing is started.
    //If status is false, location sharing is stopped.
});

// Destroy instance in onDestroy()
liveLocationShareAPI.lifecycle().onDestroy();

If you are using Topbar Notification SDK, you can initialize it once Core SDK is successfully initialized.

    //The MapstedTopbarNotificationApi is initialized by providing the following:
    //FragmentManager: Used to manage and display the notification fragment.
    //Default Container (FrameLayout): The container view where the notifications will be displayed.
    //MapApi: The API that interacts with map-related notifications.
    //The initialization sets up the notification fragment in the provided container and associates it with the map API to handle notification events seamlessly.

    // Import necessary classes
    import androidx.fragment.app.FragmentManager
    import android.widget.FrameLayout

    // Example initialization
    val fragmentManager: FragmentManager = supportFragmentManager // Use FragmentManager from the activity or fragment
    val notificationContainer: FrameLayout = binding.topNotificationsContainer // The container for notifications
    val mapApiInstance: MapApi = mapApi // An instance of your MapApi implementation

    // Create an instance of MapstedTopbarNotificationApi
    val topNotificationApi = MapstedTopbarNotificationApi(
        fragmentManager = fragmentManager,
        defaultContainer = notificationContainer,
        mapApi = mapApiInstance
    )

Adding Notifications - Use the showInTopNotificationBar method to display a notification in the top bar.

    // Example notification to add
    val notification = TopbarNotifications(
        id = "notification_id_1", // Unique ID for the notification
        title = "New Notification",
        message = "This is a notification message",
        notificationType = 1 // Custom type identifier
    )

    // Add the notification to the top bar
    topNotificationApi?.showInTopNotificationBar(notification)

Removing Notifications - You can remove a notification using its unique ID

    // Remove the notification by its unique ID
    topNotificationApi?.removeFromTopNotificationBar("notification_id_1")

Follow the same steps to initialize Mapsted Prebuilt UI/UX Components as you did for Mapsted Map. You can use a variety of prebuilt UI/UX components (ui-components-sdk) within your own application, and you also have the ability to add UI/UX components into the MapView. Please see Prebuilt UI Components to learn more.

Choose this mode when you want to create your own application using some of Mapsted's prebuilt UI/UX components.

Choose this option if you prefer to use Mapsted's out-of-the-box app template. This mode doesn’t require any additional customization on your part.

Please see Prebuilt App Templates for more details.

7. Managing Location Services

The location services functionality enables developers to manage location tracking within the app, providing flexibility to start or stop services as needed. By default, location services initialize automatically when the SDK loads.

To prevent the app from automatically requesting location permissions, set the following parameter before SDK initialization:

    val params = CustomParams.newBuilder(this)
    // Add additional custom content here

    .setAutoRequestLocationPermissions(false)
    .build()

To manually start location services, use the following method:

    coreApi.setup().startLocationServices(this, object : CoreApi.LocationServicesCallback{
        override fun onSuccess() {
            //Location service started
        }

        override fun onFailure(sdkError: SdkError?) {
            //failed to start Location service
        }
    })

To stop location services, call the following method:

    coreApi.setup().stopLocationServices(this, object : CoreApi.LocationServicesCallback{
        override fun onSuccess() {
            //Location service stop success
        }

        override fun onFailure(sdkError: SdkError?) {
            //failed to stop Location service
        }
    })

To verify if location services are currently active, use:

    coreApi.setup().areLocationServicesRunning()

This returns a Boolean value indicating whether location services are active.

8. Location Simulator Testing

The location simulator feature of our mobile-sdk provides you the opportunity to force the blue-dot to slide along a predefined path. This can be extremely useful for feature development (e.g., if you want to develop your own UI for routing or geofence pop-ups). Note that this can also be useful for better visualizing what a user experience may be like when using your application.

When initializing the core-sdk, simply supply the CoreParams with a SimulatorPath. For reference, the SimulatorPath consists of:

public static class SimulatorPath {
    // Path the blue dot will slide along (can be multi-floor or multi-building)
    public List<MercatorZone> path = new ArrayList<>(); 

    // Speed at which it will slide
    // 1.0F will slide at a typical user walk-speed
    // For development purposes, you may want to increase this to test more rapidly (e.g., 2.0F or 4.0F)
    public float walkSpeedModifier = 1.0F;
}

When using the Square One Shopping Center sample property, the following methods can be used for generating some sample paths.

/**
 * Generates location simulator path along level one
 */
private List<MercatorZone> getLocationSimulatorPath_LevelOne_ToFido() {

    LatLng[] levelOneLatLngs = new LatLng[] {

            new LatLng(43.59270591410157,-79.64468396358342),
            new LatLng(43.59275554576186,-79.64405625196909),
            new LatLng(43.59293620465817,-79.64386985725366),
            new LatLng(43.59302554127498,-79.64237869953212),
            new LatLng(43.59312480402684,-79.64235677074178),
            new LatLng(43.5931704648377,-79.64221149250811),
            new LatLng(43.593152597568235,-79.6420333210891),
            new LatLng(43.59316116651411,-79.64169529771698),
            new LatLng(43.593177048529554,-79.64133621378046),
            new LatLng(43.59336167665214,-79.64134443707688),
            new LatLng(43.59344307166634,-79.6413142849905),
    };

    List<MercatorZone> simulatorPath = new ArrayList<>();
    Arrays.stream(levelOneLatLngs).forEach(latLng -> simulatorPath.add(new MercatorZone(504, 504, 941, MapCalc.toMercator(latLng))));

    return simulatorPath;
}

/**
 * Generates location simulator path along level one and level two to Foot Locker
 */
private List<MercatorZone> getLocationSimulatorPath_LevelOne_LevelTwo_ToFootLocker() {

    LatLng[] levelOneLatLngs = new LatLng[] {
            new LatLng(43.59270506141888,-79.64467918464558),
            new LatLng(43.59274299108304,-79.64407554834054),
            new LatLng(43.59284979290362,-79.6439460008228),
            new LatLng(43.59286875769334,-79.64355460194005),
            new LatLng(43.59291567056778,-79.64341265093671),
            new LatLng(43.59290777113583,-79.64330951843408),
    };

    LatLng[] levelTwoLatLngs = new LatLng[] {
            new LatLng(43.59290777113583,-79.64330951843408),
            new LatLng(43.59291305771916,-79.64321462730396),
            new LatLng(43.59354343449601,-79.64326847002535),
            new LatLng(43.59363085147197,-79.64315247246824),
            new LatLng(43.59367739812217,-79.6420787112964),
            new LatLng(43.59363085147197,-79.64207400869265),
    };

    List<MercatorZone> simulatorPath = new ArrayList<>();
    Arrays.stream(levelOneLatLngs).forEach(latLng -> simulatorPath.add(new MercatorZone(504, 504, 941, MapCalc.toMercator(latLng))));
    Arrays.stream(levelTwoLatLngs).forEach(latLng -> simulatorPath.add(new MercatorZone(504, 504, 942, MapCalc.toMercator(latLng))));

    return simulatorPath;
}

Finally, make sure to update your CoreParams as follows:

CoreParams.SimulatorPath paramsPath = new CoreParams.SimulatorPath();
paramsPath.path = getLocationSimulatorPath_LevelOne_ToFido(); // For example, from above
paramsPath.walkSpeedModifier = simulatorWalkSpeedModifier;

// Note that if you have an instance of CustomMapParams or CustomParams
// You can use those instead of creating a new instance of CoreParams.
coreParams.setSimulatorPath(paramsPath);

// Initialize as normal
coreApi.setup().initialize(coreParams, ...);

9. Fake Gps Testing

By mocking your location, you can test MapstedSDK to simulate being at the property. There are a number of apps that can mock gps data on your android device. Once installed, that app needs to be set as the Mock Location app in your device’s Settings. This setting is in devices Setting > Developer Option.

Here are the steps.

  1. Install any gps mocking app in your device from Google Play store. Here is one we have verified to be working. FakeGPS on Google Play Store

  2. Enable Developer Option in your device. Follow the instructions on this link to enable developer options. Once the developer option menu is enabled, open the Developer option menu. Find Select mock location app. Then select the fake gps app. This will set that app as the mock location provider.

  3. Open the Fake GPS app and set your location to the location you wish to test. (e.g., for our sample property, Square One Shopping Center, you may use 43.59305369537576, -79.64327301294524).

  4. Depending on fakegps app feature, you may be able to save this location so that you do not have to enter the coordinates again. It might also show up in location history in the app. The fakegps app may or may not contain this feature. The suggested FakeGps app has this convenience.

  5. Open your test app (e.g., you can use the Mapsted Sample app)

  6. If you need to simulate walking movement, you can shake/oscillate your device. When using mocked location, this simulated walking is limited to work for few meters only.