Thank you for being a valued client of CM First Group. If you have any technical issues or concerns, please open a ticket on support.cmfirstgroup.com, email CM First technical support at support@cmfirstgroup.com or call us on our 24/7 customer hotline at +1 (512) 623-7586.

Follow

Incident Reporter for Mobile

Video Walkthrough

Pattern Functions

All functions will be under "Patterns.Mobile".

CordovaPage

This function inherits from ~WebShell, and has an IMPL Name of Cordova.  Any function inheriting from this will use the Cordova-page.ctrl template.  This pattern is to be used with any function using Cordova (PhoneGap) plugins.

GeoLocation

This function inherits from ~WebShell.  The panel contains a field called "LatitudeLongitudeCoordinates" in "LocationP".  It has a Control Name of "GeoLoc:HiddenArea:template=WebLocation".  The "WebLocation.ctrl" template will fetch a latitude/longitude string whenever the panel is shown.  An event "GeoLocationUpdated" tied to the Updated event on the field.  The event itself only has an Edit Point in it at this level.  Any functions that needs to use the device's GeoLocation feature will inherit from this pattern.

GoogleMaps

This function inherits from ~WebShell.  The panel displays the following field with the following Control Name:

MobileGoogleMap for GoogleMap
Control Name: gMap:FullscreenArea:template=WebMap

 

This uses our WebMap control template to display a Google Map centered on the value cast into it.  In our action diagram, we are casting Local< LatitudeLongitudeCoordinates> to this field.  So, any function that inherits from this function will need to set this local value to center the map.

IncidentMobilePage

This is a simple page template with the IMPL Name of "IncidentMobilePage".  Any function that inherits from this will bring in the code from " IncidentMobilePage-page.ctrl", which initialized the CSS file, custom.js file, and Google map api.

ToolbarBottom

This is a simple page template with the IMPL Name of " ToolbarBottom".  Any function that inherits from this will bring in the code from " ToolbarBottom-page.ctrl", which contains a footerbar, which 3 attach points.

MobileWebClientPanel

This is the basis for all of our Mobile panels.  It inherits from ~WebShell, _Abstract.~WebMessages, and Patterns.Mobile.IncidentMobilePage.  The panel contains these buttons:

Incident Reporter
Control Name:
Events:
Notes:
TitleBtn:ToolbarArea:align=center:cls=LabelButton
None
This is just being used as a Title for the application.
Logout
Control Name:
Event:
Notes:
LogoutBtn:ToolbarArea:align=right:direction=left
Pressed = Logout
The Logout event will just call the Login Page again.
*Blank (Back Button)
Control Name:
Event:
Notes:
BackBtn:ToolbarArea:align=left:ui=back:direction=right:iconCls=arrow_left
Pressed = Close
This button is hidden on most screens
PlaceH
Control Name:
Events:
Notes:
PlaceholderBtn:ToolbarArea:cls=placeholderBtn:align=left:direction=right
NONE
This button is only shown on functions where the Back Button is hidden.

 

It is used to keep the spacing even on the toolbar.

MobileMenuPanel

This pattern is being used by the screens that will have the menu items displayed in the footer bar.  It inherits from Patterns.Mobile.MobileWebClientPanel and Patterns.Mobile.ToolbarBottom.  It also has the "LoginEmail" as in Input field.  It adds 3 buttons to the panel:

Info
Control Name:
Event:
Notes:
InfoBtn:ToolbarBottomCenter:direction=right:seq=1:iconCls=infomenu
Pressed = Info
Event calls " User Splashscreen.Mobile.Info"
Report
Control Name:
Event:
Notes:
ReportBtn:ToolbarBottomCenter:direction=right:seq=2:iconCls=reportmenu
Pressed = Report
Event calls " Incident.Mobile.Report"
My Reports
Control Name:

Event:
MyReportsBtn:ToolbarBottomCenter:direction=right:seq=3:
iconCls=myreportsmenu

Pressed = My Reports 

Notes:  Event calls "Incident.Mobile.MyReports"

Login Functions

Panel Setup

In this panel, we are displaying the following fields:

LoginEmail for DetailP
Control Name: LoginEmail:MainArea:fieldSet=Login:hint=Email/Cell:align=center
Password for DetailP
Control Name: LoginPassword:MainArea:fieldSet=Login:hint=Password:align=center:
template=WebPasswordNoLabel
LoginEmail for CookieP
Control Name: UserID:MainArea:template=WebCookie
Password for CookieP
Control Name: Password:MainArea:template=WebCookie
YesNo for CookieP
Control Name:
Event:
Control Name: SaveUser:MainArea:fieldSet=Login:align=center
Modified = SaveOptionChanged
Login Button
Event:
Control Name:
Pressed = Login
LoginBtn:MainArea:fieldSet=3:align=center:direction=left
Register Button
Event:
Control Name:
Pressed = Register
RegisterBtn:MainArea:fieldSet=4:align=center:direction=left

 

Notes:  Both the CookieP and CookieP fields have event mapped to Modified and Updated.  These fields do not actually show up on the panel.  The events are triggered from the WebCookie template.  This will be explained further later on.

Action Diagram

Initialize

We initialize all of DetailP to Blank, and CookieP to No.  We also are setting the "Login Valid?" and "Cookie Modified?" flags to No.  These will be used later.

Subroutines

Sub Call Main Menu: This is where we call the initial function after the user logs in.  We are currently calling the "Info" panel.
Sub Validate Password: This is where validate the entered password compared to the one saved to the database.
Sub Login: We start by validating the Login information.  The user can login with an email address or their cell phone number, so we need to check both.

If the Login is valid, then we check to see if the user wants to save the login information to local storage, but it has not been saved yet.  If this is the case, we set the CookieP fields and set the "CookieModified?" flag to Yes.   This flag will prevent us from calling the next function until after the Cookie has been saved to local storage.  This will be explained more later.

The LoginEmail is also saved to the ObClient file.  So, if we want to reference it later, we can.

Finally, we call the "Main Menu" function if we are not currently saving the Cookie to local storage.

 

Events

 

Login: This just calls our Login Subroutine
Register: This calls our Register panel, which we will mention later in the document.  If the user Registers correctly, we will also automatically log them in using their created information.
SaveOptionChanged: If the checkbox value is Yes, then we are setting the CookieP fields.  If it is set to No, then we will clear the CookieP fields.  Our templates with handle the adding/removing of the cookie from local storage.  This will be explained further later.
UserPWFound: This event is triggered when the Cookie template loads a Cookie from local storage.  It will take the information from the cookie and set it to the DetailP.
UserPWSaved: This event is triggered when the Cookie template saves the cookie to local storage.  In our code, if the login information has already been validated, then we want to call the "Main Menu" function.

 

Custom Templates

This function makes use of the WebCookie template included with WebClient Mobile.  This causes the field to be a non-visible element in the dom.  Any time a "Put" is done on a field using this template, the field information will be saved to the Local Storage and will trigger the Updated event for the field.  Also, when the page is loaded, if the local storage element is found, then it will set the field value and trigger the Modified event for the field.

Register Functions

In this panel, we are displaying the following fields:

FirstName for DetailP
Control Name: FirstName:MainArea:hint=First Name:align=center:fieldSet=1
LastName for DetailP
Control Name: LastName:MainArea:hint=Last Name:align=center:fieldSet=1
LoginEmail for DetailP
Control Name: Email:MainArea:hint=Email:align=center:fieldSet=1
Cell Number Text for DetailP
Control Name: CellNumTxt:MainArea:hint=Cell#:align=center:fieldSet=1:
template=
WebPhoneNumber

 

Note: WebPhoneNumber is a template that brings up a different keypad when the use edits the field.

Password for DetailP
Control Name: Password:MainArea:hint=Password:align=center:fieldSet=1:
template=
WebPasswordNoLabel
Register Button
Control Name:
Events:
RegisterBtn:MainArea:align=center:direction=left:fieldSet=2
Pressed = Register

 

Action Diagram

This field outputs the registered LoginEmail and Password, as well as a flag showing the user registered.

Initialize

We initialize all of the Output to Blank and the Registered flag to No.

Subroutines

Sub Validate DetailP: This is where validate that all of the DetailP has been entered.
Sub Create Record: This is where we create the User record, set the Output, and exit the function.

 

Events

Register: This casts the CellPhoneText to the CellPhone field.  CellPhoneText is used for display purposes.  We call the Validate subroutine and, if valid, call the create record subroutine.

 

Info Function

This function only exists for Mobile.  It is designed to load a customized image and message for a user.  If one is not found, then a default image and message will be shown.

 

Panel

In this panel, we are displaying the following fields:

SplashImage for DetailP
Control Name: AppLogo:MainArea:template=WebURLPicture:seq=1:imageCls=FramedImage:
imageAlign=center
SplashMessage for DetailP
Control Name: GeneralInfo:MainArea:template=WebMultilineEdit:align=center:seq=2:
cls=
generalInfo

 

We are also protecting the "Info" button, so that the function cannot call itself.  We also add the following element to the Control Name: "cls=protectedMenuButton".  This will add some CSS changes to the button.

Action Diagram

This field outputs the registered LoginEmail and Password, as well as a flag showing the user registered.

Initialize

In the initialize, we try to load the User Splashscreen record.  If it is found, we set the DetailP with the fetched data.  If not, we set the values to their default values.

My Reports Functions

These functions are designed to show all of the Incidents reported by the current user.

 

Panel

In this panel, we are displaying the following fields, which are being populated in the BlockFetchSet:

ThumbnailURL for GridP
IncidentStatusDescription for GridP
DateString for GridP

 

GridP has a Control Name of "Grid1P:FullscreenArea:template=WebGrid:grouped=false:tplGenerator=cmfirst.custom.myReportsTpl".  The tplGenerator portion of the Control Name tells WebClient Mobile how it will display the grid.  This Tpl can be found in the custom.js file in "incidentmobile/WebContent/js/cmfirst".

We are also protecting the "My Reports" button, so that the function cannot call itself.  We also add the following element to the Control Name: " cls=protectedMenuButton".  This will add some CSS changes to the button.

Action Diagram

We want to call the View Details function (mentioned later) on the Grid Selected event.  Since Plex selects the first row after it loads the grid automatically, it would call the View Details function right away.  To prevent this, in "Pre Point Start Load Grid", we set the "Allow SelectGrid?" flag to No.  Then, in "Pre Point Start Select Grid" , if this flag is No, we set it to Yes, then exit the subroutine.  This will prevent the Select Grid event from running it's code on the first pass.

Then, just add a call to our "IncidentDetails" function in the "Process Selected Grid Row" edit point.

Reports Functions

These functions are used to create Incident records.  An image can be attached and uploaded to server.  This uses the Upload Servlet in the workspace to accomplish this.  For more information in setting this up, please refer to our documentation on the File Upload Servlet.

Referencing an External Server

When the files are uploaded with the Upload Servlet, they are stored in a location relative to the Web Server.  The problem with this is that if you deploy a new WAR file, all uploaded files stored here would be lost.  To solve this, we will copy the files from this location to one outside of the workspace.  In our case, we are using "C:\Uploads".  For the WebServer to be able to access these files, we need to add a reference to this folder in the "server.xml" file.  Please refer to this file and you will see the following line:

"C:/Uploads" path="incidentmobile/photos"/>"C:/Uploads" path="IncidentWeb/photos"/>

This will allow you to access the files in this folder using the "incidentmobile/photos" and "IncidentWeb/photos" paths.  You can see evidence of this in the code setting the ThumbnailURL in the BlockFetchSet being used by the My Reports functions.

This function inherits from both "Patterns.Mobile.CordovaPage" and "Patterns.Mobile.GeoLocation".  This allows the function to use Cordova (PhoneGap) plugins and will use our pattern GeoLocation code.

 

Panel

In this panel, we are displaying the following fields:

IncidentType for DetailP
Control Name:
Control Type:
IncidentType:MainArea:align=center:seq=1:fieldSet=1:label=Type
Combo Box
IncidentDescription for DetailP
Control Name: IncidentDesc:MainArea:template=WebMultilineEdit:align=center:seq=3:
fieldSet=1:label=Description
ImageName for DetailP
Control Name: ImageName:MainArea:template=WebCameraUpload:align=center:
seq=2:fieldSet=2
ImageLocation for DetailP
Control Name: ImgLoc:HiddenArea:template=WebHiddenEdit:align=center:seq=6:
fieldSet=1
Select Location Button
Control Name:
Events:
SelectLocBtn:MainArea:direction=right:fieldSet=1:seq=5
Pressed = SelectLocation

 

Note: This stores the location of the Photo after it is uploaded to the server.

Submit Button
Control Name:
Events:
SubmitBtn:MainArea:direction=right:fieldSet=3:seq=5
Pressed = Submit Report

 

Please note that the ImageName field is using the " WebCameraUpload " template, which turns the field into a button.   When pressed, this launches the camera.  After a picture is taken and approved, it will be uploaded to the WebServer.  The location in the WebServer is saved to the ImageLocation field in DetailP.   This button uses Cordova's camera and file upload APIs, which take a few steps to setup.  These steps are listed later in the document.  And to use these features, you will need to install the application on an Android device, which is also explained later in the document.  For now, if you try to test this function in the regular browser, you will receive messages like ones shown below.  Please press "Cancel" on these messages, or you will crash the application.

 

Action Diagram

Initialize

We initialize the DetailP, "Image Selected?" flag, and "Address Selected?" flag.  We call the subroutine to load the Incident Type Combobox.  We also fetch the User record for later reference.

Please note that this function uses the GeoLocation template, which will run when the panel is shown.

Subroutines

Sub Validate Submit: This is subroutine validates that all the information has been entered.   It also checks if a location has been selected, either by the GeoLocation or by the "SelectLocation" function.  If no image was selected, the user is warned, but allowed to continue without one.
Sub Save Report: This is where we create the Incident record.  If an image was selected, we will copy the file to the permanent folder, create a thumbnail version of the image, and create the Incident Image record.  Then, we call the My Reports function, which will show the newly created report.
Sub Load IncidentType Combobox: This is subroutine that populates the Incident Type Combobox based on the records in the Incident Type table.
Sub UpdateLatLng This subroutine breaks up the Latitude/Longitude string fetched from the GeoLocation control into the Latitude and Longitude to be saved to the database.
Sub Select Location: This subroutine calls the "Select Location" function.  It will warn the user if a GeoLocation has already been set by the GeoLocator template.

 

Events

GeoLocationUpdated: This event is triggered by the GeoLocation template.  We just do a Go Sub UpdateLatLng to process what was fetched.
Submit Report: This subroutine makes sure the Latitude/Longitude has been set, then validates the details.  If it passes validation, then it calls the Save Report subroutine.
Image Selected: This event is triggered after the photo has been selected and uploaded to the Web Server.  We are just setting a flag showing that an image was selected.
SelectLocation: This subroutine just calls the Select Location subroutine.

 

Incident Details Functions

 

Panel

In this panel, we are displaying the following fields:

IncidentDate for DetailP
Control Name: IncDate:MainArea:template=DatePicker:align=center:seq=1:
label=Report Date
IncidentType for DetailP
Control Name: IncType:MainArea:align=center:seq=2:label=Type
IncidentStatus for DetailP
Control Name: IncStatus:MainArea:align=center:seq=3:label=Status
IncidentDescription for DetailP
Control Name: IncDesc:MainArea:template=WebMultilineEdit:align=center:seq=4:
label=Description
CloseDate for DetailP
Control Name: CloseDate:MainArea:template=DatePicker:align=center:seq=5:
label=Close Date
ImageName for DetailP
Control Name: IncidentImage:MainArea:template=WebURLPhoto:seq=6:
imageCls=FramedImage:imageAlign=center
View Location Button
Control Name:
Events:
ViewMap:MainArea:align=center:seq=7
Pressed = ViewMap

 

Action Diagram

This field outputs the registered LoginEmail and Password, as well as a flag showing the user registered.

Initialize

We fetch all the Incident record information to display. We also fetch the User record, since we need the Cell Number to locate the attached Incident Image. We then attempt to fetch the Incident Image. If none exists, then we hide the ImageLocation field. Finally, we hide the CloseDate field is it does not contain a valid value.

Events

ViewMap: This calls the "ViewLocation" function for the record selected.

 

Select Location Functions

These functions both use the Google Map API to convert a search string into a GeoLocation.  For example, if you enter " 7000 North Mopac Expressway Austin, TX".  The function will use the custom templates to give the Latitude and Longitude of that location.  These functions both have the Latitude and Longitude as Input and Output.

Panel

In this panel, we are displaying the following fields:

LocationString for DetailP
Control Name: LocString:MainArea:hint=Location:fieldSet=1
Full Address for DetailP
Control Name:
Events:
FullAddress:MainArea:template=MobileAddressLocator:fieldSet=1
Updated = AddressConverted
Confirm Button
Control Name:
Events:
Confirm:MainArea:fieldSet=2
Pressed = ConfirmLocation

 

Action Diagram

Initialize

We initialize the Output to what was Input.  So, if the user cancels their change, then the values will not be overwritten.

Events

ConfirmLocation: We get the LocationString entered by the user and Set/Put the Full Address. Putting the Full Address will cause the template to calculate the Latitude/Longitude.  We do not want to exit the function until the calculation has finished.
AddressConverted: This event is triggered once the Full Address has been calculated.  So we break up the Latitude/Longitude string, set the output, then terminate.

 

View Location Functions

This function is for Mobile only.  It is using the "Patterns.Mobile.GoogleMaps" pattern.  The pattern will take care of nearly everything.  We only need to set the Local in the Post Point Process Options.  The function will display a GoogleMap centered on this location in the Full Screen Area.

 

Android Application Setup

This is an Android Project already setup in the Eclipse workspace: DevComm.  Any instructions that are given in here are relative to this project.

Cordova API Setup

We need to install the Plugin APIs for Cordova File Transfer and Camera.  Start by opening a command line interface.  From your start menu, select 'Run...', then enter 'cmd' to bring up a command prompt. Change directory to the location of your Android project.   The command will look something like this: "cd C:\IncidentReporter\Workspace\DeviceComm".   Now run the following commands:

1) To install the Cordova Camera plugin:

        cordova plugin add org.apache.cordova.camera

2) To install the Cordova File Transfer plugin:

        cordova plugin add org.apache.cordova.file-transfer

In your workspace, open "DevComm/AndroidManifest.xml".  Click on the AndroidManifest.xml tab.  Make sure you have the following permissions set for your app:

    "android.permission.WRITE_EXTERNAL_STORAGE" />
   "android.permission.ACCESS_COARSE_LOCATION" />
   "android.permission.ACCESS_FINE_LOCATION" />
   "android.permission.ACCESS_LOCATION_EXTRA_COMMANDS" />
   "android.permission.CAMERA" />
   "android.hardware.camera" />
   "android.hardware.camera.autofocus" />
   "android.hardware.camera.flash" />

Installing on Android Device

To install the application on an Android device, we will need to create an APK file.  But first, we need to configure the files to point to your web server.

Initial Setup

First, determine your PC's IP Address, but going to the Command Prompt and entering "ipconfig".  Take note of the IPv4 Address.

Open the "incidentmobile/WebContent/www/index.html" file.  Scroll to the bottom and change the "window.location" line to use your current IP address.

window.location = 'http://192.168.1.105:8080/incidentmobile/wc';

Icon and App Name

Open "DevComm/AndroidManifest.xml".  Click on the Application tab.  Under the Icon entry, press the Browse button.  You can use the Android Resources to create any icon that you want.

To change the App name, go to "DevComm/res/values/string.xml".  Click on the app_name item, and change the Value to what you would like to name the App.

Create and Deploy an APK

An Android application can be exported to an Android installation file (APK).  Applications are usually signed with a key within a keystore.  Please Note that these screen shots are for a different Android Project, but the instructions are still the same.

Select your DevComm project, right-click and select Android Tools --> Export Signed Application Package

 

Click Next.

Select Create a New Keystore.  Put this file in a place that you can easily find and give it a password that you will remember.  This keystore can be used for all Android Applications that you create.  After you create the keystore, login to it and set the location where you want to create your APK file.

 

You can use Hightail, Dropbox, email, ect. to get the APK file on your device.

You now need to setup your Android Device.

By default, Android prevents you from installing APK files from unverified sources outside of the Play Store.  To install this file, you will need to bypass this check.  Go to the 'Settings' app, select the 'Security' option, then check the 'Unknown sources' option.

 

You will be prompted with a warning screen when you select the option.  Remember to uncheck this option when you are finished working with your application.

 

Now open the APK file on your Android device.

You should now have the application on your device.  Remember that the application is configured to access the web application on your PC, so it will only run while the web server is started.

Remember to reset the 'Unknown Sources' security option in Settings when you are finished.

Was this article helpful?
0 out of 0 found this helpful
Have more questions? Submit a request

Comments

Powered by Zendesk