Android App Quick Start

The following information will help you integrate the ARRIVE SDK with your app using Android Studio and Java.

Requirements

  • Android 4.0.3 and above
  • GPS, INTERNET, ACCESS_FINE_LOCATION and ACCESS_COARSE_LOCATION permissions

Create an account

You’ll need to create an account to complete the steps below. Already have an account? Sign in.

Steps

  1. Integrate the SDK
  2. Ask for Location Services permissions
  3. Add FCM in your app
  4. Set Notification Object for Foreground Service (for apps targeting OS 8.0+)
  5. Add a site
  6. Start and cancel trips
  7. Test your app

Step 1: Integrate the SDK

Get a Usage Token

If your app will be used in production, check Production token when you are getting your usage token. You can manage and get more usage tokens in your account at Account > Access > Usage Tokens. Your mobile and monitor apps must use the same environment.

Install the SDK From Maven

Add the following lines in the build.gradle file for your app:

repositories {
    maven {url "https://raw.github.com/Curbside/curbside-android-sdk-release/master"}
}

dependencies {
    compile 'com.curbside:sdk:3.2.2'
}

Initialize the SDK

Initialize CSUserSession with the context and usage token. Use the following code snippet to do so:

String USAGE_TOKEN = "PASTE_YOUR_USAGE_TOKEN_HERE";
CSUserSession.init(this /*context*/, new TokenCurbsideCredentialProvider(USAGE_TOKEN));

Keep in mind that you should initialize the CSUserSession only once in your application.

Step 2: Ask for Location Services permissions

The ARRIVE SDK makes use of Location Services.

Your AndroidManifest.xml should include the following permissions and features:

...
</application>

<uses-permission android:name="android.permission.INTERNET" />
<uses-permission android:name="android.permission.ACCESS_FINE_LOCATION" />
<uses-permission android:name="android.permission.ACCESS_COARSE_LOCATION" />
<uses-feature android:name="android.hardware.location.gps" />
</manifest>

Beginning with Android 6.0, users have to explicitly grant location permission to an app when it is running. If your app has not asked the user for the required permission, you can use the following code snippet to do so:

// Define PERMISSION_REQUEST_CODE field in your class
private static final int PERMISSION_REQUEST_CODE = 1;

// Request for location permissions
if (ActivityCompat.checkSelfPermission(this /*context*/, Manifest.permission.ACCESS_FINE_LOCATION) != PackageManager.PERMISSION_GRANTED &&
        ActivityCompat.checkSelfPermission(this /*context*/, Manifest.permission.ACCESS_COARSE_LOCATION) != PackageManager.PERMISSION_GRANTED) {
    String[] permissions = new String[]{Manifest.permission.ACCESS_COARSE_LOCATION, Manifest.permission.ACCESS_FINE_LOCATION};
    ActivityCompat.requestPermissions(this, permissions, PERMISSION_REQUEST_CODE /*int requestCode*/);
}

// Request permissions results
@Override
public void onRequestPermissionsResult(int requestCode, String permissions[], int[] grantResults) {
    switch (requestCode) {
        case PERMISSION_REQUEST_CODE:
            Arrays.sort(grantResults);
            if (Arrays.binarySearch(grantResults, PackageManager.PERMISSION_DENIED) >= 0) {
                //Location permission not given by the user. Can try showing rationale to the user.
            } else {
                //Location permissions given by the user.
            }
            break;
    }
}

Step 3: Add FCM in your app

ARRIVE SDK requires location from the device in order to notify the site’s associate of the customer’s arrival. Starting from OS 6.0, Android introduced doze mode. When the device is in doze mode, the OS tries to conserve battery by restricting the app’s access to the network. ARRIVE SDK addresses this issue by sending a high priority FCM to the client whenever it needs a location from the device. A high priority FCM will wake up the sleeping device and provide a small window for the app to make a network call. (source: Android Doze Mode)

Following documentation will help you integrate the FCM with Android SDK. It has two sections which will help apps with/without FCM integrated in them.

Step 4: Set Notification Object for Foreground Service (for apps targeting OS 8.0+)

Clients on Android OS 8.0+ require a foreground service to be started so that the app can receive locations. For the foreground service to be started, a notification object is required which will be shown to the user when the service is running. Sample notification object:

if(Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
    final NotificationChannel notificationChannel = NotificationChannel(CHANNEL_ID, CHANNEL_NAME, CHANNEL_IMPRORTANCE);
    
    final NotificationManager notificationManager = 
        (NotificationManager) context.getSystemService(Context.NOTIFICATION_SERVICE);
    
    notificationManager.createNotificationChannel(notificationChannel);

    return new Notification.Builder(this, CHANNEL_ID)
        .setContentTitle("Content Title")
        .setContentText("Content Text")
        .setSmallIcon(R.drawable.app_notification_icon)
        .setLargeIcon(R.drawable.app_notification_icon)
        .setOngoing(true)
        .build();
}

Set the notification object by using following API:

CSUserSession.getInstance().setNotificationForForegroundService(notification);

Step 5: Add a site

A site is a physical location near a road network and is the destination for a trip. It is usually (but not necessarily) a store, a restaurant, or a place of business. To track trips to a site, you must add that site to your account. When you add a site, you create a site ID, which you will use in your app when you add trip tracking.

Step 6: Start and cancel trips

Start Trips

This section covers what is needed to integrate the ARRIVE SDK with your app.

Curbside requires you to provide a unique tracking identifier for each user. This unique id is used by Curbside to identify the user. It should be the same across all logins for the same user, and across multiple devices. Once the user is logged in, you should use the following method to register this property to identify the user:

CSUserSession.getInstance().registerTrackingIdentifier("USER_UNIQUE_TRACKING_ID");

You can subscribe to EventBus before calling this method to listen for successful or failure events for this method. You can use the following code snippet to do so:

   //create the observer
   final Action1<com.curbside.sdk.event.Event> registerTrackingIdEventObserver = new Action1<com.curbside.sdk.event.Event>() {
        @Override
        public void call(com.curbside.sdk.event.Event event) {
            if(event.status == Status.SUCCESS) {
                 Log.d(TAG, String.format("Register Tracking Identifier successful"));
                 //do something like startTripToSiteWithIdentifier()
            }

            else if (event.status == Status.FAILURE) {
                Log.d(TAG, String.format("Failure in Registering Tracking Identifier due to: %s", (CSErrorCode)event.object));
                //do something
            }
        }
    };

    //subscribe
    CSUserSession.getInstance().getEventBus().getObservable(Path.USER, Type.REGISTER_TRACKING_ID).subscribe(registerTrackingIdEventObserver);

When the user logs out, use the following method to unregister the same property:

CSUserSession.getInstance().unregisterTrackingIdentifier();

You can also subscribe to EventBus before calling this method to listen to successful or failed events for this method. You can use the following code snippet to do so:

//create the observer
final Action1<com.curbside.sdk.event.Event> unregisterTrackingIdEventObserver = new Action1<com.curbside.sdk.event.Event>() {
    @Override
    public void call(com.curbside.sdk.event.Event event) {
        if(event.status == Status.SUCCESS) {
        Log.d(TAG, String.format("Unregistering Tracking Identifier successful"));
            //do something
        }

        else if (event.status == Status.FAILURE) {
            Log.d(TAG, String.format("Failure in Unregistering Tracking Identifier due to: %s", (CSErrorCode)event.object));
            //do something
        }
    }
};

//subscribe
CSUserSession.getInstance().getEventBus().getObservable(Path.USER, Type.UNREGISTER_TRACKING_ID).subscribe(unregisterTrackingIdEventObserver);

After the tracking identifier is set, the app is ready to start tracking the user:

CSUserSession.getInstance().startTripToSiteWithIdentifier("SITE_ID", "UNIQUE_TRACK_TOKEN");

SITE_ID is the unique identifier for a site where users will arrive. You create the Site ID when you add a site to your account. UNIQUE_TRACK_TOKEN is the unique identifier for a trip. A track token is needed to start tracking each user. The track token has a maximum of 60 characters.

  • If your site accepts orders, you can use your order ID as a track token. Appointment or confirmation numbers can also be used in situations where no orders are placed.
  • Track tokens are passed to the monitor app.

You can also subscribe to EventBus prior to calling this method to listen to successful or failed events for this method. You can use the following code snippet to do so:

    //create the observer
    final Action1<com.curbside.sdk.event.Event> startTripToSiteEventObserver = new Action1<com.curbside.sdk.event.Event>() {
        @Override
        public void call(com.curbside.sdk.event.Event event) {
        if(event.status == Status.SUCCESS) {
            Log.d(TAG, String.format("Start Trip to Site successful"));
            //do something
        }

        else if (event.status == Status.FAILURE) {
            Log.d(TAG, String.format("Failure in Start Trip to site due to: %s", (CSErrorCode)event.object));
            //do something
        }
    }
};

//subscribe
CSUserSession.getInstance().getEventBus().getObservable(Path.USER, Type.START_TRIP).subscribe(startTripToSiteEventObserver);

Cancel Trips

If the trip completes all the way through the system (that is, the monitor application is also integrated with ARRIVE), then the tracking for the site will automatically be stopped when the pickup is completed.

If the user is cancelling the trip in your app, and there will be no active trip at the given site, call the following method to cancel the trip:

CSUserSession.getInstance().cancelTripToSiteWithIdentifier("SITE_ID", "UNIQUE_TRACK_TOKEN");

SITE_ID is the unique identifier for a site where users will arrive. You create the Site ID when you add a site to your account. UNIQUE_TRACK_TOKEN is the unique identifier for a trip. A track token is needed to start tracking each user. The track token has a maximum of 60 characters.

You can also subscribe to EventBus before calling this method to listen for successful or failed events for this method. You can use the following code snippet to do so:

//create an observer for listening complete trip event
    final Action1<Event> cancelTripToSiteEventObserver = new Action1<Event>() {
        @Override
        public void call(Event event) {
            if(event.status == Status.SUCCESS) {
                Log.d(TAG, String.format("Succesfully cancelled trip to site"));
                //do something
            }
            else if (event.status == Status.FAILURE) {
                Log.d(TAG, String.format("Unsuccessful in cancelling trip to site due to: %s", (CSErroCode)event.object));
                //do something
            }
        }   
    };

//subscribe to the event on the eventBus
CSUserSession.getInstance().getEventBus().getObservable(Path.USER, Type.CANCEL_TRIP).subscribe(cancelTripToSiteEventObserver);

User Confirming Arrival

The ARRIVE SDK sends an event on the eventBus when the user is near a site that is being tracked. We suggest using it to enable a button that the user can click to confirm she is on-site:

    //create an observer to observe if user is near to any site that is being tracked
    final Action1<Event> canNotifyMonitoringUserAtSiteEventObserver = new Action1<Event>() {
        @Override
        public void call(com.curbside.sdk.event.Event event) {
            if(event.status == Status.TRUE) {
                //Check for the sites which are near to the user
            }
        }
    };

//subscribe to the event
CSUserSession.getInstance().getEventBus().getObservable(Path.USER, Type.CAN_NOTIFY_MONITORING_USER_AT_SITE).subscribe(canNotifyMonitoringUserAtSiteEventObserver);

When the event above is received on the eventBus, call the following method to get back the sites you can notify that the user has arrived.

Set<String> siteIdentifiers = CSUserSession.getInstance().getSitesToNotifyMonitoringSessionUserOfArrival();

If siteIdentifiers is not empty, it means you can notify the monitoring session user by using notifyMonitoringSessionUserOfArrivalAtSite method:

// Check if user is near to any site to notify the monitoring session user of that site
    Set<String> siteIdentifiers = CSUserSession.getInstance().getSitesToNotifyMonitoringSessionUserOfArrival();
        if (siteIdentifiers.size() > 0) {
        //We can notify the monitoring session user at these sites
            for (String siteIdentifierToNotifyMonitoringUser : siteIdentifiers) {
                CSUserSession.getInstance().notifyMonitoringSessionUserOfArrivalAtSite(new CSSite(siteIdentifierToNotifyMonitoringUser));
            }
        } else {
            //User is not near to any site
}

You can also subscribe to EventBus before calling this method to listen for successful or failed events for this method. You can use the following code snippet to do so:

    final Action1<Event> notifyMonitoringSessionUserEventObserver = new Action1<Event>() {
        @Override
        public void call(Event event) {
            if(event.status == Status.SUCCESS) {
                Log.d(TAG, "Successfully notified monitoring user"));
            }
            else if (event.status == Status.FAILURE) {
                Log.d(TAG, String.format("Failure in notifying monitoring session user due to: %s", (CSErrorCode)event.object));
            }
        return;
    }
};

//subscribe to the event on the eventBus
CSUserSession.getInstance().getEventBus().getObservable(Path.USER, Type.NOTIFY_MONITORING_SESSION_USER).subscribe(notifyMonitoringSessionUserEventObserver);

Step 7: Test your app

The ARRIVE SDK should now be fully integrated in your app. Run the app and view your dashboard to start seeing trips as they are being tracked. You’re done!

If you are receiving errors, see the error code documentation to help you troubleshoot.

Next Steps