Hexagon Geospatial
MENU

M.App Enterprise Tutorials

Not sure on how to get started or looking for a workflow to get M.App Enterprise up and running. Tutorials provide step by instruction on some of the most common configurations and workflows to get M.App Enterprise configured up and running quickly.
Showing results for 
Search instead for 
Do you mean 

How to setup a Mobile App - Part 2

by sturcato on ‎11-05-2018 08:09 AM - edited on ‎04-16-2019 09:03 AM by sclow (2,324 Views)

In this tutorial we are going to extend the first article published here. We will start from the same data and shell and we will extend the configuration step by step.

 

The present article is divided in incremental labs. The material attached to this post is organized in the following way:

  1. Main folder is the current configuration of your shell. The workflow to update the shell configuration is:
    1. You will be working on the xaml files in this folder
    2. you create a zip file containing the modified xaml files 
    3. you upload the zip into the existing shell configuration in StudioCapture.PNG
  2. You have a subfolder for each Lab. In this folder you have:
    • the xaml files containing the result of the Lab (what is described in the Lab's paragraph below)
    • eventually a templates folder if you have to copy an existing configuration (it is described in the Lab's paragraph) 
    • eventually a script to update the data model (if described in the Lab's paragraph)

In the description below we assume you are working with a Postgresql database. You will find anyway the same scripts for Oracle or SqlServer databases.

 

 

Lab 1: Adding a Map

 

The goal of this first lab is to add a Map in your mobile App configuration. The Map will contain just the native Map available on your mobile device.

 

1.      Copy NativeMap.xaml from templates folder

2.      Shell.xaml ->  Add to MasterDetail.Views:

<Navigation Id="MapNavigation">

<NativeMap Id="NativeMap" Title="Map" Center="40.6239644;-74.00624" View="NativeMap" ZoomLevel="14" MapType="Roads"/>

</Navigation>

3.      Menu.xaml ->

a.      Add to Menu:

<MenuItem Target="MapNavigation" Title="Map" Icon="Map" Type="Toolbar"/>

b.      Add to Logout item

Type="Toolbar"

4.      Test App (logout and login again)

 

Lab 2a: Adding spatial information to Locations

 

The goal of this lab is to add a geometry field to our Locations table and to be able to capture this geometry within the mobile App.

 

1.      PostgreSql2.sql -> add geometry field

2.      Shell.xaml -> Add to Entity Id="Locations":

<Field Name="geometry" Type="Geometry" />

3.      NativeMap.xaml -> add to NativeMap.Layers:

<MarkerVectorLayer Entity="Locations" Icon="Map.Pin.png" ZIndex="3" MinimumZoomLevel="13" MaximumZoomLevel="22">

</MarkerVectorLayer>

4.      LocationForm.xaml -> add to Form:

<Geometry Name="geometry" Title="Geometry"> 

<GeometryFieldAction Target="NativeMap" Capture="True">

            <Parameter Name="ZoomLevel" Value="19" />

        </GeometryFieldAction>

</Geometry>

5.      Test App

 

Lab 2b: Adding tools to the Map

 

In this lab we are adding some new tools to interact with the map and get info about the selected object on the map (FeatureInfo with included details and actions to edit the object and to navigate to the object using the native mobile navigator App).

 

1.      NativeMap.xaml ->

a.      Add to NativeMap.ShellActions:

    <NavigateSelectionAction Type="Secondary" />

    <ToggleLayerAction Type="Secondary" />

    <CaptureDistanceAction Type="Secondary" />

    <CurrentLocationAction Type="Secondary" />

    <AutoCenterMapAction Type="Secondary" />

a.      Add to MarkerVectorLayer:

         <FeatureInfo Title="Name: @{name}" Detail="Comments: @{description}">

             <NavigateShellAction Icon="Edit" Target="LocationForm">

                 <Parameter Name="Id" Value="@{id}" />

             </NavigateShellAction>

             <NavigateSelectionAction />

         </FeatureInfo>

2.      Test App

 

Lab 3: Adding a 1:N relationship to store pictures

 

The goal of this lab is to learn how to create a one to many relationship to store, in this particular case, several pictures related to the currently selected location. 

The idea to implement such a relationship is to create an additional table (entity in our Shell) and to store for each new row the primary key of the current Location. To implement this behavior we will have the following configuration:

  1. in our LocationForm.xaml
    1. a table widget  to show the pictures already captured for the current Location
    2. a NavigateFieldAction to get the user redirected to a new form called LocationImageForm and passing the id of the Location as parameter to be stored in the entity_id of the Image
  2. a new LocationImageForm.xaml with
    1. a table widget like in the LocationForm
    2. other widgets to capture additional details about the new picture

 

1.      PostgreSql3.sql -> add image table

2.      Shell.xaml ->

a.      add to Entities:

<Entity Id="Image" Table="images" Key="id" SyncType="Automatic" RevisionField="lastupdatetime">

<Field Name="id" Type="Guid" IsRequired="True"/>

<Field Name="imagetype" Type="String"/>

<Field Name="entity_id" Type="Guid" ForeignEntity="Locations"/>

<Field Name="description" Type="String"/>               

<Field Name="image" Type="Binary" LazyLoading="True"/>

<Field Name="image_thumb" Type="Binary" LazyLoading="False"/>       

<Field Name="image_size" Type="Number"/>

<Field Name="image_mimetype" Type="String"/>                

<Field Name="lastupdatetime" Type="Timestamp"/>

</Entity>

b.      Add to MasterDetail.Views:

<Navigation Id="LocationImageNavigation">

<Form Id="LocationImageForm" Title="Images" View="LocationImageForm" Entity="{x:Reference Image}"/>

</Navigation>

3.      LocationForm.xaml -> add to Form:

<Table Name="Images" Title="Images" Entity="Image" Target="LocationImageForm" RowCount="5" LazyLoading="False">

     <Table.RowActions>

            <DownloadImageRowAction Field="image"/>

</Table.RowActions>

     <Table.Actions>

            <NavigateFieldAction Icon="Camera" Target="LocationImageForm">

                <Parameter Name="Field.Value.entity_id" Value="@{id}" />

            </NavigateFieldAction>

     </Table.Actions>

     <TableCell Name="imagetype" Title="Type"/>

     <TableCell Name="description" Title="Comment"/>

     <TableCell Name="lastupdatetime" Title="Created"/>              

</Table>

4.      Copy LocationImageForm.xaml from templates folder

5.      Test App

 

Lab 4: Adding values based on a picklist table

 

Goal of this lab is to add a new entity and use the whole table in a picker of the LocationForm using the key/value pairs (id/type fields in the newly created table loc_type).

 

1.      PostgreSql4.sql -> add table loc_type (picklist) and field type to locations

2.      Shell.xaml ->

a.      add Entity Id="LocationType":

<Entity Id="LocationType" Key="id" SyncType="Automatic" Table="loc_type">

<Field IsRequired="True" Name="id" Type="Guid" />

<Field Name="type" Type="String"/>

</Entity>

b.      Add to Entity Id="Locations":

<Field Name="type" Type="String" />

3.      LocationForm.xaml -> add to Form:

<Picker Name="type" Title="Location Type" KeyMember="id" DisplayMember="type" Items="{Entity LocationType}"/>

4.      Test App (you must wipe local data while connecting because data model has changed)

 

Lab 5a: Adding scripts to the form

 

In this lab we start adding custom actions in our form using scripts.  JavaScript functions can be executed based on several events in App lifecycle:

  • Form
    StartupScript
  • Field
    ChangeScript
  • Action
    BeforeScript
    AfterScript
  • List
    SelectionScript

The Javascript API is documented here.

 

We are going to add a function OnFormStartup to check the current status in the form and eventually set it to a new value (Open) and a custom action placed by the status entry to manually set it (for asking for approval).

 

1.      PostgreSql5.sql -> add field status to locations

2.      Shell.xaml -> add to Entity Id="Locations":

<Field Name="status" Type="String" />

3.      LocationForm.xaml ->

a.      Add to Form:

<Entry Name="status" Title="Status" IsEnabled="false"/>

b.      Add to Form:

    <Form.Scripts>

        <StartupScript Name="OnFormStartup">

            if (!Context.getValue('status')) {

                Context.setValue('status','Open');

            }

        </StartupScript>        

    </Form.Scripts>

c.      Update Entry Name="status" to (change status for requesting approval):

    <Entry Name="status" Title="Status" IsEnabled="false">

        <ScriptFieldAction Icon="Click">

            Context.setValue('status','Awaiting Approval');

        </ScriptFieldAction >           

    </Entry>

 

Lab 5b: Displaying locations in different lists based on the status

 

In this lab we are going to add a new Navigation to display the list of Locations based on the specific status (Open/Awaiting Approval). This will be handled by a Filter set in the Entity and then referenced in the two LocationNavigation and LocationToApproveNavigation.

 

1.      Shell.xaml ->

a.      add Entity.Filters to  Entity Id="Locations" to handle sql query:

<Entity.Filters>

<Filter Id="LocationsOpen" Sql="status = 'Open'" IsDefault="False" />

<Filter Id="LocationsToApprove" Sql="status = 'Awaiting Approval'" IsDefault="False" />

</Entity.Filters>   

b.      Add Navigation to handle a different list:

<Navigation Id="LocationToApproveNavigation">

<List Id="LocationToApproveList" Title="Locations To Approve" View="LocationList" Entity="{x:Reference Locations}">

</List>

</Navigation>

c.      Add List.Filters to both Navigation elements:

                                i.     Navigation id="LocationNavigation":

<List.Filters>

<FilterRef Filter="{x:Reference LocationsOpen}" Title="Locations" IsDefault="True"/>

</List.Filters>

                               ii.          Navigation id="LocationToApproveNavigation":

<List.Filters>

<FilterRef Filter="{x:Reference LocationsToApprove}" Title="Locations To Approve" IsDefault="True"/>

</List.Filters> 

 

  1. Menu.xaml ->

a.      Add Menuitem to show the new Navigation:

<MenuItem Target="LocationToApproveNavigation" Title="Locations To Approve" Icon="Work" />

 

Lab 6: Customizing via Javascript

 

In this lab we are adding 2 more custom actions.

The first one is used to fix an improper behavior while we capture pictures: if the Location has NOT been saved already and we try to capture a new Image, the newly created image will be saved without any id set in entity_id. With this custom script we are checking if the the Location has been saved (there is an id set in the form) and in case it is not we cancel the action itself.

The second action is used to customize the default behavior of the DeleteShellAction: we prompt the user if he really wants to delete the current Location, in this case we delete it, otherwise we cancel the action.

 

1.      LocationForm.xaml ->

a.      Disable camera action if location has not been saved yet

Add to <NavigateFieldAction Icon="Camera" Target="LocationImageForm">:

<NavigateFieldAction.BeforeScript>

var id = Context.getValue('id');

if (!id) {

Context.message('Location must be saved before start capturing pictures');

Context.cancel();

}

</NavigateFieldAction.BeforeScript>

b.      Ask the user for confirmation before deleting a Location

Change DeleteShellAction this way:

<DeleteShellAction.BeforeScript>

Context.alert('Would you really like to delete?', 'Yes', 'No', function (result) {

if (!result)

Context.cancel();

else

Context.done();

});

</DeleteShellAction.BeforeScript>

Comments
by
on ‎11-14-2018 07:13 AM
Dear Sturcato, Thank you for this tutorial!!!! I'm working myzelf through the different Labs. I found an issue with Lab3. I uploaded the lab3.zip to M.App Enterprise that I created from your step-by-step tutorial. I can start the Mobile App of M.App Enterprise and select the "mobile / lab3" application. The apps works fine until I push the orange camera button. Then the Mobile App "crashed / exitst". I'm not able to take a photo. I have tested this with an Iphone 5se with IOS 10.3.1 and on an Iphone 5s with IOS 10.2.1. Is the Mobile M.App Enterprise App not working properly on my phones or are the xaml script incorrect or is there an eror in the sql script? Can you help me? Thank you, Wim
by sturcato
on ‎11-16-2018 08:00 AM

hi Wim,

 

have you tried to capture a picture before saving the location (there is an improvement of the workflow at lab6 to prevent the image capturing if the location is not saved beforehands)? Also have you tried to delete local cache before loading the app? Since we are modifying data structure it may be you have an inconsistent data model on the client side.

 

We have tested this configuration on all of the platoforms with no issues. Have you downloaded the app from the Apple store?

 

Stefano

by
‎11-20-2018 05:24 AM - edited ‎11-20-2018 05:25 AM

Hey Stefano,

 

It almost embarresing to say, but I made a mistake and did not add one script to the zip file. It is now working properly Smiley Happy

 

Now I have an additional question. I have noticed that the scripts is using the map differently:

  • From the Form I can add a location, but not use my current (GPS) location.
  • From the Map I can use my current location, and after confiming my position, fill-out the rest of the form.

Now I like to change the application so that from the form if I add a location, I can use my current (GPS) location.

 

Best Regards, Wim

by sturcato
on ‎11-21-2018 08:07 AM

Hi Wim,

 

there is a setGpsPosition method provided by the API, please check the mobile doc here:

 

https://community.hexagongeospatial.com/t5/M-App-Enterprise-Tutorials/M-App-Enterprise-Mobile-Docume...

 

HTH,

Stefano

by
on ‎11-22-2018 01:32 AM

Hey Stefano,

 

Thank you for the link, but I still don't get it:

  1. If I go from the menu to the map, "NativeMap.xaml" is loaded, with the option to select your GPS location 
    <CurrentLocationAction Type="Secondary"/>
  2. If I edit an entry in the form "LocationForm.xaml" and edit the location, "NativeMap.xaml" is loaded, with the option o select your GPS location
    <CurrentLocationAction Type="Secondary"/>
  3. If I create a new entry in the form "LocationForm.xaml" and edit the location, "NativeMap.xaml" is loaded, but there is no option to select your GPS location. However it's the same "NativeMap.xaml" is loaded with 
    <CurrentLocationAction Type="Secondary"/>

 

What do I need to do, to get that option, if I create a new entry?

 

Thanks, Wim

Overview
Contributors