Building with Android SDK

Building with the ENGAGE® Android SDK

The ENGAGE Android SDK is a low-effort integration that will enable Android applications to receive ENGAGE content and deliver an enhanced calling experience for consumers. This guide provides the detailed integration steps for Android developers to implement allowing applications to communicate with the ENGAGE platform.

SDK Version History

VersionDateChanges
3.1.212-September-2022Minor Bug Fixes
3.1.112-July-2022Minor Bug Fixes
3.1.018-March-2022Migrated Network Library to Retrofit
3.0.516-December-2021Minor Updates
3.0.47-October-2021Minor Bug Fix and Work Manager changes
3.0.320-September-2021Minor Bug Fix and Firebase changes
3.0.210-September-2021Minor Bug fix
3.0.119-August-2021ENGAGE Configuration changes and bug fixes
3.0.015-July-2021Initial Android 3.0.0 SDK release

Pre-Integration Steps

For a streamlined integration of the ENGAGE SDK into a host app, First Orion may request an Enterprise to provide the configuration that will enable communication from the ENGAGE platform to the app. First Orion will provide the necessary tools needed to decrease the integration efforts and increase the time-to-market for an ENGAGE-enabled app.

📘

First Orion will provide the following during pre-integration:

App ID - the App ID is required for communication from a host app to the ENGAGE platform. The first step must be completed by the First Orion team

Android Gold Copy - a reference application, including source code for understanding the integration points for a host app

engage-config.json - a host app configuration file to understand how to communicate with the ENGAGE platform. This configuration file will contain the ENGAGE URL

First Orion Artifactory Credentials - required for accessing the Maven repository in the First Orion Artifactory

📘

Integration Customer will provide to First Orion:

Communication - notify the First Orion team as soon as possible if the ENGAGE-enabled host app will be an Android application so First Orion may deliver all required configurations

🚧

Cross-Platform Compatibility

Cross-platform frameworks are not supported and not compatible with the ENGAGE SDK

Content Delivery

ENGAGE content is delivered to the device using Firebase Cloud Messaging (FCM).

First Orion provides the necessary components to deliver content to ENGAGE-enabled apps. Aside from declaring the required dependencies in the host app’s build.gradle file, ENGAGE content delivery is handled by First Orion.

Content delivery by First Orion will not interfere with current messaging and notifications a host app may already be sending through Firebase.

Skills Required

  • Java/Kotlin
  • Android
  • Gradle + Groovy
  • Linux (executing CURL command for testing - not required)

System Requirements

  • Android Studio
  • Gradle 4.0+
  • Java 1.8+
  • Host app written in native Android language:
    • Java
    • Kotlin

Java 8

The ENGAGE SDK uses Java 8 features. Since Java 8 is not enabled in gradle by default, it must be explicitly enabled in the host app side, otherwise, when the SDK uses one of the Java 8 features, it will give an exception in runtime.

android {
   ...
   // Configure only for each module that uses Java 8
   // language features (either in its source code or
   // through dependencies).
   compileOptions {
     sourceCompatibility JavaVersion.VERSION_1_8
     targetCompatibility JavaVersion.VERSION_1_8
   }
   // For Kotlin projects
   kotlinOptions {
     jvmTarget = "1.8"
   }
}

Work Manager

The ENGAGE SDK uses WorkManager for job scheduling. ENGAGE SDK will initialize a default WorkManager if one does not exist. If the host app already uses WorkManager, measures should be taken to guard against an already initialized state.

Work Manager 2.5.0 or Lower

If the host app uses WorkManager 2.5.0 or lower, there will be no limit on usage of WorkManager functionalities except when attempting to initialize WorkManager. Therefore WorkManager.initialize() should not be called in the host app.

Work Manager 2.6.0 or Higher

If the host app uses WorkManager 2.6.0 or higher, the following code must be added in the AndroidManifest.xml:

When host app uses androidx.startup

<provider
  android:name="androidx.startup.InitializationProvider"
  android:authorities=\"${applicationID}.androidx-startup"
  android:exported="false"
tools:node=\"merge">

<!-- If you are using androidx.startup to initialize other components -->

  <meta-data
    android:name="androidx.work.impl.WorkManagerInitializer"
    android:value="androidx.startup"
    tools:node="remove" />

</provider>

When host app does not use androidx.startup
Work Manager 2.6.0 should not call WorkManager.initialize() in host app.

<!-- If you want to disable android.startup completely. -->
<provider
  android:name="androidx.startup.InitializationProvider"
  android:authorities="${applicationId}.androidx-startup"
  tools:node="remove">
</provider>

Host App Requirements

  • Android API level >= 14 (Android 4.4+)
  • Written in Java or Kotlin
  • Required Permissions:
    • READ_CONTACT
    • WRITE_CONTACT

Additional Library Requirements

LibraryVersionPurpose
org.jetbrains.kotlin:kotlin-stdlib1.4.0 (most likely declared in top-level build.gradle)Needed for ENGAGE SDK for Kotlin-based code
com.google.firebase:firebase-messaging> 22.0.0Needed for Firebase functionality allowing Push Notifications

Level of Effort

TaskSkillsetTime of Effort
Configure build.gradle to resolve ENGAGE SDK dependencies and read properties file containing credentialsGradle + Groovy15 min
Place ENGAGE configuration file in the appropriate locationJava/Kotlin5 min
Integrate ENGAGE SDK: (Notify SDK if permissions change)Java/Kotlin + Android15 min

Testing the ENGAGE SDK integration steps will take roughly 45 min and will require:

  • Registering a device (perform challenge)
  • Push content to device from Portal
  • Make phone call to device - through Portal or a different device
  • Check device 15 min after successful Push and call to ensure content is removed from device

Permissions

The ENGAGE SDK requires certain Android app permissions to be managed and coordinated by the host app. Without prompting users to enable these permissions, the SDK will not perform as expected. Some services provided by the SDK will not work properly without them. The main permission set supported:

  • Contact

ENGAGE functionality is driven by the permissions a host app is comfortable asking the consumers. The set of ENGAGE components included in the host app’s build file also relates to the functionality and permissions required.

Permission Set Functionality ENGAGE Components
READ_CONTACTS and WRITE_CONTACTS Displays Content 'com.firstorion:engage-core:3.1.x'
Content is not cleaned up immediately after the call 'com.firstorion:engage-contacts:3.1.x'
Call telemetry and answer rates not captured 'com.firstorion:engage-firebase:3.1.x'
  • Contact - the system dialer shows a contact that has been previously created by the SDK on an incoming call:

    • READ_CONTACTS and WRITE_CONTACTS
      • The Contacts group is categorized as dangerous permission
      • READ_CONTACTS is required to prevent the SDK from overwriting an existing contact
      • WRITE_CONTACTS is required to create and remove the contact

Resolve Library Dependencies

The ENGAGE Android SDK is published in the First Orion artifact repository. Credentials to access the repository will be provided by First Orion before integration efforts begin.

❗️

These artifact repository credentials:

  • should be securely stored
  • should never be checked into a source code repository
  • should be appropriately retrieved during integration and app build processes

Configure build.gradle

Consuming the library requires configuration in the host apps build.gradle file in the same manner as adding any ordinary Android dependency.

Edit Top-level build.gradle File

  1. Add the following maven{} repository closure inside the buildscript.repositories{} closure:
repositories {
  ...
  maven {
    url "https://firstorion.jfrog.io/firstorion/fo-libs-release-external/"
    credentials {
      def artPropFile = rootProject.file("artifactory.properties")
      def artProps = new Properties()
      artProps.load(new FileInputStream(artPropFile))
      username = artProps ['username']
      password = artProps ['password']
      }
    }
  }
...

}
  1. Include JFrog BuildInfo dependency on the class path in the buildscript{} dependencies{} closure:
dependencies {
  ...
  classpath 'org.jfrog.buildinfo:build-info-extractor-gradle:4.24.15'
  ...

}
  1. Include the Artifactory Gradle plugin:
allprojects {

  apply plugin: "com.jfrog.artifactory"
  repositories {
    ...
  }
  ... 
    
}
  1. Add the artifactory {} closure to resolve the Android ENGAGE Library:
artifactory {
  contextUrl ="https://firstorion.jfrog.io/firstorion/"
  resolve {
    repository {
      repoKey = 'fo-libs-release-external'

      def artPropFile = rootProject.file("artifactory.properties")
      def artProps = new Properties()
      artProps.load(new FileInputStream(artPropFile))

      username = artProps ['username']
      password = artProps ['password']
      maven = true
    }
  }
}

Edit App-level build.gradle File

Add the Android SDK dependencies in the dependencies{} closure:

def engage_version = "3.1.2"
implementation "com.firstorion:engage-core:$engage_version"
implementation "com.firstorion:engage-contacts:$engage_version"
// OPTIONAL  
implementation "com.firstorion:engage-firebase:$engage_version"

Once added, click the Sync Now link in Android Studio for the host app to consume the library.

📘

Please contact the First Orion integration team if you have any issues

Setting Artifactory Credentials

When setting the First Orion Artifactory credentials, best practice is to set the values in a properties file, which will be ignored by the host app source code management and will not be checked into a source code repository.

In the project root:

  1. Create a properties file named artifactory.properties with two fields listed below.
  2. Insert the First Orion Artifactory credential values:

    username=external-user
    password=9zqcvu8desy

The build.gradle file will be responsible for reading the credentials to securely connect to the First Orion artifact repository.

❗️

Storing the artifactory.properties File

It is unsafe to store the artifactory.properties containing credentials file into a source code repository

Select ENGAGE Components

The ENGAGE SDK is represented by the list of components below. Each component provides flexibility around the features and functionality provided by the ENGAGE SDK.

ENGAGE Component Overview

ENGAGE ComponentDescription
com.firstorion.engage:coreRequired component responsible for core logic of the ENGAGE SDK
com.firstorion.engage:contactsRequired component responsible for creating native Contact on device
com.firstorion.engage:firebaseOptional component responsible for Firebase messaging to deliver content to device

ENGAGE Configuration

The ENGAGE SDK must be configured before use. The engage-config.json file, provided by First Orion, needs to be placed in the app/src/main/assets folder.

The engage-config-.json file has the following fields:

{
  "EngageEndpoint": "engage_endpoint_provided_by_first_orion",
  "EngageAppId": "engage_app_id_provided_by_first_orion",
  "EngageTokenType": "token_type_provided_by_first_orion",
  "EngageVerificationType": "verificaton_type",
  "ConfigVersion": 3.0
}

User Onboarding

Requesting permissions from end-users is a required step that allows the ENGAGE SDK to perform its core functionality. The Contact permission is the most important permission a host app must require.

First Orion follows best practices for educating users regarding the Contact permission request, especially when such a request may seem outside a typical Enterprise function.

📘

If more information regarding acceptable methods of requesting the Contact and other permissions is needed, First Orion will provide supplemental documentation.

Gold Copy Example

The ENGAGE Android Gold Copy has complete code examples for requesting permissions and related functionality. Please reference the PermissionsActivity in the project.

Authentication

Authenticating the host app with the ENGAGE platform is required to validate the communication between the device and platform. The Registration process validates up to three phone numbers and establishes the communication between the platform and device.

The following authentication mechanisms are possible:

  • SMS
  • Silent Registration

Registration Handler

To register a phone number, pass the phone number along with EngageRegistrationhandler callback:

EngageApp.getInstance().register(number, engageRegistrationHandler)

Observation of the registration status is possible with the following callback functions.

Initialization Success

InitializationSuccess is called when the registration is initialized successfully. For an SMS registration, this is the time an SMS message is sent to the given phone number:

EngageRegistrationHandler.onInitializationSuccess(number)

Registration Success

RegistrationSuccess is called when the registration is successfully completed for the given number:

EngageRegistrationHandler.onRegistrationSuccess(number)

Registration Failure

RegistrationFailure is called when the registration fails at any time. EngageRegistrationError depicts the cause of the error:

EngageRegistrationHandler.onRegistrationFailure(number, engageRegistrationError)

SMS Registration

For SMS registration, the 6-digit code delivered in the SMS needs to be passed to ENGAGE:

EngageSmsRegistration.completeWithCode(code)

Unregister

The unregister() function disassociates the given number. The number will no longer receive any ENGAGE content:

engageApp.unregister(number, engageUnregistrationhandler)

ChangeNumber

The changeNumber alters the registered old number to a new number:

engageApp.changeNumber (oldNumber, newNumber, engageNumberChangeHandler)

Check App Authentication

If the app has already been authenticated, the host app does not need to re-authenticate. A list of validated phone numbers may be generated by running the following check:

EngageApp.getRegisteredPhoneNumbers(context) // returns a list
// or, for known phone numbers, this function can be called.

EngageApp.isPhoneNumberRegistered(context, number) // returns boolean

🚧

Programming Tip

To check if a phone number is registered, call:

val is Engage Verified = 
EngageApp.getRegisteredPhoneNumbers(context).isNotEmpty()

Firebase Integration

The app must communicate with Firebase in order for apps to receive content, and in some cases to perform Registration. Aside from including the required Firebase components in the project, the First Orion Firebase is used without additional integration steps.

Integrating with Host App's Firebase

ENGAGE content is delivered by using the First Orion Firebase. If the host app is using another Firebase account or to ensure the host app delivers content in the appropriate method, the project must include the required com.firstorion:engage-firebase:

class AppSideFirebaseService: FirebaseMessagingService() {
   override fun onNewToken(newToken: String) {
      super.onNewToken(newToken)
   }
   override fun onMessageReceived(message: RemoteMessage) {
      super.onMessageReceived(message)
      if (EngageApp.isEngageMessage (message.data)) {      
         EngageApp.getInstance().handlePushMessage(message.data)
      }
   }
}

Integration Scenarios

Four common integration scenarios and how to get each working are addressed in this section.

Scenario 1: Host App does not use FCM, SDK uses First Orion FCM
The host app does not use its own Firebase Cloud Messaging but relies upon the SDK's built-in FCM Implementation.

  • No additional work is required in order to get started with the SDK
  • Follow the integration mentioned in this scenario
  • Skip the Firebase Integration section

Scenario 2: Host App uses its own FCM, SDK uses First Orion FCM
The host app has its own instance of Firebase Cloud Messaging, but the SDK will use First Orion's Firebase.

  • The host app will need to pull in the com.firstorion:engage-firebase component (see Edit App-level build.gradle file section)
  • Allow to complete
  • Follow the steps listed in the _Firebase Integration__ section

Scenario 3: Host App uses its own Firebase, SDK uses Host App Firebase
The host app will use its own Firebase and the SDK will rely on the host app's Firebase Implementation.

  • The host app will need a custom token type provided by First Orion
  • Once that has been set-up, make sure the appropriate ENGAGE token type shows up in the ENGAGE configuration file (see ENGAGE Configuration section)
  • This scenario does not require the use of the com.firstorion:enage-firebase component since the SDK will not use First Orion's Firebase
  • Since the host app is using its own Firebase instance, all messages and token refreshes will come through to the host app's FirebaseMessagingService
  • The host app must propagate this information to the ENGAGE SDK


The following code needs to be implemented in the host app's FirebaseMessagingService Implementation to ensure proper functionality:

class HostAppFirebaseService: FirebaseMessagingService() {
   override fun onNewToken(newToken: String) {
      super.onNewToken(newToken)

      .
      .
      .

      // Required
      EngageApp.getInstance().onCustomTokenRefreshed(newToken)

   }
   
   override fun onMessageReceived(message: RemoteMessage) {
      super.onMessageReceived(message)
      
      .
      .
      .

      // Required
      if (EngageApp.isEngageMessage (message.data)) {      
         EngageApp.getInstance().handlePushMessage(message.data)
      }
   }
}

Scenario 4: Host App uses OneSignal, SDK uses First Orion FCM
The host app uses OneSignal or another library that includes a Firebase/FCM Implementation, but the ENGAGE SDK will use First Orion's Firebase.

  • No extra work is needed if the host app is using OneSignal (see Integration Scenario 1)
  • If OneSignal is not used, more development work may be required depending on changes to priority for FCM

Test ENGAGE SDK Integration

Functionality needs to be tested after completing the ENGAGE SDK integration. From the Content Portal, customers can deliver content to a device through an easy-to-use interface.

A valid, configured ENGAGE Program must be created in the Content Portal before delivering the content. First Orion will provide testing assistance at any time.

Delivering ENGAGE Content to Device

First Orion provides a set of APIs to deliver ENGAGE content to an enabled device. The Content Portal also provides an easy-to-use mechanism to deliver content in real-time for testing purposes. From the Content Portal, a Batch Push may be scheduled by uploading a formatted .csv file.

APIs and Programmatic Delivery options

  1. Real-Time Push
  2. Batch Push
  3. Mobile Push Library
    • Android
    • iOS (Swift)

Cross-Platform Frameworks

Cross-platform frameworks are not supported with the ENGAGE SDK. There are various restrictions to native capabilities that are included in the frameworks. These restrictions will prevent the full functionality of the ENGAGE SDK when attempting to integrate a host app as constructed in cross-platform frameworks.

Cross-platform frameworks are defined as:

Development frameworks that allow developers to create mobile applications, with a single codebase, that are compatible with one or more mobile operating systems, both Android and iOS.

The following, but not limited to, are cross-platform frameworks that are not supported:

  • React Native
  • Ionic
  • Flutter

Additional Notes

Whenever the Contact permission changes, call the following method:

engageApp.onPermissionChanged()

Logging level sets the minimum Logging Level as defined in Android's Log class. Default level is set to Log.VERBOSE:

Engage.Settings.setMinimumLoggingLevel(Log.WARNING) // or Log.ERROR etc.

Logging Interceptor implementation allows host app to access the logs come from the SDK:

import android.app.Application
import com.firstorion.engage.core.EngageApp
import com.firstorion.engage.core.IEngageLoggingInterceptor 

class MainApplication: Application(), IEngageLoggingInterceptor {
   override fun onCreate() {
      super.onCreate()
     //Enable logging of Engage SDK // 
     EngageApp.Settings.setLoggingInterceptor(this)
   }
   override fun intercept(message: String, level: Int) {
      println("engage.app $message")
   }
}

Upgrading to 3.x

One of the main features of ENGAGE 3.0 is the support for devices with multiple SIMs. In ENGAGE 2.x, the registered phone number was not stored in the SDK database due to only a single phone number could be registered, whereas ENGAGE 3.x can register up to 3 numbers.

If upgrading from version 2.x and a phone number has already been verified in version 2.x, the following function cannot return the verified phone number since numbers were not saved in the database. This is the only instance in which this function will not return a registered number.

EngageApp.getRegisteredPhoneNumbers(context)

If there is a phone number registered in 2.x, the list returned from the function above will include:

EngageApp.UNKNOWN_NUMBER

This string value indicates that a phone number hasn't been registered in version 2.x but is no longer known.