The Maps sample application demonstrates how to use map services, such as geocoding, place search, routing, maps view, maps view object, and maps view event using the Maps Service API.

The following figure illustrates the main views of the Maps application.

Figure: Maps screens

## Prerequisites

To ensure proper application execution, the following privileges must be set:

- `http://tizen.org/privilege/mapservice`
- `http://tizen.org/privilege/internet`
- `http://tizen.org/privilege/network.get`

## Implementation

### Application View

1. Create the application layout with the `view_create()` function:

       Eina_Bool
       view_create(void *user_data)
       {
           appdata_s *ad = (appdata_s *)user_data;

           elm_config_accel_preference_set("opengl");

           /* Create the window */
           s_info.win = view_create_win(PACKAGE);
           if (s_info.win == NULL) {
               dlog_print(DLOG_ERROR, LOG_TAG, "failed to create a window.");

               return EINA_FALSE;
           }

           ad->win = s_info.win;

           /* Create the conformant */
           s_info.conform = view_create_conformant_without_indicator(s_info.win);
           if (s_info.conform == NULL) {
               dlog_print(DLOG_ERROR, LOG_TAG, "failed to create a conformant");

               return EINA_FALSE;
           }

           /* Create the naviframe */
           ad->nf = view_create_naviframe(s_info.conform);
           if (ad->nf == NULL) {
               dlog_print(DLOG_ERROR, LOG_TAG, "failed to create a naviframe");
               return EINA_FALSE;
           }

           /* Show the window after the main view is set up */
           evas_object_show(s_info.win);

           return EINA_TRUE;
       }

2. Create a toolbar with the `view_create_toolbar()` function:

       Evas_Object*
       view_create_toolbar(appdata_s *ad)
       {
           /* Create and initialize the toolbar */
           ad->toolbar = elm_toolbar_add(ad->nf);
           elm_object_style_set(ad->toolbar, "tabbar");
           elm_toolbar_shrink_mode_set(ad->toolbar, ELM_TOOLBAR_SHRINK_EXPAND);
           elm_toolbar_transverse_expanded_set(ad->toolbar, EINA_TRUE);
           elm_toolbar_select_mode_set(ad->toolbar, ELM_OBJECT_SELECT_MODE_DEFAULT);

           elm_toolbar_item_selected_set(elm_toolbar_item_append(ad->toolbar, NULL, "Map", create_main_view, ad), EINA_TRUE);
           elm_toolbar_item_append(ad->toolbar, NULL, "POI", create_search_view, ad);
           elm_toolbar_item_append(ad->toolbar, NULL, "Route", create_route_view, ad);

           elm_object_item_part_content_set(ad->nf_it, "tabbar", ad->toolbar);

           return ad->toolbar;
       }

3. Define the main view:

   1. Create the main view with the `create_main_view()` function:

          void
          create_main_view(void *data, Evas_Object *obj, void *event_info)
          {
              dlog_print(DLOG_DEBUG, LOG_TAG, "create_main_view: Enter");
              appdata_s *ad = (appdata_s *)data;

              if (ad->prev_view == MAIN_VIEW)
                  return;

              init_view(ad);
              ad->prev_view = MAIN_VIEW;

              char edj_path[PATH_MAX] = {0,};
              app_get_resource(MAIN_VIEW_EDJ_FILE, edj_path, (int)PATH_MAX);

              ad->main_view_layout = elm_layout_add(ad->nf);
              elm_layout_file_set(ad->main_view_layout, edj_path, "map-view");
              evas_object_size_hint_weight_set(ad->main_view_layout, EVAS_HINT_EXPAND, EVAS_HINT_EXPAND);
              evas_object_size_hint_align_set(ad->main_view_layout, EVAS_HINT_FILL, EVAS_HINT_FILL);
              evas_object_show(ad->main_view_layout);

              __create_genlist_layout(ad);

              if (ad->main_map_layout == NULL)
                  ad->main_map_layout = __create_map_layout(ad);
              elm_object_part_content_set(ad->main_view_layout, "map", ad->main_map_layout);
              maps_view_unset_event_cb(ad->map_view_handle, MAPS_VIEW_EVENT_GESTURE);
              maps_view_unset_event_cb(ad->map_view_handle, MAPS_VIEW_EVENT_OBJECT);
              maps_view_set_event_cb(ad->map_view_handle, MAPS_VIEW_EVENT_GESTURE, main_view_event_gesture_cb, ad);

              elm_object_item_content_set(ad->nf_it, ad->main_view_layout);

              /* Create and initialize the more button */
              Evas_Object *more_btn = elm_button_add(ad->nf);
              elm_object_style_set(more_btn, "naviframe/more/default");
              elm_object_focus_allow_set(more_btn, EINA_FALSE);
              evas_object_smart_callback_add(more_btn, "clicked", create_ctxpopup_cb, ad);
              elm_object_item_part_content_set(ad->nf_it, "toolbar_more_btn", more_btn);
          }

   2. Create the input field for the geocoding and reverse geocoding with the `__create_genlist_layout()` function:

          static void
          __create_genlist_layout(appdata_s *ad)
          {
              /* Create and initialize the genlist */
              Evas_Object *genlist = elm_genlist_add(ad->main_view_layout);
              evas_object_size_hint_weight_set(genlist, EVAS_HINT_EXPAND, EVAS_HINT_EXPAND);
              evas_object_size_hint_align_set(genlist, EVAS_HINT_FILL, EVAS_HINT_FILL);
              elm_genlist_mode_set(genlist, ELM_LIST_COMPRESS);
              evas_object_show(genlist);

              evas_object_data_set(genlist, "app_data", ad);

              Elm_Genlist_Item_Class *search_itc = elm_genlist_item_class_new();
              search_itc->item_style = "full";
              search_itc->func.text_get = NULL;
              search_itc->func.content_get = __search_gl_content_cb;
              search_itc->func.del = NULL;

              /* Append an item to the genlist */
              elm_genlist_item_append(genlist, search_itc, NULL, NULL, ELM_GENLIST_ITEM_NONE, NULL, NULL);

              elm_genlist_item_class_free(search_itc);

              elm_genlist_realized_items_update(genlist);
              elm_object_part_content_set(ad->main_view_layout, "searchbar", genlist);
          }

          static Evas_Object*
          __search_gl_content_cb(void *data, Evas_Object *obj, const char *part)
          {
              appdata_s *ad = evas_object_data_get(obj, "app_data");

              if (!strcmp(part, "elm.swallow.content")) {
                  Evas_Object *editfield = create_editfield(obj);
                  eext_entry_selection_back_event_allow_set(editfield, EINA_TRUE);

                  ad->main_entry = elm_object_part_content_get(editfield, "elm.swallow.content");
                  evas_object_size_hint_weight_set(ad->main_entry, EVAS_HINT_EXPAND, EVAS_HINT_EXPAND);
                  evas_object_size_hint_align_set(ad->main_entry, EVAS_HINT_FILL, EVAS_HINT_FILL);
                  elm_object_part_text_set(ad->main_entry, "elm.guide", "Search place");

                  evas_object_smart_callback_add(ad->main_entry, "activated", __search_pressed_cb, ad);

                  return editfield;
              }

              return NULL;
          }

   3. Create the map layout for the maps view and maps view object with the `__create_map_layout()` function:

          static Evas_Object*
          __create_map_layout(appdata_s *ad)
          {
              char edj_path[PATH_MAX] = {0,};

              /* Create and initialize the map layout */
              Evas_Object *map_layout = elm_layout_add(ad->nf);
              app_get_resource(MAIN_VIEW_EDJ_FILE, edj_path, (int)PATH_MAX);
              elm_layout_file_set(map_layout, edj_path, "map_object");

              evas_object_size_hint_weight_set(map_layout, EVAS_HINT_EXPAND, EVAS_HINT_EXPAND);
              evas_object_size_hint_align_set(map_layout, EVAS_HINT_FILL, EVAS_HINT_FILL);
              evas_object_show(map_layout);

              /* Create and initialize the maps view object */
              Evas_Object *map_image_layout = elm_layout_add(map_layout);
              elm_layout_content_set(map_layout, "content", map_image_layout);

              /* Create the maps view handle */
              int error = maps_view_create(ad->maps_service_handle, map_image_layout, &(ad->map_view_handle));
              if (error == MAPS_ERROR_NONE) {
                  /* Set the zoom level */
                  maps_view_set_zoom_level(ad->map_view_handle, 15);

                  /* Create the coordinates and set them to the center */
                  maps_coordinates_h maps_coord;
                  maps_coordinates_create(DEFAULT_LAT, DEFAULT_LON, &maps_coord);
                  maps_view_set_center(ad->map_view_handle, maps_coord);
                  maps_coordinates_destroy(maps_coord);
              }

              return map_layout;
          }

4. Define the POI (point of interest) view:

   1. Create the POI view with the `create_search_view()` function:

          void
          create_search_view(void *data, Evas_Object *obj, void *event_info)
          {
              dlog_print(DLOG_DEBUG, LOG_TAG, "create_search_view: Enter");
              appdata_s *ad = (appdata_s *)data;

              if (ad->prev_view == SEARCH_VIEW)
                  return;

              init_view(ad);
              ad->prev_view = SEARCH_VIEW;

              char edj_path[PATH_MAX] = {0,};
              app_get_resource(MAIN_VIEW_EDJ_FILE, edj_path, (int)PATH_MAX);

              ad->search_view_layout = elm_layout_add(ad->nf);
              elm_layout_file_set(ad->search_view_layout, edj_path, "search-view");
              evas_object_size_hint_weight_set(ad->search_view_layout, EVAS_HINT_EXPAND, EVAS_HINT_EXPAND);
              evas_object_size_hint_align_set(ad->search_view_layout, EVAS_HINT_FILL, EVAS_HINT_FILL);
              evas_object_show(ad->search_view_layout);

              ad->search_entry = __create_entry_layout(ad);
              ad->search_genlist = __create_genlist_layout(ad);

              ad->nf_it = elm_naviframe_item_push(ad->nf, NULL, NULL, NULL, ad->search_view_layout, "tabbar/icon/notitle");
              create_search_toolbar(ad);
          }

   2. Create an input field for the POI keyword with the `__create_genlist_layout()` function:

          static Evas_Object*
          __create_entry_layout(appdata_s *ad)
          {
              Evas_Object *searchbar_obj = elm_layout_add(ad->search_view_layout);
              evas_object_size_hint_weight_set(searchbar_obj, EVAS_HINT_EXPAND, EVAS_HINT_EXPAND);
              evas_object_size_hint_align_set(searchbar_obj, EVAS_HINT_FILL, EVAS_HINT_FILL);
              evas_object_show(searchbar_obj);
              elm_layout_theme_set(searchbar_obj, "layout", "searchbar", "default");

              /* Create an input field */
              Evas_Object *editfield = create_editfield(searchbar_obj);
              eext_entry_selection_back_event_allow_set(editfield, EINA_TRUE);
              evas_object_size_hint_weight_set(editfield, EVAS_HINT_EXPAND, EVAS_HINT_EXPAND);
              evas_object_size_hint_align_set(editfield, EVAS_HINT_FILL, EVAS_HINT_FILL);

              Evas_Object *search_entry = elm_object_part_content_get(editfield, "elm.swallow.content");
              evas_object_size_hint_weight_set(search_entry, EVAS_HINT_EXPAND, EVAS_HINT_EXPAND);
              evas_object_size_hint_align_set(search_entry, EVAS_HINT_FILL, EVAS_HINT_FILL);
              elm_entry_single_line_set(search_entry, EINA_TRUE);

              elm_entry_input_panel_return_key_type_set(search_entry, ELM_INPUT_PANEL_RETURN_KEY_TYPE_DONE);
              elm_object_part_text_set(search_entry, "elm.guide", "Search POI");
              evas_object_show(search_entry);

              elm_object_part_content_set(searchbar_obj, "elm.swallow.content", search_entry);
              evas_object_smart_callback_add(search_entry, "activated", __done_pressed_cb, ad);

              elm_object_part_content_set(ad->search_view_layout, "searchbar", searchbar_obj);

              return search_entry;
          }

   3. Create a genlist for the POI category with the `__create_genlist_layout()` function:

          static Evas_Object*
          __create_genlist_layout(appdata_s *ad)
          {
              Evas_Object *genlist = elm_genlist_add(ad->search_view_layout);
              elm_list_mode_set(genlist, ELM_LIST_COMPRESS);
              evas_object_show(genlist);
              evas_object_data_set(genlist, "app_data", ad);

              /* Category */
              Elm_Genlist_Item_Class *category_itc = elm_genlist_item_class_new();
              category_itc->item_style = "type1";
              category_itc->func.content_get = NULL;
              category_itc->func.text_get = __get_here_category_text_cb;

              for (int i = 0; i < NUM_OF_CATEGORY; i++)
                  elm_genlist_item_append(genlist, category_itc, (void *)i, NULL, ELM_GENLIST_ITEM_NONE, __category_selected_cb, (void *)i);

              elm_genlist_item_class_free(category_itc);
              elm_object_part_content_set(ad->search_view_layout, "list", genlist);

              return genlist;
          }

5. Define the route view:

   1. Create the route view with the `create_route_view()` function:

          void
          create_route_view(void *data, Evas_Object *obj, void *event_info)
          {
              dlog_print(DLOG_DEBUG, LOG_TAG, "create_route_view: Enter");
              appdata_s *ad = (appdata_s *)data;

              if (ad->prev_view == ROUTE_VIEW)
                  return;

              init_view(ad);
              ad->prev_view = ROUTE_VIEW;

              char edj_path[PATH_MAX] = {0,};
              app_get_resource(MAIN_VIEW_EDJ_FILE, edj_path, (int)PATH_MAX);

              ad->route_view_layout = elm_layout_add(ad->nf);
              elm_layout_file_set(ad->route_view_layout, edj_path, "route-view");
              evas_object_size_hint_weight_set(ad->route_view_layout, EVAS_HINT_EXPAND, EVAS_HINT_EXPAND);
              evas_object_size_hint_align_set(ad->route_view_layout, EVAS_HINT_FILL, EVAS_HINT_FILL);
              evas_object_show(ad->route_view_layout);

              __create_route_searchbox(ad);

              elm_object_part_content_set(ad->route_view_layout, "map", ad->main_map_layout);
              maps_view_unset_event_cb(ad->map_view_handle, MAPS_VIEW_EVENT_GESTURE);
              maps_view_unset_event_cb(ad->map_view_handle, MAPS_VIEW_EVENT_OBJECT);
              maps_view_set_event_cb(ad->map_view_handle, MAPS_VIEW_EVENT_GESTURE, route_view_event_gesture_cb, ad);

              create_route_toolbar(ad);
              elm_object_item_content_set(ad->nf_it, ad->route_view_layout);
          }

   2. Create 2 input fields for the starting point and destination with the `__create_route_searchbox()` function:

          static void
          __create_route_searchbox(appdata_s *ad)
          {
              Evas_Object *genlist = elm_genlist_add(ad->route_view_layout);
              evas_object_size_hint_weight_set(genlist, EVAS_HINT_EXPAND, EVAS_HINT_EXPAND);
              evas_object_size_hint_align_set(genlist, EVAS_HINT_FILL, EVAS_HINT_FILL);
              elm_genlist_mode_set(genlist, ELM_LIST_COMPRESS);
              evas_object_show(genlist);

              evas_object_data_set(genlist, "app_data", ad);

              Elm_Genlist_Item_Class *from_itc = elm_genlist_item_class_new();
              from_itc->item_style = "full";
              from_itc->func.text_get = NULL;
              from_itc->func.content_get = __from_gl_content_cb;
              from_itc->func.del = NULL;
              elm_genlist_item_append(genlist, from_itc, NULL, NULL, ELM_GENLIST_ITEM_NONE, NULL, NULL);

              Elm_Genlist_Item_Class *to_itc = elm_genlist_item_class_new();
              to_itc->item_style = "full";
              to_itc->func.text_get = NULL;
              to_itc->func.content_get = __to_gl_content_cb;
              to_itc->func.del = NULL;
              elm_genlist_item_append(genlist, to_itc, NULL, NULL, ELM_GENLIST_ITEM_NONE, NULL, NULL);

              elm_genlist_item_class_free(from_itc);
              elm_genlist_item_class_free(to_itc);

              elm_genlist_realized_items_update(genlist);
              elm_object_part_content_set(ad->route_view_layout, "searchbar", genlist);
          }

          static Evas_Object*
          __from_gl_content_cb(void *data, Evas_Object *obj, const char *part)
          {
              appdata_s *ad = evas_object_data_get(obj, "app_data");

              if (!strcmp(part, "elm.swallow.content")) {
                  Evas_Object *editfield = create_editfield(obj);
                  eext_entry_selection_back_event_allow_set(editfield, EINA_TRUE);

                  ad->route_from_entry = elm_object_part_content_get(editfield, "elm.swallow.content");
                  evas_object_size_hint_weight_set(ad->route_from_entry, EVAS_HINT_EXPAND, EVAS_HINT_EXPAND);
                  evas_object_size_hint_align_set(ad->route_from_entry, EVAS_HINT_FILL, EVAS_HINT_FILL);
                  elm_object_part_text_set(ad->route_from_entry, "elm.guide", "From - Long press in Map");

                  elm_entry_editable_set(ad->route_from_entry, EINA_FALSE);

                  return editfield;
              }

              return NULL;
          }

          static Evas_Object*
          __to_gl_content_cb(void *data, Evas_Object *obj, const char *part)
          {
              appdata_s *ad = evas_object_data_get(obj, "app_data");

              if (!strcmp(part, "elm.swallow.content")) {
                  Evas_Object *editfield = create_editfield(obj);
                  eext_entry_selection_back_event_allow_set(editfield, EINA_TRUE);

                  ad->route_to_entry = elm_object_part_content_get(editfield, "elm.swallow.content");
                  evas_object_size_hint_weight_set(ad->route_to_entry, EVAS_HINT_EXPAND, EVAS_HINT_EXPAND);
                  evas_object_size_hint_align_set(ad->route_to_entry, EVAS_HINT_FILL, EVAS_HINT_FILL);
                  elm_object_part_text_set(ad->route_to_entry, "elm.guide", "To      - Long press in Map");

                  elm_entry_editable_set(ad->route_to_entry, EINA_FALSE);

                  return editfield;
              }

              return NULL;
          }

### Application Operation

To use the map service:

1. Create a maps service handle:

       static void
       user_consent_cb(bool consented, const char *maps_provider, void *user_data)
       {
           dlog_print(DLOG_DEBUG, LOG_TAG, "user_consent_cb: Enter[%s]", maps_provider);

           appdata_s *ad = (appdata_s *)user_data;
           int error = 0;
           bool supported = false;

           if (consented == true)
               maps_service_create(maps_provider, &(ad->maps_service_handle));
           else
               ui_app_exit();

           /* Create a default view */
           if (view_create(ad) != EINA_TRUE)
               return;
           dlog_print(DLOG_ERROR, LOG_TAG, "view_create and create_maps_handle : done");

           /* Set the provider Key to access the services from provider */
           maps_service_set_provider_key(ad->maps_service_handle, HERE_PROVIDER_KEY);

           /* Check if routing is available */
           error = maps_service_provider_is_service_supported(ad->maps_service_handle, MAPS_SERVICE_SEARCH_ROUTE, &supported);
           ad->is_search_route_supported = (error == MAPS_ERROR_NONE) ? supported : false;

           error = maps_service_provider_is_service_supported(ad->maps_service_handle, MAPS_SERVICE_SEARCH_PLACE, &supported);
           ad->is_search_place_supported = (error == MAPS_ERROR_NONE) ? supported : false;

           error = maps_service_provider_is_service_supported(ad->maps_service_handle, MAPS_SERVICE_REVERSE_GEOCODE, &supported);
           ad->is_reverse_geocode_supported = (error == MAPS_ERROR_NONE) ? supported : false;

           /* Push an item to the naviframe */
           ad->nf_it = elm_naviframe_item_push(ad->nf, NULL, NULL, NULL, NULL, "tabbar/icon/notitle");

           if (error == MAPS_ERROR_NONE) {
               /* Create the toolbar */
               if (view_create_toolbar(ad) == NULL)
                   dlog_print(DLOG_ERROR, LOG_TAG, "failed to create a toolbar");
           }
       }

2. Destroy the maps view handle and the maps service handle:

       void
       destroy_maps_handle(appdata_s *ad)
       {
           if (ad->map_view_handle) {
               int error = maps_view_destroy(ad->map_view_handle);
               if (error != MAPS_ERROR_NONE)
                   dlog_print(DLOG_ERROR, LOG_TAG, "maps_view_destroy: fail [%d]", error);
               else
                   dlog_print(DLOG_ERROR, LOG_TAG, "maps_view_destroy: success");
               ad->map_view_handle = NULL;
           }
           if (ad->maps_service_handle) {
               int error = maps_service_destroy(ad->maps_service_handle);
               if (error != MAPS_ERROR_NONE)
                   dlog_print(DLOG_ERROR, LOG_TAG, "maps_service_destroy: fail [%d]", error);
               else
                   dlog_print(DLOG_ERROR, LOG_TAG, "maps_service_destroy: success");
               ad->maps_service_handle = NULL;
           }
       }

3. Display a marker and get the reverse geocode by performing a long press gesture on a particular location on the map:

   1. Add a marker on a particular location over the maps view:

          void
          add_marker(maps_view_h view, place_info_s *place, bool selected)
          {
              dlog_print(DLOG_ERROR, LOG_TAG, "add_marker: [%f,%f]", place->location.latitude, place->location.longitude);

              char image_path[PATH_MAX] = {0,};
              if (selected == true)
                  app_get_resource(CUR_POI_MARKER_IMAGE, image_path, (int)PATH_MAX);
              else
                  app_get_resource(POI_MARKER_IMAGE, image_path, (int)PATH_MAX);

              maps_coordinates_h coord;
              maps_coordinates_create(place->location.latitude, place->location.longitude, &coord);
              maps_view_object_create_marker(coord, image_path, MAPS_VIEW_MARKER_PIN, &(place->marker));
              maps_view_add_object(view, place->marker);

              if (selected == true) {
                  maps_view_object_marker_set_z_order(place->marker, 100);
                  maps_view_object_marker_resize(place->marker, 80, 80);
              }
          }

   2. Request the reverse geocode:

          int
          request_revgeocode(appdata_s *ad, double latitude, double longitude)
          {
              dlog_print(DLOG_DEBUG, LOG_TAG, "request_revgeocode: Enter");

              int request_id = -1;

              maps_preference_h preference = NULL;
              maps_preference_create(&preference);

              int error = maps_service_reverse_geocode(ad->maps_service_handle, /* Maps service handle */
                                                       latitude, /* Center location */
                                                       longitude, /* Search radius from center location */
                                                       preference, /* Reverse geocode preference */
                                                       reverse_geocode_cb, /* Callback */
                                                       (void *)ad, /* user_data */
                                                       &request_id); /* request_id */

              if (error != MAPS_ERROR_NONE)
                  __geocode_request_id = REQ_ID_IDLE;
              else
                  __geocode_request_id = request_id;

              maps_preference_destroy(preference);

              return error;
          }

   3. Get the reverse geocode result:

          static void
          reverse_geocode_cb(maps_error_e result, int request_id, int index, int total, maps_address_h address, void *user_data)
          {
              dlog_print(DLOG_DEBUG, LOG_TAG, "reverse_geocode_cb: Enter");
              appdata_s *ad = (appdata_s *)user_data;

              if (result != MAPS_ERROR_NONE) {
                  dlog_print(DLOG_ERROR, LOG_TAG, "Invalid Reverse Geocode Result");

                  return;
              }

              char resultText[1024] = {0,};

              char *street = NULL;
              maps_address_get_street(address, &street);
              if (street != NULL) {
                  strcat(resultText, street);
                  free(street);
                  street = NULL;
              } else {
                  dlog_print(DLOG_ERROR, LOG_TAG, "Street is NULL");
              }

              char *district = NULL;
              maps_address_get_district(address, &district);
              if (district != NULL) {
                  if (strlen(resultText) > 0)
                      strcat(resultText, ", ");
                  strcat(resultText, district);
                  free(district);
                  district = NULL;
              } else {
                  dlog_print(DLOG_ERROR, LOG_TAG, "District is NULL");
              }

              char *city = NULL;
              maps_address_get_city(address, &city);
              if (city != NULL) {
                  if (strlen(resultText) > 0)
                      strcat(resultText, ", ");
                  strcat(resultText, city);
                  free(city);
                  city = NULL;
              } else {
                  dlog_print(DLOG_ERROR, LOG_TAG, "City is NULL");
              }

              char *state = NULL;
              maps_address_get_state(address, &state);
              if (state != NULL) {
                  if (strlen(resultText) > 0)
                      strcat(resultText, ", ");
                  strcat(resultText, state);
                  free(state);
                  state = NULL;
              } else {
                  dlog_print(DLOG_ERROR, LOG_TAG, "State is NULL");
              }

              char *country = NULL;
              maps_address_get_country(address, &country);
              if (country != NULL) {
                  if (strlen(resultText) > 0)
                      strcat(resultText, ", ");
                  strcat(resultText, country);
                  free(country);
                  country = NULL;
              } else {
                  dlog_print(DLOG_ERROR, LOG_TAG, "Country is NULL");
              }

              char *country_code = NULL;
              maps_address_get_country_code(address, &country_code);
              if (country_code != NULL) {
                  if (strlen(resultText) > 0)
                      strcat(resultText, ", ");
                  strcat(resultText, country_code);
                  free(country_code);
                  country_code = NULL;
              } else {
                  dlog_print(DLOG_ERROR, LOG_TAG, "Country Code is NULL");
              }

              char *postal_code = NULL;
              maps_address_get_postal_code(address, &postal_code);
              if (postal_code != NULL) {
                  if (strlen(resultText) > 0)
                      strcat(resultText, ", ");
                  strcat(resultText, postal_code);
                  free(postal_code);
                  postal_code = NULL;
              } else {
                  dlog_print(DLOG_ERROR, LOG_TAG, "Postal Code is NULL");
              }

              if (strlen(resultText) > 0) {
                  strcpy(ad->tmp_place->place_name, resultText);
                  create_address_button(ad);
              }

              elm_object_part_text_set(ad->main_entry, "elm.guide", ad->tmp_place->place_name);
              dlog_print(DLOG_DEBUG, LOG_TAG, "address: %s", ad->tmp_place->place_name);
              maps_address_destroy(address);

              __geocode_request_id = REQ_ID_IDLE;

              elm_entry_input_panel_hide(ad->main_entry);
          }

4. Search POIs in the POI view when selecting any of the predefined search category:

   1. Perform a POI search by keyword and selected category:

          int
          request_search_place(appdata_s *ad, char *search_keyword, place_type category_type)
          {
              int ret = 0;
              int request_id = 0;

              maps_place_filter_h filter = NULL;
              maps_preference_h preference = NULL;
              maps_place_category_h category = NULL;
              maps_coordinates_h coords = NULL;

              maps_preference_create(&preference); /* Create maps preference */
              maps_place_filter_create(&filter); /* Create maps place filter */

              maps_place_category_create(&category); /* Create the place category */
              maps_place_category_set_id(category, __get_here_category_id(category_type)); /* Set the category name for place search */

              ret = maps_place_filter_set_category(filter, category); /* Set the place category to the filter */
              if (ret != MAPS_ERROR_NONE) {
                  dlog_print(DLOG_ERROR, LOG_TAG, "maps_place_filter_set error [%d]", ret);
                  goto EXIT;
              }

              if (search_keyword != NULL) {
                  dlog_print(DLOG_DEBUG, LOG_TAG, "poi search keyword: %s", search_keyword);
                  ret = maps_place_filter_set_keyword(filter, search_keyword); /* Keyword search. No POI category search */
                  if (ret != MAPS_ERROR_NONE)
                      dlog_print(DLOG_ERROR, LOG_TAG, "maps_place_filter_set error [%d]", ret);
              }

              maps_preference_set_max_results(preference, MAX_RESULT_OF_SEARCH); /* Set the max results preference */

              ret = maps_view_get_center(ad->map_view_handle, &coords);
              if (ret != MAPS_ERROR_NONE) {
                  dlog_print(DLOG_DEBUG, LOG_TAG, "map_view_get_center: fail [%d]", ret);
                  goto EXIT;
              }

              /* Place search */
              ret = maps_service_search_place(ad->maps_service_handle, coords, RADIUS_OF_SEARCH, filter, preference,
                                              __maps_service_search_place_cb, (void *)ad, &request_id);

              if (ret != MAPS_ERROR_NONE) {
                  dlog_print(DLOG_ERROR, LOG_TAG, "failed to poi_service_search.");
                  __place_request_id = REQ_ID_IDLE;
                  goto EXIT;
              } else {
                  __place_request_id = request_id;
                  dlog_print(DLOG_ERROR, LOG_TAG, "request_id: %d", __place_request_id);
              }

          EXIT:
              if (coords)
                  maps_coordinates_destroy(coords);
              if (category)
                  maps_place_category_destroy(category);
              if (filter)
                  maps_place_filter_destroy(filter);
              maps_preference_destroy(preference);

              return ret;
          }

   2. Get the POI search result:

          static bool
          __maps_service_search_place_cb(maps_error_e error, int request_id, int index, int length, maps_place_h place, void *user_data)
          {
              dlog_print(DLOG_DEBUG, LOG_TAG, "Place result >> index [%d]/ length [%d]", index, length);

              appdata_s *ad = (appdata_s *)user_data;
              maps_coordinates_h coordinates = NULL;
              double cur_lat = 0.0, cur_lon = 0.0;
              char *name = NULL;

              if (error != MAPS_ERROR_NONE || !place) {
                  ad->total_poi = index;
                  show_category_result(ad);
                  maps_place_destroy(place);

                  return false;
              }

              maps_view_get_center(ad->map_view_handle, &coordinates);
              maps_coordinates_get_latitude_longitude(coordinates, &cur_lat, &cur_lon);
              maps_coordinates_destroy(coordinates);
              coordinates = NULL;

              ad->poi_places[index] = (place_info_s *) malloc(sizeof(place_info_s));

              /* Place name */
              maps_place_get_name(place, &name);
              strcpy(ad->poi_places[index]->place_name, name);

              /* Place location */
              maps_place_get_location(place, &coordinates);
              maps_coordinates_get_latitude_longitude(coordinates, &(ad->poi_places[index]->location.latitude), &(ad->poi_places[index]->location.longitude));
              maps_coordinates_destroy(coordinates);

              /* Distance calculation */
              location_manager_get_distance(cur_lat, cur_lon, ad->poi_places[index]->location.latitude, ad->poi_places[index]->location.longitude, &(ad->poi_places[index]->distance));
              ad->poi_places[index]->distance = ad->poi_places[index]->distance * 0.001;

              if (index == (length-1)) {
                  ad->total_poi = length;
                  show_category_result(ad);
              }

              /* Release the place result */
              maps_place_destroy(place);

              __place_request_id = REQ_ID_IDLE;

              return true;
          }

5. Search a route from the selected origin to the destination by long press in the route view:

   1. Perform a route search:

          int
          request_route(appdata_s *ad, double src_lat, double src_lon, double dest_lat, double dest_lon)
          {
              dlog_print(DLOG_ERROR, LOG_TAG, "request_route origin=%f,%f destination=%f,%f", src_lat, src_lon, dest_lat, dest_lon);
              int request_id = -1;
              int ret = MAPS_ERROR_NONE;

              if (ad->route)
                  free(ad->route);
              ad->route = NULL;

              maps_coordinates_h origin = NULL;
              maps_coordinates_h destination = NULL;

              /* Origin coordinates */
              maps_coordinates_create(src_lat, src_lon, &origin);
              /* Destination coordinates */
              maps_coordinates_create(dest_lat, dest_lon, &destination);

              /* Maps preference */
              maps_preference_h preference = NULL;
              maps_preference_create(&preference);

              /* Set the route transport mode preference */
              /* Transport mode - Car */
              maps_preference_set_route_transport_mode(preference, MAPS_ROUTE_TRANSPORT_MODE_CAR);

              /* Route search */
              ret = maps_service_search_route(ad->maps_service_handle, origin, destination, preference, __maps_service_search_route_cb, ad, &request_id);

              if (ret == MAPS_ERROR_NONE) {
                  dlog_print(DLOG_ERROR, LOG_TAG, "request_id: %d", request_id);
                  __route_request_id = request_id;
              } else {
                  dlog_print(DLOG_ERROR, LOG_TAG, "Route Service Request Failed: [%d]", ret);
                  __route_request_id = REQ_ID_IDLE;
              }

              maps_coordinates_destroy(origin);
              maps_coordinates_destroy(destination);
              maps_preference_destroy(preference);

              return ret;
          }

   2. Get the route search result:

          static bool
          __maps_service_search_route_cb(maps_error_e error, int request_id, int index, int total, maps_route_h route, void *user_data)
          {
              appdata_s *ad = (appdata_s *)user_data;

              if (!route) {
                  dlog_print(DLOG_ERROR, LOG_TAG, "route handle is null");

                  return false;
              }

              __parse_route_data(route, index, total, ad);

              show_route_in_map(ad);

              maps_route_destroy(route);

              return false;
          }

          static void
          __parse_route_data(maps_route_h route, int index, int total, appdata_s *ad)
          {
              maps_distance_unit_e dist_unit;
              double distance = 0;
              long duration = 0;

              /* Route - Total distance */
              maps_route_get_total_distance(route, &distance);
              /* Route - Distance unit */
              maps_route_get_distance_unit(route, &dist_unit);

              /* Change everything to kilometers (by default) */
              if (dist_unit == MAPS_DISTANCE_UNIT_M)
                  distance = distance / 1000; /* Convert the distance into km */
              dlog_print(DLOG_DEBUG, LOG_TAG, "distance: %.5f km", distance);

              /* Route - Total duration */
              maps_route_get_total_duration(route, &duration);
              dlog_print(DLOG_DEBUG, LOG_TAG, "duration: %ld sec", duration);
              duration = (duration + 30) / 60; /* Convert duration to minutes */

              /* Route - Origin, destination */
              maps_coordinates_h coord;
              double origin_lat, origin_lon, dest_lat, dest_lon;

              maps_route_get_origin(route, &coord);
              maps_coordinates_get_latitude_longitude(coord, &origin_lat, &origin_lon);
              maps_coordinates_destroy(coord);

              maps_route_get_destination(route, &coord);
              maps_coordinates_get_latitude_longitude(coord, &dest_lat, &dest_lon);
              maps_coordinates_destroy(coord);

              dlog_print(DLOG_ERROR, LOG_TAG, "origin=%f,%f destination=%f,%f", origin_lat, origin_lon, dest_lat, dest_lon);
              ad->route = (route_info_s *)malloc(sizeof(route_info_s));
              ad->route->distance = distance;
              ad->route->duration = duration;

              /* Check if maneuver path data is supported */
              bool supported = false;
              int error = maps_service_provider_is_data_supported(ad->maps_service_handle, MAPS_ROUTE_SEGMENTS_PATH, &supported);
              const bool is_route_segment_path_supported = (error == MAPS_ERROR_NONE) ? supported : false;

              /* Check if maneuver segment data is supported */
              error = maps_service_provider_is_data_supported(ad->maps_service_handle, MAPS_ROUTE_SEGMENTS_MANEUVERS, &supported);
              const bool is_route_segment_maneuvers_supported = (error == MAPS_ERROR_NONE) ? supported : false;

              if ((is_route_segment_path_supported) && (is_route_segment_maneuvers_supported)) {
                  /* Allow segment maneuvers and path usage */
                  maps_route_foreach_path(route, __maps_route_path_cb, (void *)ad);
              }
          }

   3. Display the route in the maps view:

          void
          show_route_in_map(appdata_s *ad)
          {
              double lat = 0.0, lon = 0.0;

              maps_coordinates_h coord;
              maps_coordinates_list_h coord_list;
              maps_coordinates_list_create(&coord_list);

              maps_coordinates_create(ad->start_place->location.latitude, ad->start_place->location.longitude, &coord);
              maps_coordinates_list_append(coord_list, coord);

              for (int i = 0; i < ad->route->path_count && i < MAX_ROUTE_PATH; i++) {
                  lat = ad->route->path[i].latitude;
                  lon = ad->route->path[i].longitude;
                  dlog_print(DLOG_ERROR, LOG_TAG, "Maneuver[%d] - [%f,%f]", i, lat, lon);
                  maps_coordinates_create(lat, lon, &coord);
                  maps_coordinates_list_append(coord_list, coord);
              }

              maps_coordinates_create(ad->destination->location.latitude, ad->destination->location.longitude, &coord);
              maps_coordinates_list_append(coord_list, coord);

              maps_view_object_h polyline;
              maps_view_object_create_polyline(coord_list, 255, 0, 0, 255, 3, &polyline);
              maps_view_add_object(ad->map_view_handle, polyline);

              create_info_button(ad);
          }

          static void
          create_info_button(appdata_s *ad)
          {
              dlog_print(DLOG_ERROR, LOG_TAG, "create_info_button: Enter");
              char route_info[30] = {0,};
              snprintf(route_info, 30, "%.2lf km / %d min by car", ad->route->distance, ad->route->duration);

              Evas_Object *info_box = elm_box_add(ad->route_view_layout);
              evas_object_size_hint_align_set(info_box, EVAS_HINT_FILL, EVAS_HINT_FILL);
              evas_object_size_hint_weight_set(info_box, EVAS_HINT_EXPAND, EVAS_HINT_EXPAND);
              evas_object_show(info_box);
              elm_object_part_content_set(ad->route_view_layout, "info", info_box);

              ad->route_info_btn = elm_button_add(info_box);
              elm_object_text_set(ad->route_info_btn, route_info);
              elm_object_disabled_set(ad->route_info_btn, EINA_TRUE);
              evas_object_size_hint_align_set(ad->route_info_btn, EVAS_HINT_FILL, EVAS_HINT_FILL);
              evas_object_size_hint_weight_set(ad->route_info_btn, EVAS_HINT_EXPAND, EVAS_HINT_EXPAND);
              evas_object_show(ad->route_info_btn);
              elm_box_pack_end(info_box, ad->route_info_btn);
          }