Getting Started: Android

Minumum Operating System

Android v16+ (Jelly Bean)

Get API keys

If you do not have a Foursquare API key whitelisted for Pilgrim access, read our guide on Foursquare API Access.


Add Your Android Key Hash

Important: In order for Pilgrim SDK to authenticate with our server, you’ll need to add your app’s Android Key Hash to your Foursquare app’s configuration. Navigate to your Foursquare app settings page here: foursquare.com/developers/app/CLIENT_ID

  1. Generate a key hash of your developer certificate using this command:
    keytool -list -v -keystore [your keystore file path]
    

    For example, your debug key for development might look like:

    keytool -list -v -keystore ~/.android/debug.keystore -alias androiddebugkey -storepass android -keypass android
    
  2. Near the bottom of the page, under Install options, paste your Android SHA1 Key Hash in the Android Key Hashes field: screenshot showing Android key hashes
    Note: you can add multiple key hashes delimited by commas.

  3. Click Save changes.

Installation

1. Adding the dependency

Once you have been given a username and password from Foursquare, you can access the repository that has the Pilgrim SDK. Add the following snippet to your root build.gradle file and you will be able to resolve the library.

allprojects {
    repositories {
        maven {
            url 'https://foursquare.jfrog.io/foursquare/libs-release/'
        }
    }
}

Then, in the build.gradle file for the project for which you would like to include the Pilgrim SDK, add:

implementation 'com.foursquare:pilgrimsdk:2.2.0'

Configure and Start Pilgrim

1. Configure the Pilgrim SDK

Use the following code to configure the Pilgrim SDK notification handler in your App.java’s onCreate method. Also, you can optionally set the log level to DEBUG to receive more detailed logs while you’re developing and persist them on disk.

PilgrimSdk.Builder builder = new PilgrimSdk.Builder(this)
        .consumer("CLIENT_ID", "CLIENT_SECRET")
        .notificationHandler(pilgrimNotificationHandler)
        .logLevel(LogLevel.DEBUG);
PilgrimSdk.with(builder);
PilgrimSdk.with(
    PilgrimSdk.Builder(this)
        .consumer("CLIENT_ID", "CLIENT_SECRET")
        .notificationHandler(pilgrimNotificationHandler)
        .logLevel(LogLevel.DEBUG)
)

2. Set up the Pilgrim Notification Handler

In order to be notified of visits, add the Pilgrim SDK notification handlers to your Application’s onCreate method.

private final PilgrimNotificationHandler pilgrimNotificationHandler = new PilgrimNotificationHandler() {
    // Primary visit handler
    @Override
    public void handleVisit(Context context, PilgrimSdkVisitNotification notification) {
        // Process the visit however you'd like:
        Visit visit = notification.getVisit();
        Venue venue = visit.getVenue();
        Log.d("PilgrimSdk", visit.toString());
    }

    // Optional: If visit occurred while in Doze mode or without network connectivity
    @Override
    public void handleBackfillVisit(Context context, PilgrimSdkBackfillNotification notification) {
        // Process the visit however you'd like:
        super.handleBackfillVisit(context, notification);
        Visit visit = notification.getVisit();
        Venue venue = visit.getVenue();
        Log.d("PilgrimSdk", visit.toString());

    }

    // Optional: If visit occurred by triggering a geofence
    @Override
    public void handleGeofenceEventNotification(Context context, PilgrimSdkGeofenceEventNotification notification) {
        // Process the geofence events however you'd like:
        List<GeofenceEvent> geofenceEvents = notification.getGeofenceEvents();
        for (GeofenceEvent geofenceEvent : geofenceEvents) {
          Log.d("PilgrimSdk", geofenceEvent.toString());
        }
    }
};
private val pilgrimNotificationHandler = object : PilgrimNotificationHandler() {
    // Primary visit handler
    override fun handleVisit(context: Context, notification: PilgrimSdkVisitNotification) {
        val visit = notification.visit
        val venue = visit.venue
        Log.d("PilgrimSdk", visit.toString())
    }

    // Optional: If visit occurred while in Doze mode or without network connectivity
    override fun handleBackfillVisit(context: Context, notification: PilgrimSdkBackfillNotification) {
        val visit = notification.visit
        val venue = visit.venue
        Log.d("PilgrimSdk", visit.toString())
    }

    // Optional: If visit occurred by triggering a geofence
    override fun handleGeofenceEventNotification(context: Context, notification: PilgrimSdkGeofenceEventNotification) {
        super.handleGeofenceEventNotification(context, notification)
        // Process the geofence events however you'd like:
        notification.geofenceEvents.forEach { geofenceEvent ->
            Log.d("PilgrimSdk", geofenceEvent.toString())
        }
    }
}

Note the types of notifications you may receive:

  • handleVisit: The primary visit handler that receives arrival and departure events.
  • handleBackfillVisit: This handler receives visits that occurred when theire was no network connectivity or for failed visits that have been retried. For arrivals, departureTime will be null.
  • handleGeofenceEventNotification: This handler receives visits for geofences.

3. Start Pilgrim

Once Pilgrim is configured, you can start running it by calling PilgrimSdk.start(this); in your MainActivity#onCreate.

PilgrimSdk.start(this);

4. Handle a Visit

With Pilgrim properly configured, the notification handlers hit whenever you arrive or depart one of our 105M+ places around the world. In order to test your visit callback without physically walking around, we provide a test method:

  • PilgrimNotificationTester.sendTestVisitArrivalAtLocation can test your PilgrimNotificationHandler implementation without moving around. By passing a latitude and longitude, this method communicates with the Foursquare servers and sends back a notification if the location matches your configuration.
    void PilgrimNotificationTester.sendTestVisitArrivalAtLocation(
          @NonNull Context context,
          double lat,
          double lng,
          boolean isDeparture
    )
    

Tips

Get Current Location

By default, Pilgrim SDK runs in the background and pushes you visits when it detects a stop. You can also actively request the current location manually when the app is in use by calling the PilgrimSdk.get().getCurrentLocation() method:

if (ContextCompat.checkSelfPermission(this, android.Manifest.permission.ACCESS_FINE_LOCATION) == PackageManager.PERMISSION_GRANTED) {
    new Thread(new Runnable() {
        @Override
        public void run() {
            Result<CurrentLocation, Exception> currentLocationResult = PilgrimSdk.get().getCurrentLocation();
            if (currentLocationResult.isOk()) {
                CurrentLocation currentLocation = currentLocationResult.getResult();
                Log.d("PilgrimSdk", "Currently at " + currentLocation.getCurrentPlace().toString() + " and inside " + currentLocation.getMatchedGeofences().size() + " geofence(s)");
            } else {
                Log.e("PilgrimSdk", currentLocationResult.getErr().getMessage(), currentLocationResult.getErr());
            }
        }
    }).start();
}
if (ContextCompat.checkSelfPermission(this, android.Manifest.permission.ACCESS_FINE_LOCATION) == PackageManager.PERMISSION_GRANTED) {
    Thread(Runnable {
        val currentLocationResult: com.foursquare.pilgrim.Result<CurrentLocation, Exception> = PilgrimSdk.get().currentLocation
        if (currentLocationResult.isOk) {
            val currentLocation: CurrentLocation = currentLocationResult.result
            Log.d("PilgrimSdk", "Currently at ${currentLocation?.currentPlace} and inside ${currentLocation?.matchedGeofences?.size} geofence(s)")
        } else {
            Log.e("PilgrimSdk", currentLocationResult.err!!.message, currentLocationResult.err)
        }
    }).start()
}

This will return the current venue the device is most likely at (in the currentLocation object), as well as any geofences that the device is in (if configured). Note that this will forgo any “stop detection” so it shouldn’t be used as a proxy for visits. For example, this method could return a high confidence result for Starbucks if called while someone is walking by the entrance.

Reasons for a nil or error response

There are a couple reasons that calling getCurrentLocation would return an error or a nil value:

  1. Lack of network connectivity: The most likely reason the SDK cannot retrieve the device’s current location would be because the API request has failed to make a proper connection to the Foursquare server.
  2. Lack of location permissions: If the proper location permissions have not been properly set or granted by the user.
  3. getCurrentLocation is being run from the main thread.

Stop Monitoring Visits

If you need to stop monitoring the user’s visits (for example, if they opt out or turn off your background feature), you can turn off the Pilgrim SDK by calling:

PilgrimSdk.stop(context);

This will stop all Pilgrim activity. To resume Pilgrim, just call start() again. Repeatedly starting and stopping the SDK will temporarily reduce accuracy and drain battery.

Clearing All History

In certain instances, you may want to clear a users visit history entirely from the device, including their Home and Work locations. An example of this may be a user logging out of your app. For this you should use:

PilgrimSdk.clearAllData(context);

Permissions

The following permissions are automatically added to your manifest file when you import the Pilgrim SDK library:

<uses-permission android:name="android.permission.ACCESS_FINE_LOCATION" />
<uses-permission android:name="android.permission.INTERNET" />
<uses-permission android:name="android.permission.CHANGE_WIFI_STATE" />
<uses-permission android:name="android.permission.ACCESS_WIFI_STATE" />
<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />
<uses-permission android:name="android.permission.RECEIVE_BOOT_COMPLETED" />
<uses-permission android:name="android.permission.WAKE_LOCK" />

Please let us know if you have any questions about this list. An example AndroidManifest.xml file can be found here.

Targeting Android Marshmallow

If you are using targetSdk 23, then you will need to make sure that your app requests the ACCESS_FINE_LOCATION permission. Pilgrim will not run without the location permission. Once your user accepts the location permission, you should call PilgrimSdk.start(context).

public void requestLocationPermission(Activity activity, int requestCode) {
    ActivityCompat.requestPermissions(activity, new String[]{Manifest.permission.ACCESS_FINE_LOCATION},
            requestCode);
}

Next Steps

Configuration

Was this page helpful?
Yes
No
Thank you!