Get started with the Network SDK

📘

Please visit the new version of our documentation here.

The Karhoo Network SDK offers an end-to-end ride booking experience. It enables partners to add Karhoo Mobility Exchange functionality into their own native apps without any additional maintenance. The SDK handles the data models, networking, business logic and the general caveats that come from a direct API integration.

The SDKs are kept up to date with changes to the Karhoo Platform and native mobile platform changes. With our Sandbox environment, you can get up and running in no time. The Sandbox provides the functionality to test the integration end to end before going live.

With the Karhoo Mobile SDK, you can:

  • Select pick up and drop off points
  • Retrieve quotes
  • Book a trip (ASAP/Prebook)
  • Receive trip updates
  • Track driver
  • See current and past bookings

Add the Network SDK to your project

iOS

The Karhoo iOS SDK is compatible with iOS 10 and above.

Add the following to your podfile:

# Karhoo podspec source
source '[email protected]:karhoo/karhoo-ios-pods.git'
source 'https://github.com/CocoaPods/Specs.git'


pod 'KarhooSDK'

Android

The Karhoo Android SDK is compatible with Android 5.0 Lollipop and above.

Add the following to your Gradle build file

// Add the following into your Root level build.gradle
allprojects {
    repositories {
        ... // Other maven repos for your project
        maven { url 'https://jitpack.io' }
    }
}

//In your app dependancies add the latest UISDK verison
implementation 'com.github.karhoo:karhoo-android-sdk:1.4.0'

Network SDK Initialisation

To initialise the Network SDK on either iOS or Android, a working network environment must be provided. The network environments are Sandbox and Production. Sandbox is used for development and testing purposes. Bookings in sandbox are not paid for and trip progress is simulated using Karhoo Bot fleets. A custom environment can also be provided.

iOS

// set up KarhooSDKConfiguration implementation
struct KarhooSDKConfig: KarhooSDKConfigurationProvider {

  func environment() -> KarhooSDKConfiguration {
       return .sandbox
   }
 
  func authenticationMethod() -> AuthenticationMethod {
    	return .karhooUser
   }
}

//App Delegate
Karhoo.set(configuration: KarhooSDKConfig())

Android

// set up KarhooSDKConfiguration
import com.karhoo.sdk.api.KarhooEnvironment
import com.karhoo.sdk.api.KarhooSDKConfiguration

class KarhooSDKConfig : KarhooSDKConfiguration {

    override fun environment(): KarhooEnvironment {
        return KarhooEnvironment.Sandbox()
    }

    override fun context(): Context {
        return context
    }
  
    override fun authenticationMethod(): AuthenticationMethod {
    	return AuthenticationMethod.KarhooUser()
    }
}

//Application file
KarhooApi.setConfiguration(configuration = KarhooSDKConfig(context = this.applicationContext))

Authentication

The network SDK currently supports 3 different types of authentication methods, each for different use cases depending on the integration:

  • Username/password (A user created and managed in the Karhoo platform)
  • Token authentication (Your own users in your own platform )
  • Guest authentication (No sign in required)

The AuthenticationMethod is set as part of the configuration. The sample code above is the config for username/password.

Token authentication

You will first need to integrate your external authentication system with the Karhoo platform before initialising the SDK with your client id. When using this authentication method, the authentication service must be used to login and revoke access before interacting with other Karhoo services.

iOS

// KarhooSDKConfig
func authenticationMethod() -> AuthenticationMethod {
  	let settings = TokenExchangeSettings(clientId: "",
                                         scope: "")
    	return .tokenExchange(settings: settings)
   }
}

Android

override fun authenticationMethod(): AuthenticationMethod {
  return AuthenticationMethod.TokenExhange(clientId = "",
                                           scope = "") 
 }

Guest users

iOS

func authenticationMethod() -> AuthenticationMethod {
  let guestSettings = GuestSettings(identifier: "",
                                    referer: "",
                                    organisationId: "")
    	return .guest(settings: guestSettings)
   }
}

Android

override fun authenticationMethod(): AuthenticationMethod {
    	return AuthenticationMethod.Guest(identifier = "client_identifier", referer = "referer", organisationId = "organisation_id")
    }
}

Using Network SDK Services

Every call to SDK services returns either a Call or PollCall dependent upon the nature of the endpoint.

Call

Call has one function available, called execute. Calling execute will open up a completion handler, which will contain a Result type enum. What’s going on behind the scenes is a single network request to the KarhooAPI and the result being returned asynchronously to the completion handler.

PollCall

PollCall has two functions available, called execute and observable. Calling execute will simply do the same as a Call. observable however will return an Observable, which can be used for endpoints that require polling, such as tracking a moving vehicle or the state of a trip in progress. See the Driver Tracking Service as an example of a PollCall return type

Result/Resource Type

All calls to the KarhooSDK are returned; as a success or as a typed Error. These two result types are encapsulated inside an enum.

iOS example

public enum Result<T> {
    case success(result: T)
    case failure(error: KarhooError?)

// was the result successful?
public func isSuccess() -> Bool

// get the success value (returns optional expected result type as the result may have failed)
public func successValue() -> T? 

// get the error value (returns optional KarhooError as the result may have succeeded)
public func errorValue() -> KarhooError? 
}

// recommended unwrap approach

let result = Result<String>.success(result: "Hello World")

switch result {
case .success(let result):
    print(result)
case .failure(let error):
    print(error)
}

// OR

if let value = result.successValue() {
    print(result)
} else if let error = result.errorValue() {
    print(error)
}

Observable

Returned from PollCall is an Observable. An Observable has a subscribe and unsubscribe function. These functions take an Observer.

Observer

An Observer is generic and takes a model. In the code example, the Observer is constructed with a result type of DriverTrackingInfo.

The Observer can now be subscribed or unsubscribed on an observable. In this case, the observable returned from the PollCall of the Driver Tracking Service endpoint.

Remember to unsubscribe Observers when you no longer need them, such as in the unloading of a view.

iOS

let driverTrackingObserver = Observer<DriverTrackingInfo> { [weak self] result in
    switch result {
        case .success(let driverTrackingInfo):
            print("Driver position: \(driverTrackingInfo.position)")
        case .failure(let error):
            // handle error (KarhooError)
    }
}

Android

val driverPositionObserver = object : Observer<Resource<DriverTrackingInfo>> {
    override fun onValueChanged(value: Resource<DriverTrackingInfo>) {
        when (value) {
            is Resource.Success -> print(value.data)
            is Resource.Failure -> print(value.error.internalMessage)
        }
    }
}

Subscribe / Unsubscribe observers

iOS

// create observable
let driverTrackingObservable = driverTracking.trackDriver(tripId: "1234").observable(pollTime: 5)

// subscribe observer to observable
driverTrackingObservable.subscribe(observer: driverTrackingObserver)

// unsubscribe observer from observable
driverTrackingObservable.unsubscribe(observer: driverTrackingObserver)
Changelog

Android

// Subscribe to observable with repeatable poll time
val REPEAT_INTERVAL = 50000
val driverTrackingInfoObservable = driverTrackingService.trackDriver("1234").observable().apply {
    driverPositionObserver?.let {
        subscribe(it, REPEAT_INTERVAL)
    }
}

// Unsubscribe from observable
driverPositionObserver?.let {
    driverTrackingInfoObservable?.unsubscribe(it)
}