SDKs & Sample Apps
SDKs
Dispatch SDK
43min
for every workflow service docid 3yv38kxhtmuykxynkwcdr , a corresponding pre coded module is expected in the app as part of sdk this module executes the task on the device running the delivery agent app thus, the dispatcher sdk allows you to build this app with the minimum amount of effort the mobile app sdk will orchestrate the execution of tasks objective status updates will flow back as objective events to dispatch service through api calls made by the sdk and they will be stored in the objective events store this sdk can be used to render execution task screens on ui, maintain their states, and manage movement tracking system docid\ ehihv0zwowjnvh5q3gapc dispatch sdk is an expo based sdk that is written in typescript and some modules in java/kotlin currently supports sdk>=21 (android) features sync manager provides sync manager for syncing events & docs in the background with retry functionality execution tasks provides a list of execution tasks which are as follows deliver, capture input, deliver cash, complete success, complete failure, pickup, doodle, forms, display, verify location, verify otp, verify string, scan qr/barcode, image capture, init payment, process payment, and complete payment execution engine provides methods for executing a given workflow/job in a dispatch firebase cloud messaging provides a method for receiving firebase cloud messaging async storage provides async storage for storing key value pairs higher order ets provides a way to customize execution task ui asynchronous event handling provides a method for handling execution tasks asynchronously installation setup expo (for non expo projects only) npx install expo modules install dispatch sdk package npm install @os1 platform/dispatch mobile\@latest version yarn add @os1 platform/dispatch mobile\@latest version install these dependencies { "dependencies" { "@apollo/client" "^3 5 6", "graphql" "^16 2 0", "@expo google fonts/ibm plex sans" " ", "@os1 platform/mts mobile" "^1 0 0", "@react native async storage/async storage" "^1 15 5", "@react native community/datetimepicker" "^3 5 2", "@react native community/netinfo" "^6 0 2", "@react native community/slider" "^4 1 8", "@react native firebase/analytics" "^14 1 0", "@react native firebase/app" "^14 1 0", "@react native firebase/messaging" "^14 1 0", "@react native firebase/remote config" "^14 1 0", "@react navigation/native" "^6 0 6", "@react navigation/native stack" "^6 2 5", "axios" "^0 24 0", "expo" "^43 0 4", "expo barcode scanner" "^11 2 1", "expo file system" " 13 0 3", "expo font" " 10 0 3", "expo image manipulator" "^10 1 2", "expo image picker" "^11 0 3", "expo location" "^13 0 4", "expo sqlite" "^10 0 3", "react" "17 0 2", "react native" "0 66 1", "react native paper" "^4 9 2", "react native safe area context" "^3 3 2", "react native screens" "^3 9 0", "react native vector icons" "^9 0 0" } } async storage size increase add the following line in gradle properties file for increasing storage (asyncstorage db size in mb=10) android\ allowbackup="false" tools\ replace="android\ allowbackup" add jcenter() if not added already added in the project level build gradle (/build gradle) (android only) buildscript { repositories { jcenter() } } allprojects { repositories { jcenter() } } fix for apollo graphql client (metro config js) add the following changes in the metro config js file issue link const { getdefaultconfig } = require('metro config'); const { resolver defaultresolver } = getdefaultconfig getdefaultvalues(); exports resolver = { defaultresolver, sourceexts \[ defaultresolver sourceexts, 'cjs'], }; usage init dispatch sdk import { dispatchsdkmanager } from '@os1 platform/dispatch mobile'; await dispatchsdkmanager getinstance() initdispatchsdk({ username 'testuser', userid 'testid', tenantid 'tenantid', tenantbaseurl 'baseurl', accesstoken 'accesstoken', }); init execution engine import { dispatchstatecontainer } from '@os1 platform/dispatch mobile'; / call this function when dispatch data is fetched successfully @param dispatchid @param jobs @param logging @param maxtaskreattempt / await dispatchstatecontainer getinstance() initdispatchexecutor( dispatchid, dispatch data dispatch jobs data as job\[], false ); query objective status import { dispatchstatecontainer } from '@os1 platform/dispatch mobile'; / @param objref @param jobid / dispatchstatecontainer getinstance() fetchobjectivestate( 'objective ref', 'job id' ); start objective execution interface sdkerror { code string; message string; } // error handling from the calling screen react useeffect(() => { if (route params? sdkerror) { console log(json stringify(route params sdkerror)); alert alert('error', json stringify(route params sdkerror)); } }, \[route params? sdkerror]); navigation navigate('dispatchexec', { success true, objectives \[], // pass objective list successroute 'successscreen', failureroute 'failurescreen', initroute 'taskdetail', // calling screen name (optional parameter) used to throw errors back to calling screen }); fcm setup (android only) add the firebase android configuration file to your app create a firebase project (check firebase instructions for creating an app) click download google services json to obtain your firebase android config file (google services json) move your config file into the module (app level) directory of your app to enable firebase products in your app, add the google services plugin to your gradle files in your module (app level) gradle file (usually app/build gradle), apply the google services gradle plugin apply plugin 'com android application' // add the following line apply plugin 'com google gms google services' // google services plugin android { // } in your root level (project level) gradle file (build gradle), add rules to include the google services gradle plugin check that you have google's maven repository, as well buildscript { repositories { // check that you have the following line (if not, add it) google() // google's maven repository } dependencies { // // add the following line classpath 'com google gms\ google services 4 3 10' // google services plugin } } allprojects { // repositories { // check that you have the following line (if not, add it) google() // google's maven repository // } } get fcm token import { getfcmtoken, requestfirebasepermissions, } from '@os1 platform/dispatch mobile'; //get fcm token let token = await getfcmtoken(); //request notifications permissions (ios) // it will ask for user permissions for showing alert/notifications let enabled = await requestfirebasepermissions(); background fcm messages register a callback for receiving fcm messages in the background 📘 note note call this function in the root component, i e, in the `index js file of the app import { registerbackgroundhandler } from '@os1 platform/dispatch mobile'; registerbackgroundhandler((message object) => { // handle fcm message here }); foreground fcm messages usefcmmessage() custom hook in functional components to receive fcm messages in foreground import { usefcmmessage } from '@os1 platform/dispatch mobile'; const fcmmessage = usefcmmessage(); if (fcmmessage != null) { // update ui here to show the message } or extend fcm base class in case of class components import { fcm } from '@os1 platform/dispatch mobile'; class classcomponent extends fcm { //implement these methods handlefcmmessage(remotemessage object) void {} //implement these methods handlenotification(remotemessage object) void {} } mts in the case of the dispatch mobile app, the location tracking module of the sdk provides a configurable way to capture and stream location data from the mobile device to the movement tracking system docid\ ehihv0zwowjnvh5q3gapc service, without any user intervention to learn more, see dispatch service docid\ kjdpcl9yep5kbek1isxku mts default config export class mtsdefaults { locationfrequency number = 10000; // in milli seconds (no of seconds after which location updates will happen) distanceaccuracylimit number = 250; // in metres speedlimit number = 28; // in m/s mode mtsmode = mtsmode hybrid; environment mtsenv = mtsenv dev; batchsize number = 25; ismqttcleansession boolean = true; mqttkeepaliveinterval number = 15 60; //in seconds maxlocationage number = 15000; // in milliseconds maxtracesession number = 24 3600 100; //in milliseconds isodometerenabled boolean = true; retriesbeforefallback number = 1; httpfailurelimit number = 5; datasenddelay number = 30000; // in milli seconds alarmtime number = 60000; // in milli seconds missingseqcheckduration number = 5 60 1000; // in milli seconds odometerpushfrequency number = 5 60 1000; // in milli seconds qoslevel number = 1; // values can be 0 ,1 } check for mandatory mts permissions let granted = await mtslib requestpermissionsformts(); // if granted = true all permissions granted // granted = false one or more permissions denied init mts import type { mtsinitrequest } from '@os1 platform/mts mobile'; let mtsdefaults = new mtslib mtsdefaults(); mtsdefaults speedlimit = 5000; mtsdefaults locationfrequency = 10000; mtsdefaults environment = mtslib mtsenv pre prod; mtsdefaults isodometerenabled = false; //change mts default values as per your use case // use this for initiating mts let mtsinitreq mtsinitrequest = { appname 'app name', appversion '1', mtsdeviceid 'deviceid', // use fcm id here configdata mtsdefaults, baseurl 'https //{tenantid} example io/{mtsendpoint}', accesstoken 'token', tenantid 'tenantid', }; await mtslib initmts(mtsinitreq); //see error codes for possible error types start mts let startreq mtsstartrequest = { accesstoken 'token', // update access token resetsequence false, dispatchid '12345', // pass dispatch id here expirytime date now() + 24 2600 1000, // expiry time after which mts will stop automatically }; await mtslib startmts(startreq); publish event await mtslib publishevent('testevent', { battery 56, network 100 }); stop mts await mtslib stopmts(); error codes permissions error\[2500] = 'mandatory android permissions not provided'; mts init error\[2501] = 'mts init not called! mts device id is empty'; param missing\[2502] = 'mandatory paramater is missing in request'; sync manager import sync manager import { appsyncmanager, sdksynctype } from '@os1 platform/dispatch mobile'; // start events sync await appsyncmanager getinstance() startsyncing( false, // pass true for force sync sdksynctype events sync ); //start documents sync await appsyncmanager getinstance() startsyncing( false, // pass true for force sync sdksynctype document sync ); //get all events by dispatch id await appsyncmanager getinstance() getallevents('dsp id'); //get all documents by dispatch id await appsyncmanager getinstance() getalldocuments('dsp id'); start sync manager as a foreground service in android import { nativesyncmanager } from '@os1 platform/dispatch mobile'; nativesyncmanager startsyncmanager( interval, notificationtitle, notificationtext ); // interval will be in seconds nativesyncmanager startsyncmanager( 2000, 'dispatch service', 'syncing events ' ); //to stop the foreground android service nativesyncmanager stopsyncmanager(); asynchronous event handling the dispatch sdk support handling execution tasks asynchronously by emitting two events for each et this lets your apps to listen to these events and perform necessary actions for every et, two events will be triggered in a fire and forget mode task start event triggered upon arrival of the et, along with input data task end event triggered just before moving to the next et, with the output data of objectives executed in that et and the id of the next et to be executed to use this feature, you need to work with the eventlistener method, which is used to listen and remove events it contains the following methods on to listen to a specific event remove to remove a specific event eventlistener = { 	on(event, callback) { //add event listener and execute callback with event data } 	remove(event) { //add remove event listener fn } } example import { eventlistener } from "@dispatch sdk"; eventlistener on("eventname", (eventdata) => { console log(eventdata); }); eventlistener remove("eventname"); event payloads see the examples below to describe event payloads using a captureimage event on task start triggered before starting the execution of et ontaskstart {etcustomname} = { "timestamp" "number", "taskid" "string", "etdata" { "jobid1" { et inputs }, "jobid2" { et inputs } } } on task end triggered after the completion of et and before moving to the next et ontaskend {etcustomname} = { timestamp string, taskid string, nexttaskid string, "etdata" { "jobid1" { "success" "boolean", "eventcode" "string", "reasoncode" "string", et output }, "jobid2" { "success" "boolean", "eventcode" "string", "reasoncode" "string", et output } }, "meta"? {}, } on task back triggered when goback is executed for an et, before moving to the next et ontaskback {etcustomname} = { timestamp string, taskid string, nexttaskid string, "etdata" { "jobid1" { "success" "boolean", "eventcode" "string", "reasoncode" "string", et output }, "jobid2" { "success" "boolean", "eventcode" "string", "reasoncode" "string", et output } }, "meta"? {}, } sample events for captureimage { "data" { "etdata" { "job\ aab73b6a dc00 49c8 8d5a 7884bbdbc4eb" { "resolution" { "length" 6000, "breadth" 6000 }, "filesizelimit" 600, "capturemode" "multi", "title" "image capture", "applicablereasons" { "e 010" \[ ], "e 011" \[ ] } }, "job\ d9f3c351 8eaf 4b74 a8e5 310aa6430a48" { "resolution" { "length" 6000, "breadth" 6000 }, "filesizelimit" 600, "capturemode" "multi", "title" "image capture", "applicablereasons" { "e 010" \[ ], "e 011" \[ ] } }, "job 28246b42 1a84 43e3 9564 301f195dd9cb" { "resolution" { "length" 6000, "breadth" 6000 }, "filesizelimit" 600, "capturemode" "multi", "title" "image capture", "applicablereasons" { "e 010" \[ ], "e 011" \[ ] } } }, "taskid" "etask 9370d00a 8d84 5bf9 94bb cd8cc73eeeec", "timestamp" 1677149461591 } } { "data" { "meta" { }, "etdata" { "job\ aab73b6a dc00 49c8 8d5a 7884bbdbc4eb" { "entitycode" "0011", "success"\ true, "eventcode" "e 010", "reasoncode" "", "captures" \[ { "url" "", "timestamp" 1677065789173, "file" { "folder" "dsp 20230222", "name" "img 1677065789173 jpg" } } ] }, "job\ d9f3c351 8eaf 4b74 a8e5 310aa6430a48" { "entitycode" "0011", "success"\ true, "eventcode" "e 010", "reasoncode" "", "captures" \[ { "url" "", "timestamp" 1677065789173, "file" { "folder" "dsp 20230222", "name" "img 1677065789173 jpg" } } ] }, "job 28246b42 1a84 43e3 9564 301f195dd9cb" { "entitycode" "0011", "success"\ true, "eventcode" "e 010", "reasoncode" "", "captures" \[ { "url" "", "timestamp" 1677065789173, "file" { "folder" "dsp 20230222", "name" "img 1677065789173 jpg" } } ] } }, "taskid" "etask 9370d00a 8d84 5bf9 94bb cd8cc73eeeec", ‘nexttaskid’ “etask\ cea7c9a7 3ee7 52e9 ab3e 82849675d745”, "timestamp" 1677149655294 } } sdk utility methods import { sdkutils } from '@os1 platform/dispatch mobile'; await sdkutils getremoteconfig(3000); // 3000 is the number of seconds to cache the config download api from public url / function to download apk file from a public url @param apkurl url where apk is hosted @param version expected version of apk (used for naming the file) @param callback callback for getting progress of download / await sdkutils downloadapk('https //apk url com', '1', (progress) => console log(progress totalbyteswritten) ); open and install an apk file / opens & install an apk file @param uri source of apk file / await sdkutils openapkfile(result uri); send events to firebase analytics / @param eventname > string @param tag > string @param message > string / await logger getinstance() sendtofirebaseanalytics('ev name', 'tag', 'message'); log events to console / @param tag @param message @param logtype / logger getinstance() logevent('tag', 'message', log type sdk error); error codes const enum baseerrorcodes { invalidargumenterror = '100100', invalidbaseurl = '100101', syncmanagernotinitialized = '100102', missingorinvalidprops = '100103', sqlitedbissue = '100104', appsyncnotinitialized = '100105', fms folder creation error = '100106', reason code api error = '100107', merging error = '100108', location permission denied = '100109', camera permission denied = '100110', storage permission denied = '100111', graphql client not initialized = '100112', fms graphql api error = '100113', internet not enabled = '100114', location or gps not enabled = '100115', execution engine error = '100116', unexpected error = '100117', }