Skip to content

The Android SDK Guide

DHollowellHPE edited this page Oct 27, 2026 · 1 revision

The Android SDK Guide

The Meridian Android SDK has all the tools you’ll need to embed the Meridian Editor’s maps, turn-by-turn navigation, indoor location awareness, and notifications into your own custom Android app.

Once you’ve added maps, routes, and placemarks to the Meridian Editor, you can use the Meridian SDK to integrate that content into your Meridian-powered Android app.

Go here for the Meridian Android SDK Reference documentation.

Go here to download the latest version of the Android SDK.

The Meridian Samples App

The Meridian Samples app is included with the Android SDK to demonstrate common Meridian features and workflows.

Add the SDK to Your Project

In order to simplify using the Meridian SDK library with your Android project, we’ve bundled our SDK code into a binary distribution of the Android Library Project (AAR) file.

The Meridian SDK supports devices with Android 11, API Level 30 and higher.

The Meridian SDK targets the latest version of Android

Add the AAR Relative Path

Complete these steps to add the AAR file to your Android project.

  1. Choose a location for meridian-x.y.z.aar.

  2. Edit your app’s build.gradle file to add the relative path to the meridian-x-y-z.aar file location inside flatDir { }, where our app will look for dependencies. Into repositories { }, insert:

    repositories {
        google()
        mavenCentral()
        // Tell gradle to look in our parent directory for the meridian AAR package.
        flatDir {
            dirs '[relative file path to the AAR directory]'
        }
    }

Add Dependencies

To use the Meridian SDK classes in your project, add the implementation information for the dependencies to the build.gradle file. These are the meridian-x.y.z.aar file and two required external dependencies.

To find the project’s current dependencies, look in build.gradle in the MeridianSamples directory.

In the build.gradle file inside dependencies { }, insert implementation for the meridian-x.y.z.aar file and the three required external dependencies:

dependencies {
        implementation 'com.arubanetworks.meridian:meridian:x.y.z@aar'

        // Google Support Libraries
        implementation 'androidx.legacy:legacy-support-v4:1.0.0'
        implementation 'androidx.appcompat:appcompat:1.4.0'
        // Required for GPS on newer Android devices.
        implementation 'com.google.android.gms:play-services-location:18.0.0'
        implementation 'com.google.android.material:material:1.7.0'

        // The SDK also has these external dependencies that you'll need to include: 
        implementation 'com.android.volley:volley:1.2.1'
        implementation 'com.squareup:otto:1.3.8'
        implementation 'org.conscrypt:conscrypt-android:2.5.2'
        implementation 'org.greenrobot:eventbus:3.3.1'
        implementation 'com.lemmingapex.trilateration:trilateration:1.0.2'
}

Import Packages

When this is done, you’ll be able to import the com.arubanetworks.meridian packages to your project and use Meridian classes in your source files.

The SDK’s MeridianSamples/app project folder has an example of what the finished build.gradle file should look like.

Add Permissions

To enable the Meridian SDK’s location-awareness features, add the following permissions to your project’s AndroidManifest.xml file:

<!-- For using GPS and Location in general -->
<uses-permission android:name="android.permission.ACCESS_FINE_LOCATION"/>

<!-- For using location derived from bluetooth beacons -->
<uses-permission android:name="android.permission.BLUETOOTH"/>
<uses-permission android:name="android.permission.BLUETOOTH_ADMIN"/>

<!-- For using location derived from bluetooth beacons on Android 12 and later -->
<uses-permission android:name="android.permission.BLUETOOTH_SCAN/>

To enable Meridian SDK's location-aware features (e.g. location sharing) in the background, add the following permission to your project’s AndroidManifest.xml file and request the permission from the user as required for the Android version:

<!-- For using bluetooth in the background -->
<uses-permission android:name="android.permission.ACCESS_BACKGROUND_LOCATION"/>

Configure the SDK

Before you can use the features of the Meridian SDK, you’ll need to create an instance of MeridianConfig. This will configure the SDK.

Meridian uses token-based authentication. In order for your Meridian-powered app to communicate with the Editor, you’ll need to specify a Meridian token when initializing the SDK.

Put the following line in the onCreate method of your Application class or main activity.

    // Configure Meridian
    Meridian.configure(this, YOUR_EDITOR_TOKEN);

Using Editor Keys

Use instances of EditorKey to specify apps, maps, and placemarks that have been created in the Meridian Editor. Most of the Meridian SDK classes require a valid key during initialization.

    // Create a key representing your app in the Meridian Editor.
    EditorKey appKey = new EditorKey("5809862863224832");

    // Create a key representing a map in the Meridian Editor.
    EditorKey mapKey = EditorKey.forMap("5668600916475904", appKey.getId());

    // Create a key representing a placemark.
    EditorKey placemarkKey = EditorKey.forPlacemark("5668600916475904_5709068098338816", mapKey);

When you create an EditorKey to represent a map, the app identifier you provide becomes the parent of the map key. Likewise, when you create a placemarkKey, the map you specify becomes the parent of that placemark.

    EditorKey placemarkKey = EditorKey.forPlacemark("375634485771", someMapKey);

    EditorKey mapKey = placemarkKey.getParent();
    Log.i(TAG, "My map ID: " + mapKey.getId());

    EditorKey appKey = mapKey.getParent();
    Log.i(TAG, "My app ID: " + appKey.getId());

Display Maps

You can use MapFragment to provide a self-contained interface for maps and directions. Simply initialize the fragment with a valid EditorKey:

    // Create a key representing your app in the Meridian Editor.
    EditorKey appKey = new EditorKey("5809862863224832");

    // Create a key representing a map in the Meridian Editor.
    EditorKey mapKey = EditorKey.forMap("5668600916475904", appKey.getId());

    MapFragment mapFragment = new MapFragment.Builder().setMapKey(mapKey).build();

MapFragment hosts a MapView and implements the MapView.MapViewListener interface, handling the basic tasks delegated by MapView.

You can also use MapView directly in your own activity or fragment, optionally implementing methods defined by the MapView.MapViewListener interface so that your activity can respond to MapView events.

Call the setMapKey() method to choose the map to display.

NOTE: We strongly advise using MapFragment whenever possible. If you decide to use a MapView independently, you must always pass your activity’s pause/resume/destroy events to the MapView to ensure resources are managed properly.

    // Using pause/resume/destroy events with a MapView in your activity

    private MapView mapView;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);

        EditorKey appKey = new EditorKey("5809862863224832");
        mapView = new MapView(this);
        mapView.setAppKey(appKey); 

        // If you want to handle MapView events
        mapView.setListener(this);

        // Set the map to load
        mapView.setMapKey(EditorKey.forMap("5668600916475904", appKey.getId()));

        // Assume myLayout is this activity's root view
        myLayout.addView(mapView);
    }

    @Override
    protected void onResume() {
        super.onResume();

        // MapView needs to know when its host activity is resumed
        mapView.onResume();
    }

    @Override
    protected void onPause() {
        super.onPause();

        // MapView needs to know when its host activity is paused
        mapView.onPause();
    }

    @Override
    protected void onDestroy() {
        super.onDestroy();

        // MapView needs to know when its host activity is destroyed
        mapView.onDestroy();
    }

Load Directions

MapFragment handles loading and presenting directions in response to user interaction. When you create the map fragment, include the pendingDestination parameter to present directions to a placemark when direction-finding resumes.

If you’re using MapView directly in your activity, you’ll need to load the directions manually with the Directions class.

To do so, first ensure that your activity implements the Directions.DirectionsRequestListener interface so that it can handle the results of the directions request. Use a Directions.Builder instance to configure the details of the desired route. To do this, specify the start and end points for the route using instances of DirectionsSource and DirectionsDestination, which contain information about a point or placemark on a map.

Next, call build() to create the Directions object from the builder.

Finally, call calculate() to start the directions process.

The Directions object will call onDirectionsComplete() after successful completion or onDirectionsError() if something went wrong.

In the following code example, MeridianLocation is the source of the directions.

A new route is calculated when the user’s blue dot location is approximately 10 meters from the route. To customize the reroute distance, you can use Meridian.getShared().setRerouteDistance().

Related to this, you can also use Meridian.getShared().setRouteSnapDistance() to configure the distance from the route at which the user's blue dot will be "snapped" to the determined route. This value is 5 meters by default.

    // In your Activity

    private static final EditorKey appKey = new EditorKey("YOUR_APP_KEY");

    private void getDirections(MeridianLocation source, Placemark destination) {
        Directions.Builder directionsBuilder = new Directions.Builder()
                .setAppKey(appKey)
                .setSource(DirectionsSource.forMapPoint(source.getMap(), source.getPoint()))
                .setDestination(DirectionsDestination.forPlacemarkKey(destination.getKey()))
                .setTransportType(TransportType.WALKING)
                .setListener(this);

        Directions directions = directionsBuilder.build();
        directions.calculate();
    }

    @Override
    public void onDirectionsComplete(DirectionsResponse response) {
        if (response.getRoutes().size()  0) {

            // Normally only one route will be returned
            Route route = response.getRoutes().get(0);

            // If we have a MapView we can tell it to display this route
            myMapView.setRoute(route);
        }
    }

If a current location isn’t available, you may want to prompt the user to choose a starting location with SearchActivity.

In the example, SearchActivity and startActivityForResult() will prompt the user to choose a starting placemark.

    // In your Activity

    private Directions.Builder directionsBuilder;
    private static final EditorKey appKey = new EditorKey("5085468668573440");
    public static final int PLACEMARK_PICKER_CODE = 42;

    private void getDirections(Placemark placemark) {
        directionsBuilder = new Directions.Builder()
            .setContext(this)
            .setAppKey(appKey)
            .setDestination(DirectionsDestination.forPlacemark(placemark))
            .setTransportType(TransportType.WALKING)
            .setListener(this);

        // start a search Activity to get the starting point for the route
        startActivityForResult(SearchActivity.createIntent(this, appKey), PLACEMARK_PICKER_CODE);
    }

    @Override
    public void onActivityResult(int requestCode, int resultCode, Intent data) {

        // Now that the user picked a placemark to start from, we can calculate the route
        if (requestCode == PLACEMARK_PICKER_CODE) {
            if (resultCode == Activity.RESULT_OK) {

                LocalSearchResult result = (LocalSearchResult) data.getSerializableExtra(SearchActivity.SEARCH_RESULT_KEY);
                Placemark source = result.getPlacemark();
                directionsBuilder.setSource(DirectionsSource.forPlacemark(source));
                directions = directionsBuilder.build();
                directions.calculate();
            }
        }
    }

Get a User’s Location

A user’s most recent location can be retrieved with the LocationRequest class. This request is asynchronous.

    private LocationRequest request = null;
        private static final EditorKey appKey = new EditorKey("5809862863224832");
        @Override
        public void onResume() {
            super.onResume();
            request = LocationRequest.requestCurrentLocation(getActivity(), appKey, new LocationRequest.LocationRequestListener() {
                @Override
                public void onResult(MeridianLocation location) {
                    // Update UI with new Location
                }

                @Override
                public void onError(LocationRequest.ErrorType location) {
                    // Notify user that there was an error retrieving the location

                }
            });
        }

        @Override
        public void onPause() {
            if (request != null && request.isRunning()) {
                request.cancel();
                request = null;
            }
            super.onPause();
        }

Get Continuous Updates About a User’s Location

MeridianLocationManager determines the user’s location by gathering all available location data for your Meridian-powered app. Implement the MeridianLocationManager.LocationUpdateListener interface to get callbacks as new locations are gathered.

    // In an Activity that implements the LocationUpdateListener interface

    private static final EditorKey appKey = new EditorKey("5809862863224832");
        private MeridianLocationManager locationHelper;

        @Override
        protected void onCreate(Bundle savedInstanceState) {
            super.onCreate(savedInstanceState);
            locationHelper = new MeridianLocationManager(this, appKey, this);
            // Build out the UI ...
        }

        @Override
        protected void onStart() {
            locationHelper.startListeningForLocation();
            super.onStart();
        }

        @Override
        protected void onStop() {
            locationHelper.stopListeningForLocation();
            super.onStop();
        }

        @Override
        public void onLocationUpdate(MeridianLocation location) {
            // Update the UI with the new location
        }

        @Override
        public void onLocationError(Throwable tr) {
            // Update the UI to inform the user that their location could not be determined.
        }

Location Sharing

Location sharing lets users share their location with each other.

Prerequisites

Location Sharing requires a blue dot subscription.

If you haven’t already done so, you’ll need to generate a valid token in the Editor. To generate one, in the sidebar menu click Permissions, and then click Application Tokens. Click Add Application + to generate a token for your app. You can name it anything.

When configuring the Meridian SDK, set the application token you generated in the Editor:

    LocationSharing.init("kd84hf83ck93k39dyi3nxo3mf94");

For best results, call init from your Application class.

LocationSharing

LocationSharing is the main access point to the Location Sharing API. Use the User, Friend, Invite, and Location classes to get the Location Sharing data.

Create Accounts

    // Creates a location sharing user. All users require a first name. Last name is optional.
    User sampleUser = new User();
    sampleUser.setFirstName("Sample User");

    LocationSharing.shared().createUser(sampleUser, new LocationSharing.Callback

Start Location Sharing

    LocationSharing.shared().startPostingLocationUpdates(applicationContext);

Stop Location Sharing

    LocationSharing.shared().stopPostingLocationUpdates(applicationContext);

Check Location Sharing Status

    LocationSharing.shared().isUploadingServiceRunning()

    // example: button that performs start and stop sharing location
    if (LocationSharing.shared().isUploadingServiceRunning()) {
        LocationSharing.shared().stopPostingLocationUpdates(applicationContext);
    } else {
        LocationSharing.shared().startPostingLocationUpdates(applicationContext);
    }

Start and Stop Location Sharing Listener

    LocationSharing.shared().addListener(new LocationSharing.Listener() {
            @Override
            public void onPostingLocationUpdatesStarted() {
                // ...
            }

            @Override
            public void onFriendsUpdated(List

Create an Invite

Invitations expire after 7 days.

    LocationSharing.shared().createInvite(new LocationSharing.Callback

Get the Current Friend List

    LocationSharing.shared().getFriends(new LocationSharing.Callback

createInvite and getFriends

LocationSharing keeps a copy of the current user, for use by calls like createInvite and getFriends. The implementor is responsible for storing the current user and setting it to the LocationSharing object.

When an account is created, the new user is automatically set to the current user.

Store the New User

After creating the new user, store it:

    LocationSharing.shared().createUser(newUser, new LocationSharing.Callback

Set the Current User

If a user restarts the app, the current user needs to be set again. This is equivalent to a login operation.

    LocationSharing.shared().setCurrentUser(OurOwnStorage.retrieveLocationSharingUser());

Using Local Search

You can use the LocalSearch classes to find points of interest near a user’s location. You’ll usually use this in conjunction with MeridianLocationManager so that you can provide a location and nearby placemarks.

For best performance, limit local search results to 20 or less.

    // This Activity implements the LocalSearch.LocalSearchListener interface

    private void findNearbyCafe() {
        LocalSearch localSearch = new LocalSearch.Builder()
            .setQuery("Cafe")
            .setApp(appKey)
            .setLocation(locationManager.getLocation())
            .setListener(this)
            .setLimit(20)
            .build();

        localSearch.start();
    }

    @Override
    public void onSearchComplete(LocalSearchResponse response) {
        for (LocalSearchResult result : response.getResults()) {
            Log.i(TAG, String.format("%s is %f seconds away", result.getPlacemark().name, result.time / 1000));
        }
    }

    @Override
    public void onSearchError(Throwable tr) {
        Log.e(TAG, "Search error", tr);
    }

Asset Tracking

Asset Tracking is a feature that uses BLE Tags hardware to track valuable locations on a map. You can use the SDK to get Tag location updates and render Tag locations on a map.

Get Tag Updates

Before you can get Tag updates, you’ll need to create an instance of Asset Tracking’s main class, TagStream.

First, create your own instance of TagStream using its Builder:

    tagStream = new TagStream.Builder()
                            .setMapKey(yourMapKeyHere)
                            .setListener(this)
                            .build();

With the TagStream instance created, call the following method to get updates on your tagged assets:

    tagStream.startUpdatingTags();

To stop getting updates:

    tagStream.stopUpdatingTags();

The TagStream builder class takes a listener that will be used to pass information about Tags to your code. The listener must implement two methods:

    void onTagsUpdated(List

The first method will be called when we get information about new Tags or when existing Tags are updated. This list of Tags will contain all Tags.

The second method will get called when a Tag is removed. This list of Tags will contain the deleted Tags.

To dispose of the TagStream:

    tagStream.dispose();

Render Tags on the Map

Use the marker TagMarker to render your Tags on a map. It will show a generic asset icon. Create a marker in the following way:

    tagMarker = new TagMarker(getContext(), tag);

The marker gets the name and position of the marker from the tag object. At that point, you can add it to your map.

You can find working examples of this in the Samples app with TagsFragment and SingleTagFrament.

Clone this wiki locally