Tuesday, July 23, 2024

Implementing Geolocation Maps in Oracle APEX

Geolocation Maps have become a crucial part in many applications built in Oracle APEX. Prior to release 21.1, developers had to rely on third-party geolocation map providers and had to obtain API keys and third-party plugins to integrate Geolocation Maps in Oracle Apex.

But since release 21.1, Oracle has introduced native Maps region in Apex. It eliminates the need to obtain third-party plugins, API keys and best of all - it's free.

Map component is based on Oracle Elocation Service. More details can be found at https://maps.oracle.com. 
Map region supports Vector map layers based on OpenStreetMap Position, OpenStreetMap Bright, and OpenStreetMap DarkMatter.

Let's see how to implement this functionality in our Apex App.

- Create a new App in Oracle Apex

- Create a new page

- Create a page item to store GeoLocation details




- Create a Region and set type to Map






- Set the SQL Query in source of Map region to 


SELECT :P4_GEOLOC GEOJSON_COL FROM DUAL

Set Page Items to Submit to P4_GEOLOC




- Now, let's see how we can obtain the current location of the user

- Navigate to Dynamic Actions

- Create a DA at Page Load level



- Set Action to 'Get Current Position'



- Set Return Type to GeoJSON
- Set Item to P4_LATLONG



This will enable our App to acquire device's current location and return Geolocation in GeoJSON format and store it in item P4_LATLONG


About GeoJSON:
GeoJSON is a geospatial data interchange format based on JavaScript Object Notation (JSON).  It defines several types of JSON objects and the manner in which they are combined to represent data about geographic features, their properties, and their spatial extents. Broadly it accommodates 7 different kinds of geometry objects: "Point", "LineSegment", "Polygon", "MultiPoint", "MultiLineString", "MultiPolygon", and "GeometryCollection".

In above example, it will return the data as shown in below example:

{
    "latitude":20.7195718,
    "longitude":-103.4363326,
    "altitude":null,
    "accuracy":16.452,
    "altitudeAccuracy":null,
    "heading":null,
    "speed":null
}


BUT the Map Region in Oracle Apex requires the data in below GeoLocation format:

{
"type": "point",
"coordinates": [
Longitude,
Latitude
]
}

- So we need to Transform the data returned by Get Current Position action into this format.

- Let's create another Dynamic Action named Transform with Action as Execute Server-side code and embed below PLSQL code in it. We will be using json_table function to transform the data in the desired format.

Set Items to submit as P4_LATLONG
Set Items to Return as P4_GEOLOC

P4_GEOLOC is the item we originally used in the Source of Map region



Code:

declare
   lv_geojson varchar2(4000);
begin
 
   with device_json as (
           select :P4_LATLONG json_res 
           from dual )
 
   select '{"type": "Point", "coordinates": ['||json_data.longitude||', '||json_data.latitude||']}' coordinates
       into lv_geojson 
       from device_json,
       json_table(json_res, '$[*]'
          columns (longitude varchar2(100) path '$.longitude',
                   latitude  varchar2(100) path '$.latitude')
       ) as json_data;
 
   :P4_GEOLOC := lv_geojson;
 
end;



- Let's add another Dynamic Action to refresh the map



- Let's run the App and see what we see.

- Here, we can see the Map region shows my current location and it shows I'm somewhere in Seattle area.




- Let's zoom into the map and we'll see my exact location which is near the famous Starbucks Pike Place Market location.




- In above examples, if you notice you will see it says OpenStreetMap in the footnote of the map.

This is because I've selected OpenStreetMap Bright as the Standard in Map Region Attributes




You can experiment using all these options and select the one that suits your use case the best.

Here's the output using Oracle World Map standard





Using Latitude/Longitude instead of GeoJSON:

We saw how we can obtain the geolocation data in GeoJSON format using Get Current Position action.

There's another type supposed by this action and that is Latitude and Longitude values. 
If we want to only obtain these two and do not require other values such as Altitude, Speed etc., then we can use this method. Let's take a look into that.

- Let's create two separate page items one to store Latitude and other for Longitude and make them hidden




- Now, let's navigate back to our Dynamic Action and let's change the Return Type to Latitude and Longitude






- Now, assign P4_LAT and P4_LONG page items as below.



This will return the Latitude and Longitude values of user's current location in these page items.

- Now, let's navigate to Map Region

- Set Source SQL Query as below. This will simply use the Latitude and Longitude values stored in hidden page items.

Note: We need to convert these to NUMBER format before using it in Map Region


SELECT TO_NUMBER(:P4_LAT) P_LAT 
      ,TO_NUMBER(:P4_LONG) P_LONG
FROM DUAL




- Set Page Items to Submit to P4_LAT,P4_LONG

- Navigate to Column Mapping section under Map Layer

- Set Geometry Column Data Type to Longitude/Latitude

- Set the page items corresponding values




- Now, let's assume the user is near Museum of the City of New York while accessing the App, the Map Region will precisely show his location as below -





Share: