Setup Guide for Android CPIK Libraries
Contents
Note: The CPIK libraries React Native framework and the sample app use React Native version 0.68.0.
React Native is a cross-platform framework that allows you to build native mobile applications with JavaScript. As a result, you can develop iOS and Android applications that share most of the same code.
With our CoPilot React Native module, you can integrate turn-by-turn, voice-guided navigation into your application by calling our CPIK libraries APIs.
The goal of this guide is to get you set up to build an Android application.
What You’ll Need
The following software is required for your Windows machine:
- Node 14.0 or above
- The React Native command-line interface
- Java SE Development Kit (JDK) 11.0 or above
- Android Studio
Environment Setup
Step 1: Install Chocolatey
We recommend you install Node via Chocolatey, a popular package manager for Windows. Installation instructions can be found on the Chocolatey site.
Step 2: Install Node and JDK
React Native requires a recent version of the Java SE Development Kit (JDK).
Open an Administrator Command Prompt (right click Command Prompt and select “Run as Administrator”), then run the following command:
choco install -y nodejs-lts openjdk11
Note: If you have already installed Node on your system, make sure it is Node 14.0 or later. If you already have a JDK on your system, make sure it is version 11 or later.
Step 3: Install React Native command-line interface
Node comes with npm, which lets you install the React Native command-line interface. Run the following command in a Command Prompt or shell:
npm install -g react-native-cli
Step 4: Set up Android development environment
4.1 Install Android Studio
Download and install Android Studio. Choose a Custom setup when prompted to select an installation type. Make sure the boxes next to all of the following are checked:
- Android SDK
- Android SDK Platform
- Performance (Intel ® HAXM) (See here for AMD)
- Android Virtual Device
Click Next to install all of these components.(If the checkboxes are grayed out, you will have a chance to install these components later.)
Once setup has finalized and you’re presented with the Welcome screen, proceed to the next step.
4.2 Install the Android SDK
Android Studio installs the latest Android SDK by default. Building a React Native app with native code, however, requires the Android 9 (Pie) SDK in particular. Additional Android SDKs can be installed through the SDK Manager in Android Studio.
The SDK Manager can be accessed from the Welcome to Android Studio screen. Click on Configure, then select SDK Manager.
The SDK Manager can also be found within the Android Studio Preferences dialog, under Appearance & Behavior > System Settings > Android SDK.
In the SDK Manager
Select the SDK Platforms tab, and check the box next to Show Package Details in the bottom right corner. Look for and expand the Android 9 (Pie) entry, then make sure the following items are checked:
- Android SDK Platform 28
- Intel x86 Atom_64 System Image or Google APIs Intel x86 Atom System Image
Next, select the SDK Tools tab and check the box next to Show Package Details here as well. Look for and expand the Android SDK Build-Tools entry, then make sure that 28.0.3 is selected.
Finally, click Apply to download and install the Android SDK and related build tools.
4.3 Configure the ANDROID_HOME environment variable
The React Native tools require some environment variables to be set up in order to build apps with native code.
-
Open the System pane under System and Security in the Windows Control Panel, then click on Change settings.
-
Open the Advanced tab and click on Environment Variables.
-
Click on New to create a new ANDROID_HOME user variable that points to the path to your Android SDK:
The SDK is installed, by default, at the following location:
c:\Users\YOUR_USERNAME\AppData\Local\Android\Sdk
You can find the actual location of the SDK in the Android Studio “Preferences” dialog, under Appearance & Behavior > System Settings > Android SDK.
Open a new Command Prompt window to ensure the new environment variable is loaded before proceeding to the next step.
4.4 Add platform-tools to path
-
Open the System pane under System and Security in the Windows Control Panel, then click on Change settings.
-
Open the Advanced tab and click on Environment Variables.
-
Select the Path variable, then click Edit. Click New and add the path to platform-tools to the list.
The default location for this folder is:
c:\Users\YOUR_USERNAME\AppData\Local\Android\Sdk\platform-tools
Integrate React Native CPIK libraries library
npm Method
In React Native, you can provide a dependency library or component name in package.json
. It will download all of the dependent components when you run “npm install”. The following is sample code for package.json
. It will override all of the manual operations described below. Please go here to view the most current versions of CoPilot.
"dependencies": {
"trimble-maps-cpik-react-native-library": "{CoPilot version number}" //For example "10.26.0".
},
Note: Depending on your React Native version, make sure your application sets up auto-linking for packages. This online guide from React Native should tell you what is needed in the Android build files.
In our sample app, android/app/build.gradle
, we use:
apply from: file("../../node_modules/@react-native-community/cli-platform-android/native_modules.gradle"); applyNativeModulesAppBuildGradle(project)
In our sample app, android/settings.gradle
, we use:
apply from: file("../node_modules/@react-native-community/cli-platform-android/native_modules.gradle"); applyNativeModulesSettingsGradle(settings)
Manual Method
Native libraries, assets and resources are located at Library and Resource\android
.
-
Copy cpik_react.aar Copy
jars\cpik_react.aar
file to<<Customer App>>\android\app\libs\
-
Copy CoPilot assets folder Copy
assets\copilot
to<<Customer App>>\android\app\src\assets\
-
Copy native libraries All native libs are located at
Library and Resource\android\app\src\jniLibs\
Copy:-
arm64-v8a\libcopilot.so
to<<Customer App>>\android\app\src\jniLibs\arm64-v8a\libcopilot.so
-
armeabi-v7a\libcopilot.so
to<<Customer App>>\android\app\src\jniLibs\armeabi-v7a\libcopilot.so
-
armeabi\libcopilot.so
to<<Customer App>>\android\app\src\jniLibs\armeabi\libcopilot.so
-
Add the CPIKPackageHolder to the MainApplication.java
In order to use the CPIK libraries APIs, you need to add CPIKPackagesHolder() as part of the getPackages() method in MainApplication.java: (<<Customer App>>android/app/src/main/java/[...]/MainApplication.java
)
- Add `import com.alk.cpik.react.CPIKPackagesHolder;` to the imports at the top of the file
- Add `new CPIKPackagesHolder()` to the list returned by the `getPackages()` method
Add the details below to the AndroidManifest.xml in the Android application
First we need to add some attributes to the main activity in your application that is used on startup.
<activity>
android:name="com.alk.helloworld.MainActivity"
android:multiprocess="false"
android:configChanges="mcc|mnc|locale|keyboard|keyboardHidden|orientation|screenSize|fontScale|uiMode"
android:launchMode="singleTask"
android:label="@string/mainactivity_label"
android:windowSoftInputMode="stateHidden|adjustPan">
<intent-filter>
<!-- Launcher intent (Your manifest probably has this already) -->
<action android:name="android.intent.action.MAIN">
<category android:name="android.intent.category.LAUNCHER">
</intent-filter>
</activity>
The application will also need to add the following services and metadata to the ‘application’ element inside the Android Manifest.
<service android:name="com.alk.copilot.CopilotService" android:enabled="true"></service>
<!-- This should always be "true" -->
<meta-data android:value="true" android:name="ALK_isCustomFragment">
<!-- "true" if you want CoPilot to store data (maps, speech, etc) in the default install directory
"false" if you want CoPilot to store data using the external storage dir (usually on the SD card) -->
<meta-data android:value="false" android:name="ALK_useInternalStorage">
<!-- "true" if you will be starting CoPilot in the background and do not want to show a splash screen. false" otherwise -->
<meta-data android:value="true" android:name="ALK_doBackgroundStart"><meta-data android:name="ALK_useOpenGL" android:value="true" >
Finally, the application will need additional permission access inside the ‘manifest’ element, sibling to the ‘application’ element in the xml tree.
<uses-permission android:name="android.permission.INTERNET"/>
<uses-permission android:name="android.permission.ACCESS_FINE_LOCATION"/>
<uses-permission android:name="android.permission.ACCESS_LOCATION_EXTRA_COMMANDS"/>
<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE"/>
<uses-permission android:name="android.permission.WAKE_LOCK"/>
<uses-permission android:name="android.permission.READ_CONTACTS"/>
<uses-permission android:name="android.permission.ACCESS_WIFI_STATE"/>
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE"/>
Running the Sample Application
The Sample App requires Node 16 or later
Debug mode
-
Running the sample application in a debug mode is straightforward. The sample application provided by Trimble contains all necessary files including asset, jars, native library and updated androidmanifest.xml.
-
Install all module dependencies in your local project by using the following command. It will install all the dependencies to your local folder. Run the following command from the SampleApplication directory:
$npm install
. You might need the flag--legacy-peer-deps
depending on which version of the app you have. -
Once all the dependencies are installed, you can run the following command from the SampleApplication directory. It will build the application as well as host the Android device.
$ react-native run-android
Release mode
-
Running the sample application in a release mode, you need to add the keystore details. The sample application provided by Trimble contains all necessary files including asset, jars, native library and updated androidmanifest.xml.
-
Install all module dependencies in your local project by following command. It will install all dependencies to your local folder. Run following command from the SampleApplication directory:
$npm install
. You might need the flag--legacy-peer-deps
depending on which version of the app you have. -
Open the build.gradle file from SampleApplication\android\app location and add the following information. Place holders are provided where you need to add keystore details.
signingConfigs {
release {
storeFile file("*.keystore")
storePassword ''
keyAlias ''
keyPassword ''
}
}
-
After adding the above information, you need to sign the apk in release mode. Go to SampleApplication\android\ and run following command to create the signed apk file:
$ ./gradlew assembleRelease
-
Run the following command from the sample application directory, which will install and run the signed apk file:
$ react-native run-android --variant=release
Sample Code
Start CoPilot
import { NativeModules } from "react-native";
if (Platform.OS == "android") {
const { CopilotStartupMgr } = NativeModules;
CopilotStartupMgr.bindCoPilotService();
} else NativeModules.Copilot.startNavApp();
Exit CoPilot
import {NativeModules} from 'react-native';
componentWillUnmount() {
if (Platform.OS == 'android')
CopilotStartupMgr.unbindCopilotService();
else
CopilotApplication.shutdownNavApp();
}
License Activation
import {NativeModules} from 'react-native';
const LicenseListener = NativeModules.LicenseListener;
//Licensing with AMS using an assetID and companyID
await LicenseListener.setAMSLoginInfo(assetID, companyID)
//Licensing with AMS using an assetID, externalAccountID, and partnerID
await LicenseListener.setAMSLoginInfo(assetID, externalAccountID, partnerID)
//Add hook to use your AMS Login Info you assigned in the code above. This will let the LicenseMgtCredentialHook be called that checks during CoPilot startup if you have set AMS credentials
LicenseEventEmitter.addListener('licenseMgtCredentialHook', licenseMgtCredentialHook);
//Add listener to notify us when LicenseMgtLogin has fired and logged into our AMS credentials
this.onLicenseMgtLogin = LicenseEventEmitter.addListener('onLicenseMgtLogin', this.onLicenseMgtLogin);
//This function will let you know when the licenseMgtCredentialHook has been fired
licenseMgtCredentialHook = () => {
console.log(licenseMgtCredentialHook received');
}
//This function will let you know when the onLicenseMgtLogin callback has been fired
onLicenseMgtLogin = () => {
console.log("onLicenseMgtLogin received");
};
Callback Registration
Callback register and unregister should be done on componentDidMount and componentWillUnmount.
import {NativeModules} from 'react-native';
import { DeviceEventEmitter, NativeEventEmitter } from 'react-native';
const CopilotListener = NativeModules.CopilotListener;
const CopilotEventEmitter = Platform.OS == 'android' ? DeviceEventEmitter : new NativeEventEmitter(CopilotListener);
onCPStartup = () => {
console.log('onCPStartup received');
}
onCPShutdown = () => {
console.log('onCPShutdown received');
}
componentDidMount() {
this.onCPStartuplistener = CopilotEventEmitter.addListener('onCPStartup', this.onCPStartup);
this.onCPShutdownlistener = CopilotEventEmitter.addListener('onCPShutdown', this.onCPShutdown);
}
componentWillUnmount() {
this.onCPStartuplistener.remove();
this.onCPShutdownlistener.remove();
}
Display CoPilot View
Step 1: Expose native view component in CopilotView.js
import { requireNativeComponent } from "react-native";
module.exports = requireNativeComponent("CopilotView", null);
Step 2: Render the exported native view in your react component
import React, { Component } from "react";
import CopilotView from "./CopilotView.js";
class CopilotScreen extends React.Component {
static navigationOptions = {
title: "Copilot"
};
render() {
return <CopilotView style={{ flex: 1 }} />;
}
}
Get Configuration
import { NativeModules } from "react-native";
const CopilotMgr = NativeModules.CopilotMgr;
const ConfigurationName = NativeModules.ConfigurationName;
var config = await CopilotMgr.getConfigurationSetting(
ConfigurationName.GPS_FREQUENCY
);
console.log(config.value);
Set Configuration
import { NativeModules } from "react-native";
const CopilotMgr = NativeModules.CopilotMgr;
const ConfigurationName = NativeModules.ConfigurationName;
const ConfigurationValue = NativeModules.ConfigurationValue;
var configSetting = {};
configSetting.name = ConfigurationName.CHEVRON_DISPLAY;
configSetting.value = ConfigurationValue.CHEVRON_DISPLAY_LAT_LON;
CopilotMgr.setConfigurationSetting(configSetting);