📲

Mobile App Documentation

Verification
Tags
Last edited
Last edited time
OwnerRidgeway
Person

SPSI Mobile app documentation

Table of contents

1. Business requirements

2. Environment setup and running the app

1. Setting up the environment

Follow this link to setup the environment.

Make sure to choose Development OS and Target OS to setup for android and iOS separately.

2. Running the application

Run start script to start the app in an emulator.

You can also choose to run the app on an actual device, Reference Link.

3. Code structure

1. Src folder structure

2. Redux setup

Lets see how redux is setup

1. Actions

Four action files are created.

2. Reducers

Four reducer files are present

3. Action types

Action types are present in ActionType.js file. Path is /src/constant/ActionType.js

4. Store composer

All the reducers and middlewares are combined to form a configure store function.

Path: /src/store.js

3. Containers content

1. Attendance

attendance folder is not used, it is kept as a future implementation.

2. Auth

auth folder contains all the authentication screens.

filein usedescription
About.jsyesAbout app permissions and release details
Editprofile.jsnoUpdate user info
Forgotpassword.jsyesResetting the password
Profile.jsyesView user info
Registration.jsyesRegistering the user
SignIn.jsyesLoggin in the user
SignUp.jsnoUser registering for being officer at spsi(Screen not used)
UpdatePassword.jsnoupdating the password but not in use. About.js allows officer to update their password instead

3. Dashboard

dashboard folder holds home screen, shift action and geofence not valid map screen.

filein usedescription
AvailableShift.jsnoShift actions page with access to reports and end shift.
availableShift2.jsnobackup file of older version of AvailableShift.js
index.jsyeshome screen displays upcoming shifts, active shifts, timesheet link and leave link
index2.jsnoolder version of home screen
NotExactLocationWarning.jsyesIf geofence fails, map screen opens with client and user location with gps accuracy details.
ShiftActions.jsyesLunch and tea break timers, access links to individual reports and end shift option
ShiftDetails.jsnoShift details screen with shift description and map with client location pointing. On click of map, location opens up in native navigation apps.

4. Leave

This folder handles everything about leaves.

filein usedescription
AddNewLeave.jsyesAllows officer to apply for a leave
EditLeave.jsnoAllows officer to update leave information.
index.jsyesLists all the leaves with their respective status
index2.jsnobackup
ViewLeave.jsyesOnce a leave is created, it cannot be updated. Officer can check leave contents here.

5. Notification

Screen that lists all the recent notifications.

6. Report

Screen that allows officer to perform all the actions related to reports.

Others folder contains backup files which are not in use

filein usedescription
CourtesyReport.jsyesLists both published and unpublished courtesy reports for the past 30 days. Officer can create new one from here.
DailyReport.jsyesLists both published and unpublished dar reports for the past 30 days. Officer can create new one from here.
EditCourtesyReport.jsyesOfficer can edit the report and publish.
EditDailyReport.jsyesOfficer can edit the dar description and publish it. Can also create and edit entries from here
EditDailyReportEntry.jsyesOfficer can edit dar entries. They can attach medias from here.
EditIncidentReport.jsyesOfficer can edit incident report and attach medias to it.
IncidentReport.jsyesLists both published and unpublished incident reports for the past 30 days. Officer can create new one from here.
index.jsyesProvides buttons to enter individual reports.
ViewCourtesyReport.jsyesPublished reports cannot be edited. They can viewed from here.
ViewDailyReport.jsyesPublished reports cannot be edited. They can viewed from here.
ViewIncidentReport.jsyesPublished reports cannot be edited. They can viewed from here.

7. Schedule

Deals with shifts and its details

filein usedescription
index.jsyeslists all the shift from current day to future 30 days
index2.jsnobackup
ShiftDetails.jsyesShift details screen with shift description and map with client location pointing. On click of map, location opens up in native navigation apps.

8. Timesheet

Holds screens related to timesheets

filein usedescription
AddNewTimesheet.jsnoAllows officer to add new timesheet. Timesheets are created by backend so this screen is redundand.
EditTimesheet.jsnoOfficer can edit timesheet. As per client requirements officer cannot update timesheet. Edit features are disabled.
EditTimesheet2.jsnobackup
Timesheet.jsyesLists all the timesheets
timesheet2.jsnobackup
ViewTimesheet.jsyesOnce shifts ends, timesheet's status changes to published. This screen allows officer to just the content.

4. Implementations

1. Geolocation fetching

App requires gps cordinates to verify whether the officer is present within the client location geofence or not.

Package used: react-native-geolocation-services

Package configuration: Setup of this package

Sample code:

import Geolocation from 'react-native-geolocation-service';

Geolocation.getCurrentPosition(
          position => {
            let region = {
              lat: position.coords.latitude,
              lng: position.coords.longitude,
            };
            log.info('Location:', position.coords);
          },
          error => {
            log.error('[container/dashboard/index] in get location:', error);
          },
          {enableHighAccuracy: true, timeout: 5000, maximumAge: 3000},
        );

Note:

2. Permissions

App requires permission for accessing gps, camera, microphone, file system and media files. In order to use those services user must provide permission for the app to use them. To get permission from the user we are using a package.

Package used: react-native-permissions

Package configuration: Configuration link

Sample code:

import { requestMultiple, PERMISSIONS } from "react-native-permissions";

//iOS multiple permission request

async function requestAndroidPermission() {
  try {
    let statuses = requestMultiple([
      PERMISSIONS.ANDROID.CAMERA,
      PERMISSIONS.ANDROID.RECORD_AUDIO,
      PERMISSIONS.ANDROID.WRITE_EXTERNAL_STORAGE,
      PERMISSIONS.ANDROID.READ_EXTERNAL_STORAGE,
      PERMISSIONS.ANDROID.ACCESS_FINE_LOCATION,
    ]);
    if (
      statuses[PERMISSIONS.ANDROID.CAMERA] == "granted" &&
      statuses[PERMISSIONS.ANDROID.READ_EXTERNAL_STORAGE] == "granted" &&
      statuses[PERMISSIONS.ANDROID.WRITE_EXTERNAL_STORAGE] == "granted" &&
      statuses[PERMISSIONS.ANDROID.ACCESS_FINE_LOCATION] == "granted" &&
      statuses[PERMISSIONS.ANDROID.RECORD_AUDIO] == "granted"
    ) {
      log.info("info", "SUCCESS:", "all android permissions granted");
    }
  } catch (error) {
    log.error("[utils/permission] in request android permission:", error);
  }
}

//android multiple permission request

Note: Permission names are different for both android and iOS. Check package documentation for exact names. Before using permissions check the type of OS. You cant ask iOS permissions in android. Use Platform module from react native to check the OS. Instead of multiple permissions you can ask for single permission also.

3. Notifications

App uses push notifications. When a new shift is created for that officer by admin, it should be notified in the app. Notifications work if the app is in background, foreground or even closed. We are using firebase for handling notifications.

Package used: react-native-push-notification for android, react-native-community/push-notification-ios for iOS and @react-native-firebase.

Package configuration: react-native-push-notification , react-native-community/push-notification-ios and @react-native-firebase

References: push notifications and firebase remote notifications

How it works: While logging in the user, fcm token is generated and its sent to backend to send notifications. While logging out, we remove the token from backend.

Files involved:

4. Media handling

Officers upload images, videos, audios and documents to attach to reports.

Package used: react-native-image-crop-picker for images and videos, react-native-document-picker for audio and document files

Package configuration: react-native-image-crop-picker , react-native-document-picker

How it works:

Files involved:

Viewing uploaded media:

5. Map display

Map is used to display the client location markers in shift details.

Package used: react-native-maps

Reference: using maps in react native

Files involved:

6. Remote config handling

If we store cofigurations of the app locally, if we have to make any changes we will have to make new release. So we are serving app configurations from one of the API. Config data is encoded and we have decode at mobile end to use it.

7. Device online status finding

Before making any API call app checks whether user is connected to internet or not.

Package used: @react-native-community/netinfo

Reference: @react-native-community/netinfo

8. Navigation

Lets see screens and tabs are navigated within the app. There are two types of navigations, 1: Stack navigation 2: Tab navigation.

package used: React navigation

Reference: React navigation

1. Stack navigation

Screens are stacked on one top of another to render a new screen view and removed from the stack to go back to the previous screen.

Reference: Stack navigation

Files involved:

2. Tab navigation

Tab navigations are the ones that appear at the bottom the app screen. Within a tab we can use stack navigation.

Reference: Tab navigation

Bottom icons are called tab navigators

Files involved:

After succesfully logging in the user, navigation is moved to tab navigator. In file /src/container/auth/SignIn.js. StackActions.replace replaces the current screen with new screen instead of stacking on top of it, due to that when the user presses back button it doesnt go to the previous screen.

import { StackActions } from "@react-navigation/native";
props.navigation.dispatch(StackActions.replace("TabNavigator"));

9. AWS media upload

We are using AWS s3 buckets to store all the media files. Media files include images, videos, audios and documents.

Media upload flow:

Uploading files to aws s3

After selecting media files, they are uploaded to aws s3. S3 returns unique id for each file.

Saving the file ids to database:

After uploading files to s3, all file unique ids are saved in the database linked to particular report.

10. Geofence verification

App uses geofence verification to check whether the officer is present within the client property before starting the shift. Geo fence verification is happening while starting shift, starting breaks and ending shift.

Package used: geolib

Reference: geolib

Files involved:

locationData = await verifyGeoFence(
              {latitude: currentLocation.lat, longitude: currentLocation.lng},
              shiftLocation,
              fenceRadius,
            );

if (
              locationData.status ||
              !isGeoFencingOn ||
              (shiftActionAttempt &&
                shiftActionAttempt === this.state.geoFenceAttemptConstant)
            ) {

Based on the above if condition shift is started if not navigated to NotExactLocationWarning.js screen.

this.props.navigation.navigate('NotExactLocationWarning', {
                nextShiftTime: this.state.nextShiftHours,
                selectedShift: selectedShift,
                currentLocation: this.state.currentLocation,
                centerPoint: locationData.centerPoint,
                // maxDistance: locationData.maxDistance,
                radius: locationData.radius,
                showCircle: locationData.showCircle,
                getshifts: this.getShiftDetails,
              });

11. API call setup

REST API calls are made using axios npm package. Lets see how its setup and being used in actions.

Package used: Axios

Reference: Axios

Lets take an example of getCourtesyReports funtion from /src/actions/reports.js

12. Form validation

Form validations are very important. Without validating user inputs, data should never be send to backend.

Package used: React hook form

Reference: React hook form

Lets take file /src/container/leave/AddNewLeave.js for example

13. App update prompt

Whenever a new app release is available, app checks it and prompts the user to update it.

Package used: React native version check

Reference: React native version check

/src/index.js file is the root file. Here we check for new updates.

14. Navigation service

We can use the React navigation’s navigation services only within react components. For being able to navigate from other than React components we create a navigation service.

15. Splash screen

Splash screen is what we see when app is loaded closed state. We show SPSI logo on splash screen

Note: We setup splashscreens differently for both android and iOS refer this blog

Package used: React native splash screen

Setup Reference: React native splash screen

File /src/utils/SplashScreen.js is a stack screen which shows up and closes when initial app loading is done.

  1. We register it as any other stack screen in /src/RootNavigation.js
    import SpalshScreen from './utils/SplashScreen';
    
    <NavigationContainer ref={navigationRef}>
          <Stack.Navigator initialRouteName="SplashScreen">
    <Stack.Screen
              name="SplashScreen"
              component={SpalshScreen}
              options={{headerShown: false}}
            />
    </Stack.Navigator>
        </NavigationContainer>
  1. We can perform all the actions when components mounts and when all the loading operations are done, we can use StackAction.replace() to navigate to login screen
    async componentDidMount() {
        try {
          let userInfo = await AsyncStorage.getItem("userInfo");
          let isShiftEnd = await AsyncStorage.getItem("isShiftEnd");
          let shiftStatus = await AsyncStorage.getItem("shiftStatus");
          let breakStarted = await AsyncStorage.getItem("breakStarted");
          if (shiftStatus) {
            shiftStatus = JSON.parse(shiftStatus);
            this.props.setShiftActiveStatus(shiftStatus);
          }
          if (breakStarted) {
            breakStarted = JSON.parse(breakStarted);
            this.props.setBreakStarted(breakStarted);
          }
          if (isShiftEnd) {
            isShiftEnd = JSON.parse(isShiftEnd);
            this.props.setShiftEndStatus(isShiftEnd);
          }
          let route = "SignIn";
          if (userInfo !== null) {
            userInfo = JSON.parse(userInfo);
            this.props.setUserInfo(userInfo);
            route = "TabNavigator";
          }
          return this._navigate(route);
        } catch (error) {
          log.error("[splashscreen] :", error);
          return this._navigate("SignIn");
        }
      }
    
      _navigate = (route) => {
        SplashScreen.hide();
        return this.props.navigation.dispatch(StackActions.replace(route));
      };

16. App icon

App icon is the brand icon that appears on mobile screens which on click opens the actual app.

Video reference

Blog Reference

Note: Setup is different for both android and iOS

along with ic_launcher.png add ic_launcher_round.png aswell.

17. Allowing access to remote servers(Transport security setup)

To communicate with a remote host we have to specify that in app cofigurations.

18. Setting up push notification icon

This icon appears in the notification.

  1. Generate notification icons in black and white for different resolutions same as app icon and place it in android/app/main/res/mipmap-* by the name

    ic_notification

  1. In /src/utils/LocationNotificationService.js add this ic_notification name in configuration.
buildAndroidNotification = (id, title, message, data = {}, options = {}) => {
    return {
      id: id,
      autoCancel: true,
      largeIcon: options.largeIcon || "ic_launcher",
      smallIcon: options.smallIcon || "ic_notification",
      vibrate: options.vibrate || true,
      vibration: options.vibration || 300,
      priority: options.priority || "high",
      importance: options.importance || "high",
      color: options.color || "white",
    };
  };

19 NotExactLocationWarning screen

This screen is rendered when the officer is not in the client location. It shows the positions of both officer and client locations. Buttons are provided to switch focus on client location and officer location. It also displays the gps accuracy of the officer.

As the officer starts moving a blue line is drawn to indicate officer’s direction of movement. This helps officer to know whether he is moving towards or away from client location.

5. Building and publishing the app

Note: You can find all the app release notes here

1. Android building and publishing

  1. Change the version code and version name in android/app/build.gradle file
    defaultConfig {
            applicationId "com.securityofficerapp"
            minSdkVersion rootProject.ext.minSdkVersion
            targetSdkVersion rootProject.ext.targetSdkVersion
            versionCode 20
            versionName "2.8"
        }
  1. Go to android studio and open just the android folder of spsiofficerapp project. Let is start indexing. Once done go to build > signed bundle or APK >
  1. Select from project android folder. Current keystore password isFill key-alias as Click next.

    keystore

    my-release-keystore.keystore

    murali.

    my-key-alias.

  1. Select relase and click finish to build the app.
  1. After building you will find the app in folder.

    android/app/release/

  1. Navigate to Select tab and click on create new release button. Upload the apk file and let the rest of the autofilled fields be same. Click on publish button.

    google play console

    .

    Production

  1. Currently manual publish is setup, so reviewed apps will not avaiable on playstore automatically. We have publish from the button

    Releases overview

2. iOS building and publishing

general app information

certificate signing tab

Selecting emulator device

  1. Open the project in xcode
  1. From general tab after selecting project name, you can see the app display name and version and build numbers. You have to updated version number from previous version number.
  1. In signing and capabilites tab you have to select signing certificate. If not present you can

    create one

    .

  1. Select from select devices tab present at the top.

    Any iOS device

  1. Click from top bar. Select

    Product

    Clean Build Folder.

  1. Once done, From select

    Product

    Archive.

  1. Once built Select the build from Archives list which you want to push to appstore and click .

    Distribute App

  1. Select itll build and from check all the options and click next.

    App Store Connect,

    App Store Connect distribution options

  1. Click on

    Automatically manage signing.

  1. Click upload button to upload it to appstore connect.
  1. Login in to

    appstore connect

    .

  1. Click on plus button to the right of Add the new version number of the app. Fill in whats new in this version in input under heading.

    iOS app.

    Version information

  1. Select the build from section. If the new build is not diplayed here, wait and try again after some time. Pushed app may take some time to reflect on appstore connect sometimes.

    Build

  1. After filling up create a new release from the button at the top right corner.
  1. Published app will take between 2 to 4 days for review. Once reviewed succesfully we have to manually publish it from appstore connect console.

6. Walkaround of Playstore and Appstore console

Android

1. Releases overview: This tab will show latest app available on the playstore 1. Production: This tab will allow you to publish new apps 1. Publishing overview: We can setup manual or automated publishing of the app

iOS

1. iOS app menu from left top, will display all the general informations of the app from app store description, app store icon, build version etc. 1. In the same page, under Version Release heading we can set the app release type whether manual or automatic. Currently its set to manual in both appstore and playstore.

Copied