Install SDK on React Native

GitHub npm iOS SDK Android SDK

HyperTrack lets you add live location tracking to your mobile app. Live location is made available along with ongoing activity, tracking controls and tracking outage with reasons.

React Native HyperTrack SDK is a wrapper around native iOS and Android SDKs that allows to integrate them into React Native apps.

SDK provides access to functionality that collects location, activity and device health data. The module exposes methods to start and stop tracking, and interact with the HyperTrack APIs.

Functionality is provided through one single npm package so you can use it for both platforms without downloading any extra packages.

Integrate the React Native SDK

First, go to Setup page, where you can copy your publishable key.

In case you are not using React Native, you can refer to the iOS or Android versions. If you want to quickly try the module in a test app, you can use the React Native Quickstart app.

You will need either npm or Yarn in order to install the SDK and configure the Android and iOS projects.

  1. Create React Native project
  2. Install JavaScript packages
  3. Configure projects
  4. Enable remote notifications
  5. Usage

Step 1: Create React Native project

First create a React Native project:

react-native init YourApp

Step 2: Install JavaScript packages

Run yarn (or npm install, if using npm) inside your new YourApp directory:

cd YourApp
yarn

Then, install the hypertrack-sdk-react-native package:

yarn add hypertrack-sdk-react-native

Or, if using npm:

npm install hypertrack-sdk-react-native --save
note

We constantly work on making our SDKs better, so make sure you have the latest version of it. You might take a look of its changelog here.

Step 3: Configure projects

Android

Assuming you have latest Android Studio installed, open the project with Android Studio.

Go to build.gradle and change minimum sdk version:

minSdkVersion = 21

Add in repositories section:

maven {
name 'hypertrack'
url 'https://s3-us-west-2.amazonaws.com/m2.hypertrack.com/'
}

iOS

Add HyperTrack iOS SDK to your Podfile

The native iOS SDK is distributed using CocoaPods dependency manager.

If you don't have CocoaPods, install it first. Using the latest version is advised.

In your project's ios directory, create a Podfile (if you don't have one).

cd ios
pod init

HyperTrack iOS SDK supports iOS 11 and above, that's why platform :ios, '11.0' is included explicitly. And lastly, add the post_install script to keep dependencies with the correct Swift version.

require_relative '../node_modules/react-native/scripts/react_native_pods'
require_relative '../node_modules/@react-native-community/cli-platform-ios/native_modules'
platform :ios, '11.0'
target 'Quickstart' do
config = use_native_modules!
use_react_native!(:path => config["reactNativePath"])
# Enables Flipper.
#
# Note that if you have use_frameworks! enabled, Flipper will not work and
# you should disable these next few lines.
use_flipper!
post_install do |installer|
flipper_post_install(installer)
end
end

Install the native HyperTrack SDK through CocoaPods:

pod install
important

If your using Xcode 12 and newer, open your workspace in Xcode, right-click on Your App Name in the Project Navigator on the left, and click New File. Create a single empty Swift file to the project (make sure that Your App Name target is selected when adding) when Xcode asks, press Create Bridging Header and do not remove Swift file then.

Enable background location updates

Enable Background Modes in your project target's Capabilities tab. Choose "Location updates".

Capabilities tab in Xcode

Add purpose strings

Set the following purpose strings in the Info.plist file:

Always authorization location

You can ask for "When In Use" permission only, but be advised that the device will see a blue bar at the top while your app is running.

In use authorization location

Be advised, purpose strings are mandatory, and the app crashes without them.

Step 4: Enable remote notifications

The SDK has a bi-directional communication model with the server. This enables the SDK to run on a variable frequency model, which balances the fine trade-off between low latency tracking and battery efficiency, and improves robustness. This also enables HyperTrack Trips to start and stop tracking automatically when trip starts and ends. For this purpose, the iOS SDK uses APNs silent remote notifications and Android SDK uses FCM silent notifications.

Android

This guide assumes you have configured FCM in your application. If you haven't, read the Firebase guide.

Configure FCM key on the Dashboard

Log into the HyperTrack dashboard, and open the setup page. Enter your FCM Key.

This key will only be used to send remote push notifications to your apps.

iOS

This guide assumes you have configured APNs in your application. If you haven't, read the iOS documentation on APNs.

Configure APNs on the dashboard

Log into the HyperTrack dashboard, and open the setup page. Upload your Auth Key (file in the format AuthKey_KEYID.p8) and fill in your Team ID.

This key will only be used to send remote push notifications to your apps.

Enable remote notifications in the app

In the app capabilities, ensure that remote notifications inside background modes is enabled.

Remote Notifications in Xcode

In the same tab, ensure that push notifications is enabled.

Push Notifications in Xcode

Registering and receiving notifications

The following changes inside AppDelegate will register the SDK for push notifications and route HyperTrack notifications to the SDK. Open your /ios/{projectName}/AppDelegate.m file.

At the top of the file, import the HyperTrack SDK:

@import HyperTrack;
Register for notifications

Inside didFinishLaunchingWithOptions, use the SDK method to register for notifications.

- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions {
[HTSDK registerForRemoteNotifications];
return YES;
}
Register device token

Inside and didRegisterForRemoteNotificationsWithDeviceToken and didFailToRegisterForRemoteNotificationsWithError methods, add the relevant lines so that HyperTrack can register the device token.

- (void)application:(UIApplication *)application didRegisterForRemoteNotificationsWithDeviceToken:(NSData *)deviceToken {
[HTSDK didRegisterForRemoteNotificationsWithDeviceToken:deviceToken];
}
- (void)application:(UIApplication *)application didFailToRegisterForRemoteNotificationsWithError:(NSError *)error {
[HTSDK didFailToRegisterForRemoteNotificationsWithError:error];
}
Receive notifications

Inside the didReceiveRemoteNotification method, add the HyperTrack receiver. This method parses only the notifications that sent from HyperTrack.

- (void)application:(UIApplication *)application didReceiveRemoteNotification:(NSDictionary *)userInfo fetchCompletionHandler:(void (^)(UIBackgroundFetchResult))completionHandler {
[HTSDK didReceiveRemoteNotification:userInfo fetchCompletionHandler:completionHandler];
}

If you want to make sure to only pass HyperTrack notifications to the SDK, you can use the "hypertrack" key:

- (void)application:(UIApplication *)application didReceiveRemoteNotification:(NSDictionary *)userInfo fetchCompletionHandler:(void (^)(UIBackgroundFetchResult))completionHandler {
if (userInfo[@"hypertrack"] != nil) {
// This is HyperTrack's notification
[HTSDK didReceiveRemoteNotification:userInfo fetchCompletionHandler:completionHandler];
} else {
// Handle your server's notification here
}
}

Step 5: Usage

// Import HyperTrack SDK API
// You can also use CriticalErrors to react to different kind of errors preventing tracking (ex: permissions deined)
import {CriticalErrors, HyperTrack} from 'hypertrack-sdk-react-native';
const PUBLISHABLE_KEY = "Paste_your_publishable_key_here";
export default class App extends Component {
state = {
deviceId: "",
trackingState: "Stopped",
isTracking: false
};
_initializeHyperTrack = async () => {
// (Optional) This turns on logging for underlying native SDKs. Placed on top so SDKs start logging immediately
HyperTrack.enableDebugLogging(true);
// Initialize HyperTrack with a publishable key
this.hyperTrack = await HyperTrack.createInstance(PUBLISHABLE_KEY, true);
// Obtain the unique HyperTrack's DeviceID identifier to use it with HyperTrack's APIs
const deviceId = await this.hyperTrack.getDeviceID();
this.setState({deviceId: deviceId});
// (Optional) Set the device name to display in dashboard (for ex. user name)
this.hyperTrack.setDeviceName("RN Quickstart");
// (Optional) Attach any JSON metadata to this device to see in HyperTrack's API responses
this.hyperTrack.setMetadata({driver_id: "83B3X5", state: "IN_PROGRESS"});
// (Optional) Register tracking listeners to update your UI when SDK starts/stops or react to errors
this.hyperTrack.registerTrackingListeners(this,
// Display or log errors
(error) => {
if (error.code === CriticalErrors.INVALID_PUBLISHABLE_KEY
|| error.code === CriticalErrors.AUTHORIZATION_FAILED) {
console.log("Initialization failed")
} else {
console.log("Tracking failed")
}
this.setState({
trackingState: "Stopped with error: " + error.code + " - " + error.message,
isTracking: false
})
},
// Update UI when tracking starts
() => this.setState({trackingState: "Started", isTracking: true}),
// Update UI when tracking stops
() => this.setState({trackingState: "Stopped", isTracking: false}));
};
// Call the initialization in componentWillMount
UNSAFE_componentWillMount() {
this._initializeHyperTrack();
}
// (Optional) Unregister tracking listeners if they were registered in previous step
UNSAFE_componentWillUnmount() {
this.hyperTrack.unregisterTrackingListeners(this);
}

Step 6: Tag locations with geotags

Some places are more important then the others, so you can mark them on map, creating geotag when specific action in your app happens (e.g. delivery is marked done or driver confirmend pickup)

// Tag the geolocation of app action
this.hyperTrac.addGeotag({"action": "Login"});

If you already know the address, where action is supposed to happen, you can specify it to analyze the deviations

// Tag the geolocation of app action
const expectedLocation = {latitude: 35.0476912, longitude: -90.0260493};
this.hyperTrac.addGeotag({"action": "Login"}, expectedLocation);

Step 7: Prepare for App Store and Play Market submission

Read the Prepare for App Store submission section of iOS SDK guide and Get approved for the background location access section of Android SDK guide.

You are all set

You can now run the app and start using HyperTrack. You can see your devices on the dashboard.

Dashboard

Once your app is running, go to the dashboard where you can see a list of all your devices and their live location with ongoing activity on the map.

Dashboard

Frequently Asked Questions

iOS

Supported versions on iOS

Currently we do support all of the iOS versions starting from iOS 11.

Error: Access to Activity services has not been authorized

You are running your app on the iOS simulator, which currently does not support CoreMotion services. You can test the quickstart app on real iOS devices only.

Android

What API levels (Android versions) are supported?

Currently we do support all of the Android versions starting from API 21 (Android 5.0 Lollipop).

Why do I have dependencies conflicts?

SDK dependencies graph looks like below:

+--- com.android.volley:volley:1.2.0
+--- com.google.code.gson:gson:2.8.6
+--- org.greenrobot:eventbus:3.1.1
+--- org.jetbrains.kotlinx:kotlinx-coroutines-android:1.4.1
+--- org.jetbrains.kotlinx:kotlinx-coroutines-core:1.4.1
\--- org.jetbrains.kotlinx:kotlinx-coroutines-core-jvm:1.4.1
+--- org.jetbrains.kotlin:kotlin-stdlib:1.4.0
\--- org.jetbrains.kotlin:kotlin-stdlib-common:1.4.0
\--- org.jetbrains.kotlin:kotlin-stdlib:1.4.0
+--- androidx.appcompat:appcompat:1.3.0 (*)
+--- androidx.legacy:legacy-support-v4:1.0.0 (*)
+--- com.google.android.gms:play-services-location:18.0.0 // safe to downgrade to 17.1.0
+--- com.google.android.gms:play-services-base:17.5.0
+--- androidx.collection:collection:1.0.0
+--- androidx.core:core:1.2.0
+--- androidx.fragment:fragment:1.0.0
+--- com.google.android.gms:play-services-basement:17.5.0
+--- androidx.collection:collection:1.0.0
+--- androidx.core:core:1.2.0
\--- androidx.fragment:fragment:1.0.0
\--- com.google.android.gms:play-services-tasks:17.2.0
\--- com.google.android.gms:play-services-basement:17.4.0
+--- com.google.android.gms:play-services-basement:17.5.0 (*)
+--- com.google.android.gms:play-services-places-placereport:17.0.0
\--- com.google.android.gms:play-services-basement:17.0.0
\--- com.google.android.gms:play-services-tasks:17.1.0
+--- androidx.annotation:annotation:1.2.0
+--- com.google.firebase:firebase-messaging:22.0.0 // safe to downgrade to 17.0.0
+--- androidx.collection:collection:1.0.0
+--- androidx.core:core:1.0.0
+--- com.google.android.datatransport:transport-api:3.0.0
\--- androidx.annotation:annotation:1.1.0
+--- com.google.android.datatransport:transport-backend-cct:3.0.0
+--- androidx.annotation:annotation:1.1.0
+--- com.google.android.datatransport:transport-api:3.0.0 (*)
+--- com.google.android.datatransport:transport-runtime:3.0.0
+--- androidx.annotation:annotation:1.1.0
+--- com.google.android.datatransport:transport-api:3.0.0 (*)
\--- javax.inject:javax.inject:1
+--- com.google.firebase:firebase-encoders:17.0.0
\--- androidx.annotation:annotation:1.1.0
\--- com.google.firebase:firebase-encoders-json:18.0.0
+--- androidx.annotation:annotation:1.1.0
\--- com.google.firebase:firebase-encoders:17.0.0 (*)
+--- com.google.android.datatransport:transport-runtime:3.0.0 (*)
+--- com.google.android.gms:play-services-basement:17.0.0
+--- com.google.android.gms:play-services-cloud-messaging:16.0.0
+--- com.google.android.gms:play-services-basement:17.0.0
\--- com.google.android.gms:play-services-tasks:17.0.0
+--- com.google.android.gms:play-services-stats:17.0.0
+--- androidx.legacy:legacy-support-core-utils:1.0.0 (*)
\--- com.google.android.gms:play-services-basement:17.0.0
+--- com.google.android.gms:play-services-tasks:17.0.0
+--- com.google.firebase:firebase-common:20.0.0
+--- com.google.android.gms:play-services-basement:17.0.0
+--- com.google.android.gms:play-services-tasks:17.0.0
\--- com.google.firebase:firebase-components:17.0.0
+--- androidx.annotation:annotation:1.1.0
\--- com.google.firebase:firebase-annotations:16.0.0
+--- com.google.firebase:firebase-components:17.0.0 (*)
+--- com.google.firebase:firebase-datatransport:18.0.0
+--- androidx.annotation:annotation:1.1.0
+--- com.google.android.datatransport:transport-api:3.0.0 (*)
+--- com.google.android.datatransport:transport-backend-cct:3.0.0 (*)
+--- com.google.android.datatransport:transport-runtime:3.0.0 (*)
+--- com.google.firebase:firebase-common:20.0.0 (*)
\--- com.google.firebase:firebase-components:17.0.0 (*)
+--- com.google.firebase:firebase-iid-interop:17.1.0
+--- com.google.android.gms:play-services-basement:17.0.0
\--- com.google.android.gms:play-services-tasks:17.0.0
+--- com.google.firebase:firebase-installations:17.0.0
+--- com.google.android.gms:play-services-tasks:17.0.0
+--- com.google.firebase:firebase-common:20.0.0 (*)
+--- com.google.firebase:firebase-components:17.0.0 (*)
\--- com.google.firebase:firebase-installations-interop:17.0.0
+--- com.google.android.gms:play-services-tasks:17.0.0
\--- com.google.firebase:firebase-annotations:16.0.0
+--- com.google.firebase:firebase-installations-interop:17.0.0 (*)
\--- com.google.firebase:firebase-measurement-connector:19.0.0
+--- com.google.android.gms:play-services-basement:17.0.0
\--- com.google.firebase:firebase-annotations:16.0.0
+--- androidx.lifecycle:lifecycle-extensions:2.2.0
+--- androidx.lifecycle:lifecycle-runtime:2.2.0
+--- androidx.arch.core:core-common:2.1.0 (*)
+--- androidx.arch.core:core-runtime:2.1.0 (*)
+--- androidx.fragment:fragment:1.2.0
+--- androidx.lifecycle:lifecycle-common:2.2.0
+--- androidx.lifecycle:lifecycle-livedata:2.2.0 (*)
+--- androidx.lifecycle:lifecycle-process:2.2.0
\--- androidx.lifecycle:lifecycle-runtime:2.2.0
+--- androidx.lifecycle:lifecycle-service:2.2.0
\--- androidx.lifecycle:lifecycle-runtime:2.2.0
\--- androidx.lifecycle:lifecycle-viewmodel:2.2.0
+--- org.jetbrains.kotlin:kotlin-stdlib-jdk7:1.5.0 (*)
\--- com.squareup.okhttp3:okhttp:3.12.12
\--- com.squareup.okio:okio:1.15.0

Common problem here is depending on different versions of com.android.support library components. You need to migrate to Android X to resolve the issue.

Why do I have persistent notification on my app?

HyperTrack SDK by default runs as a foreground service. This is to ensure that the location tracking works reliably even when your app is minimized.

A foreground service is a service that the user is actively aware of and isn't a candidate for the system to kill when it is low on memory.

Android mandates that a foreground service provides a persistent notification in the status bar. This means that the notification cannot be dismissed by the user.

persistent-notification

How do I handle custom ROMs?

Smartphones are getting more and more powerful, but the battery capacity is lagging behind. Device manufacturers are always trying to squeeze some battery saving features into the firmware with each new Android release. Manufactures like Xiaomi, Huawei and OnePlus have their own battery savers that kills the services running in the background.

To avoid OS killing the service, users of your app need to override the automatic battery management and set it manual.

To inform your users and direct them to the right setting page, SDK shows a special promt on requestPermissionsIfNecessary() invocation.

Unfortunately whitelisting can't be performed programmatically. So you need to always rely on user performing particular action.

In that case the only way to achieve service reliability is manual setup. E.g. for Oxygen OS (OnePlus) you need to select Lock menu item from app options button in Recent Apps view:

one-plus-example

Why does HyperTrack notification show even after my app is terminated?

The HyperTrack service runs as a separate component and it is still running when the app that started it is terminated. That is why you can observe that notification. When you tracking is stopped, the notification goes away.

How does tracking work in Doze mode?

Doze mode requires device to be stationary, so before OS starts imposing power management restrictions, exact device location is obtained. When device starts moving, Android leaves Doze mode and works regularly, so no special handling of Doze mode required with respect to location tracking.

What is AAPT: error: attribute android:foregroundServiceType not found?

If build fails with error like AAPT: error: attribute android:foregroundServiceType not found that means that you're targeting your app for Android P or earlier. To fix this update your build tools and set the target platform as Android 10 (target SDK level 30). Although there are other workarounds to fix the build still targeting earlier versions, starting from Android 10 Google imposes additional restrictions on services, that access location data while phone screen is turned off, so the drawback will be tracking gaps on devices that run Android 10 or later.

Why doesn't setting device metadata and name work in SDK?

Devices API or in PlayGround take precedence over SDK methods in setting device name and metadata. If you used either Devices API or PlayGround, these SDK methods setDeviceMetadata and setDeviceName will not modify device metadata and name.

What is device Id that I get from SDK?

Device ID uniquely identifies SDK installation. Make sure that you stored it on your backend as a part of user profile to be able to identify location data. On Android 8 and later it is always the same for the app + publishable Key pair and persists across the installation. On devices, powered by earlier versions, it could change after reinstall, although there are some cases in which we are able to keep it the same. Anyway, users change devices and can use one login for multiple phones, so you need to handle that logic of updating device ids in backend.

What permissions are required for the SDK to work

SDK requires following permissions:

Most of listed above don't considered dangeourous permissinos, so granted automatically on install. They also included in SDK's AndroidManifest.xml that is mergerd into your app manifest during the build so you no action required from your side. Contrary to that, your app should request permissions from two last paragraphs interactively if it targets API 29 or later and only location permissions, if it targets API 28 or earlier. This could be achieved via sdkInstance.requestPermissionsIfNecessary() method invocation that presents required permissions request dialog, if neccessary, or does nothing, if they were already granted. Background location access permission is special since it cannot be requested interactively, so on Android 11 user is navigated to device's Settings menu where he needs to select Always Allow menu item. HyperTrack SDK shows an info snackbar with message like Please, select "Always Allow" option. with can be customized by overriding ht_background_permission_toast_template string resource. Menu item name is taken from OS APIs (so it will be in user's locale), so you need to leave a template placeholder instead of it like Please, select "%" option..

Since background location permission complicates Google Play Store review process it is recommended to remove it from the manifest if you don't use platfrom based tracking start in your application, using following tag in your AndroidManifest.xml:

<uses-permission android:name="android.permission.ACCESS_BACKGROUND_LOCATION" tools:node="remove" />

Can I test functionality without actual movement

Although HyperTrack SDK ignores mocked locations by default, you can use standard emulator, that comes with Android Studio. Check the official manual on how to use it. All the emulators have (Emulator) suffix appended to the device-hardware field, so they can be easily identified, if you need it to distinguish between them and real devices.

caution

Make sure the mock data, you feeding to the SDK, looks real. Instant teleport from Delhi to New York doesn't make sense, so those values will be ignored by processing logic, that is present on HyperTrack platform. Make sure you set desired start location before turning the traking on.

Support

Join our Slack community for instant responses. You can also email us at help@hypertrack.com.