NAV
android ios xamarin

Introduction

Welcome to the Sitata Software Development Kits (SDKs)! You can use our SDKs to access the Sitata API endpoints within your existing mobile application. Create your own user interface designs or display our turn-key screens to your users.

You can view code examples in the dark area to the right.

Using the SDKs

Sitata currently has SDKs available for iOS, Android, and Xamarin. Each SDK might have its own unique configurations or dependencies. Use of the SDKs assumes that you have had a thorough read through of our API documentation.

Typical Use Case

There are many ways to use and access the API depending on your partnership with Sitata. However, the typical use case is one in which a company wishes to provide Sitata’s services for its own travellers. In this case, the following procedure is recommended.

  1. Create a traveller record using the company endpoint.
  2. Create a trip using the company endpoint and the newly created traveller record.
  3. Use the authentication_token of the traveller to access the remaining (client/end-user) portions of the API. Typically, this would include downloading the traveller’s trip information to a mobile device, including country backgrounds, disease information, alerts, advisories and so on.

Getting Started

Integration Workflow

To ensure a successful integration, Sitata’s support team will work with you during the integration process. The approach is as follows:

  1. Ensure you have access to Sitata. You should have a Server API key which will allow you to generate Trips, Travellers, and Traveller API keys. If you do not have access to Sitata, please contact us!

  2. Follow the process below to integrate our SDKs into your project.

  3. Configure the SDK using a Traveller API key and initialize it during application start-up. Test launching a few of the turn key User Interface screens. This may require you to create a trip for the traveller. Ideally, you can create a trip and traveller at the same time.

  4. Create a workflow to determine exactly when Trip and Traveller records will be created. Determine when the traveller’s authentication token will be sent to the device. This could be on application start-up and/or after application startup through a push notification or background sync process.

  5. Determine if you want to use Sitata’s turn key User Interface Screens, how you want to customize it, and where it fits into your app. If not, use the rest of the SDK manually to download data, store data on the phone, and then display it using your own user interface design.

Using Your Own User Interface

Sitata has provided several turn key User Interface screens for your convenience, however, you may decide to use your own design. In this situation, you can still use the SDK to download and store Sitata data to the device.

There are three core layers to the SDK for manually downloading and storing data to the device.

1. API

The API layer will allow you to fetch data from the Sitata API. Data will be returned using the data models described in this documentation.

2. Sync

The Sync layer will allow you to download and store Sitata data to the mobile device. It is a convenience wrapper around the API layer and the database layer. Further, sync processes occur on a background thread and persistent queue process. Therefore, if a sync process is performed and it fails, it will retry in the future.

3. Events Layer

The Events Layer allows you to catch and respond to events. The events currently supported allow you to see new and updated models as they are saved to the device, and also monitor the progress of jobs. This layer is only available in Android.

4. DB Layer

The DB Layer allows you to query the local database for data. This layer is only available in Android. In iOS, database interactions occur through static methods on the model objects themselves.

Android

The Android SDK is packaged into 4 different AAR modules that can be used in various combinations. The modules depend on each other in a linear way: core -> api -> controller -> gui. This means, for example,

Thus, you must use one of the following configurations:

Maven Gradle repository support can be made available, please contact us if you need this. Otherwise, you can drop the AAR files into your project’s lib folder and import them using Gradle.

<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android">

    <application android:label="YOUR_APP_NAME" android:theme="@android:style/Theme.Material">

        <meta-data android:name="com.google.android.geo.API_KEY" android:value="YOUR_GOOGLE_MAPS_API_KEY" />
        <meta-data android:name="com.google.android.gms.version" android:value="@integer/google_play_services_version" />

        <!-- You will need to reference your own firebase services to enable push notifications! -->
        <service android:name=".PATH.TO.MyFirebaseMessagingService">
            <intent-filter>
                <action android:name="com.google.firebase.MESSAGING_EVENT"/>
            </intent-filter>
        </service>

        <service android:name=".PATH.TO.MyFirebaseInstanceIDService">
            <intent-filter>
                <action android:name="com.google.firebase.INSTANCE_ID_EVENT"/>
            </intent-filter>
        </service>

    </application>

</manifest>

Permissions and Manifest Meta Data

Any apps including the Sitata SDK must have specific permissions to enable certain features such as those required for Google Maps. Please ensure your manifest has, at a minimum, the entries listed in the example manifest.

Note that to ensure proper functionality, you must obtain your own Google Maps API Key. You should also replace YOUR_APP_NAME

You will have to create a FirebaseMessagingService and FirebaseInstanceIDService to enable push notifications and adjust your manifest to reference these services accordingly. For more information refer to Enabling Push Notifications for Android.

iOS

CocoaPods

The SDK is available as a CocoaPod. CocoaPods is an open source dependency manager for Swift and Objective-C Cocoa projects. If you don’t already have the CocoaPods tool, install it on macOS by running the following command from the terminal. For details, see the CocoaPods Getting Started guide.

sudo gem install cocoapods

Create a Podfile for the Sitata SDK and any other dependencies your app may rely on:

source 'https://github.com/CocoaPods/Specs.git'
target 'YOUR_APPLICATION_TARGET_NAME_HERE' do
  pod 'SitataCore'
end
  1. Create a file named Podfile in your project directory. This file defines your project’s dependencies.
  2. Edit the Podfile and add your dependencies.
  3. Save the Podfile.
  4. Run the pod install command from your project directory. This will install the dependencies specified in the Podfile, along with any dependencies they may have.
  5. Close Xcode and then open your project’s .xcworkspace file to launch Xcode. From this point onward, you must use the .xcworkspace file to open the project.

Permissions and PList Data

<key>UIBackgroundModes</key>
<array>
  <string>fetch</string>
    <string>location</string>
    <string>remote-notification</string>
</array>

<key>NSLocationWhenInUseUsageDescription</key>
<string>This app requires your permission to show your location on a map</string>

The Sitata SDK requires a few configuration entries in the parent application’s plist file to enable push notifications and location data. To enable push notifications and location data, please enter these snippets into your plist file.

Xamarin

The first step required to get started with Xamarin, for either iOS or Android, is to install the Sitata bindings project for each platform as a project dependency.

Once you’ve installed the Sitata NuGet package(s), you must ensure you have a compatible manifest in Android. Any apps including the Sitata SDK must have specific permissions to enable certain features such as those required for Google Maps. Please follow these instructions to ensure your manifest has the proper definitions.

In addition, for iOS, you must ensure that you have the required entries in your plist file.

MultiDex and Xamarin

In Xamarin, the dex limit is exceeded and therefore you must configure your build to ensure your app will compile. In order to do so you must:

  1. Right-click android project
  2. Choose Properties
  3. Navigate to Android Options
  4. Choose “Enable Multi-Dex”

Proguard and Xamarin

Proguard is not currently supported in Xamarin

Push Notifications and Xamarin

The entries in the Android manifest in Xamarin may be different. Refer to the following documentation for information on how to set up cloud messaging in Xamarin Android:

Firebase Cloud Messaging

Google Cloud Messaging

Initial Setup

public class App extends Application {

  private static SitataGui mySitataGui;

  @Override
  public void onCreate() {
    // sync Sitata data on app start
    getSitataGui( this ).ctrlr.jobs.sync.all().replaceAndStart();
    super.onCreate();
  }R

  private static void initSitataGui( Context ctx ) {
      var cfg = new SitataConfig.Builder()
          .setApiEndpoint( "https://staging.sitata.com/api/" )
          .setContext( ctx )
          .setAuthToken( "API_KEY_HERE" )
          .setTripBuilderConfig( new SitataConfig.TripBuilderConfig.Builder()
              // ...
              .build() )
          .setFontConfig( new SitataConfig.FontConfig.Builder()
              // ...
              .build() )
          .build();

      mySitataGui = new SitataGui( cfg );
  }

  // Creates a singleton pattern for accessing a SitataGui instance. This could be
  // important in situations such as push notifications where an instance must be
  // present, even before application boot. Using either this getter will ensure that
  // you will always have a properly configured SitataGui instance.
  public static SitataGui getSitataGui( Context ctx ) {
    if ( mySitataGui == null ) initSitataGui( ctx );
    return mySitataGui;
  }

}
// In iOS, the SDK needs to be initialized within your App Delegate
@implementation AppDelegate

- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions
{

  // Note that you are encouraged to use build configurations for specifying various values.
  // https://www.appfoundry.be/blog/2014/07/04/xcode-env-configuration/
  // or
  // https://medium.com/@danielgalasko/change-your-api-endpoint-environment-using-xcode-configurations-in-swift-c1ad2722200e
  NSString *token = @"API_KEY_HERE";
  STASDKController *ctrl = [STASDKController sharedInstance];
  [ctrl setConfig:token apiEndpoint:@"https://www.sitata.com"];
  [ctrl sync];
}

- (void)applicationWillResignActive:(UIApplication *)application
{
    // Sent when the application is about to move from active to inactive state. This can occur for certain types of temporary interruptions (such as an incoming phone call or SMS message) or when the user quits the application and it begins the transition to the background state.
    // Use this method to pause ongoing tasks, disable timers, and throttle down OpenGL ES frame rates. Games should use this method to pause the game.


    // Tells the Sitata SDK to stop syncing data.
    [[STASDKController sharedInstance] stop];
}

- (void)applicationDidBecomeActive:(UIApplication *)application
{
    // Restart any tasks that were paused (or not yet started) while the application was inactive. If the application was previously in the background, optionally refresh the user interface.

    // Tells the Sitata SDK to start syncing data.
    [[STASDKController sharedInstance] start];
}


// etc...

@end


// == ANDROID == //

// MyApp.cs

namespace YourAppNameIsHere.Droid {

  [Application]
  class MyApp : Application {

    private static SitataGui MySitataGui { get; set; }

    public MyApp( IntPtr handle, JniHandleOwnership transfer ) : base( handle, transfer ) { }

    public override void OnCreate() {
      base.OnCreate();
      // sync Sitata data on app start
      GetSitataGui( Application.Context ).Ctrlr.Jobs.Sync.All.ReplaceAndStart();
    }

    private static void InitSitataGui( Context ctx ) {
        var cfg = new SitataConfig.Builder()
            .SetApiEndpoint( "https://staging.sitata.com/api/" )
            .SetContext( ctx )
            .SetAuthToken( "API_KEY_HERE" )
            .SetTripBuilderConfig( new SitataConfig.TripBuilderConfig.Builder()
                // ...
                .Build() )
            .SetFontConfig( new SitataConfig.FontConfig.Builder()
                // ...
                .Build() )
            .Build();

        MySitataGui = new SitataGui( cfg );
    }

    // Creates a singleton pattern for accessing a SitataGui instance. This could be
    // important in situations such as push notifications where an instance must be
    // present, even before application boot. Using this getter will ensure that
    // you will always have a properly configured SitataGui instance.
    public static SitataGui GetSitataGui( Context ctx ) {
        if ( MySitataGui == null ) InitSitataGui( ctx );
        return MySitataGui;
    }

  }
}


// == IOS == //

// AppDelegate.cs

public class AppDelegate : UIApplicationDelegate {
  // etc...

  public override bool FinishedLaunching(UIApplication application, NSDictionary launchOptions) {

    // set up the sitata sdk
    var token = "API_KEY_HERE";
    var ctrl = STASDKController.SharedInstance;
    ctrl.SetConfig(token, "https://www.sitata.com");
    ctrl.Sync();
  }

  public override void OnResignActivation(UIApplication application) {
    // Invoked when the application is about to move from active to inactive state.
    // This can occur for certain types of temporary interruptions (such as an incoming phone call or SMS message)
    // or when the user quits the application and it begins the transition to the background state.
    // Games should use this method to pause the game.

    // Pause the sitata sdk (sync jobs)
    STASDKController.SharedInstance.Stop();
  }

  // etc...
  public override void OnActivated(UIApplication application) {
    // Restart any tasks that were paused (or not yet started) while the application was inactive.
    // If the application was previously in the background, optionally refresh the user interface.

    // Start the sitata sdk (sync jobs)
    STASDKController.SharedInstance.Start();
  }

  // etc...
}

The end-user’s authentication token is required to access various parts of the Sitata API. Therefore, you must configure the SDK with the authentication token and other properties such as the API endpoints you wish to use.

Typically, the SDK should perform a full sync on application load. To do so, you should call sync data at the appropriate times. If the user has a current trip, then the SDK will download all relevant data to the phone for display. In order to accomplish this, only a few lines of code are required.

In android, this process should occur in your application class or within a splash screen activity where you are starting up the application. In iOS, this process should occur inside your App Delegate.

If the sync process is successful, you should be able to launch a User Interface screen to display data such as trip alerts (provided the end-user has a current trip to display).

SDK Configuration

There are a few configuration settings that can be applied to modify the behavior of the SDK as a whole.

// Set 'fixedTripDates' to true
NSString *token = @"API_KEY_HERE";
STASDKController *ctrl = [STASDKController sharedInstance];
[ctrl setConfig:token apiEndpoint:@"https://www.sitata.com"];
ctrl.fixedTripDates = YES;
// Set 'fixedTripDates' to true
var token = "API_KEY_HERE";
var ctrl = STASDKController.SharedInstance;
ctrl.SetConfig(token, "https://www.sitata.com");
ctrl.FixedTripDates = true;
SitataConfig cfg = new SitataConfig.Builder()
    .setApiEndpoint( "https://staging.sitata.com/api/" )
    .setContext( ctx )
    .setAuthToken( "API_KEY_HERE" )
    .setTripBuilderConfig( new SitataConfig.TripBuilderConfig.Builder()
        .setFixedTripDates( true )
        .setSkipTripActivitySelect( true )
        .setSkipTripTypeSelect( true )
        .build() )
    .setFontConfig( new SitataConfig.FontConfig.Builder()
        // ...
        .build() )
    .build();

mySitataGui = new SitataGui( cfg );

iOS

Config Type Description
apiToken string The user’s API access token.
apiEndpoint string The API endpoint to use on Sitata. Default is “https://www.sitata.com”.
fixedTripDates boolean When true, trip builder will fix the range of possible dates during trip editing to be between the trip’s start and finish date (inclusive) which were previously set.
skipTBTypes boolean When true, trip builder will skip the screen which allows a user to select the trip type.
skipTBActivities boolean When true, trip builder will skip the screen which allows a user to select trip activities.

On iOS, the above settings are set directly on the STASDKController shared instance.

Android

SDK Arguments (Required)

Config Type Description
apiEndpoint String
authToken String Token to use for API requests, ie the traveller token
context Context The context that the library will use internally, for example for resolving resources

These are properties of the SitataConfig object, see usage in Android code section.

Trip Builder Settings (Optional)

Config Type Description
fixedTripDates Boolean When true, trip builder will fix the range of possible dates during trip editing to be between the trip’s start and finish date (inclusive) which were previously set.
skipTripTypeSelect Boolean When true, trip builder will skip the screen which allows a user to select the trip type.
skipTripActivitySelect Boolean When true, trip builder will skip the screen which allows a user to select trip activities.

These are properties of the TripBuilderConfig object, see usage in Android code section.

Font Config

Custom fonts are also specified at this point, please see the customization section for more information.

Third Party API Dependencies

iOS

On iOS, the Trip Builder functionality relies on the Google Places iOS API. You will need to setup a Google API Key, which can be generated from the Google API Console. Then ensure that the Google Places API for iOS is enabled in the Google API Console.

In order for the Sitata SDK to use your Google API Key, you will need to add it as a string value to your application’s main Info.pList file under a key named GoogleApiKey.

Android

On Android, the Google Maps Android API is used extensively. In addition, you must also enable the Google Places API for Android. Both API’s will require a Google API Key, which can be generated from the Google API Console. To use your API key, you must add it to your application’s manifest as described above. The Google Maps API is used in any User Interface screen which includes a map. The Google Places API is used during the Trip Builder functionality in addition to the Alerts and Advisories screen when geographical data is not present.

Detecting Empty Trips


// == iOS == //
using SitataCore;

STASDKMTrip trip = STASDKMTrip.CurrentTrip;
if (trip.IsEmpty) {
  STASDKUI.ShowTripBuilder(trip.Identifier);
}


// == Android == //

var trip = MySitata.Ctrlr.Db.Trips.FindCurrent();
if (trip != null && trip.isEmpty()) {
  // Note: "returnTo" is a class reference to an activity to return to when trip
  // builder is complete. See "user interface" section for more info
  MySitata.LaunchTripBuilder( ctx, returnTo, trip.Id );
}

#import <SitataCore/STASDKMTrip.h>
#import <SitataCore/STASDKUI.h>

STASDKMTrip *trip = [STASDKMTrip currentTrip];
if ([trip isEmpty]) {
  [STASDKUI showTripBuilder:[trip identifier]];
}
Trip trip = App.sitataGui.ctrlr.db.trips.findCurrent();
if (trip != null && trip.isEmpty()) {
  // Note: "returnTo" is a class reference to an activity to return to when trip
  // builder is complete. See "user interface" section for more info
  App.getSitataGui( ctx ).launchTripBuilder( ctx, returnTo, trip.getId() );
}

Sitata allows for trips that do not have associated destination information. These are called “empty” or “blank” trips. A company might not know the exact locations that a traveller will be visiting, but still have the start and finish date of a trip. In this situation, it is desirable to launch trip builder for the user so they can specify itinerary details. Otherwise, they won’t receive trip alerts or itinerary specific health and safety information.

When using our turn-key user interface screens, Trip Builder will automatically launch if the current trip is empty, however, you may wish to launch trip builder at another point in time depending on your user experience workflow. Doing so is fairly trivial. The process first must query the local database for the user’s current trip, detect if the trip is empty, and finally launch trip builder if it is an empty trip.

Gotchas

Below are a few scenarios that you should be aware of when incorporating the SDKs into your own mobile application.

Multiple Users and Login / Logout


// == iOS == //
STASDKController.SharedInstance.DestroyAllData();

// == Android == //
// Note: This is fairly slow, you should do it in a background thread:
App.GetSitataGui( ctx ).Ctrlr.DestroyAllData();

STASDKController *ctrl = [STASDKController sharedInstance];
[ctrl destroyAllData];
// Note: This is fairly slow, you should do it in a background thread:
App.getSitataGui( ctx ).ctrlr.destroyAllData();

The Sitata SDK downloads data for a single user only. Therefore, in order to provide login and logout functionality, it is important to remove Sitata related data between logins. This way, there is zero possibility of displaying the wrong trip to the wrong user.

Working With Asynchronous Requests


// == iOS == //
SitataCore.STASDKSync.FullSync((NSError err) => {
  // Check if err is nil or not and react accordingly
  System.Console.WriteLine("Perform more actions here.");
});

// == Android == //
// Use the synchronous methods available which will return after completion or
// after the given timeout (in milliseconds) is reached, whichever happens first.
var sitataGui = App.GetSitataGui( ctx );
bool success = sitataGui.Ctrlr.Jobs.Trips.Current.WaitForCompletion(10000 /*ms*/);
success = success && sitataGui.Ctrlr.Jobs.Countries.List.WaitForCompletion(10000 /*ms*/);
#import <SitataCore/STASDKSync.h>

[STASDKSync fullSync:^(NSError *err) {
  // Check if err is nil or not and react accordingly
  NSLog(@"Perform more actions here.");
}];
// This demo is a typical use case, where you would like to sync data and listen
// for changes in an activity.
// Please see the docs for "event" and "jobs" layers for more instructions.
public class MyActivity extends Activity {

  private Button tripSyncBtn;
  private TextView tripName;

  @Override
  protected void onCreate() {
      // ...
      tripSyncBtn = (Button) findViewById( R.id.trip_sync_btn );
      tripName = (TextView) findViewById( R.id.trip_name );
      // add a button that starts a sync job on click
      final Context ctx = this;
      tripSyncBtn.setOnClickListener( new View.OnClickListener() {
          @Override
          public void onClick( View v ) {
              App.getSitataGui( ctx ).ctrlr.jobs.trips.getById( "abc123" ).replaceAndStart();
          }
      } );
  }

  // register for events on start
  @Override
  protected void onStart() {
      App.getSitataGui( this ).ctrlr.events.register( this );
      super.onStart();
  }

  // unregister from event system on stop
  @Override
  public void onStop() {
      App.getSitataGui( this ).ctrlr.events.unregister( this );
      super.onStop();
  }

  // optional threadMode arg specifies whether you want it to run in
  // background or on ui thread
  @Subscribe( threadMode = ThreadMode.MAIN )
  public void myUiThreadHandler( TripEvent e ) {
    // find the updated trip
    Trip trip = App.getSitataGui( this ).ctrlr.db.trips.fetchById( e.tripId );
    // safe to update UI here
    if (trip != null) tripName.setText( trip.getName() );
  }

}

Almost all data requests within the Sitata SDK are performed asynchronously. Therefore, there may be times when you might have to wait for data to be downloaded to the phone before displaying it or launching various user interface screens. For example, if you choose to launch the Trip Builder User Interface Screen before the SDK has had a chance to download the traveller’s current trip (and list of countries, on Android), then you will experience an unexpected result.

In IOS, all sync mathods contain a callback argument which you can use to ensure that the operation has completed.

On Android, you should start jobs to start syncing needed data, then detect when they have completed using events. You can monitor the status of the jobs themselves, or just monitor for changes to specific models (like detecting when a new Trip object is saved to the local DB) using events. The sample code demonstrates a typical use case inside an activity.

On Xamarin Android, the events layer does not behave correctly due to issues with the JNI, so you will have to use the WaitForCompletion method. This is explained in more detail in the sync section.

User Interface

The Sitata SDKs provide a number of user interface screens should you wish to use a turn-key solution for display of Sitata data. These screens provide a basic layout for display and can be customized in a limited fashion.

Alerts

// == ANDROID == //

// show alerts for the current trip
App.GetSitataGui( ctx ).LaunchAlerts( this );

// or for a trip with Id "abc123"
App.GetSitataGui( ctx ).LaunchAlerts( this, "abc123" );


// == IOS == //
using static SitataCore.STASDKUI;

// show alerts for the current trip
ShowAlerts();

// or for a trip with Id "abc123"
ShowAlerts("abc123");

// show alerts for the current trip
[STASDKUI showAlerts];

// or for a trip with Id "abc123"
[STASDKUI showAlerts:"abc123"];

// show alerts for the current trip
App.getSitataGui( ctx ).launchAlerts( ctx );

// or for a trip with Id "abc123"
App.getSitataGui( ctx ).launchAlerts( ctx, "abc123" );

The alerts screen can be launched to display to the user a list of travel alerts pertaining to end-user’s current trip or a given trip. Selecting a specific alert will display the trip alert’s full details.

Advisories

// == ANDROID == //
// show advisories for the current trip
App.GetSitataGui( ctx ).LaunchAdvisories( this );

// or for a trip with Id "abc123"
App.GetSitataGui( ctx ).LaunchAdvisories( this, "abc123" );


// == IOS == //
using static SitataCore.STASDKUI;

// show advisories for the current trip
ShowAdvisories();

// or for a trip with Id "abc123"
ShowAdvisories("abc123");

// show advisories for the current trip
[STASDKUI showAdvisories];

// or for a trip with Id "abc123"
[STASDKUI showAdvisories:"abc123"];
// show advisories for the current trip
final Context ctx = this;
App.getSitataGui( ctx ).launchAdvisories( ctx );

// or for a trip with Id "abc123"
App.getSitataGui( ctx ).launchAdvisories( ctx, "abc123" );

The advisories screen can be launched to display to the user a list of travel advisories pertaining to end-user’s current trip. Selecting a specific alert will display the trip advisory’s full details.

Diseases

// == ANDROID == //
App.GetSitataGui( ctx ).LaunchDiseases( this );

App.GetSitataGui( ctx ).LaunchDiseases( this, "abc123" );


// == IOS == //
using static SitataCore.STASDKUI;

ShowTripDiseases();

ShowTripDiseases("abc123");

[STASDKUI showTripDiseases];

[STASDKUI showTripDiseases:"abc123"];
final Context ctx = this;
App.getSitataGui( ctx ).launchDiseases( ctx );

App.getSitataGui( ctx ).launchDiseases( ctx, "abc123" );

The diseases screen can be launched to display to the user a list of diseases pertaining to end-user’s current trip or a given trip identifier.

Vaccinations

// == ANDROID == //
App.GetSitataGui( ctx ).LaunchVaccinations( this );

App.GetSitataGui( ctx ).LaunchVaccinations( this, "abc123" );


// == IOS == //
using static SitataCore.STASDKUI;

ShowTripVaccinations();

ShowTripVaccinations("abc123");

[STASDKUI showTripVaccinations];

[STASDKUI showTripVaccinations:"abc123"];
final Context ctx = this;
App.getSitataGui( ctx ).launchVaccinations( ctx );

App.getSitataGui( ctx ).launchVaccinations( ctx, "abc123" );

The vaccinations screen can be launched to display to the user a list of vaccinations pertaining to end-user’s current trip or a given trip identifier.

Medications

// == ANDROID == //
App.GetSitataGui( ctx ).LaunchMedications( this );

App.GetSitataGui( ctx ).LaunchMedications( this, "abc123" );


// == IOS == //
using static SitataCore.STASDKUI;

ShowTripMedications();

ShowTripMedications("abc123");

[STASDKUI showTripMedications];

[STASDKUI showTripMedications:"abc123"];
final Context ctx = this;
App.getSitataGui( ctx ).launchMedications( ctx );

App.getSitataGui( ctx ).launchMedications( ctx, "abc123" );

The medications screen can be launched to display to the user a list of medications pertaining to end-user’s current trip or a given trip identifier.

Hospitals

// == ANDROID == //
App.GetSitataGui( ctx ).LaunchHospitals( this );

App.GetSitataGui( ctx ).LaunchHospitals( this, "abc123" );


// == IOS == //
using static SitataCore.STASDKUI;

ShowTripHospitals();

ShowTripHospitals("abc123");

[STASDKUI showTripHospitals];

[STASDKUI showTripHospitals:"abc123"];
final Context ctx = this;
App.getSitataGui( ctx ).launchHospitals( ctx );

App.getSitataGui( ctx ).launchHospitals( ctx, "abc123" );

The hospitals screen can be launched to display to the user a list of hospitals pertaining to end-user’s current trip or a given trip identifier.

Safety

// == ANDROID == //
App.GetSitataGui( ctx ).LaunchSafety( this );

App.GetSitataGui( ctx ).LaunchSafety( this, "abc123" );

// == IOS == //
using static SitataCore.STASDKUI;

ShowTripSafety();

ShowTripSafety("abc123");

[STASDKUI showTripSafety];

[STASDKUI showTripSafety:"abc123"];
final Context ctx = this;
App.getSitataGui( ctx ).launchSafety( ctx );

App.getSitataGui( ctx ).launchSafety( ctx, "abc123" );

The safety screen can be launched to display to the user a list of safety information pertaining to end-user’s current trip or a given trip identifier.

Emergency Numbers

// == ANDROID == //
App.GetSitataGui( ctx ).LaunchEmergencyNumbers( this );


// == IOS == //
using static SitataCore.STASDKUI;

ShowEmergencyNumbers();

[STASDKUI showEmergencyNumbers];
final Context ctx = this;
App.getSitataGui( ctx ).launchEmergencyNumbers( ctx );

The emergency numbers screen can be launched to display to the user a list of emergency numbers for various countries. The country displayed will be either the country that the user is in based on GPS data or the country of the current trip that user is in based on their itinerary.

Trip Builder

// == ANDROID == //

// Specify what activity to launch when trip builder completes.
// There is a bit of boilerplate needed in order to pass a C# activity
// through the JNI.
// This paramter can just be null. If it is null, the SDK will attempt
// to navigate to the activity that was open before launching trip builder.
var returnTo = Java.Lang.Class.FromType(typeof(MyActivity));

// to start trip buidler to create a new trip (and optionally specify which
// activity to launch on completion)
App.GetSitataGui( ctx ).LaunchTripBuilder( ctx, returnTo, null );

// to start trip builder to edit an existing trip
var trip = App.GetSitataGui( ctx ).Ctrlr.Db.Trips.FindCurrent();
if (trip != null) App.GetSitataGui( ctx ).LaunchTripBuilder( ctx, returnTo, trip.Id );


// == IOS == //
using static SitataCore.STASDKUI;

// this example uses the current trip's identifier, passing NULL or an empty string will start trip builder for creating a new trip
var trip = STASDKMTrip.CurrentTrip;
string tripId = "";
if (trip != null)
{
    tripId = trip.Identifier;
}
ShowTripBuilder(tripId);

// this example uses the current trip's identifier, passing NULL or an empty string will start trip builder for creating a new trip
STASDKMTrip *trip = [STASDKMTrip currentTrip];
[STASDKUI showTripBuilder:trip.identifier];
// Specify what activity to launch when trip builder completes.
// This paramter may be null. If it is null, the SDK will attempt
// to navigate to the activity that was open before launching trip builder.
Class<?> returnTo = MyActivity.class;

// to start trip buidler to create a new trip
App.getSitataGui( ctx ).launchTripBuilder( ctx, returnTo, null );

// to start trip builder to edit an existing trip
Trip trip = App.getSitataGui( ctx ).db.trips.findCurrent();
if (trip != null) App.getSitataGui( ctx ).launchTripBuilder( ctx, returnTo, trip.getId() );

Trip Builder provides user interface screens which allow the user to create or edit a trip. It is possible to launch trip builder without trip data. In this case, the process will create a new trip for the traveller. This may or may not be desired. For example, you may not want your users to be able to access trip builder without a trip previously created for them. Either way, you have complete control on when trip builder should be launched.

Customization

The turn key User Interface screens can be customized in a limited fashion on all platforms.

iOS

// Simply access the `STASDKUIStylesheet` singleton and configure accordingly. The UI screens
// will adjust upon load. Therefore, this is typically performed one time, on application boot.
STASDKUIStylesheet sheet = [STASDKUIStylesheet sharedInstance];
sheet.navigationBarBackgroundColor = [UIColor redColor];
sheet.navigationBarTextColor = [UIColor whiteColor];

On iOS, the STASDKUIStylesheet is provided to allow basic customization of various elements within the turn key User Interface screens. Simply access the STASDKUIStylesheet singleton and configure accordingly. The UI screens will adjust upon load. Therefore, this is typically performed one time, on application boot.

A full list of properties can be seen here.

Android

Colours

<!-- res/values/styles.xml -->
<resources>
    <style name="MyDarkSitataSdkTheme" parent="Theme.AppCompat.Light.NoActionBar">
        <item name="colorPrimary">@color/sitata_gui_color_primary</item>
        <item name="colorPrimaryDark">@color/sitata_gui_color_primary_dark</item>
        <item name="colorAccent">@color/sitata_gui_color_accent</item>
        <item name="android:windowBackground">@color/sitata_gui_color_window_bg</item>
        <item name="cardBackgroundColor">@color/sitata_gui_color_card_bg</item>
        <item name="cardTextColor">@color/sitata_gui_color_card_text</item>
        <item name="android:textColorPrimary">@color/sitata_gui_color_text_primary</item>
        <item name="android:textColorSecondary">@color/sitata_gui_color_text_secondary</item>
        <item name="android:textColorTertiary">@color/sitata_gui_color_text_tertiary</item>
    </style>
    <!-- ... your other styles ... -->
</resources>

<!-- res/values/colors.xml -->
<?xml version="1.0" encoding="utf-8"?>
<resources>
    <color name="sitata_gui_color_primary">#212c3f</color>
    <color name="sitata_gui_color_primary_dark">#161e2b</color>
    <color name="sitata_gui_color_accent">#9fc179</color>
    <color name="sitata_gui_color_window_bg">#0c1119</color>
    <color name="sitata_gui_color_card_bg">#dcdcdc</color>
    <color name="sitata_gui_color_card_text">#212121</color>
    <color name="sitata_gui_color_text_primary">#eee</color>
    <color name="sitata_gui_color_text_secondary">#c6c6c6</color>
    <color name="sitata_gui_color_text_tertiary">#616161</color>
    <!-- ... your other colours ... -->
</resources>
// Apply a dark theme
SitataConfig myConfig = new SitataConfig.Builder()
  // ... other config ...
  .setTheme(R.style.MyDarkSitataSdkTheme)
  .build();
SitataGui gui = new SitataGui( myConfig );

Open your styles.xml and create a style scope that contains all of the keys specified in the XML code sample in the sidebar.

Style Key Description
colorPrimary Used for main title bars / headers / etc. This should not be too saturated or too muted, and should be the representative colour of your brand for use in the app
colorPrimaryDark Occassionally used as a secondary header colour or to otherwise contrast the primary colour
colorAccent Bright colour that works well with the primary colour, used to indicate interactive elements
cardBackgroundColor Background colour for cards found in various places (alert details page, safety page)
android:windowBackground This is used on almost all screens as the background colour (medications, vaccinations, alerts, etc)
cardBackgroundColor This is used as the background colour for all “card” UI elements
android:textColorPrimary This is the colour of text drawn onto the primary colour. White or off-white is usually a good choice.
android:textColorSecondary This is the colour for text drawn onto the main window background colour. For light themes, this should be a very dark grey (pure black is best avoided).
android:textColorTertiary This colour is used as “disabled” / “greyed-out” / “hint” text alongside the secondary text colour. It will be drawn onto the main background colour. In a light theme, this would be a slightly lighter grey than the secondary text colour.

Then, to set the customization, simply reference the custom style when instantiating the Sitata SDK, as seen in the Java code in the sidebar.

Fonts

// The following fonts are stored in `src/main/assets/fonts`
Typeface heading = Typeface.createFromAsset( getAssets(), "fonts/heading.otf" );
Typeface body = Typeface.createFromAsset( getAssets(), "fonts/body.otf" );

SitataConfig myConfig = new SitataConfig.Builder()
        // ... other config ...
        .setFontConfig( new SitataConfig.FontConfig.Builder()
                // .setNavigationFont( ... )
                .setHeadingFont( heading )
                // .setSubheadingFont( ... )
                // .setRowTitleUnreadFont( ... )
                // .setRowTitleNormalFont( ... )
                // .setRowBodyFont( ... )
                // .setTitleFont( ... )
                .setBodyFont( body )
                // .setButtonFont( ... )
                // .setUrlEmailPhoneFont( ... )
                .build() )
        .build();

App.sitataGui = new SitataGui( myConfig );

There are several categories of fonts you may change, which are applied across the whole SDK. The example code here outlines how to import font files in a native Java Android project for API levels less than 26. All font overrides are optional – a font will fall back to the system default when nothing is provided.

Place custom font files in the “assets” folder (you may need to create this folder) and access them as shown in the example code. Note that the assets folder must live at src/main/assets, ie the same level as the src/main/res and src/main/java folders. For example src/main/assets/fonts/my_heading.otf.

Xamarin

The structure is exposed in C# for xamarin consumption.

Notifications

Sitata’s services include notifications to travellers. There are two types of notifications that are available:

  1. New Trip

  2. Trip Alert

For each type of notification, the SDK can handle downloading of associated data and actions to take for the incoming notification such as launching a UI screen. In all cases, the parent application must enable and control the receipt of notifications.

Enabling For iOS


@implementation AppDelegate

- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions
{

    // etc..

    // app launched from user interacting with a notification in notification tray
    if (launchOptions[UIApplicationLaunchOptionsRemoteNotificationKey]) {

        STASDKController *ctrl = [STASDKController sharedInstance];

        // sync data
        [ctrl receivePushNotification:launchOptions onFinished:^(UIBackgroundFetchResult result) {
            // can do something after sync if necessary
        }];

        // launch the screen for a particular push notification (when applicable)
        [ctrl launchPushNotificationScreen:launchOptions];

    }

}

- (void) application:(UIApplication *)application didRegisterForRemoteNotificationsWithDeviceToken:(NSData *)deviceToken {

    // Extract token from data object
    NSString *token = [[deviceToken description] stringByTrimmingCharactersInSet: [NSCharacterSet characterSetWithCharactersInString:@"<>"]];
    token = [token stringByReplacingOccurrencesOfString:@" " withString:@""];
    NSLog(@"Registered for remote notifications: %@", token);

    // Pass token to Sitata SDK Controller
    STASDKController *ctrl = [STASDKController sharedInstance];
    [ctrl setPushNotificationToken:token];
}

- (void) application:(UIApplication *)application didFailToRegisterForRemoteNotificationsWithError:(NSError *)error {
    NSLog(@"Failed to register for remote notifications.");
}

// Called when push notification is received in foreground or background
- (void)application:(UIApplication *)application didReceiveRemoteNotification:(NSDictionary *)userInfo fetchCompletionHandler:(void (^)(UIBackgroundFetchResult))completionHandler
{

    // In all three states, pass notification to Sitata to download additional data.
    STASDKController *ctrl = [STASDKController sharedInstance];
    [ctrl receivePushNotification:userInfo onFinished:^(UIBackgroundFetchResult result) {
        completionHandler(result);
    }];


    if (application.applicationState == UIApplicationStateActive) {
        // app is currently active, can update badges or visuals here

    } else if (application.applicationState == UIApplicationStateBackground) {
        // app is in background

    } else if (application.applicationState == UIApplicationStateInactive) {
        // app is transitioning from background to foreground (user has tapped notification)

    }
}


// You could call this function from anywhere in your application.
// Ideally, you would want to do this after explaining to the
// user why you're requesting them.

#define SYSTEM_VERSION_GREATER_THAN_OR_EQUAL_TO(v)  ([[[UIDevice currentDevice] systemVersion] compare:v options:NSNumericSearch] != NSOrderedAscending)
#define SYSTEM_VERSION_LESS_THAN(v)                 ([[[UIDevice currentDevice] systemVersion] compare:v options:NSNumericSearch] == NSOrderedAscending)

- (void)registerForPushNotifications
{
    if( SYSTEM_VERSION_LESS_THAN( @"10.0" ) ){
        [[UIApplication sharedApplication] registerUserNotificationSettings:[UIUserNotificationSettings settingsForTypes:(UIUserNotificationTypeSound | UIUserNotificationTypeAlert | UIUserNotificationTypeBadge) categories:nil]];
        [[UIApplication sharedApplication] registerForRemoteNotifications];
    } else {
        UNUserNotificationCenter *center = [UNUserNotificationCenter currentNotificationCenter];
        center.delegate = self; // this assumes the function is placed inside AppDelegate
        [center requestAuthorizationWithOptions:(UNAuthorizationOptionSound | UNAuthorizationOptionAlert | UNAuthorizationOptionBadge) completionHandler:^(BOOL granted, NSError * _Nullable error)
        {
            if(!error) {
                // required to get the app to do anything at all with push notifications
                [[UIApplication sharedApplication] registerForRemoteNotifications];
                NSLog( @"Push registration success." );
            } else {
                NSLog( @"Push registration FAILED" );
                NSLog( @"ERROR: %@ - %@", error.localizedFailureReason, error.localizedDescription );
                NSLog( @"SUGGESTIONS: %@ - %@", error.localizedRecoveryOptions, error.localizedRecoverySuggestion );
            }
        }];
    }

}

@end

To receive notifications, your app’s plist must be setup according to the Permissions and PList Data.

Notifications in iOS are typically controlled within your AppDelegate. The AppDelegate has to be configured such that receipt of notifications are handled when the application is in the foreground, background, stopped, and when the application is launched from a notification entry.

In order to handle incoming notifications a few AppDelegate methods need to be implemented.

didRegisterForRemoteNotificationsWithDeviceToken needs to be added to your AppDelegate to receive the push notification token from Apple after you have requested it. Sitata requires this push notification token and so a convenince method has been created to allow you to pass it to Sitata (setPushNotificationToken).

didFailToRegisterForRemoteNotificationsWithError should be implemented in case the device was unable to register for remote notifications, but this has no bearing on the Sitata SDK.

didReceiveRemoteNotification should be implemented to receive the push notification payload and do something with it. For Sitata purposes, two convenience methods have been created. The first, receivePushNotification will ensure that any associated data (e.g. a trip alert) for the push notification will be synced to the device. Second, launchPushNotificationScreen will perform an action (e.g. launch trip alert details page) for the incoming push notification payload. The ideal use case is to use this function after the user has tapped the notification and launched the application. In our example, we are doing so in the didFinishLaunchingWithOptions function by checking to see if the launchOptions dictionary has the key UIApplicationLaunchOptionsRemoteNotificationKey.

Requesting Permission

It is a good idea to request permission to receive push notifications after explaining to the user why they might want to receive them. For example, we recommend you design a welcome screen or series of introduction screens to tell the user what notifications are used for before asking for their permission. This is a much more appealing user experience than simply requesting permission on application start when the user has no idea what the notifications will be used for.

Regardless, the registerForRemoteNotifications should be used to request the push notification token from Apple Push Notification Services.

Enabling For Android


// Service class to obtain push notification token

import com.sitata.sdk.controller.SitataController;

public class MyFirebaseInstanceIDService extends FirebaseInstanceIdService {

    private static final String TAG = "MyFirebaseIIDService";

    @Override
    public void onTokenRefresh() {
        // Get updated InstanceID token.
        String refreshedToken = FirebaseInstanceId.getInstance().getToken();
        Log.d(TAG, "Refreshed token: " + refreshedToken);
        App.getSitataGui( this ).ctrlr.setFcmToken( refreshedToken );
    }

}

// Service class to receive incoming push notifications

import com.sitata.sdk.controller.SitataController;
import com.sitata.sdk.gui.SitataGui;

public class MyFirebaseMessagingService extends FirebaseMessagingService {

    private static final String TAG = "MyFirebaseMsgService";

    @Override
    public void onMessageReceived(RemoteMessage remoteMessage) {

        Log.d(TAG, "Got push from: " + remoteMessage.getFrom());

        if (remoteMessage.getData().size() > 0) {
            Log.d(TAG, "Message data payload: " + remoteMessage.getData());
        }

        // First, sync data
        App.getSitataGui( this ).ctrlr.handlePushData( remoteMessage );

        // Display a push notification
        SitataGui.showPushNotification( this, remoteMessage,
            // icon for the notification
            R.drawable.ic_my_push_notif_icon,
            // fallback activity to launch when a notification is clicked and there isn't
            // a specific SDK UI activity to launch. e.g. new trip notification
            MyMainActivity.class );
    }

}

To receive push notifications, your app’s manifest must be set up according to Permissions and Manifest Meta Data. This requires setting up two services in order to receive the push notification token during the registration process and to receive a push notification. In addition, you should add Firebase messaging to your application according to these instructions.

MyFirebaseInstanceIDService is used to receive the push notification token from Google during the registration process. The token is sent to sitata using the instance method setFcmToken.

onMessageReceived is used to receive a push notification. In this siutation, you should use handlePushData to trigger the Sitata SDK to sync all relevant data, then optionally you may use showPushNotification to display a push notification in the notification tray. The last argument of showPushNotification is an activity to launch when a “new trip” notification is clicked. When a trip alert push notification is received and the notification is clicked, the SDK will automatically launch the alert details page. However, when a new trip notification is clicked there is no specific user interface screen defined in the SDK to handle this click. In this situation, the class you provide will be launched.

Enabling for Xamarin

Enabling push notifications for Xamarin is largely a translation exercise from what is described above for iOS and Android. The methods required to receive push notifications, sync data, and display notification screens are exposed in the Xamarin bindings libraries with identical method names.

Firebase cloud messaging documentation for Android and Xamarin can be found here.

User notifications for iOS and Xamarin are documented here

Push Notification Types

The types of push notifications and their data structure are explained below. Your company can opt-out entirely from sending any type of notification to your travellers.

Message Format

Generally, all push notifications have the following attributes:

iOS

Attribute Type Description
alert string Title for the notification
badge integer Badge count
content_available boolean Always equal to true so sync is possible
sitataPt integer Sitata push notification type
sitataData string Stringified json for extra data

Android

Attribute Type Description
title string Title for the notification
alert string Body snippet for the notification
sitataPt integer Sitata push notification type
sitataData string Stringified json for extra data

SitataPt

Sitata defines the following push notification types:

Type Description
0 trip alert
1 good news
3 new trip

Trip Alert Notification

This notification is sent to the traveller’s device when a new trip alert has been issued for them. The message payload will have the following sitataData attributes:

sitataData

Attribute Type Description
alert_id string The alert’s identifier

Good News Notification

This notification is sent to the traveller’s device when no trip alerts have been issued yet for their itinerary. How often this alert is sent is configurable by your company. The message payload will not include extra sitata data.

New Trip Notification

This notification is sent to the traveller’s device when a new trip is created on their behalf. The message payload will have the following sitataData attributes:

sitataData

Attribute Type Description
trip_id string The trip’s identifier
silent boolean Whether or not the user should be notified. If false, can silently sync new data in background.

User Settings

Sitata keeps track of an individual traveller’s notification settings through a UserSettings object associated with their traveller account. These settings are independent of whether a trip is “muted” or not and will apply to all notifications for any trip past, present, or future.

Attribute Type Description
sendTripAlertEmail Boolean If true, will send trip alert emails to the traveller
sendAllGoodEmail Boolean If true, will send good news emails to the traveller
sendTripAlertPush Boolean If true, will send trip alert push notifications to the traveller
sendAllGoodPush Boolean If true, will send good news push notifications to the traveller

Adjusting User Settings

STASDKMTraveller *trav = [STASDKMTraveller findFirst];
STASDKMUserSettings *settings = trav.settings;
RLMRealm *realm = [[STASDKController sharedInstance] theRealm];
[realm transactionWithBlock:^{
    settings.sendAllGoodPush = NO;
    settings.sendAllGoodEmail = NO;
}];
NSError *error;
[settings backgroundUpdate:&error];

iOS

To adjust user settings in iOS, you must first pull out the settings object from a given user. You will need a reference to the correct user if your application supports multiple users (log in/out). In this situation you can call [STASDKMUser findBy:@"SITATA_USER_ID_HERE"].

Since the iOS SDK relies on Realm for persistance, you must make all adjustments to the user settings within a Realm transaction block. After your changes are made, you may save the settings by calling backgroundUpdate on teh settings object. This will save the settings object to Sitata’s server using a background process.

Android

// 1. Creating your own settings object
App.getSitataGui( ctx ).ctrlr.jobs.traveller.updateSettings( new UserSettings.Builder()
        .setSendTripAlertEmail( true )
        .setSendAllGoodEmail( false )
        .build() ).replaceAndStart();

// 2. modifying the existing settings
// first, retrieve settings
Traveller trav = App.getSitataGui( ctx ).ctrlr.db
        .travellers.findBy( TravellerDao.Properties.Email, "a@b.c" );
UserSettings setns = trav == null ? null : trav.getSettings();
// now, as before...
App.getSitataGui( ctx ).ctrlr.jobs.traveller.updateSettings( new UserSettings.Builder( setns )
        .setSendTripAlertEmail( true )
        .setSendAllGoodEmail( false )
        .build() ).replaceAndStart();

In Android, user settings are updated by passing a UserSettings object to the traveller.updateSettings job. The user whose settings will be updated is implicitly specified by the auth (traveller) token that the SDK is using. The request to update settings for a given user can only be performed by that user. Use the UserSettings.Builder class for more convenient usage (see code examples).

Xamarin

// == iOS == //
var trav = SitataCore.STASDKMTraveller.FindFirst();
var settings = trav.Settings;
var realm = SitataCore.STASDKController.SharedInstance.TheRealm();
realm.TransactionWithBlock(() => {
    settings.SendAllGoodPush = false;
    settings.SendAllGoodEmail = false;
});
NSError error;
settings.BackgroundUpdate(out error);
if (error != null) {
    // do some error catching
}

// == Android == //
App.GetSitataGui( ctx ).Ctrlr.Jobs.Traveller.UpdateSettings(
    new Com.Sitata.Sdk.Core.Models.UserSettings.Builder()
        .SetSendAllGoodEmail( true )
        .SetSendAllGoodPush( false )
        .Build()
);

Saving settings in Xamarin is largely a translation exercise from iOS or Android.

Clearing Data

[[STASDKController sharedInstance] destroyAllData];
App.getSitataGui( ctx ).ctrlr.destroyAllData()
// == iOS == //
STASDKController.SharedInstance.DestroyAllData();

// == Android == //
App.GetSitataGui( ctx ).Ctrlr.DestroyAllData()

It can be useful to remove all data from the user’s device in certain scenarios such as logging out.

In addition, the User Interface screens are designed to be used with a single user. When using the SDK’s UI screens or sync layers, the application will download relevant trip data to the phone and display it based on the current trip. However, the SDK does not associate such data with the current user. As such, if your application allows multiple users to log into it and you switch user tokens then it may be possible that the current trip displayed by the Sitata SDK is for the first user and not the second.

In order to avoid this issue, you should clear data from the phone before allowing a different user to log into the application. This can be done when the first user logs out of your application.

Sync Current Data

STASDKController *ctrl = [STASDKController sharedInstance];
// configure the SDK controller if necessary. e.g. just received token for the first time *after* app start
[ctrl setConfig:@"API_KEY_HERE"];
[ctrl resync];
// get your SitataController instance
SitataController ctrlr = App.getSitataGui( ctx ).ctrlr;

// OPTIONAL: you may need to replace the api auth token used by the SDK, eg if you
// instantiate the SDK before receiving the traveller token from your backend
ctrlr.setAuthToken( "API_KEY_HERE" );

// perform the actual sync
ctrlr.jobs.sync.all().replaceAndStart();
// == iOS == //
var ctrl = STASDKController.SharedInstance;
// configure the SDK controller if necessary. e.g. just received token for the first time *after* app start
ctrl.SetConfig("API_KEY_HERE")
ctrl.Resync();

// == Android == //
// get your SitataController instance
var ctrlr = App.GetSitataGui( ctx ).Ctrlr;

// OPTIONAL: you may need to replace the api auth token used by the SDK, eg if you
// instantiate the SDK before receiving the traveller token from your backend
ctrlr.SetAuthToken( "API_KEY_HERE" );

// perform the actual sync
ctrlr.Jobs.Sync.All().ReplaceAndStart();

When the SDK is initialized (e.g. on application start), it will sync data for the current user and their current trip. This process can also be performed manually. For example, it could be the case that you have just received the Sitata Authentication after the user has already opened the application. In this situation, you would not have been able to configure the Sitata SDK on application load. Therefore, you can configure the SDK at this point and time and manually sync data from Sitata.

For more details on how to sync individual data models, refer to the Sync section.

Models

The SDK provides model class objects around all important objects within the Sitata API. For properties of each model object, please refer to the API documentation.

On iOS, local database fetching of model objects is performed using static methods on the model classes.

On Android, a separate namespace has been created to perform local database fetching.

Traveller

A traveller is the current user of the application.

iOS

On iOS, the class for the traveller model is STASDKMTraveller.

Static Methods

Name Description
findBy Finds a stored traveller in the local database based on the given sitata traveller id
findFirst Finds the first stored traveller in the local database

Instance Methods

Name Description
resave Destroys all previous data and related models and resaves to the local database
removeAssociated Removes related models from the local database
Name Description
settings The traveller’s User Settings

Android

On Android, this model only maintains property accessors. For querying the local databse, please refer to the Android DB Layer.

Xamarin

The models are replicated in C# for xamarin consumption.

User Settings

User settings are specific settings which can be enabled by the Traveller

iOS

On iOS, the class for the traveller model is STASDKMUserSettings.

Static Methods

Name Description
findBy Finds a stored user settings in the local database based on the given identifier

Instance Methods

Name Description
backgroundUpdate Saves the settings locally and creates a background job to post the changes to Sitata

Android

On Android, this model only maintains property accessors. For querying the local databse, please refer to the Android DB Layer.

Xamarin

The models are replicated in C# for xamarin consumption.

Trip

A trip belongs to a traveller and contains itinierary and health and safety information.

iOS

On iOS, the class for the trip model is STASDKMTrip.

Static Methods

Name Description
currentTrip Finds and returns the current, ongoing trip or the next upcoming trip based on the trips’ start and finish dates
currentAndFutureTrips Returns a list of current and future trips as a RLMResults object
findBy Finds a stored trip by the given identifier
destroy Remove the trip and associated data from the local database by the given identifier

Instance Methods

Name Description
resave Destroys all previous data and related models and resaves to the local database
removeAssociated Removes related models from the local database
isEmpty Returns true if the trip does not have any destination data
sortedDestinations Returns a list of Destinations as a RLMResults object
currentCountry Returns the country that the user is currently in according to the itinerary or NULL
currentDestination Returns the Destination that the user is currently in according to the trip itinerary or NULL
activitiesArr Returns an array of integers that represent the activities of the trip
hasActivity Returns true if the given activity is included in the trip
addActivity Adds an activity to the trip
removeActivity Removes an activity from the trip
Name Description
destinations RLMArray of Destinations
alerts RLMArray of Alerts
advisories RLMArray of Advisories
tripDiseaseComments RLMArray of Trip Disease Comments
tripVaccinationComments RLMArray of Trip Vaccination Comments
tripMedicationComments RLMArray of Trip Medication Comments

Android

On Android, this model only maintains property accessors. For querying the local databse, please refer to the Android DB Layer.

Name Description
getDestinations Returns a List of Destinations
getTripDiseaseComments Returns a List of Trip Disease Comments
getTripVaccinationComments Returns a List of Trip Vaccination Comments
getTripMedicationComments Returns a List of Trip Medication Comments

Xamarin

The models are replicated in C# for xamarin consumption.

Trip Disease Comment

A Trip Disease Comment provides a country specific explanation about why a Disease is recommended for a particular country. This resource is rarely accessed directly and usually only accessed when dealing with a Trip.

iOS

On iOS, the class for this model is STASDKMTripDiseaseComment.

Static Methods

Name Description
commentsForDisease Returns a list of Trip Disease Comments based on the given disease identifier and trip.

Android

On Android, this model only maintains property accessors. For querying the local databse, please refer to the Android DB Layer.

Xamarin

The models are replicated in C# for xamarin consumption.

Trip Medication Comment

A Trip Medication Comment provides a country specific explanation about why a Medication is recommended for a particular country. This resource is rarely accessed directly and usually only accessed when dealing with a Trip.

iOS

On iOS, the class for this model is STASDKMTripMedicationComment.

Static Methods

Name Description
commentsForMedication Returns a list of Trip Medication Comments based on the given medication identifier and trip.

Android

On Android, this model only maintains property accessors. For querying the local databse, please refer to the Android DB Layer.

Xamarin

The models are replicated in C# for xamarin consumption.

Trip Vaccination Comment

A Trip Vaccination Comment provides a country specific explanation about why a Vaccination is recommended for a particular country. This resource is rarely accessed directly and usually only accessed when dealing with a Trip.

iOS

On iOS, the class for this model is STASDKMTripVaccinationComment.

Static Methods

Name Description
commentsForVaccination Returns a list of Trip Vaccination Comments based on the given vaccination identifier and trip.

Android

On Android, this model only maintains property accessors. For querying the local databse, please refer to the Android DB Layer.

Xamarin

The models are replicated in C# for xamarin consumption.

Destination

A trip is made up of one or more destination objects. This resource is rarely accessed directly and usually only accessed when dealing with a Trip.

iOS

On iOS, the class for the destination model is STASDKMDestination.

Instance Methods

Name Description
removeAssociated Removes related models from the local database
Name Description
destinationLocations The Destination Locations that the destination includes

Android

On Android, this model only maintains property accessors. For querying the local databse, please refer to the Android DB Layer.

Name Description
getDestinationLocations Returns a list of Destination Locations that the destination includes

Xamarin

The models are replicated in C# for xamarin consumption.

Destination Location

A destination can have locations associated with it. This resource is rarely accessed directly and usually only accessed or changed when dealing with a Destination. These entries are used during Sitata’s Trip Alert process.

iOS

On iOS, the class for the destination location model is STASDKMDestinationLocation.

Static Methods

None.

Instance Methods

None.

Android

On Android, this model only maintains property accessors. For querying the local databse, please refer to the Android DB Layer.

Xamarin

The models are replicated in C# for xamarin consumption.

Country

A Country object represents a real-world country and contains various health and safety information for the region. A Country object also maintains geographical information used to highlight regions to the end user.

iOS

On iOS, the class for the country model is STASDKMCountry.

Static Methods

Name Description
findBy Finds a stored country in the local database based on the given identifier
findByCountryCode Finds a stored country in the local database based on the given country code
allCountries Finds all countries saved to the local database, sorted alphabetically

Instance Methods

Name Description
emergNumbersArray Returns an array of Contact Details representing emergency numbers for the country
Name Description
hospitals Returns a list of hospitals within the country as an RLMArray

Android

On Android, this model only maintains property accessors. For querying the local databse, please refer to the Android DB Layer.

Name Description
getAlerts Returns a list of Alerts associated with the country
getAdvisories Returns a list of Advisories associated with the country
getHospitals Returns a list of Hospitals associated with the country
getContactDetails Returns a list of Contact Details representing the emergency numbers of the country
getCountryDivisions Returns a list of Country Divisions for the country
getCountryRegions Returns a list of Country Regions for the country

Xamarin

The models are replicated in C# for xamarin consumption.

Country Division

The Country Division object contains information about a country’s province/state, its travel status, and its geographical border.

iOS

On iOS, the Country Division object is stored on a parent object (e.g Alert) as a json string. The obejct is converted to an NSDictionary when needed.

Static Methods

Not applicable.

Instance Methods

Not applicable.

Android

On Android, this model only maintains property accessors. For querying the local databse, please refer to the Android DB Layer.

Xamarin

The models are replicated in C# for xamarin consumption.

Country Region

The Country Region object contains information about a country’s municipality, its travel status, and its geographical border.

iOS

On iOS, the Country Region object is stored on a parent object (e.g Alert) as a json string. The obejct is converted to an NSDictionary when needed.

Static Methods

Not applicable.

Instance Methods

Not applicable.

Android

On Android, this model only maintains property accessors. For querying the local databse, please refer to the Android DB Layer.

Xamarin

The models are replicated in C# for xamarin consumption.

Disease

The Disease object contains information about a particular disease that a traveller should know about.

iOS

On iOS, the class for the disease model is STASDKMDisease. Each disease contains a DiseaseDatum which is stored as a json string. The obejct is converted to an NSDictionary when needed and the datum’s properties can be accessed directly through the disease’s instance methods.

Static Methods

Name Description
findBy Finds a stored disease in the local database based on the given identifier

Instance Methods

Name Description
description Returns a description of the disease from its datum
transmission Returns the transmission text of the disease from its datum
susceptibility Returns the susceptibility text of the disease from its datum
symptoms Returns the symptoms text of the disease from its datum
prevention Returns the prevention text of the disease from its datum
treatment Returns the treatment text of the disease from its datum

Android

On Android, this model only maintains property accessors. For querying the local databse, please refer to the Android DB Layer.

Instance Methods

Name Description
getData Returns a DiseaseDatum

Disease Datum

On Android, the Disease Datum is stored as a separate model and contains the description, transmission, susceptibility, symptoms, prevention, and treatment attributes. These are all textual details about the disease.

Xamarin

The models are replicated in C# for xamarin consumption.

Vaccination

The Vaccination object contains information about a particular vaccination that a traveller should know about.

iOS

On iOS, the class for the country model is STASDKMVaccination.

Static Methods

Name Description
findBy Finds a stored vaccination in the local database based on the given identifier

Android

On Android, this model only maintains property accessors. For querying the local databse, please refer to the Android DB Layer.

Instance Methods

Name Description
getDatum Returns a Vaccination Datum
Name Description
getDiseases Returns a list of Diseases related to the vaccination

Vaccination Datum

On Android, the Vaccination Datum is stored as a separate model and contains the description, routine, schedule, and sideEffects properties. These are all details about the vaccination.

Xamarin

The models are replicated in C# for xamarin consumption.

Medication

The Medication object contains information about a particular medication that a traveller should know about.

iOS

On iOS, the class for the country model is STASDKMMedication.

Static Methods

Name Description
findBy Finds a stored medication in the local database based on the given identifier

Android

On Android, this model only maintains property accessors. For querying the local databse, please refer to the Android DB Layer.

Instance Methods

Name Description
getDatum Returns a Medication Datum
Name Description
getDiseases Returns a list of Diseases related to the medication

Medication Datum

On Android, the Medication Datum is stored as a separate model and contains the description, routine, schedule, and sideEffects properties. These are all details about the medication.

Xamarin

The models are replicated in C# for xamarin consumption.

Alert

An Alert or “Trip Alert” contains information about a situation which may disrupt a traveller’s trip. The Alert object can contain geographical data. Refer to Geographical Objects for more information.

iOS

On iOS, the class for the country model is STASDKMAlert.

Static Methods

Name Description
findBy Finds a stored alert in the local database based on the given identifier

Instance Methods

Name Description
alertSourcesArr Returns an array of Alert Sources
alertLocationsArr Returns an array of Alert Locations
countriesArr Returns an array of NSDictionary objects representing the associated countries for geographical purposes
countryDivisionsArr Returns an array of NSDictionary objects representing the associated country divisions for geographical purposes
countryRegionsArr Returns an array of NSDictionary objects representing the associated country regions for geographical purposes
diseaseIdsArr Returns an array of disease identifiers associated with the alert
isDiseaseType Returns true if alert is for a disease
setRead Marks the alert as read and creates a background job to post this to Sitata

Android

On Android, this model only maintains property accessors. For querying the local databse, please refer to the Android DB Layer.

Name Description
getCountries Returns a list of Countries
getDiseases Returns a list of Diseases
getLocations Returns a list of Locations
getCountryDivisions Returns a list of Country Divisions
getCountryRegions Returns a list of Country Regions
getSources Returns a list of Sources

Xamarin

The models are replicated in C# for xamarin consumption.

Alert Source

An Alert Source is a reference to where Sitata discovered the information.

iOS

On iOS, an Alert Source is represented by the STASDKMAlertSource class. It is not stored in the Realm database as a separate object. Instead, it is stored as a json string on the Alert and instantiated when accessed through the Alert.

Static Methods

None.

Instance Methods

None.

Android

On Android, this model only maintains property accessors. For querying the local databse, please refer to the Android DB Layer.

Xamarin

The models are replicated in C# for xamarin consumption.

Alert Location

An Alert Location represents a singular location (map pin) for the event.

iOS

On iOS, an Alert Location is represented by the STASDKMAlertLocation class. It is not stored in the Realm database as a separate object. Instead, it is stored as a json string on the Alert and instantiated when accessed through the Alert.

Static Methods

None.

Instance Methods

None.

Android

On Android, this model only maintains property accessors. For querying the local databse, please refer to the Android DB Layer. In addition, the model in Android is called Location and is a general purpose model which is shared across Hospitals and Alerts.

Xamarin

The models are replicated in C# for xamarin consumption.

Advisory

An Adviory contains information about a long-standing situation which may disrupt a traveller’s trip. The main difference between an advisory and an alert is simply that an advisory is an ongoing issue that can last for a much longer period of time. The Advisory object can contain geographical data for the requested country. Refer to Geographical Objects for more information.

iOS

On iOS, the class for the advisory model is STASDKMAdvisory. This class stores Country Divisions and Country Regions as a json string. The instance methods below describe how to access these obejcts.

Static Methods

Name Description
findBy Finds a stored advisory in the local database based on the given identifier

Instance Methods

Name Description
countryDivisionsArr Returns an array of NSDictionary objects representing the associated country divisions
countryRegionsArr Returns an array of NSDictionary objects representing the associated country regions
setRead Marks the adviosry as having been read

Android

On Android, this model only maintains property accessors. For querying the local databse, please refer to the Android DB Layer.

Xamarin

The models are replicated in C# for xamarin consumption.

Hospital

A hospital is a place where a traveller might be able to visit for medical help.

iOS

On iOS, the class for the hospital model is STASDKMHospital.

Static Methods

Name Description
findForCountry Returns a list of hospitals for the given country identifier as a RLMResults object

Instance Methods

Name Description
longitude The longitude of the hospitals coordinates
latitude The latitude of the hospitals coordinates
isAccredited Returns true if the hospital has been accredited
contactDetailsArray Returns an array of Contact Details
addressObj Returns the Address of the hospital

Android

On Android, this model only maintains property accessors. For querying the local databse, please refer to the Android DB Layer.

Name Description
getAddress Returns an Addresses
getContactDetails Returns a list of Contact Details

Xamarin

The models are replicated in C# for xamarin consumption.

Address

An object to keep track of address information.

iOS

On iOS, the class for the address model is STASDKMAddress.

Static Methods

None.

Instance Methods

Name Description
addressString Returns a pre-formatted address string

Android

On Android, this model only maintains property accessors. For querying the local databse, please refer to the Android DB Layer.

Xamarin

The models are replicated in C# for xamarin consumption.

Contact Detail

An object to keep track of contact details.

iOS

On iOS, the class for the address model is STASDKMContactDetail.

Static Methods

None.

Instance Methods

None.

Android

On Android, this model only maintains property accessors. For querying the local databse, please refer to the Android DB Layer.

Xamarin

The models are replicated in C# for xamarin consumption.

Geographical Objects

Sitata uses TopoJSON to represent geographical boundaries and areas for display on a map. Typically, these TopoJSON objects are contained within an attribute such as topo_json. Examples of models that have a topo_json attribute are Country, Country Division, and Country Region.

iOS


// conversion into GeoJson from TopoJson and then
NSDictionary *topoJSON = [division objectForKey:@"topo_json"];
if (objects != NULL) {
   NSDictionary *targetObj = [objects objectForKey:@"geometry"];
   if (targetObj != NULL) {
       NSDictionary *geoJSON = [STASDKGeo feature:topoJSON obj:targetObj];
   }
}


// using the convenience method to add polygons to a MKMapView object
NSDictionary *topoJSON = [division objectForKey:@"topo_json"];
[STASDKGeo handleTopoJSON:topoJSON mapView:self.mapView];

On iOS, the STASDKGeo class provides some helper methods to convert the TopoJSON into GeoJson and even place polygons directly on a MkMapView object.

Static Methods

Name Description
feature Given a TopoJSON dictionary, will return a NSDictionary representing the GeoJson.
regionFromTopoBBox Given a TopoJSON dictionary, will return a MKMapRect representing the bounds of the TopoJSON region.
handleTopoJSON A convenience method that will perform the necessary conversions from TopoJSON and place polygons on the map.

Android

// imports for clarity
import com.sitata.sdk.core.models.Country;
import com.sitata.sdk.core.util.SitataTopoJson;
import com.sitata.sdk.core.util.TopoUtil;
import com.google.android.gms.maps.model.LatLng;
import com.google.android.gms.maps.model.LatLngBounds;

// use a country as an example (topojson fields exist on country regions
// and divisions as well)
Country c = ctrlr.db.countries.findById( someCountryId );

// obtain stringified topojson from country
String topoStr = c == null ? null : c.getTopoJson();

// convert to an intermediate object (subset spec of topojson)
SitataTopoJson stj = topoStr == null ? null : TopoUtil.parseSitataTopoJson( topoStr );

// convert to google maps objects
if (stj != null) {
    LatLng[] polygonPath = TopoUtil.parsePolygon( stj );
    LatLngBounds bounds = TopoUtil.parseBbox( stj );
    // ...
}

On Android, the TopoUtil class will provide the methods necessary to convert topoJSON to a format more manageable when dealing with google map objects.

Xamarin

Converting topoJSON to a format more manageable in Xamarin is largely a translation exercise from what is described above.

API

The API layer is used to fetch data from Sitata’s servers. The information is populated into various data models.

iOS

On iOS, each API method is contained within a corresponding class. Most methods will accept some parameters and a callback function that is executed after the network request and response parsing is made.

Android

// for only using the API layer
SitataApi api = new SitataApi( myConfig );
api.requests.trips.getList().enqueue( ... );
// otherwise, access is managed through controller or gui instances, eg
App.getSitataGui( ctx ).ctrlr.requests.trips.getList().enqueue( ... );

On Android, every API method is scoped within it’s own class. To access the api layer, you must either initialize the SitataApi class using new SitataApi(myConfig), or access it from a SitataController or SitataGui instance.

Api requests are created and handled using the Retrofit library (which in turn uses OkHTTP).

Asynchronous Requests

// asynchronous request
api.requests.trips.getList().enqueue(
    new Callback<List<Trip>>() {
        @Override
        public void onResponse(Call<List<Trip>> call, Response<List<Trip>> response) {
            if (response.isSuccessful()) {
                List<Trip> trips = response.body();
                ...
            } else {
                Log.e(TAG, response.message());
            }
        }

        @Override
        public void onFailure(Call<List<Trip>> call, Throwable t) {
            Log.e(TAG,t.getLocalizedMessage());
        }
    }
);

A typical asynchronous request is executed using the enqueue method. The enqueue method adds the request to a global network request queue, meaning the outbound requests are sent synchronously and their results are returned asynchronously.

Synchronous Requests

try {
    Trip trip = api.requests.trips.getCurrent().execute().body(); // throws IOE
    ...
} catch (IOException e) {
    e.printStackTrace();
}

To perform a synchronous request you need to catch an IOException and use the execute and body methods.

Xamarin

iOS

As with native iOS, each API method is contained within a corresponding class which can be used to fetch data from the Sitata API.

Android

var sitataGui = App.GetSitataGui( ctx );
// start a job
sitataGui.Ctrlr.Jobs.Trips.Current.ReplaceAndStart();
// wait for the next successful completion of this job type, with timeout param
bool success = sitataGui.Ctrlr.Jobs.Trips.Current.WaitForCompletion( 10000 );
if (success) {
  // ...
}

On Android, this feature requires working with the JNI at a lower level. It may not be even be possible with the current implementation. If you need API requests in Xamarin, please work around this by using the jobs layer and waiting for the results as shown.

Traveller

iOS

On iOS, the class which handles these requests is STASDKApiTraveller.

// Get Traveller's Profile Data
+(void)getProfile:(void(^)(STASDKMTraveller*, NSURLSessionDataTask*, NSError*))callback;

// Update Traveller's Profile
+(void)update:(STASDKMTraveller*)user onFinished:(void(^)(STASDKMTraveller*, NSURLSessionDataTask*, NSError*))callback;

getProfile

Fetches the current traveller’s profile information and user settings.

update

Use to update the traveller’s data and user settings.

iOS Device

// POST /users/device_push
+(void)sendDeviceToken:(NSDictionary*)deviceInfo onFinished:(void(^)(NSURLSessionDataTask*, NSError*))callback;

On iOS, the STASDKApiMisc class allows you to send the push notification token and other mobile device information to sitata. The device info NSDictionary object is needed

The attributes for the deviceInfo dictionary are as follows:

Name Type Description
token String Push notification token for the device. Required.
manufacturer String Manufacturer of the device. e.g. Apple
model String The device model.
platform String The platform of the device. e.g. ios, android. Required
osname String The devices system name.
osversion String The devices operating system version
locale String The language locale of the device
uuid String A unique identifier for the device
processorCount String The number of processors that the device CPU has
username String The device name.
ostype String The device name.

Android

On Android, the namespace which handles these requests is users.

// addDevice - Send push notification to Sitata
DevicePostBody db = new DevicePostBody(push_notfication_token);
DeviceWrapper dw = new DeviceWrapper(db);
api.requests.users.addDevice().enqueue( ... );

addDevice

Send the push notification token to Sitata. To execute this request you must provide a DeviceWrapper object.

Device Wrapper

The DeviceWrapper class accepts a DevicePostBody.

Device Post Body

The DevicePostBody accepts a single value, the push notification token.

// update - Update the current traveller
UserSettings us = new UserSettings.Builder().setCheckInWithLocation( true ).build();
TravellerPostBody tb = new TravellerPostBody( us );
TravellerWrapper tw = new TravellerWrapper(tb);
api.requests.users.update(tw).enqueue( ... );

update

Update the current traveller. To update you must provide a TravellerWrapper object which in turn includes a TravellerPostBody object.

Traveller Wrapper

The TravellerWrapper class accepts a TravellerPostBody object to prepare the http request.

Traveller Post Body

The TravellerPostBody class accepts a UserSettings object to prepare the TravellerWrapper.

User Settings

The UserSettings class allows modifications to the traveller’s settings. A Buidler object pattern is provided for convenience.

// profile - Fetch the current traveller's profile data
api.requests.users.profile().enqueue( ... );

profile

Fetchs the current traveller’s profile data.

Xamarin

The structure is exposed in C# for xamarin consumption.

User Settings

iOS

On iOS, user settings are accessed through the traveller. Therefore, you can use STASDKApiTraveller to fetch the traveller’s data and user settings.

Android

On android The UserSettings class allows modifications to the traveller’s settings. A Buidler object pattern is provided for convenience. This object is normally passed to a TravellerPostBody

Xamarin

The structure is exposed in C# for xamarin consumption.

Trip

iOS

On iOS, the class which handles these requests is STASDKApiTrip.

// Request all trips for a traveller
+(void)getTrips:(void(^)(NSArray<STASDKMTrip*>*, NSURLSessionDataTask*, NSError*))callback;


// Request current trip for the traveller
+(void)getCurrentTrip:(void(^)(STASDKMTrip*, NSURLSessionDataTask*, NSError*))callback;


// Request single trip for a traveller by id.
+(void)getById:(NSString*)tripId onFinished:(void(^)(STASDKMTrip*, NSURLSessionDataTask*, NSError*))callback;


// Create a new trip
+(void)createTrip:(STASDKMTrip*)trip onFinished:(void(^)(STASDKMTrip*, NSURLSessionTask*, NSError*))callback;


// Update an existing trip
+(void)updateTrip:(STASDKMTrip*)trip onFinished:(void(^)(STASDKMTrip*, NSURLSessionTask*, NSError*))callback;


// Change trip settings
+(void)changeTripSettings:(NSString*)tripId settings:(NSDictionary*)settings onFinished:(void(^)(NSURLSessionTask*, NSError*))callback;

getTrips

Fetches all trips for the current traveller.

getCurrentTrip

Fetch the current trip for the traveller. The current trip is the currently ongoing trip or the next upcoming trip for the traveller.

getById

Fetch a trip for the given identifier.

createTrip

Create a new trip from the given trip model.

updateTrip

Update an existing trip based on the given trip model.

changeTripSettings

Change the trip’s settings. Expects the trip and an NSDictionary representing the trip’s settings.

Trip settings currently only contain one attribute:

Name Type Description
muted Boolean If true, Sitata will not send notifications to the user for this trip

Android

On Android, the namespace which handles these requests is trips.

// getCurrent - Fetch the current trip data
api.requests.trips.getCurrent().enqueue( ... );

getCurrent

Fetchs the current trip data.

// getList - Fetch all of the traveller's trips
api.requests.trips.getList().enqueue( ... );

getList

Fetch all of the traveller’s trips.

// getById - Fetch the trip specified by the given identifier
String id = "abc123";
api.requests.trips.getById(id).enqueue( ... );

getById

Fetch the trip specified by the given identifier

// create - Create a new trip
List<DestinationPostBody> destinations = new List<DestinationPostBody>();
DestinationPostBody pb = new DestinationPostBody();
pb.entryDate = new Date();
pb.exitDate = new Date()
pb.countryCode = "CA";

List<DestinationLocationPostBody> dls = new List<DestinationLocationPostBody>();
DestinationLocationPostBody dl = new DestinationLocationPostBody();
dl.friendlyName = "Toronto";
dl.latitude = 42.6532;
dl.longitude = -79.3832;
dls.addObject(dl);

pb.destinationLocations = dls;
destinations.addObject(pb);

List<Integer> activities = new List<Integer>();
activities.addObject(Trip.Activity.BREACH_SUN);

TripPostBody tb = new TripPostBody(4, activities, destinations);
TripWrapper tw = new TripWrapper(tb);
api.requests.trips.create(tw).enqueue( ... );

create

Create a new trip. You must provide a TripWrapper object which in turn depends on a TripPostBody.

Trip Wrapper

The TripWrapper class accepts a TripPostBody object to prepare the http request.

Trip Post Body

The TripPostBody class accepts the trip type, a list of trip activities, and a list of destinations specified by the DestinationPostBody.

Destination Post Body

The DestinationPostBody allows the entryDate, exitDate, countryCode, and a list of DestinationLocationPostBody objects to be specified for the trip.

Destination Location Post Body

The DestinationLocationPostBody allows for an individual location (usually city) to be specified within a Destination. The fields are friendlyName, latitude, and longitude.

// update - Update a trip based on the given identifier
TripWrapper tw = new TripWrapper( ... );
api.requests.trips.update(tw, "abc123").enqueue( ... );

update

Update a trip based on the given identifier.

// changeSettings - Change the trip settings
TripSettingsPostBody tspb = new TripSettingsPostBody(true);
TripSettingsWrapper ts = new TripSettingsWrapper(tsb);
api.requests.trips.changeSettings(ts, "abc123").enqueue( ... );

changeSettings

Change the trip settings. You must procide a TripSettingsWrapper which depends on a TripSettingsPostBody.

Trip Settings Wrapper

The TripSettingsWrapper class accepts a TripSettingsPostBody object to prepare the http request.

Trip Settings Post Body

The TripSettingsPostBody class accepts a single value. If true, Sitata will not send notifications about the trip to the user.

Trip Activities

On iOS, valid Trip Activities are specified by the TripActivity enum. On Android, valid Trip Activities are specified by the Trip.Activity enum.

Xamarin

The structure is exposed in C# for xamarin consumption.

Country

iOS

On iOS, the class which handles these requests is STASDKApiCountry.

// Request a country from the server by country id.
+(void)getById:(NSString*)countryId onFinished:(void(^)(STASDKMCountry*, NSURLSessionDataTask*, NSError*))callback;


// Request all countries (in their short form)
+(void)getAllShortForm:(void(^)(NSArray<STASDKMCountry*>*, NSURLSessionDataTask*, NSError*))callback;

getById

Requests a country for the given identifier.

getAllShortForm

Requests a list of all countries with limited details.

Android

On Android, the namespace which handles these requests is countries.

// getList - Returns a list of all countries
api.requests.countries.getList().enqueue( ... );

getList

Returns a list of all countries.

// getShortList - Returns a list of all countries (in their short form)
api.requests.countries.getShortList().enqueue( ... );

getShortList

Requests a list of all countries with limited details.

// getById - Returns the country specified by an identifier
api.requests.countries.getById("abc123").enqueue( ... );

getById

Returns the country specified by an identifier.

Xamarin

The structure is exposed in C# for xamarin consumption.

Disease

iOS

On iOS, the class which handles these requests is STASDKApiDisease.

// Request full list of diseases from the server
+(void)getAll:(void(^)(NSArray<STASDKMDisease*>*, NSURLSessionDataTask*, NSError*))callback;

// Request a disease from the server by disease id.
+(void)getById:(NSString*)diseaseId onFinished:(void(^)(STASDKMDisease*, NSURLSessionDataTask*, NSError*))callback;

getAll

Requests the full list of diseases.

getById

Requests a singular disease based on the given identifier.

Android

On Android, the namespace which handles these requests is diseases.

// getList - Returns a list of all diseases
api.requests.diseases.getList().enqueue( ... );

getList

Returns a list of all diseases.

// getById - Returns the disease specified by an identifier
api.requests.diseases.getById("abc123").enqueue( ... );

getById

Returns the disease specified by an identifier.

Xamarin

The structure is exposed in C# for xamarin consumption.

Medication

iOS

On iOS, the class which handles these requests is STASDKApiMedication.

// Request full list of medications from the server
+(void)getAll:(void(^)(NSArray<STASDKMMedication*>*, NSURLSessionDataTask*, NSError*))callback;

// Request a medication from the server by id.
+(void)getById:(NSString*)medicationId onFinished:(void(^)(STASDKMMedication*, NSURLSessionDataTask*, NSError*))callback;

getAll

Requests the full list of medications.

getById

Requests a singular medication based on the given identifier.

Android

On Android, the namespace which handles these requests is medications.

// getList - Returns a list of all medications
api.requests.medications.getList().enqueue( ... );

getList

Returns a list of all medications.

// getById - Returns the medication specified by an identifier
api.requests.medications.getById("abc123").enqueue( ... );

getById

Returns the medication specified by an identifier.

Xamarin

The structure is exposed in C# for xamarin consumption.

Vaccination

iOS

On iOS, the class which handles these requests is STASDKApiVaccination.

// Request full list of vaccinations from the server
+(void)getAll:(void(^)(NSArray<STASDKMVaccination*>*, NSURLSessionDataTask*, NSError*))callback;

// Request a vaccination from the server by id.
+(void)getById:(NSString*)vaccinationId onFinished:(void(^)(STASDKMVaccination*, NSURLSessionDataTask*, NSError*))callback;

getAll

Requests the full list of vaccinations.

getById

Requests a singular vaccination based on the given identifier.

Android

On Android, the namespace which handles these requests is vaccinations.

// getList - Returns a list of all vaccinations
api.requests.vaccinations.getList().enqueue( ... );

getList

Returns a list of all vaccinations.

// getById - Returns the vaccination specified by an identifier
api.requests.vaccinations.getById("abc123").enqueue( ... );

getById

Returns the vaccination specified by an identifier.

Xamarin

The structure is exposed in C# for xamarin consumption.

Alert

iOS

On iOS, the class which handles these requests is STASDKApiAlert.

// Request all alerts for a trip.
+(void)getTripAlerts:(NSString*)tripId onFinished:(void(^)(NSArray<STASDKMAlert*>*, NSURLSessionDataTask*, NSError*))callback;

// Mark a trip alert as having been read by the user.
+(void)markRead:(NSString*)alertId onFinished:(void(^)(NSURLSessionDataTask*, NSError*))callback;

// Fetch an alert along with any trip ids that are associated with it.
+(void)fromPush:(NSString*)alertId onFinished:(void(^)(STASDKMAlert*, NSArray*, NSURLSessionDataTask*, NSError*))callback;

getTripAlerts

Requests the full list of alerts for the given trip identifier.

markRead

Will tell Sitata that the trip alert has been read by the user.

fromPush

Will request a trip alert and any trip identifiers for the user that are associated with that alert.

Android

On Android, the namespace which handles these requests is alerts.

// getById - Returns the alert specified by an identifier
api.requests.alerts.getById("abc123").enqueue( ... );

getById

Returns the alert specified by an identifier.

// markRead - Sends a put request to mark the alert as read by the traveller
api.requests.alerts.markRead("abc123").enqueue( ... );

markRead

Sends a put request to mark the alert as read by the traveller.

// getForTrip - Returns the alerts pertaining to a specific trip
api.requests.alerts.getForTrip("tripAbc123").enqueue( ... );

getForTrip

Returns the alerts pertaining to a specific trip.

// getForCountry - Returns the alerts pertaining to a specific country
api.requests.alerts.getForCountry("countryAbc123").enqueue( ... );

getForCountry

Returns the alerts pertaining to a specific country.

Xamarin

The structure is exposed in C# for xamarin consumption.

Advisory

iOS

On iOS, the class which handles these requests is STASDKApiAlert. This is intentional.

// Request all advisories for a trip.
+(void)getTripAdvisories:(NSString*)tripId onFinished:(void(^)(NSArray<STASDKMAdvisory*>*, NSURLSessionDataTask*, NSError*))callback;

getTripAdvisories

Requests the full list of advisories for the given trip identifier.

Android

On Android, the namespace which handles these requests is advisories.

// getForTrip - Returns the advisories pertaining to a specific trip
api.requests.advisories.getForTrip("tripAbc123").enqueue( ... );

getForTrip

Returns the advisories pertaining to a specific trip.

// getForCountry - Returns the advisories pertaining to a specific country
api.requests.advisories.getForCountry("countryAbc123").enqueue( ... );

getForCountry

Returns the advisories pertaining to a specific country.

Xamarin

The structure is exposed in C# for xamarin consumption.

Hospital

iOS

On iOS, the class which handles these requests is STASDKApiPlaces.

// Request hosptials to be save to the device for the trip
+(void)getHospitalsForTrip:(NSString*)tripId onFinished:(void(^)(NSArray<STASDKMHospital*>*, NSURLSessionDataTask*, NSError*))callback;

// Request hosptials to be save to the device for a given country
+(void)getHospitalsForCountry:(NSString*)countryId onFinished:(void(^)(NSArray<STASDKMHospital*>*, NSURLSessionDataTask*, NSError*))callback;

// Request hosptials near the user's location
+(void)getHospitalsNearby:(double)latitude longitude:(double)longitude onFinished:(void(^)(NSArray<STASDKMHospital*>*, NSURLSessionDataTask*, NSError*))callback;

getHospitalsForTrip

Requests the full list of hospitals for the given trip identifier.

getHospitalsForCountry

Requests the full list of hospitals based on the given country identifier.

getHospitalsNearby

Requests hospitals based on the given latitude and longitude.

Android

On Android, the namespace which handles these requests is hospitals.

// getNearby - Returns the hospitals close to the user's location
api.requests.hospitals.getNearby().enqueue( ... );

getNearby

Returns the hospitals close to the user’s location.

// getForTrip - Returns the hospitals pertaining to a specific trip
api.requests.hospitals.getForTrip("tripAbc123").enqueue( ... );

getForTrip

Returns the hospitals pertaining to a specific trip.

// getForCountry - Returns the hospitals pertaining to a specific country
api.requests.hospitals.getForCountry("countryAbc123").enqueue( ... );

getForCountry

Returns the hospitals pertaining to a specific country.

Xamarin

The structure is exposed in C# for xamarin consumption.

Sync

The syncing layer is used to fetch data from Sitata’s servers and persist it locally to the phone. Sync operations are generally persisted locally and re-tried until they are successful.

iOS

On iOS, all sync operations occur on the STASDKSync class.

// Sync everything necessary and save things locally
+ (void) fullSync:(void (^)(NSError*))syncCompleted;

// Sync push notification token
+ (void) syncPushToken:(NSString*)token callback:(void (^)(NSError*))callback;

All necessary data can be synced to the phone by calling the fullSync method. In addition, to ensure the user’s push notification is sent to Sitata, you may use the syncPushToken function.

Android


// == Starting a Job == //

// these all perform a full synchronization of Sitata data in the background
App.getSitataGui( ctx ).ctrlr.jobs.sync.all().start();
App.getSitataGui( ctx ).ctrlr.jobs.sync.all().replaceAndStart();
App.getSitataGui( ctx ).ctrlr.jobs.sync.all().findOrStart();

// == Other Methods == //

// check whether job is running
boolean jobIsRunning = App.getSitataGui( ctx ).ctrlr.jobs.countries.getList().isRunning();
// start a job and then block thread until it is complete
App.getSitataGui( ctx ).ctrlr.jobs.alerts.getById( "abc123" ).replaceAndStart();
App.getSitataGui( ctx ).ctrlr.jobs.alerts.getById( "abc123" ).waitForCompletion( 10_000 );

// == Examples == //

App.getSitataGui( ctx ).ctrlr.jobs.trips.getById( "abc" ).Start();
App.getSitataGui( ctx ).ctrlr.jobs.trips.getById( "def" ).Start();
// the next line will only replace one of the above jobs, for the "abc" id
App.getSitataGui( ctx ).ctrlr.jobs.trips.getById( "abc" ).replaceAndStart();
// thus only two trip jobs will be scheduled at this moment

On Android, the sync process occurs within a jobs namespace. Adding a new job consists of creating a job and executing it using one of the following methods, which all return an integer job identifier. Upon execution, the job is scheduled for execution in a background thread, and is started within a couple milliseconds of calling the below methods.

Method Description
start Schedules the job immediately, allowing parallel jobs of the same type.
replaceAndStart Schedules the job, replacing any existing, identical jobs.
findOrStart Attempts to find an unfinished job. If none can be found, will schedule a new one.

Once scheduled, the job will attempt to run until it is successful, using an exponential backoff strategy between failures. Jobs will be persisted across app reboots as well. Additional helper methods exist for managing jobs:

Method Description
isRunning Returns true if any identical jobs are running or are going to be run.
waitForCompletion Blocking call that will hang until the specified job finishes. Returns false if it times out, true if waiting was successful. This may be used as an alternative to – or in addition to – the event system also included in the Android SDK.

Traveller

iOS

On iOS, all sync operations occur on the STASDKSync class.

// Sync the traveller's profile
+ (void)syncUserProfile:(void (^)(NSError*))callback;

syncUserProfile

Fetch and save information pertaining to the current user.

Android

App.getSitataGui( ctx ).ctrlr.jobs.users.getCurrent().start();

getCurrent

Fetch and save the user’s current trip.

Xamarin

The structure is exposed in C# for xamarin consumption.

Trip

iOS

On iOS, all sync operations occur on the STASDKSync class.

// Sync all trips for the local user.
+ (void)syncAllTrips:(void (^)(NSError*))callback;

// Sync the current trip and all associated objects
+ (void)syncCurrentTrip:(void (^)(NSError*))callback;

// Sync a trip for the given trip id and all associated objects.
+ (void)syncTrip:(NSString*)tripId isAsync:(bool)isAsync onFinished:(void (^)(NSError*))callback;

// Sync associated data for the given trip
+ (void)syncExtrasFor:(STASDKMTrip*)trip;

syncAllTrips

Sync all trips for the local user.

syncCurrentTrip

Sync the current trip and all associated objects.

syncTrip

Sync a trip for the given trip id and all associated objects. If isAsync is false, then the onFinished callback will be triggered only after the trip and all associated requests have finished. If isAsync is true, then associated objects will be fetched via a background process and the onFinished callback will be triggered after the trip has been fetched.

syncExtrasFor

Sync associated data for the given trip.

Android

App.getSitataGui( ctx ).ctrlr.jobs.trips.getCurrent().start();

getCurrent

Fetch and save the user’s current trip.

App.getSitataGui( ctx ).ctrlr.jobs.trips.getList().start();

getList

Fetch and save the user’s trips.

App.getSitataGui( ctx ).ctrlr.jobs.trips.getById("tripAbc123").start();

getById

Fetch and save the user’s trip based on the given identifier.

Xamarin

The structure is exposed in C# for xamarin consumption.

Country

iOS

On iOS, all sync operations occur on the STASDKSync class.

// Sync a country for the given countryID and save locally.
+ (void) syncCountry:(NSString*)countryId callback:(void (^)(NSError*))callback;

syncCountry

Sync a country for the given identifier.

Android

App.getSitataGui( ctx ).ctrlr.jobs.countries.getList().start();

getList

Fetch and save a list of countries.

App.getSitataGui( ctx ).ctrlr.jobs.countries.getShortList().start();

getShortList

Fetch and save a list of countries (in their short form).

App.getSitataGui( ctx ).ctrlr.jobs.countries.getById("abc123").start();

getById

Fetch and save a country based on the given identifier.

Xamarin

The structure is exposed in C# for xamarin consumption.

Disease

iOS

On iOS, all sync operations occur on the STASDKSync class.

// Sync full list of diseases
+ (void) syncDiseases:(void (^)(NSError*))callback;

// Sync a disease for the given diseaseId and save locally.
+ (void) syncDisease:(NSString*)diseaseId callback:(void (^)(NSError*))callback;

syncDiseases

Sync a full list of diseases.

syncDisease

Sync a disease based on the given identifier.

Android

App.getSitataGui( ctx ).ctrlr.jobs.diseases.getList().start();

getList

Fetch and save a list of diseases.

App.getSitataGui( ctx ).ctrlr.jobs.diseases.getById("abc123").start();

getById

Fetch and save a disease based on the given identifier.

Xamarin

The structure is exposed in C# for xamarin consumption.

Medication

iOS

On iOS, all sync operations occur on the STASDKSync class.

// Sync full list of medications
+ (void) syncMedications:(void (^)(NSError*))callback;

syncMedications

Sync a full list of medications.

Android

App.getSitataGui( ctx ).ctrlr.jobs.medications.getList().start();

getList

Fetch and save a list of medications.

App.getSitataGui( ctx ).ctrlr.jobs.medications.getById("abc123").start();

getById

Fetch and save a medication based on the given identifier.

Xamarin

The structure is exposed in C# for xamarin consumption.

Vaccination

iOS

On iOS, all sync operations occur on the STASDKSync class.

// Sync full list of vaccinations
+ (void) syncVaccinations:(void (^)(NSError*))callback;

syncVaccinations

Sync a full list of vaccinations.

Android

App.getSitataGui( ctx ).ctrlr.jobs.vaccinations.getList().start();

getList

Fetch and save a list of vaccinations.

App.getSitataGui( ctx ).ctrlr.jobs.vaccinations.getById("abc123").start();

getById

Fetch and save a vaccination based on the given identifier.

Xamarin

The structure is exposed in C# for xamarin consumption.

Alert

iOS

On iOS, all sync operations occur on the STASDKSync class.

// Sync list of trip alerts for a trip
+ (void) syncTripAlerts:(NSString*)tripId callback:(void (^)(NSError*))callback;

// Sync to server that alert was marked as read
+ (void) syncAlertMarkRead:(NSString*)alertId callback:(void (^)(NSError*))callback;

// Sync singular alert (usually from push notification)
+ (void) syncAlert:(NSString*)alertId callback:(void (^)(NSError*))callback;

syncTripAlerts

Sync list of trip alerts based on given trip identifier.

syncAlertMarkRead

Sync to Sitata that alert was marked as read.

syncAlert

Sync an alert based on the given identifier. This method is usually used after receiving a push notification.

Android

App.getSitataGui( ctx ).ctrlr.jobs.alerts.getById("abc123").start();

getById

Fetch and save the alert specified by an identifier.

App.getSitataGui( ctx ).ctrlr.jobs.alerts.markRead("abc123").start();

markRead

Sends a request to mark the alert as read by the traveller. Persists until request is complete.

App.getSitataGui( ctx ).ctrlr.jobs.alerts.getForTrip("tripAbc123").start();

getForTrip

Fetch and save the alerts pertaining to a specific trip.

Xamarin

The structure is exposed in C# for xamarin consumption.

Advisory

iOS

On iOS, all sync operations occur on the STASDKSync class.

// Sync list of trip advisories for a trip
+ (void) syncTripAdvisories:(NSString*)tripId callback:(void (^)(NSError*))callback;

syncTripAdvisories

Sync list of trip advisories based on given trip identifier.

Android

App.getSitataGui( ctx ).ctrlr.jobs.advisories.getForTrip("tripAbc123").start();

getForTrip

Fetch and save the advisories pertaining to a specific trip.

App.getSitataGui( ctx ).ctrlr.jobs.advisories.getForCountry("countryAbc123").start();

getForCountry

Fetch and save the advisories pertaining to a specific country.

Xamarin

The structure is exposed in C# for xamarin consumption.

Hospital

iOS

On iOS, all sync operations occur on the STASDKSync class.

// Sync list of trip hospitals for a trip
+ (void) syncTripHospitals:(NSString*)tripId callback:(void (^)(NSError*))callback;

syncTripHospitals

Sync list of trip hospitals for a trip.

Android

App.getSitataGui( ctx ).ctrlr.jobs.hospitals.getNearby().start();

getNearby

Fetch and save the hospitals close to the user’s location.

App.getSitataGui( ctx ).ctrlr.jobs.hospitals.getForTrip("tripAbc123").start();

getForTrip

Fetch and save the hospitals pertaining to a specific trip.

App.getSitataGui( ctx ).ctrlr.jobs.hospitals.getForCountry("countryAbc123").start();

getForCountry

Fetch and save the hospitals pertaining to a specific country.

Xamarin

The structure is exposed in C# for xamarin consumption.

Events

On Android, you can register to receive events for when new data is saved to the device.

Android


// imports for clarity
import com.sitata.sdk.controller.events.TripEvent;
import com.sitata.sdk.controller.events.HospitalEvent;
import org.greenrobot.eventbus.Subscribe;
import org.greenrobot.eventbus.ThreadMode;


// == Anatomy of an Event == //

// assume we have obtained a trip event:
TripEvent event;
// Most events follow the same pattern, with JobStatusEvent being an exception.
// The ID of the model is provided:
String tripId = event.tripId;
// And then these fields, which are in all events:
boolean isNew = event.isNew;
int jobId = event.jobId;
String jobTag = event.jobTag;


// == Activity Example == //

// This is the recommended way to add event detection to an activity class

public class MyActivity extends Activity {

  // ...

  @Override
  protected void onStart() {
      App.getSitataGui( this ).ctrlr.events.register( this );
      super.onStart();
  }

  @Override
  public void onStop() {
      App.getSitataGui( this ).ctrlr.events.unregister( this );
      super.onStop();
  }

  @Subscribe( threadMode = ThreadMode.MAIN )
  public void myUiThreadHandlerForHospitals( HospitalEvent e ) {
    // safe to update UI here
  }

}


// == POJO Example == //

// Otherwise you may want to register a plain old Java object, which can be
// done like so:

public class MyReceiver {

  @Subscribe
  public void myHandlerMethodForTrips( TripEvent e ) {
    // executes on background thread
  }

  @Subscribe( threadMode = ThreadMode.MAIN )
  public void myUiThreadHandlerForHospitals( HospitalEvent e ) {
    // safe to update UI here
  }

}

MyReceiver mr = new MyReceiver();
App.getSitataGui( ctx ).ctrlr.events.register( mr );
// ... do some stuff ...
App.getSitataGui( ctx ).ctrlr.events.unregister( mr );

Events are fired for most models that are download via the jobs layer (for example Trip, Hospital, etc). When they are saved to the device, the SDK tracks whether it was a new addition to the local DB or just an update. The ID of the model is also supplied, along with the ID and tag of the job which it was downloaded through. Any Java class can be registered (and subsequently unregistered) for receiving these events. Upon registering, the event system simply looks for the Subscribe annotation and looks at the types of the arguments to that method in order to determine which methods to call and which events to send (the name of the class and methods is irrelevant).

DB Layer

// Using only the core layer
SitataCore core = new SitataCore( config );
SitataDatabase db = core.db;
// using controller or gui layers
SitataDatabase db = App.getSitataGui( ctx ).ctrlr.db;

// See various usage examples below:

// Find the current trip in local db, if one exists
Trip trip = db.trips.findCurrent();

// Get a list of all countries stored locally
List<Country> countries = db.countries.all();

// Are there any alerts on the device?
boolean alertsPresent = db.alerts.any();

// Find all unread alerts
List<Alert> unreadAlerts = db.alerts.findAllBy( AlertDao.Properties.Read, false );

// Raw query access is also provided, which uses the GreenDao API. For exmaple,
// to find trips that are unfinished
Date now = Calendar.getInstance().getTime();
List<Trip> unfinished = db.trips.queryBuilder()
        .where( TripDao.Properties.Finish.ge( now ) ).list();

On Android, access to the local database occurs through the DB Layer. This concept does not exist on iOS.

Sitata model classes such as Trip just contain accessors for fields on the model, and occassional simple instance methods such as someTrip.isEmpty(). Any methods that query the database are found in the database later, including inserts, deletes, querying based on fields, and some other custom accessors that are primarily used interally.