SmartAgora Documentation

Introduction

This documentation should give an overview of the SmartAgora Android application, if one intends do extend it.

Use case

Installation

To use this app, one must download and install Android Studio. You can find the application and how to install it here.

Then one simply imports this project as an Android Studio project.

Usage

A documentation on how to use the Application can be found here: Smart Agora Tutorial.

Overview

../_images/Smartagora Diagram.png

Above you see an overview of the most important classes of the HomeActivity class, and how they interact with each other. Note that a lot of classes are omitted, as the diagram would not be easily understandable with all of them.

Mechanics

This section explains the main mechanics of the application and how they work together.

Upon starting the application, the HomeActivity class is called, which initialises all visual elements, as well as the GPS component.

The Basics

This application lets the user answer different questions, which then can be sent to different servers. There are different Modes, which make the questionnaire behave differently. In some modes, the answers to a question can generate a score, which can vary for every question and the qiven answer for it. The idea is, that the user should only be able to answer a specific question when he is in the vicinity of a specific checkpoint.

GPS component

The GPS component is a custom LocationListener. When the coordinates get updated, the new coordinates, together with the accuracy is saved via sharedPreferences. After this a sticky gets posted with the following message:

PreferencesKeys.LOCATION_UPDATED

Further explanation on sticky messages are found here: Sticky Events

This means that on every change of the coordinates, a check whether to start the Vicinity Checking is done.

Sticky Events

Sticky messages can used to broadcast messages to specific methods and functions, it can also be used to create listeners for specific events. (Reference: Sticky Events)

In order for a method to listen to sticky events, it needs to have the flag

@Subscribe(sticky = true, threadMode = ThreadMode.MAIN)

To poste a sticky the following code needs to be executed

EventBus.postSticky( MESSAGE );

In this application, stickies are used in one place, in which gets checked if any questions are loaded and if so, vicinity checking is launched. See more about this here: Vicinity Checking

Vicinity Checking

When vicinity checking is launched, all 9 seconds a thread is checking if the phone is in the vicinity of any POI (point of interest).

If the phone is in any POI, the thread opens the corresponding question. For that, it first figures out which mode the current assignment is in. Once figured out, it creates an instance of the respective mode class and calls it’s call() method. The mode class then does the rest, explained in the section Modes.

Modes

There are 4 different modes in this application:

Mode

Key Difference

Simple

In this mode, all POI’s can be visited in any order

Sequence

In this mode, the POI’s need to be visited in a before specified order

Decision

In this mode, future question can depend on the answers of past questions

DIASSimple

This mode is the same as Simple, with the addition that all data get also sent to the DIAS server

Each of the mode classes have a constructor and a method called “call()”, which gets called as soon as the phone is in the vicinity of a POI.

The constructor of all classes initialise its elements. The call method rechecks if the phone is in range of the POI, and if so shows the question to be answered. The Mode class is also responsible of the progressbar and saving of the given answers.

Finally, if the mode is DIASSimple, the answered values get sent to the DIAS server.

Database

There are is a class called RoomDatabaseHandler, which gets used in many different places to access the database. The Database is based on SQLite and there are several queries prepared to get the following things out of it:

  • A list of answered questions

  • A list of the ids of the answered questions

  • A list of the of answered questions for the current checkpoint.

  • The previously given answer for a specific question

  • A list of all the answers for a given assignment

Servers

There are different servers connected with this app.

The Dashboard: The dashboard is an online interface to create the assignments used in the application.

DIAS DIAS is a distributed aggregation service. A documentation about DIAS can be found here. TODO: add link

Smart Agora

The parts

In this section, we will take a look at the parts from the diagram Figure1.

HomeActivity class

This Activity is the heart of this application, it is the activity, which gets launched together with the application.

OnCreate

This method initialises all needed layouts and some of the objects for this activity. The list of initialised objects include:

  • The view of the activity

  • The the progressbar for an assignment

  • The logos used on the screen

  • The navigation bar at the bootom

  • The actionbar at the top of the application

  • The actionbar drawer

  • The openStreetMap

  • The skipped, answered and unanswered questions for the current assignment.

It also calls the methods initServiceConnection, initVariables, initViews, setBottomNavigationView and slideMenuData.

animateCameraTo

Given that the map is already loaded, this moves the map position to the given latitude/longitude

buildAlertMessageNoGps

This method shows a alertDialog to ask the user to enable gps for this application.

connectAsyncTask

This is a class used as a callback for the response from DrawCompleteRoute. It draws the path on the map of the response of the google api by calling the method drawPath.

DataScientistId

The DataScientistId is used be able to select between different sets of assignments.

decodePoly

The string is an encoded polygon line from Google, this method decodes the string and adds the points into an ArrayList.

DrawCompleteRoute

Draws a route on the map of all start and destionation locations saved in the database, handled in the class QuestionsActivity. Uses the class makeURL to create a url to query to “https://maps.googleapis.com/maps/api/directions/json”. It also adds a callback called connectAsyncTask, which then handles the response.

drawPath

Given a json string, containing an array mapped to the the key “routes”, this function takes the first element and calls the method decodePoly to decode the containing polygon line. The polygon line then gets added to open street maps. Also the method sets an onClickListener on the lines, turning them blue if they were grey and the user clicked on it.

The Json string needs to contain the following elements:

{
  routes :
  [
    {
      overview_polyline :
      {
        points : encodedString
      }
    },
  ]
}

The string “encodedString” is encoded with google maps, the method decodePoly can decode it into a polygon line.

getDataFromDB

Gets data from the database, by calling getDataFromRoomDB of the class QuestionHandling

initVariables

This method initialises all variables for this class. The list includes elements, which are initialised every time, and others, which are only initialised, when they were uninitialised before.

Only when uninitialised:

  • the application context

  • the database handler

  • the list with all used sensors

  • the list with all names of the used sensors

  • the hashMap with all sensor readings

  • the list with the likertScale answers for the DIAS mode

  • the deviceId*

  • the QuestionHandling instance

  • the list for the Dias checkpoint questions

  • the arrayList for the progressBar values

  • the “loading…” dialog

  • the list of all used ProjectModel

  • the JSONObject lists called “tasks” and “tasks1”, but only if both are uninitialised.

Initialised every time:

  • the current activity (to the value ‘this’)

  • the ActivityStackManager

  • the numbers of credits (back to the value 0)

  • the textView for showing the answered value in DIAS mode

  • the list for the AnswerEntity, the AnswerEntity is one of the entities used for the RoomDatabaseHandler.

initViews

Asks for the GPS permission for this application.

makeURL

Given the start and destination coordinates, this function creates an url drawing a line between the given points, which can be interpreted by open street maps.

manageDataScientistId

This method shows a window, letting the user set a new DataScientistId.

MapStartPosition

This method fisrt checks if the questions are already loaded and loads them if not already done. Then it initialises the StaticModel with the new filenames of utils and the question list, clears the list with the skipped questions and the queued questions and initialises them with new ArrayLists. If there is a start and destination point stored in the QuestionsActivity, the databades is reloaded by calling getDataFromDB and the loaded route is then drawn on the map by calling DrawCompleteRoute. If there is not start and destionation point, but the assignment mode is of Type simple or DIAS_Simple, the database is reloaded anyway.

onActivityResult

This method is called as a callback, if an Activity is called, with the intent on receiving a result. As it seems, this is an artefact, as no activity was started with the corresponding “startActivityForResult()” method.

onBackPressed

This method is called, when the user presses the back button on his phone. This method closes all open popups or drawers. If there is no popup or drawer opened, the method closes the application after being called twice in fice seconds. When closing, it calls the methods stopServiceConnection and finish(), the latter actuallay closes the whole application.

onDestroy

This method is called, when the activity is closed. It disconnects from the DIAS server.

onEvent

This method is a callback, called by Sticky Events. It is called when the location changes. It first checks if the argument is LOCATION_UPDATED (from PreferencesKeys), because this method is only listening on those messages. Then it draws the vicinity ellipse around the user by calling drawMarkerWithEllipse. Finally, checks if any questions are loaded and if so, it calls the method StartCheckingForQuestionInRadius

onMapReady

This method is called as a callback, once open street maps is ready and the map is available. It initialises the map and saves it in a field for later usage.

onPause

This method is called, when another activity is opened. It stops the sensorListener and the GPS service.

onResume

This method is called, when the activity is reopened. It restarts the GPS service and sensorListener.

onSensorChanged

This method gets called by the Android SensorManager, when a sensor value changes. It saves the the reading, together with the sensor type, in the sensorReading list.

onAccuracyChanged

This method gets called by the SensorManager, when the accuracy of a sensor changes. It doesn’t do anything.

onStart

This mehthod initialises the sensor service.

onStop

This method is called, when the listener is stopped.

placeMarkers

Given an index i, it places a marker at the position, where question i is located, given question i exists. If the position was already visited and the question answered, the marker will be black, otherwise it will be blue.

setBottomNavigationView

This method sets the navigationView on the bottom of the screen and initialises all the buttons for it, such as:

  • This buttons lets the user set a new DataScientistId
  • SelectProject:
    This button lets the user select a new project from the list of available ones, connected with the selected DataScientistId
  • GetAllAssignments:
    This button lets the user select and load a new assignment of the list of available ones, connected to the selected project.
  • completeAssignment:
    This button lets the user finish and commit the current assignment to the server.
  • help:
    This button brings the user to the help screen.

setupDrawerContent

Sets up the side menu.

slideMenuData

Sets up the data for the slide menu header and children, the items of the menu are:

  • Transport mean

  • Survey questions

  • Checkpoints

  • Visited Points

  • Route location

When clicked on an item, a dropdown list expands under the selected item, showing the answer. The will only be shown, if available. Which means only if an assignment is loaded, and the assignment supports the selected measure.

StartCheckingForQuestionInRadius

This method checks if any questions are loaded and if it is not interrupted. If everything is fine, it checks if it is in the vicinity of any nearby question. If so, it creates a class of the corresponding mode (explained in Modes) for the question and calls the method “call”.

startRepeatingTask

This method starts a runnable, which puts itself in a callback loop afterwards. It calls the method update in each iteration.

stopRepeatingTask

This method stops the repeating task, launched in the method startRepeatingTask.

update

This method gets the latest reading of the current selected sensor.

StaticModel

The StaticModel class contains static values, shared over the whole project

Some of them are Mutable, some of them are final.

Final fields

There are fields for the overall database:

Field

Type

Description

DATABASE_VERSION

int

contains the current version of the database

DATABASE_NAME

string

contains the used name for the SQLite database

There are fields for the database tables:

Field

Type

Description

TABLE_QUESTIONS_DATA

string

name for the questions table

TABLE_ANSWERS_DATA

string

name for the answers table

TABLE_START_AND_DESTINATION

string

name for the start and destination table

TABLE_SENSOR_DATA

string

name for the sensor data table

There are fields for the table column names:

Field

Type

Description

Used in table

FILESNAME

string

column name for the file

Question, Answer, Start And Destination, Sensor data

ASSIGNMENTSTATE

string

column name for the assignment state

Start And Destination

ID

string

column name for the id, which is the key of the table

Question, Answer, Start And Destination, Sensor data

QUESTIONID

string

column name for question id

Question, Answer, Sensor data

QUESTION

string

column name for actual question

Question, Answer, Sensor data

NOISE_SENSOR

string

column name for noise sensor reading

Question, Sensor data

LIGHT_SENSOR

string

column name for light sensor reding

Question, Sensor data

ACCEL_SENSOR

string

column name for acceleration sensor reading

Question, Sensor data

PROXIMITY_SENSOR

string

column name for proximity sensor reading

Question, Sensor data

GYRO_SENSOR

string

column name for gyroscope sensor reading

Question, Sensor data

LOCATION

string

column name for location

Question, Sensor data

TIME

string

column name for measured time

Question

FREQUENCY

string

column name for measurement frequency

Question, Sensor data

SEQUENCE

string

column name for question sequence

Question

VISIBILITY

string

column name for question visibility

Question

MANDATORY

string

column name for mandatoriness

Question

VICINITY

string

column name for vicinity

Question

TYPE

string

column name for question type

Question

LATITUDE

string

column name for latitude

Question, Answer

LONGITUDE

string

column name for latitude

Question, Answer

OPTIONS

string

column name for question options

Question

ANSWERS

string

column for given answers

Answer

START_LATITUDE

string

column name for the start latitude of a start-destination line

Start and Destination

START_LONGITUDE

string

column name for the start longitude of a start-destination line

Start and Destination

DESTINATION_LATITUDE

string

column name for the destination latitude of a start-destination line

Start and Destination

DESTINATION_LONGITUDE

string

column name for the destination longitude of a start-destination line

Start and Destination

CAR

string

column name for car

Start and Destination

TRAIN

string

column name for train

Start and Destination

CYCLE

string

column name for cycle

Start and Destination

WALKING

string

column name for walking

Start and Destination

MODE

string

column name for the used transportaion mode

Start and Destination

QID

string

column name for question id used by notifications

Question, Answer

STOPNAME

string

column name for the stop name of a question

Question, Answer

DEFAULTCREDIT

string

the defualt credit given

Start and Destination

COMBINATION

string

column name for the question combinations

Question

ASSIGNMENTID

string

column name for the assignment id for the start-destination line

Start and Destination

TIMEATANSWERING

string

column name for measured time whilst answering the question

Answer

TIMEATSENSORING

string

measured time for given sensor recording

Sensor data

CREDIT

string

column name for the actually earned credit for a given answer

Answer

There are also fields for the sensor measuring:

Field

Type

Waiting time between two measurements

Measurements per second

LOW_TIME_INTERVAL

int

2 seconds

~0.5

MED_TIME_INTERVAL

int

250 ms

~4

HIGH_TIME_INTERVAL

int

200 ms

~5

Mutable fields

Field

Type

Description

skippedQuestions

List<Integer>

a list containing all skipped questions

questionsQueue

List<Integer>

a list containing all queued questions

questionsSensorsQueue

List<Integer>

a list in which the last element of shownQuestionQueue is added,
sometimes instead of the last element, just the size of shownQuestionQueue is added,
the added elements are never used, as only ever values are added

shownQuestionsQueue

List<Integer>

a list in which all shown questions are added, to keep track how many questions were actually already shown

XMLLoaded

boolean

shows if the XML is loaded up

Modes classes

In SmartAgora, there are different modes questions can be in, explained in Modes. For each of those modes, there is a class with a method called “call”, which is used to executed the assignment. There are the following mode classes:

  • SimpleMode

  • SequenceMode

  • DecisionMode

  • SimpleDIASMode

Also, there are two helper classes called ModeFunctions and SensorsInfo, used in all four modes.

all for modes classes have a method called call.

In the call method, it gets checked if the phone is in the vicinity of a POI.

If so, the corresponding questions get shown to the user. Upon answering, all questions get saved in the database. Once all questions for an assignment are answered, the questions get pushed to the server, and the Vicinity Checking gets stopped. In addition to that, in the DIASModeSimple, all answers get pushed to the DIAS server upon answering.

In the following list are classes used in those 4 classes:

  • ModeFunctions, for saving answers to the database

  • SensorsInfo, for saving sensor measurements to the database

  • AnswerThread, for loading answers from the database, AnswerThread is one of the DataBaseThreads

  • QuestionHandling, for loading questions from the database

  • QuestionThread, for loading questions from the database in a specific sequence (only in SequenceMode), QuestionThread is one of the DataBaseThreads

  • StateProgressBar, for showing the progress during question answering

  • SensorManager, for measuring the sensors

  • DIAS Library, for sending values to the DIAS server (only in DIASmode)

  • StaticModel, for updating the different question queues

ModeFunctions

This class gets used by all 4 Modes classes, it contains some universally needed functions.

saveAnswer

This method saves the given answer int the SQLite answer table, using the RoomDatabaseHandler.

updateStateBar

This method updates the progressbar, according to the amount of questions already answered, compared to the total amount of questions.

getCombinationId

Given an id list and a CombinationEntity List, this method returns the index of the latter list, which represents the idList.

showAllAnswers

Sets the progressbar to 100%. Asks if the user wants to answer the skipped questions. Calls showSkippedQuestions if yes pressed.

If there are unanswered question, the user gets asked to answer them in the correct POI’s.

showSkippedQuestions

Shows all skipped questions to answer them again.

checkEndSurvey

Checks if the phone is in the vicinity of the destination point.

SensorsInfo

This class saves the measured sensor data.

Constructor

Here, all important fields are initialised, such as:

  • context, the main activity context

  • sensors, list of all used sensors

  • sensorNamesList, list of the names of the sensors, in the same order as sensors

  • mSensorReading, a hashmap with a mapping between sensor name and measurement, converted to a string, contains the most up to date value for every sensor

  • frequency, the frequency used for the sensors.

saveSensorsValue

This method gets the index of which sensor used, matched with which value measured. First, the list of used sensors for the current assignment is loaded. Then, the list of the names of those sensors is remade to match the sensors list.

Then, the frequency is read out and the method saveSensorDataAtIntervals is called with the arguments of the index, the frequency and the measured value.

The list of sensors, as well as the frequency is accessed from the QuestionsActivity, from the list element “assignmentQuestions” at given index.

saveSensorDataAtIntervals

This method takes a given question index, a timeinterval and a answer value.

It takes the length of the measurement time from the QuestionsActivity’s current guestion, given by the provided index.

it creates a list to store all measured sensor values as json strings and creates a CountDownTimer with the provided length and interval length. With the given frequency, the timer then updates the time, location and noise level (with getNoiseLevel) in the mSensorReading hashMap and backs up all current sensor values to the RoomDatabaseHandler. It also creates a json of the readings and puts it in the json list evey time.

When the timer finished, it takes the given answer of the user, together with all json elements of the list, and calls the method saveDataToFile of FileHandling, to save it into a file.

getNoiseLevel

This method is used internally to measure the current noise level of the environment.

RoomDatabaseHandler

The RoomDatabaseHandler extends the RoomDatabase

The idea is, that this handler handles an SQLite database. For that the programmer needs to create “data accsess objects”, or short DAO (more on them here: the DAO’s). One can create as many DAO’s, as one wants, the key is to declare them in the handler. All those DAO’s are interfaces, and for every interface, a function needs to be declared in the handler:

public abstract <InterfaceName> get<InterfaceName>();

so the return type and everything after “get” in the function name must match the desired DAO. One can also create migrations.

The class needs to have the following addition before the class declaration:

@Database(entities = {<All entity.class objects here>}, version = <version_number>, exportSchema = false)

More on entities here: the entities.

For each table, there is a DAO, an entity and a thread.

the DAO’s

All the DAO’s need to have the same schema:

There needs to be an insert function with a specific Entity as parameter in the following way:

@Insert(onConflict = <chosen strategy>)
void insert(<entity class> element)

possible strategies are: REPLACE, ROLLBACK, ABORT, FAIL, IGNORE.

For getting values, there are two possible options, the first one is to only return one element of the database, in this case the return type is a list of the specific type in the DB:

@Query("SELECT Question.id FROM Answer JOIN Question on (Answer.assignmentId AND Answer.questionId) = (Question.assignmentId AND Question.id) join Assignment on Question.assignmentId = Assignment.id WHERE Assignment.name=:assignmentName ")
List<Integer> getAnsweredQuestionIds(final String assignmentName);

As seen, the query is a normal SQL querie in a @Query block before the function definition, function parameters can be used for comparison with “=:assignmentName”.

The other option is to get multiple rows per element, in this case a list of entities is returned:

@Query("SELECT Answer.id,Answer.answer ,Answer.questionId,Answer.assignmentId,Answer.credits,Answer.answeringTime, Answer.aggregateValue FROM Answer JOIN Question on Answer.questionId = Question.id and Answer.assignmentId = Question.assignmentId  join Assignment on Question.assignmentId = Assignment.id WHERE Assignment.name=:assignmentName ")
List<AnswerEntity> getAnsweredQuestions(final String assignmentName);

the entities

The entities define the actual tables.

in the @Entity before the class definition, the table key information is defines, such as foreign keys or indices in the following way:

@Entity(
  foreignKeys = {
    @ForeignKey(
      entity = <another entity class>,
      parentcolumns = <columns from other class>,
      childcolumns = <columns in this entity refering to the foreign parent columns>,
      onDelete = <action>,
      onUpdate = <action>
    )
  }

  indices = {
    @Index(value = "sensorId")
  }

)

The foreign keys are keys used in other tables, that are linked with values in this table.

The possible actions are: CASCADE, NO_ACTION, RESTRICT, SET_DEFAULT, SET_NULL If no action is defined, NO_ACTION is used.

In the class, all columns need to be defined by creating private fields for each row.

evey element need the following addition:

@ColumnInfo(name = <column name as a string>)

the primary key also needs the following:

@PrimaryKey(autoGenerate = <if true, the key gets created automatically>)

The fields can also have getter and setter methods, but they are not necessary.

DataBaseThreads

There is a class for every table in the database querying requests for the specific table, the format for every method is the same:

public List<normal datatype or database entity> getSomething(<arguments used for querying>) throws ExecutionException, InterruptedException {
   return databaseHandler.getAnswerDao().getSomething(<arguments used for querying>);
}

ActivityStackManager

The ActivityStackManager gets launched with the app. It is a singleton, which means, all classes calling getInstance get the same instance of the class.

This class is responsible for launching the different activities of this application.

getInstance

This method is statically typed. it returns the statically saved instance of this class, always returns the same instance.

startMainHomeScreen

Starts up the HomeActivity class.

startLocationService

Starts the LocationService, if not already launched.

returnLocationFlag

Returns true, if the activity is already started.

stopLocationService

Stops the LocationService, if running.

LocationService

Once started, the LocationService is listening on the gps sensor for location updates and propagates them to the correct places.

onCreate

In onCreate, the application context gets set.

onStartCommand

This method gets called once the LocationService was started via the ActivityStackManager. When this method is called the first time after it was installed, the user gets asked for Access to GPS and Network. Once granted, the LocationUpdatesListener, which is declared in this class, is started.

onDestroy

This method gets called, once the service is stopped and the object gets destroyed (either from the application or the garbage collection). It stops the LocationUpdatesListener from listening to the GPS sensor.

LocationUpdatesListener.onLocationChanged

The LocationUpdatesListener only has one method, which is really used: onLocationChanged(final Location location). The location then gets saved in Memory. Then, a sticky gets posted, with the key LOCATION_UPDATED. (Read more about Sticky Events)

This sticky then causes the method onEvent of the HomeActivity to be called.

Splash Activity

This activity gets launched together with the application.

onCreate

In this method, first the bootup logo gets displayed. Next, the ActivityStackManager gets instanciated and startLocationService gets called.

../_images/app_icon.png

Afterwards, the HomeActivity class is started, again via the ActivityStackManager with the function startMainHomeScreen.

PreferencesKeys

The Class contains all keys used to store data via sharedPreferences.

Field

Description

LATITUDE

The latitude of a gps coordinate

LONGITUDE

The logitude of a gps

LOCATION_UPDATED

Used for the postSticky in LocationUpdatesListener.onLocationChanged and the callee in onEvent.

GPS_OFF

Used for the postSticky in onStartCommand, if the GPS provider is offline.

ACCURACY

The accuracy of the sampled gps points

DATA_SCIENTIST_ID

The stored dataScientist id for distinguishing between different sets of assignments

PROJECT_ID

The stored project id for distinguishing between different projects

AUTO_ASSIGNMENT

If the assignment should be automatically loaded.

HELP

The help text for the current assignment

DeviceUuidFactory

This class is used to generate a unique user id for the phone.

constructor

In this method, the UUID gets created, it is basically the Android ID. If the Android ID should not be available, then a random UUID gets created.

getDeviceUuid

Returns the created UUID.

Ellipse

This class is used to create an ellipse and some basic arithmetic operations on it.

getAngle

Returns the angle of rotation of the ellipse.

createEllipse

This method creates the ellipse. It creates 20 points along the ellips in the ellipsePointsList, given the radius in x and y direction and the angle.

IsInEllipse

This method returns true, if the given point is in the ellipse.

drawMarkerWithEllipse

Draws the ellips on the openStreetMap, which the user sees.

FileHandling

This class is responsible for saving sensor data and answers for questions into a file.

constructor

an instance of a class called SavingDataToFileAsync, which is declared in FileHandling, is instanciated.

saveDataToFile

Given sensor measurements, a question id and the corresponding answer, those information get saved in a file, which name is given by utils.filename

QuestionHandling

This class handles everything with the assignment questions currently loaded.

constructor

Initialises thie application context, the question number and number of shown questions (to zero) and calls initValue.

initValue

This method initialises a couple of objects used in this class, such as

  • The currently used ellipse

  • The DatabaseHandler

  • A list for all loaded questions

  • A list for the questions in order of the route

  • A list with all visited points for the current series of questions

getQuestionNumber

Gets the current question number.

setQuestionNumber

Sets the current question number.

setShownQuestion

Sets the shownQuestion list to the given list.

getRouteQuestions

Returns the questions in the route order

getmEllipse

Returns the used ellipse.

getDataFromSavedFile

Gets the data from the DatabaseHandler by calling getFilesData and saves them in the SampleDataModel two instances of MainModel, one is called “questions” and one “selectedQuestions”.

getDataFromRoomDB

Gets the current assignment and all questions of it by the QuestionThread and AssignmentThread out of the DataBaseThreads and loads them into the QuestionsActivity.

QuestionInEllipseNew

Returns the question of the nearest POI, if one is in range, returns -1 otherwise.

getCurrentQuestionNew

Returns the current question given by questionNumber.

addQuestionInVisitedPointsNew

Adds the question, given by the argument qNumber, to the list of visited questions.

isDoneNew

Returns true if the given point was already visited.

utils

This class handles all file storing and loading and some other utility operations.

showFileChooser

Creates a Filechooser dialog on the secreen from a installed file manager.

getDataFromFile

Returns a string, encoded as an XML file, from the given file location.

haveNetworkConnection

Checks, if there is a working connection to the internet, returns true if so;

getSensorData

Returns the contents of the file given in the static field “filename”.

initializeProgressDialog

Initialises the progress dialog used when syncing with the server.

registerSensorListener

Returns a SensorManager, with the Accelerometer, Gyroscope, Light and Proximity sensor already registered.

updateRegisterSensorListener

Registers the Accelerometer, Gyroscope, Light and Proximity sensors to the given SensorManager.

unregisterSensorListener

Unregisters the Accelerometer, Gyroscope, Light and Proximity sensors from the SensorManager.

buildAlertMessageNoGps

Creates and shows an alertDialog, telling the user to enable gps.

makeURL

Given a source, a destionation and a tavel mode, this method creates an url for querying a google API. The response then contains markers, which can be added the the openStreetMap.

getDiasCheckPointLeaveStatus

Creates and fires a timer, which periodically checks if the user is far enough away of the checkpoint. Once the minimum distance is reached, a flag is set in the HomeActivity, such that afterwards the device appropriately leaves from the DIAS network.

distance

Calculates the distance between two given points.

deg2rad

Converts values from [0, 360) to values from [0, \(\pi\)).

rad2deg

Converts values from [0, \(\pi\)) to values from [0, 360).

getUniqeCheckpointId

Creates a CRC2 hash from the lat and long value.

DatabaseHandler

The databaseHandler is used for accessing and retrieving local data. It uses an SQLite database.

The used tables look like the following ones, the keys are underlined. All words written in caps lock are static fields from StaticModel.

TABLE_QUESTIONS_DATA

ID

QUESTION

LATITUDE

LONGITUDE

TYPE

OPTIONS

FILESNAME

NOISE_SENSOR

LIGHT_SENSOR

ACCEL_SENSOR

GYRO_SENSOR

PROXIMITY_SENSOR

LOCATION

TIME

FREQUENCY

SEQUENCE

VISIBILITY

MANDATORY

QUESTIONID

QID

STOPNAME

COMBINATION

VICINITY

TABLE_ANSWERS_DATA

ID

QUESTION

LATITUDE

LONGITUDE

FILESNAME

ANSWERS

QUESTIONID

CREDIT

QID

STOPNAME

TIMEATANSWERING

TABLE_START_AND_DESTINATION

ID

START_LATITUDE

START_LONGITUDE

DESTINATION_LATITUDE

DESTINATION_LONGITUDE

CAR

TRAIN

CYCLE

WALKING

FILESNAME

VACINITY

MODE

DEFAULTCREDIT

ASSIGNMENTID

ASSIGNMENTSTATE

TABLE_START_AND_DESTINATION

ID

FILESNAME

ACCEL_SENSOR

LIGHT_SENSOR

NOISE_SENSOR

GYRO_SENSOR

PROXIMITY_SENSOR

LOCATION

FREQUENCY

QUESTION

QUESTIONID

TIMEATANSWERING

onCreate

Here, the tables get created.

saveQuestionDataTransition

Saves the given list of questions into the database.

saveStartAndDestinationData

Saves the given start and destionation data into the database.

getFilesData

Returns all values from TABLE_QUESTIONS_DATA matching the currently open file name.

getFilesName

Returns all names of all files stored in the database.

deleteFile

Delete all data from the tables TABLE_START_AND_DESTINATION and TABLE_QUESTIONS_DATA mathing the given filename.

QuestionsActivity

The question activity is used as a popup, when the Button “Assignments” in the BottomNavigationView is pressed and the project is loaded from the server. It shows a list with all available assignments. There is also a button with the title “ADD FILES”, which calls the method chooseJsonFile

onCreate

Here, the layout is initialised. It also loads the filelist by calling FileListsNew and asks for storage reading permissions.

chooseJsonFile

Shows a filechooser by calling :ref`showFileChooser`.

onActivityResult

This method is called by the application once the fileChooser application returns, either because a file got chosen, or because the action got cancelled.

If a file got chosen, and it does not has the same name as the currently opened file, it gets loaded into the application via setJsonToClass.

setJsonToClass

Opens the file given by the filename and stores it in internally.

showQuestions

Calls populateQuestions to load the questions, then shows the questions on the screen. When clicking ok, the questions get saved to the database by calling saveDataToDB. If the button ‘cancel’ is called, the questions get discarded.

saveDataToDB

Saves the given questions into the database via the DatabaseHandler.

getDataFromRoomDB

Gets the selected assignment, the according start and destination entity an the questions of the assignment from the DataBaseThreads and starts a new QuestionsActivity.

populateQuestions

Loads the questions and shows them in the QuestionsActivity popup on the screen.

FileListsNew

Gets the list of of assignments from the database via one of the DataBaseThreads and shows them on screen. Finished assignments are shown with a star at the end of the name.

The models

There are different models, which are used for temporarily storing data, they are explained below. The StaticModel was explained earlier.

MainModel

This model is used to store the StartAndDestinationModel and a list of instances of the QuestionDataModel

OptionModel

This model is used as an answer option for the QuestionDataModel. It has the following fields, all of them have getter and setter methods:

Name

Type

Description

Name

String

The name of the answer option

ProjectModel

This class has metadata for the current project, it contains the following fields:

Name

Type

Description

name

double

The name of the project

id

String

“-&gt; checkbox disable, 1 -&gt; checkbox enable”

selected

boolean

whether the project is currently selected

autoAssignment

boolean

If the assignment should be automatically loaded.

help

String

The help text for the project

QuestionDataModel

This model is used for storing the question data.

Name

Type

Description

id

String

“question id {Attribute}”

Question

String

The question

Latitude

String

Lat-location of the question

Longitude

String

Long-location of the question

Sensor

List<SensorModel>

A list with the sensor names used in this Question

Time

String

Time at answering the question

Frequency

String

The sensor measuring frequency

Sequence

String

The question sequence

Type

String

The question type (see Modes)

Visibility

String

The visibility of the question

Mandatory

String

whether or not the question is mandatory

Option

List<OptionModel>

List of answer options with the corresponding credits

StopName

String

The stop text for the notification

QID

String

The question id for the notification

Vicinity

String

The vicinity of the question

SensorModel

This class has a field for the sensor name.

SliderMenuModel

This class has a string for the icon name and an int for the recource id.

StartAndDestinationModel

This class contations a StartAndDestination value pair.

Name

Type

Description

StartLatitude

String

the lat-Position of the start point

StartLongitude

String

the long-Position of the start point

DestitationLatitude

String

the lat-Position of the destination point

DestitationLongitude

String

the long-Position of the destination point

Mode

String

question mode

DefaultCredit

String

the default amount of credits received for this question

AppPreferences

This class is the SharedPreferences handler of the application.

saveLocation

Saves the users current location.

saveAccuracy

Saves the current measuring accuracy.

getAccuracy

Retrieves the last saved accuracy.

getLatitude

Gets the last saved latitude from saveLocation.

getLongitude

Gets the last saved longitude from saveLocation.

saveDataScientistId

Saves the dataScientistId.

getDataScientistId

Retrieves the saved dataScientistId.

saveHelpForProject

Saves the help message fo the current assignment, which gets shown when pressing on the help button.

getHelp

Retrieves the saved help message.

saveProjectId

Saves the current project id.

getProjectId

Retrieves the current project id.

saveAuto

Saves, whether the assignment should be automatically be loaded or not.

getAuto

Retrieves the saved automation preference.

NetworkCallbacks

This class is responsible for all restful API queries with a callback event. It uses an interface called RetrofitInterface for all GET and POST messages.

getAllProjectsFromServer

Uses the getAllProjects query. On response, it saves the response in a list of ProjectModel of the HomeActivity class.

getAllTasksFromServer

Uses the getTasks query, giving it the current project id. On response, it saves the response in a list of tasks of the NetworkCallbacks static list ‘serverTask’.

getAllAssetsFromServer

Uses the getAllAssetsFromSpecificProject query, giving it the current project id. On response, it saves the response in a list of tasks of the NetworkCallbacks static list ‘serverAssets’.

createUserOnServer

Uses the createUser query, giving it the current project id and user. On response, it shows a toast if not successful.

createTaskOnServer

Uses the adminCreateTasks query, giving it the current project id, task id and the task itself.

createAssignmentOnServer

Uses the assignAsset query, giving it the current project id, task id, assetId and a cookieHeader. The cookieHeader has the form:

<projectId> + "_user_id=" + <userId>

assignAssignmentsToUsers

Uses the getAllUsersFromSpecificProject query, giving it the project id. On a successful response, adds all users from the response to the NetworkCallbacks static list ‘serverUsers’ and calls getAssignment for all of them.

getAllAssignmentsFromServer

Uses the getAllAssignmentsFromSpecificProject query, giving it the project id. On response, it saves the response in a list of tasks of the NetworkCallbacks static list ‘serverAssignments’.

getAssignment

Uses the getSpecificAssignment query, giving it the project id and the assignment id. If the response code is either 500 (= internal error) or 200 and the response itself is not “finished”, createAssignmentOnServer is called. Otherwise, no action is done.

updateAssignmentInTask

Uses the userCreateAssignment query, giving it the project id, the assignment, the task id and the cookie header. Then calls createTaskOnServer, saveAssignmentInFile and disables the saved assignment in the database. Sets the assignment submission status to true in the utils class.

getSpecificTask

Uses the getSpecificTask query, giving it the project id and the task id. Upon response, it creates a new task, sets the different fields, creates a AssignmentSubmittedData (a subclass of Assignment) and sets the answers and sensor readings. Then calls updateAssignmentInTask with the new objects as parameters.

AssignmentSubmission

Uses the getAllAssignmentsFromSpecificProject query, giving it the project id. Upon response it iterates through all received assignments and saves the corresponding, given answers into the database. Also calls getSpecificTask for each task.

saveAssignmentInFile

Saves the given assignment into a file with the name givenm by the asset name.

saveDataToRoomDatabase

Saves the data of all assignments of the current project into the RoomDatabase with the RoomDatabaseHandler.

RetrofitInterface

The RetrofitInterface is used for specifying the queries with the restful servers. It uses Retrofit to serialize and create the messages. All messagaes hav type POST or GET.

The queries are defined in an interface class. The @GET/@POST parameters define the website path and the functions return values of type Call<ResponseObject>. In the following, there are all GET and POST queries.

getAllProjects

@GET("/admin/projects?from=0&size=3000")
Call<NetworkModels.ProjectModel> getAllProjects();

getTasks

@GET("/projects/{projectId}/tasks")
Call<NetworkModels.TaskModel> getTasks(@Path(value = "projectId", encoded = true) String projectId);

getAllAssetsFromSpecificProject

@GET("/admin/projects/{projectId}/assets")
Call<NetworkModels.AssetModel> getAllAssetsfromSpecificProject(@Path(value = "projectId", encoded = true) String projectId);

createUser

@POST("/projects/{projectId}/user")
Call<NetworkModels.UserModel> createUser(@Body User u, @Path(value = "projectId", encoded = true) String projectId);

adminCreateTasks

@POST("/admin/projects/{projectId}/tasks/{taskId}")
Call<NetworkModels.SingleTaskModel> adminCreateTasks(@Body Task t, @Path(value = "projectId", encoded = true) String projectId, @Path(value = "taskId", encoded = true) String taskId);

assignAsset

@GET(" /projects/{projectId}/tasks/{taskId}/assets/{assetId}/assignments")
Call<NetworkModels.AssignmentModel> assignAsset(@Path(value = "projectId", encoded = true) String projectId, @Path(value = "taskId", encoded = true) String taskId, @Path(value = "assetId", encoded = true) String assertId, @Header("Cookie") String userId);

getAllUsersFromSpecificProject

@GET("/admin/projects/{projectId}/users")
Call<NetworkModels.UserModel> getAllUsersfromSpecificProject(@Path(value = "projectId", encoded = true) String projectId);

getAllAssignmentsFromSpecificProject

@GET("/admin/projects/{projectId}/assignments?from=0&size=3000")
Call<NetworkModels.AssignmentModel> getAllAssignmentsfromSpecificProject(@Path(value = "projectId", encoded = true) String projectId);

getSpecificAssignment

@GET(" /projects/{projectId}/assignments/{assignmentId}")
Call<NetworkModels.SpecificAssignmentModel> getSpecificAssignment(@Path(value = "projectId", encoded = true) String projectId, @Path(value = "assignmentId", encoded = true) String assignmentId);

userCreateAssignment

@POST("/projects/{projectId}/tasks/{taskId}/assignments")
Call<NetworkModels.AssignmentModel> userCreateAssignment(@Path(value = "projectId", encoded = true) String projectId, @Body Assignment assignment, @Path(value = "taskId", encoded = true) String taskId, @Header("Cookie") String userId);

getSpecificTask

@GET("/projects/{projectId}/tasks/{taskId}")
Call<NetworkModels.SingleTaskModel> getSpecificTask(@Path(value = "projectId", encoded = true) String projectId, @Path(value = "taskId", encoded = true) String taskId);

HiveServerModels

The hive server models are used in the NetworkCallbacks as the returned objects for the server queries. They need to have a specific layout. All elementes need to have getter and setter methods, the variable scope is private and all variables need to have the followoing annotation:

@SerializedName("<serialized name for variable her>")

This identifier makes it possible for the Retrofit library to assign values from the received Json object to the models. In the following, the fields of all models are specified.

Asset

Name

Type

SerializedName

Description

id

String

Id

The id for the asset

project

String

Project

The project for this asset

name

String

Name

The asset name

metadata

Metadata

Metadata

An internally defined class, more on it below this list

counts

Counts

Counts

An internally defined class, more on it below this list

Metadata

Metadata has the same restrictions and rules as the other HiveServerModels. It contains a value of type Record with the serialised name “record”.

Counts

Counts is another internally defined model of Asset. It contains the following 2 elements:

Name

Type

SerializedName

Description

unfinished

int

unfinished

The amount of unfinished assignments

finished

int

finished

The amount of finished assignments

Record

Record is another internally defined model of Asset. It contains two elements:

Name

Type

SerializedName

Description

startAndDestinationModel

StartAndDestination

StartAndDestinationModel

The start and destination model for the hive server, specified futher down.

sampleDataModel

List<SampleDataModel>

SampleDataModel

A list with all data for a question, SampleDataModel is specified further below.

StartAndDestination

Record is another internally defined model of Asset. It contains the following elements:

Name

Type

SerializedName

Description

startLatitude

String

StartLatitude

The latitude of the starting point of a start and destination model.

startLongitude

String

StartLongitude

The longitude of the starting point of a start and destination model.

destinationLatitude

String

DestinationLatitude

The latitude of the destination point of a start and destination model.

destinationLongitude

String

DestinationLongitude

The longitude of the destination point of a start and destination model.

mode

String

Mode

The transportation mode.

defaultCredit

String

DefaultCredit

The deafult credit for this route.

SampleDataModel

SampleDataModel is another internally defined model of Asset. It contains the following elements:

Name

Type

SerializedName

Description

id

int

id

The question id

question

String

Question

The question itself

type

String

Type

The question type

latitude

String

Latitude

The latitude of the question on the map

longitude

String

Longitude

The longitude of the question on the map

Sensor

List<Sensor>

Sensor

The list of all used sensors. The Sensor class is defined further below

time

String

Time

Time of answering the question

frequency

String

Frequency

Sensor measuring frequency

sequence

String

Sequence

Question sequence

visibility

String

Visibility

Visibility of question

mandatory

String

Mandatory

Whether question is mandataory or not

Option

List<Option>

Option

A list of available options, the Option class is defined further below.

combination

List<Combination>

Combination

A list of combinations, the Combination class is defined further below.

vicinity

String

Vicinity

The vicinity of the question

Option

Option is another internally defined model of Asset. It contains the following elements:

Name

Type

SerializedName

Description

id

int

id

The question id

name

String

Name

Text of the textbox option

nextQuestion

String

NextQuestion

The question which follows after this one when this option is selected.

credits

String

Credits

The credits for this option when selected

Sensor

Sensor is another internally defined model of Asset. It contains the following elements:

Name

Type

SerializedName

Description

id

int

id

The question id

name

String

Name

The sensor name

Combination

Combination is another internally defined model of Asset. It contains the following elements:

Name

Type

SerializedName

Description

id

int

id

Question id

selected

List<Order>

Selected

A list with the selected combination. Order is defined further below.

nextQuestion

String

NextQuestion

The next question following after this one.

credits

String

Credits

the credits for this question

Order

Order is another internally defined model of Asset. It contains the following elements:

Name

Type

SerializedName

Description

order

String

Order

the order itself

id

int

id

the question id

Assignment

Name

Type

SerializedName

Description

assignmentid

String

id

The id of the assignment

projectName

String

Project

The name of the project

task

String

Task

The task name

userName

String

User

the username

state

String

State

The current state of the assignment

asset

Asset

Asset

The corresponding asset.

submittedData

AssignmentSubmittedData

SubmittedData

The submitted data for this assignment, AssignmentSubmittedData is defined below.

AssignmentSubmittedData

AssignmentSubmittedData is an internally defined model of Assignment. It contains the following fields:

Name

Type

SerializedName

Description

answer

List<Answer>

SubmittedData

The list of all submitted answers, Answer is defined below.

sensorreadings

List<Map<String, List<SensorReading>>>

SensorData

A list with all readings from the sensors, SensorReading is defined futher below.

Answer

Answer is an internally defined model of Assignment. It contains the following fields:

Name

Type

SerializedName

Description

id

int

Id

The corresponding question id

answer

String

Answer

The given answer

files_name

String

Files_name

The name for the file

latitude

String

Latitude

The latitude of the phone when answering

longitude

String

Longitude

The longitude of the phone when answering

question

String

Question

The question, to which the answer was given

type

String

Type

The question type

timeAtAnswering

String

TimeAtAnswering

The measured time when the question was ansered

SensorReading

SensorReading is an internally defined model of Assignment. It contains the following fields:

Name

Type

SerializedName

Description

id

String

Id

The project id

assignmentId

String

AssignmentId

The assignment id

question

String

Question

The corresponding question

questionId

String

QuestionId

The id of the corresponding question

timeAtSensoring

String

TimeAtSensoring

The time measured, when the sonsor measurement was taken

answerValue

String

Answer Value

The answer, which was given to this question

acceleration

String

Acceleration

The measured acceleration

frequency

String

Frequency

The measurement frequency

gyroscope

String

Gyroscope

The measured gyroscope value

light

String

Light

The measured light value

location

String

Location

Then measured location when answering the question

noise

String

Noise

The measured noise level when answering the question

proximity

String

Proximity

The measured porximity level when ansering the phone

Project

Name

Type

SerializedName

Description

id

String

Id

The project id

name

String

Name

The project name

description

String

Description

The project description

assetCount

String

AssetCount

The amount of assets for this project

taskCount

String

TaskCount

The amount of tasks for this project

userCount

String

UserCount

The amount of users, which have access to this task

assignmentCount

AssignmentCount

AssignmentCount

The amount of assignments for this project, AssignmentCount is defined below.

AssignmentCount

AssignmentCount is an internally defined model of Assignment. It contains the following fields:

Name

Type

SerializedName

Description

total

String

Total

The total amount of assignments

finished

String

Finished

The amount of finished assignments

unfinished

String

Unfinished

The amount of unfinished assignments

Task

Name

Type

SerializedName

Description

id

String

Id

The task id

project

String

Project

The corresponding project

name

String

Name

The name of the task

description

String

Description

The description of the task

currentState

String

CurrentState

The current state of the task

assignmentCriteria

AssignmentCriteria

AssignmentCriteria

The criteria for the assignment, AssignmentCriteria is defined below

completionCriteria

CompletionCriteria

CompletionCriteria

The criteria for completing the task, CompletionCriteria is defined further below

AssignmentCriteria

AssignmentCriteria is an internally defined model of Task. It contains one field: submittedData of the type SubmittedData defined further below.

CompletionCriteria

CompletionCriteria is an internally defined model of Task. It contains two int fields: total and matching, defining how many criteria there are in total and how many of them are matching.

SubmittedData

SubmittedData is an internally defined model of Task. It contains one field: assignments of the type Map<String, Assignment>, which stores all submitted assignments.

User

Name

Type

SerializedName

Description

id

String

Id

The user id

name

String

Name

The username

email

String

Email

The email address of the user

project

String

Project

The corresponding project

externalId

String

ExternalId

The external id of the user

NetworkModels

The network models, like HiveServerModels, are used in the NetworkCallbacks as the returned objects for the server queries. In the following, the models are defined, all of them have just one field.

UserModel

Contains a list of type User with the serialised name “Users”.

ProjectModel

Contains a list of type Project with the serialised name “Projects”.

TaskModel

Contains a List of type Task with the serialised name “Tasks”.

SingleTaskModel

Contains a single field of type Task with the serialised name “Task”.

SpecificAssignmentModel

Contains a single field of type Assignment with the serialised name “Assignment”.

AssignmentModel

Contains a list of elements of type Assignment with the serialised name “Assignments”.

AssetModel

Contains a list of elements of type Asset with the serialised name “Assets”.