VenueNext Android SDK Setup

System Requirements

  • Minimum SDK Version 21 - Android 5.0 “Lollipop”

Getting the SDK

VenueNext Android SDK is served via JFrog. Follow the guide below using your provided credentials to obtain the SDK.

Step 1. Configure your JFrog Repository and Set Up Gradle

Add the following dependencies to your project’s build.gradle file:

buildscript {
    ext {
        gradle_version = '3.4.2'
        kotlin_version = '1.3.41'
        kotlin_coroutines_version = '1.2.2'
        serialization_version = '0.11.1'
    }
    repositories {
        google()
        jcenter()
    }
    dependencies {
        classpath "com.android.tools.build:gradle:$gradle_version"
        classpath "org.jetbrains.kotlin:kotlin-gradle-plugin:$kotlin_version"
        classpath "org.jetbrains.kotlin:kotlin-serialization:$kotlin_version"
        classpath "org.jfrog.buildinfo:build-info-extractor-gradle:4.7.3"
        classpath "android.arch.navigation:navigation-safe-args-gradle-plugin:1.0.0"
        classpath 'com.google.gms:google-services:4.3.0'
        classpath 'io.fabric.tools:gradle:1.31.0'
    }
}

allprojects {
  repositories {
    google()
    jcenter()

    maven { url "https://kotlin.bintray.com/kotlinx" }
  }
}

Add the following plugin and repository to your app’s build.gradle file:

apply plugin: 'maven-publish'
  repositories {
    maven {
      url "https://venuenext.jfrog.io/venuenext/venuenextsdk-android"
        credentials {
          username = XXXXXXXXXXXXXXXXX
          password = XXXXXXXXXXXXXXXXX
        }
    }
}

Apply the following plugins to your app’s build.gradle file:

apply plugin: 'kotlin-android'
apply plugin: 'kotlin-android-extensions'
apply plugin: 'kotlin-kapt'
apply plugin: 'kotlinx-serialization'
apply plugin: 'androidx.navigation.safeargs'
apply plugin: 'io.fabric'

// Add this plugin to the bottom of your Gradle file (per Google documentation)
apply plugin: 'com.google.gms.google-services'

Enable databinding in your app’s build.gradle file:

android {
  dataBinding {
    enabled = true
  }
}

Add the following VenueNext dependencies to your app’s build.gradle file (UI dependencies can be omitted if not using VenueNext views):

// VenueNext
implementation 'com.venuenext:vncore:0.11.0'
implementation 'com.venuenext:vncoreui:0.11.0'
implementation 'com.venuenext:vnanalytics:0.11.0'
implementation 'com.venuenext:vnlocalytics:0.11.0'
implementation 'com.venuenext:vnlegacy:0.11.0'
implementation 'com.venuenext:vnorder:0.11.0'
implementation 'com.venuenext:vnorderui:0.11.0'
implementation 'com.venuenext:vnpayment:0.11.0'
implementation 'com.venuenext:vnticket:0.11.0'

Add the following additional dependencies to your app’s build.gradle file:

// Kotlin
implementation "org.jetbrains.kotlin:kotlin-stdlib-jdk8:$kotlin_version"
implementation "org.jetbrains.kotlin:kotlin-reflect:$kotlin_version"
implementation "org.jetbrains.kotlinx:kotlinx-serialization-runtime:$serialization_version"
implementation "org.jetbrains.kotlinx:kotlinx-coroutines-core:$kotlin_coroutines_version"
implementation "org.jetbrains.kotlinx:kotlinx-coroutines-android:$kotlin_coroutines_version"

// UI
implementation 'com.google.android.material:material:1.0.0'
implementation 'androidx.appcompat:appcompat:1.0.2'
implementation 'androidx.core:core-ktx:1.0.2'
implementation 'androidx.constraintlayout:constraintlayout:1.1.3'
implementation 'androidx.legacy:legacy-support-v4:1.0.0'
implementation 'com.android.support:cardview-v7:28.0.0'
implementation 'com.android.support:cardview-v7:28.0.0'
implementation 'com.android.support:appcompat-v7:28.0.0'
implementation 'com.google.android:flexbox:2.0.1'

// Lifecycle
implementation "androidx.lifecycle:lifecycle-extensions:2.2.0"
implementation "androidx.lifecycle:lifecycle-viewmodel-ktx:2.2.0"

// Navigation
implementation "androidx.navigation:navigation-ui-ktx:2.3.0"
implementation "androidx.navigation:navigation-fragment:2.3.0"
implementation "androidx.navigation:navigation-fragment-ktx:2.3.0"

// Room
implementation "androidx.room:room-runtime:2.1.0"
kapt "androidx.room:room-compiler:2.1.0"

// Firebase
implementation 'com.google.firebase:firebase-core:17.0.1'
implementation 'com.google.firebase:firebase-analytics:17.0.1'
implementation 'com.google.firebase:firebase-messaging:19.0.1'
implementation 'com.google.android.gms:play-services-tagmanager:17.0.0'

// Crashlytics
implementation 'com.crashlytics.sdk.android:crashlytics:2.10.1'

// Braintree
implementation 'com.braintreepayments.api:braintree:3.0.0'
implementation 'com.braintreepayments.api:drop-in:4.1.0'

// Facebook Shimmer
implementation 'com.facebook.shimmer:shimmer:0.4.0'

// QR codes
implementation 'com.journeyapps:zxing-android-embedded:3.6.0'
implementation 'com.google.zxing:core:3.3.3'

// Image Loading
implementation "com.github.bumptech.glide:glide:4.9.0"

// Localytics
implementation 'com.android.support:support-compat:28.0.0'
implementation "com.google.android.gms:play-services-gcm:17.0.0"
implementation "com.google.android.gms:play-services-location:17.0.0"
implementation 'com.localytics.android:library:5.5+'

// Compat
implementation 'androidx.localbroadcastmanager:localbroadcastmanager:1.0.0'
implementation 'com.android.support:multidex:1.0.3'

Step 2. Initialize the SDK

Have you been provided a config file from VenueNext? Skip to Step 2b. Initialize with a Config file.

Are you using a JSON Web Token to identify your users? See Step 2a. Initialization With a JWT Token.

To initialize the SDK, pass in your SDK key and secret. This could potentially go in the onViewCreated handler of a Fragment class. Initialization is also where we configure Crash Reporting, Analytics, & Payment Processing for plugging in a specific framework.

GlobalScope.async {
  // Note: We removed calls to add Firebase and Localytics analytics implementations.
  // You can add your own analytics implementation to receive events from the VenueNext SDK
  // as shown below.
  val analytics = VNAnalyticsInterface(applicationContext)
  VenueNext.configureAnalytics(analytics)

  // Note: This is the default implementation of payment method processing to use if you don't want to configure your own
  // payment method capturing. You can add your own payment method capturing by following the instructions on the
  // "Configuring Payment" page of these docs.
  VNPayment.configurePaymentProcessing(BraintreePaymentProcessableFragment())

  VenueNext.initialize("SDK_KEY", "SECRET_KEY", self.context!!).await()

  // Initialize modules to handle deep links
  VenueNext.registerDeepLinkable(VNOrderUI)

  withContext(Dispatchers.Main) {
    // Start navigation
    Navigation.findNavController(view).navigate(R.id.start_main)
  }
}

Please treat your SDK key and secret with care. Do not check them into source repositories or pass them around in the clear.

Initialization Variations

Step 2a. Initialization With a JWT Token

Use this if you have an external user ID at the time of initializing the VenueNext SDK Please see the example below and ensure the JWT has the correct payload.

val jwt = "xxxxxxxxxxxxxxxx.xxxxxxxxxxxxxxxxxxx.xxxxxxxxxxxxxxx"
VenueNext.initialize("SDK_KEY", "SECRET_KEY", self.context!!, jwt).await()

When using a JWT please ensure the following payload structure is included:

{
  "sub": "1234567890",
  "iat": 1516239022,
  "email": "email@example.org",
  "sth": true,
  "name": "Sam Smith"
}

Step 2b. Initialize with a Config file

If VenueNext has provided you with a configuration file, store the file in a place where it is accessible via code when you initialize the SDK. We recommend storing the file in the res/raw directory or in the assets directory. You’ll be reading the contents of the config file into a String and passing the String to the initialize function. The example below assumes the file has been stored in the res/raw directory:

val configStream = resources.openRawResource(
  resources.getIdentifier("<configFileNameWithoutExtension>", "raw", packageName)
)
var configString = ""
try {
  configStream.bufferedReader().use { configString = it.readText() }
} catch (e: Exception) {
    Log.e(TAG, "Error reading the config file")
}

// Note: We removed calls to add Firebase and Localytics analytics implementations
// You can add your own analytics implementation to receive events from the VenueNext SDK
// as shown below.
val analytics = VNAnalyticsInterface(applicationContext)
VenueNext.configureAnalytics(analytics)

VenueNext.initialize(
  sdkKey = sdkKey,
  sdkSecret = sdkSecret,
  context = this,
  jwt = null,
  configJsonString = configString,
  onSuccess = this::completeInitialize,
  onError = this::handleInitializationError
)

VNOrderUI.initialize()
VNPayment.configurePaymentProcessing(BraintreePaymentProcessableFragment())

fun completeInitialize() { }
fun handleInitializationError(e: Throwable) { }

Notes:

  • If you are logging users in via a JSON Web Token, you can pass it here instead of passing null as shown above
  • You no longer need to call VenueNext.registerDeeplinkable(VNOrderUI) - this has instead been replaced with VNOrderUI.initialize()
  • You no longer need to dispatch the initialization to another thread - you can instead pass in callback functions for success or error that will be called when initialization has completed

Step 2c. Initialize Wallet

If you intend to use VenueNext Wallet functionality, please see additional initialization documentation in the Wallet Configuration section

Step 3. Setup Fragments and Navigation

a. Add the following fragment to your MainActivity layout:
<fragment
  android:id="@+id/fragment_main"
  android:layout_width="match_parent"
  android:layout_height="match_parent"
  app:navGraph="@navigation/app_navigation"
  android:name="androidx.navigation.fragment.NavHostFragment"
  app:defaultNavHost="true"/>
b. Add an app_navigation.xml file to your navigation resource folder:
  • Add the contents of our sample app_navigation.xml
    • If you want to change the text that displays at the top of views in the Action Bar, update the vnActionBarTitle argument in the actions below. See Setting the Action Bar Title Text
    • If you wish to start directly to a navigation flow without a placeholder fragment, you will need to ensure the SDK has been initialized
c. Add a placeholder fragment as a starting point for your navigation graph

The purpose of this fragment is to give the navigation graph a starting point outside of the SDK flow. If the SDK is not initialized before navigating to a VenueNext flow you will encounter errors. This can be replaced with any fragment in your app_navigation and is optional only in this case or your start destination is a VenueNext flow (e.g. @id/food_and_bev_flow) and the SDK has been initialized.

Fragment:

class MainFragment : Fragment() {
    override fun onCreateView(inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle?): View? {
        return inflater.inflate(R.layout.fragment_main, container, false)
    }
}

XML:

<?xml version="1.0" encoding="utf-8"?>
<androidx.constraintlayout.widget.ConstraintLayout
        xmlns:android="http://schemas.android.com/apk/res/android"
        xmlns:app="http://schemas.android.com/apk/res-auto"
        xmlns:tools="http://schemas.android.com/tools"
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        tools:context=".MainFragment">

    <!-- This placeholder layout can be blank, this ProgressBar is provided as an example if you
         wish to show a loading state
     -->
    <ProgressBar
            style="?android:attr/progressBarStyle"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:id="@+id/progressBar"
            android:indeterminate="true"
            android:indeterminateTint="@color/colorAccent"
            app:layout_constraintTop_toTopOf="parent"
            app:layout_constraintBottom_toBottomOf="parent"
            app:layout_constraintStart_toStartOf="parent"
            app:layout_constraintEnd_toEndOf="parent"/>

</androidx.constraintlayout.widget.ConstraintLayout>

Step 4. Setup Deep Linking

  • Add the following intent filter to your project’s current AndroidManifest.xml file:
    <intent-filter>
      <data android:scheme="[yourAppSchemeHere]" />
      <action android:name="android.intent.action.VIEW" />
      <category android:name="android.intent.category.DEFAULT" />
      <category android:name="android.intent.category.BROWSABLE" />
    </intent-filter>
    
  • To add VenueNext Deep Link handling to your project’s current deep link implementation, ensure the following steps are performed in onNewIntent and after initial launch of your application:
    1. Initialize the VenueNext SDK (VenueNext::initialize)
    2. Register Deep Linkable objects with VenueNext (VenueNext::registerDeepLinkable)
    3. Call VenueNext::canHandleDeepLink and VenueNext::handleDeepLink as seen below:
      private fun handleIntent(intent: Intent?) {
         if (intent?.action == Intent.ACTION_VIEW) {
             intent.data?.let {
                 if (VenueNext.canHandleDeepLink(it)) {
                     // IMPORTANT: If your Activity does not include the VenueNext navigation graphs,
                     // start an Activity that does include the VenueNext navigation graphs with this
                     // Intent instead of handling the deep link here.
      
                     // The View that will be used to locate the NavController associated with the view.
                     // In practice, this will likely be fragment_main from Step 3a
                     VenueNext.handleDeepLink(view, it)
                 }
                 else {
                     // This is a deep link for your app!
                 }
             }
         }
        }
      

For setting up deep linking for virtual currency transfers, see deep linking setup.

If the above steps have been properly completed, you should be able to navigate into VenueNext views.

Updated: