Android implementation

Android

🚧

Location Permission Access

When instantiating the Android booking screen make sure the user has granted location permissions. If these haven't been granted then the user will be unable to use the map to select an address and the pickup address will not default to the user's location.

When instantiating the Android booking screen make sure the user has granted location permissions. If these are granted, then the pickup address will default to the users location and the user will be able to select a pick up or drop off point using the map as well as searching for an address. If these permissions haven't been granted then the user will be unable to use the map to select an address and the pickup address will not default to the user's location.

The Booking Activity contains all the important widgets needed to book a trip, from the address picker to the quote list, ending with the checkout and the trip tracking components.

Android Booking Screen

14401440

Android Booking Screen

Android example

To launch the Booking Activity, the BookingActivity.Builder should be use to generate an intent with the desired data and the launch it via the startActivity or startActivityForResult methods.

// launching for primary flow
val builder = BookingActivity.Builder.builder
                .initialLocation(location)
                .outboundTripId(outboundTripId)
                .comments(comment)
                .passengerDetails(passenger)
                .journeyInfo(journeyInfo)
                .tripDetails(tripDetails)
                
startActivity(builder.build(this))

// launching for callback example
val MY_REQ_CODE = 101
val callbackIntent = BookingActivity.Builder.builder
    .initialLocation(location)
    .buildForOnActivityResultCallback(this)
startActivityForResult(callbackIntent, MY_REQ_CODE)

// receiving booked trip for callback flow
override fun onActivityResult(requestCode: Int, resultCode: Int, data: Intent?) {
  if (resultCode == Activity.RESULT_OK && requestCode == MY_REQ_CODE) {
    val bookedTrip = data?.getParcelableExtra<TripInfo>(BookingCodes.BOOKED_TRIP)
    // do something with bookedTrip 
  }
  super.onActivityResult(requestCode, resultCode, data)
}

Builder variables

VariableDescription
tripDetails: TripInfoThe activity will take the origin and destination, if available from tripDetails, use this to pre-populate the addressview and begin fetching quotes
outboundTripId: StringThe outboundTripId is expected when the trip is booked from a ‘rebook’ button in another activity, it’s used for analytics purposes only
initialLocation: LocationIf an initialLocation is passed in the activity will zoom straight to this without having to wait for the device to return a location
comments: StringBy passing a comment into the Booking activity it will automatically prefill the comments field of the desired trip.
passengerDetails: PassengerDetailsBy passing passenger details into the Booking activity it will automatically prefill the passenger details of the desired trip.
journeyInfo:JourneyInfoWhen passing a journeyInfo into the Booking activity it will automatically prefill the origin, destination and date of the desired trip.

Checkout Screen

Android Checkout Activity

When an authenticated user selects a quote, they are then taken to the checkout screen which enables them to change passenger details, enable loyalty earning or burning, see the capabillities of a ride, add or update their payment details and end up by booking the ride.

The Checkout Activity can be launched independently from the Booking Activity. In order to launch it succesfully, a valid Quote is required for the component to work, the rest of the parameters are optional.

VariableDescription
quote: QuoteThe activity will take the quote object and use this to prepopulate eta, pricing and vehicle details fields
outboundTripId: String?The outboundTripId is expected when the trip is booked from a 'rebook' button in another activity
It's used for analytics purposes only
bookingMetadata: HashMap<String, String>?If an metadata map is passed in the activity, it will be used as part of the Booking API meta data
bookingInfo: BookingInfoBy passing booking status into the Booking activity it will automatically prefill the origin, destination and date of the desired trip.
passengerDetails: PassengerDetailsIf a passenger is added, then it will be used to prefill the passenger details in the booking request component
comments: StringBy passing comments into the Checkout Component it will automatically prefill the comments of the desired trip.
validityDeadlineTimestamp: LongSets the validity timestamp of the quote
When validity of the quote is expired, a popup will be shown to the user to notify him

The Checkout Activity can be launched similar to the Booking Activity, containing a builder which can handle the above params

// launching for primary flow
val builder = CheckoutActivity.Builder()
                            .quote(actions.quote)
                            .outboundTripId(outboundTripId)
                            .bookingMetadata(bookingMetadata)
                            .passengerDetails(passengerDetails)
                            .comments(bookingComments)
                            .loyaltyInfo(loyaltyInfo)
                            .bookingInfo(BookingInfo(pickup, destination, date))
                            .currentValidityDeadlineTimestamp(ts)

// launching for callback example
startActivityForResult(builder.build(this), REQ_CODE_BOOKING_REQUEST_ACTIVITY)

When an error occurs in the Checkout Component, the activity will be finished with a result containing an error code or string
In order to catch the error result, override onActivityResult in the calling activity and listen for BOOKING_CHECKOUT_ERROR result code

/**
     * Method used for finishing up the booking request activity with an error
     * The activity which launches the BookingRequestActivity should handle the error result
     * under BOOKING_REQUEST_ERROR (result code 10) and act accordingly
     * @param error reason for closing the BookingRequestActivity
     */
    private fun finishWithError(error: String) {
        val data = Intent()
        data.putExtra(BOOKING_CHECKOUT_ERROR_KEY, error)
        setResult(BOOKING_CHECKOUT_ERROR, data)
        finish()
    }

When the Checkout Component successfully books a trip, the resulting tripId will be available on the returning's intent extras of CheckoutActivity.BOOKING_CHECKOUT_PREBOOK_TRIP_INFO_KEY

if (resultCode == Activity.RESULT_OK && requestCode == REQ_CODE_BOOKING_REQUEST_ACTIVITY) {
            if (data?.hasExtra(CheckoutActivity.BOOKING_CHECKOUT_PREBOOK_TRIP_INFO_KEY) == true) {
                //In case of prebook,the trip is instantly booked. Show a confirmation
                showPrebookConfirmationDialog(data)
            } else {
                //Send the data to the trip allocation widget
          tripAllocationWidget.onActivityResult(requestCode, resultCode, data)
            }
        }
14401440

Android Checkout Component

The user can expand various sections of the checkout screen to gather more information about the selected Quote.

The quote capabillities section can be displayed by clicking on the Learn More
The loyalty section is available when Loyalty is available for the user
The pricing info section can be expanded or retracted by pressing on the info button right next to the METERED | FIXED | ESTIMATED label

Colors, texts, fonts, icons and styles can be fully customized by overriding the default styles provided by the Karhoo UISDK.

14401440

Checkout Component with partial sections expanded

14401440

Checkout Component with all sections expanded

Customizing the Checkout Component

The Checkout Component can be easily styled by overriding the default colors, fonts, texts, icons and styles.

In order to easily see which style is used on a particular sub-component, just open up the R.layout.uisdk_booking_checkout_view.xml file, locate the style name you'd wish to change and override the style in your local styles.xml file.
The below example shows the default style for the loyalty subtitle text. In order to change it's text color, just add a KhLoyaltySubtitleText style in your styles.xml file with the android:color value changed

<style name="KhLoyaltySubtitleText">
        <item name="android:textSize">@dimen/kh_uisdk_text_size_small</item>
        <item name="android:color">@color/kh_uisdk_secondary_text</item>
        <item name="android:layout_marginTop">@dimen/kh_uisdk_spacing_xxsmall</item>
        <item name="fontWeight">600</item>
        <item name="lineHeight">20dp</item>
    </style>

Same goes with the colors or dimensions, just override the default colors/dimens in your local colors.xml/dimens.xml files

In order to replace drawables or fonts, just add replacement files with the same names of the original uisdk ones.