Location: Using Location Information and Service
This tutorial demonstrates how you can retrieve and use location information, and track the route.
Warm-up
Become familiar with the Location API basics by learning about:
-
Initializing the Location Service
Fulfill the prerequisites, start the location service, and stop it when no longer needed.
-
Getting the Last Known Location
Retrieve the last known position of the device.
-
Getting Location Updates
Acquire the device's position (given as coordinates) and keep tracking whenever the position is updated.
-
Using Location Bounds
Create a location area and track its bounds.
-
Getting Satellite Information
Acquire information on satellites, which connect with the device to get location information.
Follow-up
Once we have learned the basics of the Location API, we can now move on to more advanced tasks, including:
-
Tracking the Route
Get information about the current position, velocity, and distance.
Initializing the Location Service
-
To use the location-related features of the Location Manager API (in mobile and wearable applications), include the <locations.h> header file in your application:
#include <locations.h>
-
Create a location manager handle using the location_manager_create() function before you use it. For this example, the GPS is used as the source of the position data, so the first argument is LOCATIONS_METHOD_GPS. You can use other values of the location_method_e enumeration, such as LOCATIONS_METHOD_HYBRID or LOCATIONS_METHOD_CPS, but they are less accurate.
location_manager_h manager; location_manager_create(LOCATIONS_METHOD_GPS, &manager);
Each location manager is an independent service. Multiple location managers can be created in the same application to provide different services, such as GPS and Bluetooth. Callbacks are set for a given location manager and are called depending on whether the service was started for its manager.
-
Start the location service using the location_manager_start() function. This call is asynchronous and only initiates the process of starting the service of the location manager. Once the manager is started, the registered callbacks are invoked when their corresponding events take place. To know when the service becomes enabled, use the location_manager_set_service_state_changed_cb() function.
location_manager_start(manager);
-
Using the location service is power consuming, so if the service is not used, you can stop updating the location using the location_manager_stop() function. Call the location_manager_start() function again if the update position information is needed.
location_manager_stop(manager);
-
At the end of the application, destroy all used resources, such as the location manager (location_manager_destroy()):
location_manager_destroy(manager); manager = NULL;
If you destroy the handle, there is no need to call the location_manager_stop() function to stop the service, the service is automatically stopped. Also, you do not have to unset previously set callbacks.
Getting the Last Known Location
To retrieve synchronously the last known location of the device:
-
Create the variable for location_manager_h with the method you want to apply for the application:
location_manager_h manager; int ret = location_manager_create(LOCATIONS_METHOD_GPS, &manager);
- Register a callback function for location service state changes and start the Location Manager:
ret = location_manager_set_service_state_changed_cb(manager, __state_changed_cb, NULL); ret = location_manager_start(manager);
The function __state_changed_cb is a callback function, which is called when the status of location service state changes.
static location_service_state_e service_state; static void __state_changed_cb(location_service_state_e state, void *user_data) { service_state = state; }
- After starting the Location Manager, call the location_manager_get_last_location() function to get the last location information including altitude, latitude, and direction:
double altitude, latitude, longitude, climb, direction, speed; double horizontal, vertical; location_accuracy_level_e level; time_t timestamp; ret = location_manager_get_last_location(manager, &altitude, &latitude, &longitude, &climb, &direction, &speed, &level, &horizontal, &vertical, ×tamp);
The function returns the last location stored in the system. When the current location is not fixed, the last location may not be the current location, but the old location.
Use this function instead of repeatedly requesting current locations to spare the Location Manager from running costly positioning systems.
- When getting the current location information, call the location_manager_get_location() function after the service is enabled:
static void __state_changed_cb(location_service_state_e state, void *user_data) { double altitude, latitude, longitude, climb, direction, speed; double horizontal, vertical; location_accuracy_level_e level; time_t timestamp; if (state == LOCATIONS_SERVICE_ENABLED) { ret = location_manager_get_location(manager, &altitude, &latitude, &longitude, &climb, &direction, &speed, &level, &horizontal, &vertical, ×tamp); } }
- When you no longer need the Location Manager, destroy it. You must also unset all connected callback functions and stop the Location Manager:
location_manager_unset_service_state_changed_cb(manager); location_manager_stop(manager); location_manager_destroy(manager);
Getting Location Updates
You can acquire the device's position (given as coordinates) and convert it to the corresponding address. You can get a notification of the position update periodically using the position update callback. The position update callback is invoked periodically, receiving the device's current position with every call.
-
Register the callback using the location_manager_set_position_updated_cb() function:
location_manager_set_position_updated_cb(manager, position_updated, 2, NULL);
The third parameter determines the frequency of callback calls. In this example, the callback is called every 2 seconds.
-
When the update is received, you can, for example, update the variables that store the current position:
static double user_latitude, user_longitude; static void position_updated(double latitude, double longitude, double altitude, time_t timestamp, void *user_data) { user_latitude = latitude; user_longitude = longitude; }
Note The callback is called only if the Location Manager has been started. The same holds for all other callbacks registered with the manager.
Using Location Bounds
You can define a virtual perimeter, which is tracked to see whether you enter or exit the area.
To use location bounds:
- Create location bounds with the required type (rectangle, circle, or polygon) needed for your application (each type has their own API sets):
int poly_size = 3; // Triangle shaped bounds location_coords_s coord_list[poly_size]; coord_list[0].latitude = 37; // Temporary value coord_list[0].longitude = 126; coord_list[1].latitude = 38; coord_list[1].longitude = 128; coord_list[2].latitude = 35; coord_list[2].longitude = 128; location_bounds_h bounds_poly; ret = location_bounds_create_polygon(coord_list, poly_size, &bounds_poly);
When a circular bound is needed, use the location_bounds_create_circle() function.
- Get the coordinates of the generated polygon bounds. Register a callback function to notify you of the polygon coordinates:
ret = location_bounds_foreach_polygon_coords(bounds_poly, capi_poly_coords_cb, NULL);
For the callback function (the second parameter in the function above) implement the function separately:
static double latitude, longitude; static bool capi_poly_coords_cb(location_coords_s coords, void *user_data) { latitude = coords.latitude; longitude = coords.longitude; return true; }
-
Register the callback using the location_bounds_set_state_changed_cb() function:
location_bounds_set_state_changed_cb(bounds_poly, bounds_state_changed_cb, NULL);
The bounds_state_changed_cb function is a callback, which is called when you enter or exit the defined region.
static location_boundary_state_e bound_state; static void bounds_state_changed_cb(location_boundary_state_e state, void *user_data) { bound_state = state; }
-
Call the location_manager_add_boundary() function to get the boundary information.
location_manager_add_boundary(manager, bounds_poly);
- After using the polygon bounds, destroy them:
location_bounds_destroy(bounds_poly);
Getting Satellite Information
You can acquire and update information of the satellite connected with the device. The information includes azimuth, elevation, PRN, SNR, and NMEA data. You can also get a notification of the satellite update periodically using the satellite update callback. The satellite update callback is invoked periodically, receiving the information of connected satellites with every call.
-
Register the callback using the location_manager_set_satellite_updated_cb() function:
gps_status_set_satellite_updated_cb(manager, capi_gps_status_satellite_updated_cb, 10, NULL);
The third parameter determines the frequency of callback calls. In this example, the callback is called every 10 seconds.
- When the update is received, the callback having brief satellite information is called. To get the detailed satellite information in the sky, call the gps_status_foreach_satellites_in_view() function in the callback. Variables that store current satellite information are updated:
int cur_azimuth, cur_elevation, cur_prn, cur_snr; static bool capi_gps_status_get_satellites_cb(unsigned int azimuth, unsigned int elevation, unsigned int prn, int snr, bool is_in_use, void *user_data) { cur_azimuth = azimuth; cur_elevation = elevation; cur_prn = prn; cur_snr = snr; return true; } static int numofactive, numofinview; static void capi_gps_status_satellite_updated_cb(int num_of_active, int num_of_inview, time_t timestamp, void *user_data) { numofinview = num_of_active; if (num_of_inview > 0) { gps_status_foreach_satellites_in_view(manager, capi_gps_status_get_satellites_cb, NULL); } }
Note Note that the callback is called only if the location manager has been started. The same holds for all other callbacks registered with the manager.
Tracking the Route
To get information about the current position, velocity, and distance.
- Receive periodic notifications.
-
You can get notifications of the position and velocity updates using the position and velocity update callbacks. The callbacks are invoked periodically, receiving the device's current position or velocity with every call.
-
Register the position update callback using the location_manager_set_position_updated_cb() function:
location_manager_set_position_updated_cb(manager, position_updated, 2, NULL);
-
Register the velocity update callback using the location_manager_set_velocity_updated_cb() function:
location_manager_set_position_updated_cb(manager, velocity_updated, 2, NULL);
The third parameter determines the frequency of the callback calls. In this example, the callback is called every 2 seconds.
-
-
Define the position and velocity callback functions:
void position_updated(double latitude, double longitude, double altitude, time_t timestamp, void *user_data); void velocity_updated(double speed, double direction, double climb, time_t timestamp, void *user_data);
Within the function, you can collect obtained data to get the points you have visited, to calculate traveled distance more precisely, or to calculate the average speed or climb.
-
- Receive the current information.
You can get the current information about position, velocity, or localization accuracy:
- To get information about the current position (altitude, latitude, and longitude), use the location_manager_get_position() function:
time_t timestamp; double altitude; double latitude; double longitude; location_manager_get_position(manager, &altitude, &latitude, &longitude, ×tamp);
-
To get information about the current velocity (climb in km/h, direction as degrees from the north and speed in km/h), use the location_manager_get_velocity() function:
double climb; double direction; double speed; location_manager_get_velocity(manager, &climb, &direction, &speed, ×tamp);
-
To get information about the current accuracy (level – see the location_accuracy_level_e enumeration in mobile and wearable applications, and horizontal and vertical accuracy), use the location_manager_get_accuracy() function:
location_accuracy_level_e level; double horizontal; double vertical; location_manager_get_accuracy(manager, &level, &horizontal, &vertical);
-
Use the location_manager_get_location() function to get all of the above 10 values at once:
location_manager_get_location(manager, &altitude, &latitude, &longitude, &climb, &direction, &speed, &level, &horizontal, &vertical, ×tamp);
-
If the location service is currently unavailable, get the last values recorded by the location manager when the GPS signal was available. To get the information, use the following functions:
- location_manager_get_last_position()
- location_manager_get_last_velocity()
- location_manager_get_last_accuracy()
- location_manager_get_last_location()
The syntax of these functions corresponds to the functions presented above.
- To get information about the current position (altitude, latitude, and longitude), use the location_manager_get_position() function:
- Get the distance.
To get a distance (in meters) between 2 points, use the location_manager_get_distance() function. The obtained value is a great-circle distance; the shortest distance between 2 points on the sphere.
Provide the latitude and longitude of the starting point, the latitude and longitude of the end point, and the variable to store obtained distance:
double distance; location_manager_get_distance(37.28, 127.01, 52.23, 21.01, &distance);
To get more precise traveled distance, sum distances between each 2 consecutive points, delivered by the periodic position update callback.