We have been developing a web application for a travel agency. To do so, we created transaction objects, applied the Fiori pattern that creates objects as web panels, procedures, etc., and we would continue to work in this way, developing objects until completing the web development.
In our case, we have prototyped in a local server that accessed a Hana database through Hana Cloud Platform.
However, when we deploy our application, the programs built by GeneXus in Java will be saved in a server that can be accessed from the web.
Therefore, the end user, with a browser and the URL of some of the app's pages will be able to run the corresponding object (built by GeneXus in Java). If necessary, it will make requests to the database and return the data to the browser to have it build the page with the retrieved data and display it to the user on the device screen.
How do we obtain an application similar to the web application but native for Android and/or iOS devices?
We will do so by developing some specific GeneXus objects for Smart Devices that will be compiled from a main object. GeneXus will compile that main object in Java for Android if the application will be built for that platform, and in Swift for iOS if necessary. In addition, for these native apps to be able to access the data stored in the centralized database, one part of the web app (Java) is exposed as Rest services.
Therefore, when the Android or iOS app needs data from the database, it will have to consume the corresponding Rest services. The developer doesn't need to worry about this because it is hidden inside the logic of the GeneXus objects for Smart Devices.
We will see it with an example.
To review what we have done: in the web application we have the app home object –the Launchpad, which is a sort of menu:
From this object we invoke various lists (the Fiori List Report of countries and attractions). We had also explicitly added the invocation to a transaction called Customer. Here we leave it aside.
We want something similar but for Smart Devices. To do so, first, we will apply the equivalent pattern to the Fiori List Report to the transactions we're interested in.
We open the Patterns section of the Country transaction, Work With for Smart Devices pattern. There are great differences with the same pattern for the web. The Fiori List Report showed a tree with nodes to state what GeneXus should implement later through these objects:
At runtime, these objects were displayed as two screens. That of the List itself:
And that with information of the selected country:
This screen has a “General” tab and, since each country has associated attractions, another “Attraction” tab with these attractions displayed in a grid:
If we collapse the tree adequately, we can see where each one of these screens is configured:
Here is that of the List and here is that of detailed information about a country, with their two tabs.
If now we open the equivalent pattern for Smart Devices:
We see more clearly the two screens that will be generated: one for the countries List and another one with detailed information of a country, with their two tabs displayed as “sections”.
The great difference is that here these nodes will correspond directly to the objects generated and will not be “declared” by the developer to have them later implemented by GeneXus. Instead, they will be implemented directly. So, if we click on the List node:
Here is its Layout which has been initialized and has a grid that will show the value of the CountryName attribute of each country to be loaded from the database.
In addition, we see that sections such as Rules, Events, etc. are enabled to define rules, events and other aspects of this object. That is to say, the sections that allow for its implementation are displayed.
In addition, if we open the Detail:
We see that the screen object only contains a control called <All Sections Content>. All the sections contained in this Detail will be loaded in this control. Here, they are two: one that shows the country's general information:
Here we see the attributes CountryId and CountryName.
And the other one that shows the country's attractions in a grid:
The attributes AttractionPhoto and AttractionName have been placed here.
It will be clearer when we run it.
Let's select the check box to apply this pattern; before saving, let's take a look at the generators (of programs) that we have defined. So far, only one: for Web Java.
Now, we save.
The Smart Device generator has been automatically added.
By default, it will generate for Android and iOS, but Android will be the main platform:
Note that below the Country node, the object WorkWithDevicesCountry is now displayed:
Unlike the web example, in which FioriListReportCountry was only a declaration file and the objects that effectively implement the pattern features were built separately (they are listed below), in this case it is a GeneXus object that will contain sub-objects that can be invoked independently using the corresponding syntax.
Let's also apply the pattern to the Attraction transaction and to Category.
How can we test this quickly? One option is to use a device connected to the computer in which GeneXus is running. Another option is to use the emulators provided by the platforms. For simplicity purposes, we will use this option (To see all the prototyping options, we recommend viewing the course “GeneXus for Smart Devices”. Testing on an actual device will always be better because the emulators don't have all their features available).
We're missing a menu —in the web environment we had the Launchpad— to invoke the Lists we're interested in. This menu is not automatically created by GeneXus. We need to create it ourselves.
File/New/Object, filter by the objects for Smart Devices, and select the Dashboard, which is an object to implement menus. We call it TravelAgency:
This will be the main object of the application for Smart Devices. It will be the object compiled by GeneXus for Android and/or iOS and that the end user will install on his/her device, once the development work has been completed.
Let's enter the items we want to include in the menu:
The first one will correspond to the action of invoking the List of countries:
A window is opened to select the object we want to invoke when the user selects this menu item. We filter by object type Work With for Smart Devices:
We select WorkWithDevicesCountry.
We now see this action, which by default receives the same name as the object invoked. This action —we double-click— will be associated with an event that programs the invocation:
There, the List of the WorkWithDevicesCountry object is being invoked (not the Detail).
Let's open the action's properties and change the item Description, which will be displayed in the menu at runtime:
We will also choose an image for this option, bearing in mind that Smart Device apps tend to be much more iconographic than web apps due to the reduced screen size:
We must import the image into the knowledge base from an external file. We select it here.
Now, let's add an item to invoke the attractions List.
Likewise, we change its properties, and save. The object is set as main:
Before running it, we replace the Android property, “Base Style”, with this one… so that the screen background is white with a dark “Action Bar”:
To run it, we only right-click on its tab and select Run:
If you have an emulator such as Genymotion open, the compiled file will be automatically installed there and will be run.
Otherwise, the default emulator of Android's SDK will be opened and the same will happen. We suggest using this option to avoid installing new software.
In this case we had Genymotion open, so here we see the dashboard running with the two items defined with their images and descriptions:
Tapping on “Countries” displays the List of countries, which shows each country name in a grid:
As it was implemented:
If we tap on a country:
we see the detail with two tabs: the general information in a tab (which is implemented here):
and the country's attractions in the other tab:
We see the attractions' photo and name, as implemented here:
Note that from the General tab we can change or delete the country's information:
We change the name...
The object that updated the database was one of the Rest services mentioned at the beginning.
If we run the web application again:
and refresh the page:
Here it is!
Likewise, if from here we change the name of France again... and return to the Android device:
We see it has been updated.
The country's update and delete buttons are displayed here in the WorkWith, in the application bar area:
But, while in the web pattern the transaction was invoked when trying to update or delete:
(For example, here it is invoked in UPDATE mode:
and what we're viewing is the transaction form)
…in native mobile applications the same Detail is opened but with another screen: the edit screen:
It looks exactly the same when initialized, except for the Save and Cancel buttons in the Application bar:
When the user clicks on the Save button, the device app will invoke, sending the data from this screen, the Rest service in the web server containing the transaction logic, and therefore will update the information on the database. All this is done in a transparent manner for the developer, who will not have to worry about these low-level details.
Just like for the web pattern, if we return to the List, we see that it is possible to add a new country:
Here, the same screen is invoked for the Detail and for the Update.
We add Mexico:
This is what the pattern generates by default. It can be customized, though.
If we open the Attractions List:
The attraction's image and name are displayed in the grid. We may also want to add the attraction's category.
To do so, we open the toolbox, drag the Attribute/Variable control, and select the CategoryName attribute:
We change the tag:
We could delete it with Label position None.
We select Run over the main object.
Note that by default we're offered the option to make searches by attraction name:
This is configured in the grid's properties, here:
We could add CountryName, for example, to allow making searches by country name as well.
So, if we search “Fr”… France's attractions are displayed.
We also have advanced filters... by the attributes CountryId and CategoryId, which are the foreign keys of the Attraction transaction. Let's change the description to Country and Category, respectively, and run the main menu again…
We open the attractions List and see that this option is available in the application bar:
It offers the two advanced filters we've just seen:
If we want to filter the attractions by country, for example, it opens the Work With countries component for us to select one:
Next, we click on Search:
The same will happen with the category filter.
We can add filters or delete them.
If we look at the list, it is ordered by AttractionName. This is specified in the properties of the grid's Data group:
We may want to allow the user to order by country:
Choosing the same option used for filtering:
We can order by Country:
We see the Great Wall of China and the two attractions entered for France.
We may want this option to show the information grouped by country, and for each country ordered by attraction name. To do so, we change this order... adding the AttractionName attribute… and indicating that the data will be cut by… CountryName:
Let's see it at runtime.
Now, let's see another interesting customization. For example, show the list of attractions not as a standard list but as geographic locations on a map.
To do so, we add an attribute to the transaction that records the geolocation of each attraction:
It automatically takes the Geolocation domain, which is semantic in the sense that the application will know that it is a longitude, latitude pair.
We press F5… GeneXus will prompt us to reorganize the database to add the new attribute to the Attraction transaction.
We use the web app to add the geolocations of the three attractions.
Eiffel Tower: 48.858356, 2.294492
Great Wall: 40.431884, 116.570396
Louvre Museum: 48.860604, 2.337623
Note that clicking on the field opens Google Maps with this geolocation shown with a pin.
Here we see in practice what it means when a domain is semantic.
We want the Work With attractions in the device to be a list showing its elements as points on the map.
To do so, we open the pattern List... and edit the Grid's properties. Under the Control Info group:
We change the default value of the Control Type property by selecting “SD Maps”:
After that, these properties are enabled.
We need to indicate the transaction attribute that contains the location. We specify it:
Before running it: for an Android application to allow using the maps API, we need to request a Google key that matches our app signature. The Key can be obtained rather easily from Google by registering the app we're developing.
To learn how to do it by obtaining the API key, visit our wiki. HowTo: Get an API Key from Google (http://wiki.genexus.com/commwiki/servlet/wiki?19055,HowTo%3A+Get+an+API+Key+from+Google).
There you will find simple steps to do it.
In the Smart Device generator properties below the Android group we enter this key: AIzaSyAU9YHNv6xOc4u8TPvMs_0JizxYO9sfldA
Google maps are not configured in the emulators, so we will use the device connected via USB to the computer:
We can try the same application for iOS by only changing these properties.
This was just a small example of what we can do. Just like for a web application, there are more objects available to cover other features, such as Panels for Smart Devices.