MapQuest Observer

Overview

MapQuest Observer allows clients to receive GPS observations generated from mobile applications using the MapQuest Tracking SDKs on a second by second basis.

MapQuest Observer is comprised of three parts: the Tracking SDK for Android, the Trace Firehose API, and the Trace History API.

MapQuest Observer SDK

Android Tracking SDK

Download Android Tracking AAR

Use Gradle

After creating your project, insert the following into your project's build.gradle file:

allprojects {
    repositories {
        jcenter()

        maven { url "http://artifactory.cloud.mapquest.com/artifactory/et-android-binaries" }
    }
}

Also, insert the following into your application's build.gradle file:

dependencies {
    compile('com.mapquest:asset-tracking:1.1.5@aar') {
        transitive = true
    }
}

Examples

Setting up the application

package com.mapquest.tracking.example;

import android.app.Application;

import com.mapquest.tracking.AdditionalObservationProvider;
import com.mapquest.tracking.LocationTracker;

import java.util.Collections;
import java.util.Map;
import java.util.concurrent.TimeUnit;

public class ExampleTrackingApplication extends Application {
    @Override
    public void onCreate() {
        super.onCreate();

        initializeTracker();
    }

    private void initializeTracker() {
        new LocationTracker.Builder(this, "") // TODO Update with your access key
                .withActiveLocationUpdatesDuringPassiveListening(TimeUnit.SECONDS.toMillis(15), true)
                .withPassiveListeningMinimumLocationUpdateIntervalDuration(TimeUnit.MINUTES.toMillis(3))
                .withPassiveListeningMinimumLocationUpdateDistance(0)
                .withProperty("deliveryNumber", 1L)
                .withProperty("driverEmployeeId", "ABC123")
                .withAdditionalObservationProvider(new AdditionalObservationProvider() {
                    @Override
                    public Map<String, Double> getAdditionalObservationData() {
                        return Collections.singletonMap("temperature", 23.4);
                    }
                }).buildAndInitialize();
    }
}

Basic Tracking

package com.mapquest.tracking.example;

import android.os.Bundle;
import android.support.v7.app.AppCompatActivity;
import android.view.WindowManager;
import android.widget.CompoundButton;
import android.widget.CompoundButton.OnCheckedChangeListener;
import android.widget.Toast;
import android.widget.ToggleButton;

import com.mapquest.tracking.LocationTracker;
import com.mapquest.tracking.LocationTracker.TrackingStateListener;

public class MainActivity extends AppCompatActivity {
    private ToggleButton mTrackingToggle;
    private TrackingStateListener mTrackingStateListener;

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

        setContentView(R.layout.activity_main);
        mTrackingToggle = (ToggleButton)findViewById(R.id.trackingToggle);

        mTrackingStateListener = buildTrackingStateListener();
    }

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

        // Update toggle to reflect whether tracking is in progress
        mTrackingToggle.setChecked(LocationTracker.getInstance().isTracking());

        mTrackingToggle.setOnCheckedChangeListener(new OnCheckedChangeListener() {
            @Override
            public void onCheckedChanged(CompoundButton toggle, boolean checked) {
                if (checked) {
                    startTracking();
                } else {
                    stopTracking();
                }
            }
        });

        LocationTracker.getInstance().addTrackingStateListener(mTrackingStateListener);
    }

    @Override
    protected void onStop() {
        // Because LocationTracker exists as a singleton, if you use TrackingStateListeners, be sure
        // to unregister any that might leak a reference to something like an Activity.
        LocationTracker.getInstance().removeTrackingStateListener(mTrackingStateListener);

        // Clear listener
        mTrackingToggle.setOnCheckedChangeListener(null);

        super.onStop();
    }

    private void startTracking() {
        LocationTracker.getInstance().startTrackingActively();

        // Keep the screen on while tracking
        getWindow().addFlags(WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON);
    }

    private void stopTracking() {
        LocationTracker.getInstance().stopTracking();

        // Allow the screen to turn off again
        getWindow().clearFlags(WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON);
    }

    private TrackingStateListener buildTrackingStateListener() {
        return new TrackingStateListener() {
            @Override
            public void onTrackingStopped(final boolean userInitiated) {
                if(!userInitiated) {
                    runOnUiThread(new Runnable() {
                        @Override
                        public void run() {
                            mTrackingToggle.setChecked(false);
                            mTrackingToggle.setEnabled(false); // No use in letting a user try again if their key wasn't valid.

                            Toast.makeText(MainActivity.this,
                                    R.string.tracking_disabled_message,
                                    Toast.LENGTH_LONG).show();
                        }
                    });
                }
            }
        };
    }
}

Setting up the Manifest

<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
    package="com.mapquest.tracking.example">

    <application
        android:name=".ExampleTrackingApplication"
        android:label="@string/app_name"
        android:theme="@style/AppTheme">

        <activity
            android:name=".MainActivity"
            android:label="@string/app_name">

            <intent-filter>
                <action android:name="android.intent.action.MAIN" />
                <category android:name="android.intent.category.LAUNCHER" />
            </intent-filter>
        </activity>

        <receiver android:name="com.mapquest.tracking.core.receiver.ActiveLocationUpdateAlarmReceiver"
            android:exported="false"
            android:enabled="false">
            <intent-filter>
                <action android:name="com.mapquest.tracking.intent.action.REQUEST_ACTIVE_LOCATION_UPDATE" />
                <category android:name="com.mapquest.tracking.example" />
            </intent-filter>
        </receiver>

        <receiver android:name="com.mapquest.tracking.core.receiver.LocationReportingAlarmReceiver"
            android:exported="false"
            android:enabled="false">
            <intent-filter>
                <action android:name="com.mapquest.tracking.intent.action.REPORT_LOCATIONS" />
                <category android:name="com.mapquest.tracking.example" />
            </intent-filter>
        </receiver>
    </application>
</manifest>

MapQuest Observation Data Pipeline

Trace Firehose

The Trace Firehose API provides access to GPS observations using industry standard transports such as standard HTTP streaming, Server Side Events, and Web Sockets. The Trace Firehose API provides low latency, high throughput, near real-time access to GPS observations.

STREAM
Trace Firehose API

/daas/v1/trace

Trace History

The Trace History API allows users to query the service for the saved location observations (also referred to as 'traces') for devices by ID.

GET
Last Values

/daas/v1/trace/lastValues

GET
Range

/daas/v1/trace/range