Localización y mapas

Nuestro móvil o tablet Android tienen un sensor de orientación y un receptor de GPS. Usando Google Maps vamos a aprender a localizar puntos en un mapa según sus coordenadas, buscar direcciones y establecer rutas entre dos puntos.

 Introducción

Usando el sensor de orientación de nuestro dispositivo y con Google Maps vamos a aprender a localizar puntos en un mapa por coordenadas, buscar direcciones y establecer rutas entre dos puntos.

 Brújula digital

Para el siguiente programa vamos a usar el sensor de orientación (componente OrientationSensor) para hacer una brújula digital.
Crea un nuevo proyecto y llámalo "brujula"
Cambia la propiedad ScreenOrientation del componente Screen a Portrait (vertical) según utilices un móvil o a Landscape (Horizontal) si usas un tablet. Después veremos por qué.
Añade un componente Canvas y cambia sus propiedades Width y Height a "Fill parent". 
Añade un componente ImageSprite y usa la imagen "brujula.png" que encontrarás aquí
Añade por último un componente OrientationSensor dentro de Sensors (sensores)
Como hemos visto en el ejemplo del cohete que viajaba a la luna, el componente OrientationSensor nos dice si estamos inclinando nuestro dispositivo en alguna dirección y la orientación del mismo. En concreto para nuestro siguiente programa vamos a utilizar el parámetro azimuth. Este parámetro nos devuelve un valor en grados que será igual a 0 cuando la parte superior de nuestro dispositivo apunte al norte magnético de la tierra.
Además vamos a usar una imagen (brujula.png) la cual vamos a ir girando usando el bloque "ImageSprite.Heading" según se mueva nuestra brújula. Cuando el valor del azimuth sea igual a 0, nuestra imagen estará recta. Cuando el azimuth cambie, giraremos la imagen según el valor del azimuth.
Vamos al Editor de bloques.
Lo primero que vamos a hacer es situar nuestra imagen en el centro de la pantalla.
7 Coge el evento Screen.Initialize.
Coge un procedimiento "call ImageSprite.MoveTo"
Recuerda que para encontrar el centro de nuestra pantalla (en este caso del canvas) tenemos que dividir el tamaño del canvas entre 2.
10 Crea dos bloque math /
11 En el primer espacio del primer bloque pon la variable Canvas.Width
12 En el segundo espacio un bloque numérico con el valor 2.
13 En el primer espacio del segundo bloque pon la variable Canvas.Height
14 En el segundo espacio por otro bloque numérico con el valor 2.
Como nuestra imagen tiene un tamaño de 128 x 128. Vamos a descontar la mitad (64) de cada coordenada, así centraremos perfectamente la imagen.
15 Crea otros dos bloque numéricos math -
15 En el primer espacio del primer bloque pon nuestro anterior bloque Canvas.Width/2
16 En el segundo espacio pon un bloque numérico con el valor 64
17 En el primer espacio del segundo bloque pon nuestro anterior bloque Canvas.Height/2
18 En el segundo espacio otro bloque numérico con el valor 64.
19 Ahora junta los dos bloques completos al bloque MoveTo.
Recuerda que la coordenada x corresponde al Canvas.Width y la coordenada y al Canvas.Height.
Tiene que quedarte así:

20 Coge ahora el evento OrientationSensor.OrientationChanged
Recuerda que este evento se activa cuando movemos el dispositivo.
21 Pon dentro un bloque "set ImageSprite.Heading" y en el espacio to la variable "value azimuth"
22 ¿Funciona?
En algunos dispositivos la lectura del Sensor de movimiento no es correcta hasta que instalas la aplicación en tu dispositivo. Tenlo en cuenta.
En la mayoría de los dispositivos tipo tableta (tablets) el borde de la pantalla que coincide con el norte magnético será el borde superior de la pantalla cuando se sujeta el dispositivo en horizontal. Puede que corresponda con el logo del aparato o con la situación de la cámara integrada, si tu dispositivo tiene una, pero puede no ser el caso en tu dispositivo. Para hacer coincidir el norte magnético de tu dispositivo con la orientación de nuestra aplicación y que esta no varíe conforme usamos nuestra brújula tenemos que fijar la propiedad ScreenOrientation.

 ¿Dónde estoy?

Vamos a hacer un programa para localizar nuestra posición en un mapa.
Para hacerlo usaremos el componente LocationSensor que nos dará las coordenadas de nuestra posición y con ellas haremos una llamada a Google Maps para que nos sitúe las coordenadas en un mapa. Usaremos dos formas de ver el mapa. En la primera usaremos el componente WebViewer que nos permite abrir una ventana del navegador en la pantalla de nuestra aplicación tal y como hemos visto antes. La otra será utilizando el componente ActivityStarter que nos permite abrir la aplicación de Google Maps directamente a pantalla completa.
Importante #1: Dependiendo de la configuración del idioma de tu dispositivo móvil o tablet, las coordenadas de un punto se describen usando comas p.ejem.(0,123 x 0,321) o usando puntos p.ejem. (0.123 x 0.321). Lo mismo ocurre con los separadores decimales, p.ejem. 1.300,20 en España sería 1,300.20 en Estados Unidos.
Esta diferencia puede darnos problemas en los siguientes ejercicios y es importante que entiendas por qué para que puedas arreglarlo fácilmente. Si nuestro dispositivo está configurado en el idioma Español, el componente LocationSensor de AppInventor nos va a devolver las coordenadas de nuestro dispositivo usando comas y estas coordenadas se las vamos a pasar a Google Maps para que nos muestre a qué punto del mapa corresponden esas coordenadas. El problema puede aparecer porque Google Maps espera las coordenadas usando puntos y se las estemos pasando como comas. Lamentablemente a día de hoy este problema puede o no aparecer en tu dispositivo dependiendo de la versión de Google Maps y de AppInventor que tengas así como la versión de Android y la configuración del idioma que uses.
Este problema es fácil de detectar porque al pasarlelas coordenadas de un punto desde tu programa a Google Maps te dirá que no es capaz de encontrarlas en el mapa. Casi con seguridad la razón es el problema de los puntos y las comas. La forma más sencilla de resolverlo es cambiar la configuración del idioma de tu dispositivo al Inglés o utilizar una función dentro de tu programa que sustituya las comas por puntos. Al final de este ejercicio vamos a ver cómo hacerlo en el caso de que lo necesites.
Importante #2: El servicio de localización por Wifide tu dispositivo intentará determinar tu localización en el caso de que estés conectado a una red Wifi donde no sea posible la localización por GPS, por ejemplo dentro de una casa o edificio. Este sistema de localización funciona porque el router wifi al que está conectado tu dispositivo contiene a su vez información de su localización geográfica directamente o a través del operador que proporcione el servicio de acceso a Internet. Sin embargo esta información no siempre está disponible y puede ocurrir que tu dispositivo intente encontrar esta información pero al no existir, no puede localizarte en el mapa.
Si te encuentras dentro de un edificio y estás conectado a una red Wifi y aún así tu dispositivo no es capaz de determinar tu posición puede que este sea el problema. Tenlo en cuenta para los siguientes ejercicios. Quizás tengas que probar en otra red Wifi o salir a la calle para probar tu aplicación.
Vamos con nuestro programa. Asegúrate de que tienes activado el servicio de localización de tu dispositivo y también el servicio de localización por Wifi (si tu dispositivo lo tiene).
Desde el Diseñador crea un nuevo proyecto y llámalo "donde_estoy"
Desactiva la propiedad Scrollable del componente Screen.
Coge dos etiquetas y pon una debajo de la otra.
A la primera llámala etiqueta_coordenadas y cambia el texto por: "sin coordenadas"
A la segunda llámala etiqueta_direccion y cambiar el texto por "sin dirección"
El componente LocationSensor que usaremos más adelante nos devolverá las coordenadas de nuestra posición actual que usaremos para actualizar estas etiquetas. Mientras este componente no nos de esta información mostraremos el mensaje "sin coordenadas".
10 Coge un componente HorizontalArragement y por dentro dos botones.
11 Al primero llámalo boton_mapa y cambia el texto por "ver mapa"
12 Al segundo llámalo boton_google y cambia el texto por "ver en Google"
13 Añade ahora un componente WebViewer desde "Not ready for prime time". Cambia sus propiedades Width y Height a "Fill parent". Si quieres puedes hacer este componente más grande para que el mapa sea más grande también.
14 Añade un componente LocationSensor.
15 Finalmente añade un componente ActivityStarter con las siguientes propiedades (puedes copiar y pegar el texto desde esta misma página):
1Action - android.intent.action.VIEW
1ActivityClass - com.google.android.maps.MapsActivity
1ActivityPackage - com.google.android.apps.maps
19 Vamos al Editor de bloques.
Para poder comunicarnos con Google Maps tenemos que formar una cadena de texto con una URL.
20 Crea las siguientes variables de texto:
21 codigo_google = "http://www.google.com/maps/?q=" Esta variable la utilizamos para comunicarnos con Google Maps.
22 nivel_zoom = "&z=18". Esta variable nos permite cambiar el nivel del zoom de los mapas de Google.
23 Coge el evento LocationSensor.LocationChanged.
Este evento se activa cuando cambiamos la localización de nuestro dispositivo, es decir, cuando nos movemos. Por lo tanto, cada vez que se activa, nos dice las nuevas coordenadas de nuestra posición. Vamos a usar este evento para actualizar nuestras etiquetas de la pantalla.
24 Coge el bloque "set etiqueta_coordenadas.Text"
25 Crea una etiqueta de texto "text join" y haz que tenga cuatro espacios para rellenar.
26 En el primer espacio pon un bloque de texto con el texto: "Coordenadas actuales: "
27 En el segundo la variable latitude.
28 En el tercero pon un bloque de texto con el texto " / "
29 En el último espacio pon la variable longitude
30 Finalmente pega toda la cadena de texto a la etiqueta_coordenadas.
31 Coge el bloque "set etiqueta_direccion.Text" y pégale un bloque LocationSensor.CurrentAddress
32 Ahora coge el evento boton_mapa.Click
33 Pon dentro un procedimiento "call WebViewer.GoToUrl"
34 Ahora crea una etiqueta de texto "text join" y haz que tengas cuatro espacios a rellenar.
35 En el primer espacio pon la variable "global codigo_google"
36 En el segundo la variable LocationSensor.Latitude
37 En el tercero un bloque de texto con una coma ","
38 En el último espacio la variable LocationSensor.Longitude
Con esto estamos creando una cadena de texto que corresponde a la URL que Google necesita para poder localizar en el mapa nuestras coordenadas, precisamente porque dentro de la cadena de texto estamos pasando las coordenadas.
39 Coge ahora el evento boton_google.Click
En este caso vamos a llamar a la aplicación Google Maps usando el componente ActivityStarter.
40 Coge el bloque "set ActivityStarter.DataUri"
41 Ahora crea una etiqueta de texto "text join" y haz que tengas cuatro espacios a rellenar.
42 En el primer espacio pon la variable "global codigo_google"
43 En el segundo la variable LocationSensor.Latitude
44 En el tercero la variable LocationSensor.Longitude
45 En el último espacio la variable nivel_zoom
46 Une la cadena de texto al bloque ActivityStarter.DataUri
47 Finalmente coge un procedimiento "call ActivityStarter.StartActivity"
Tu programa debe de quedar así:

Es posible que no tengamos activada la opción de localización de nuestro dispositivo. Para asegurarnos de que nuestro programa funciona correctamente deberíamos de comprobar dentro de los evento .Click que tenemos las coordenadas guardadas. En los siguientes ejemplos veremos cómo hacerlo.

48 Guarda este programa porque lo vamos a usar en el siguiente ejemplo.

El problema de los puntos y comas en las coordenadas

Como hemos visto al principio si tenemos nuestro dispositivo configurado en el idioma Español, AppInventor nos devolverá las coordenadas usando comas, p.ejem. (40,1234 x 30,132) y ya hemos visto que al pasar estas coordenadas usando comas a Google Maps nos dará problemas. Una forma de solucionar esto sin tener que cambiar la configuración del idioma de nuestro dispositivo consiste en cambiar las comas por puntos dentro de nuestro propio programa antes de pasárselas a Google Maps.
La forma más sencilla de hacerlo es crear una pequeña función que haga el trabajo por nosotros. Podemos llamar a esta función quitar_comas. A esta función le pasamos como argumento la coordenada que queremos cambiar y dentro de la función usamos el bloque de texto replace all. Este bloque busca un carácter (segment) dentro del texto que le pasemos (text) y lo sustituye por otro (replacement).
Una vez tengamos nuestra función quitar_comas hecha sólo nos queda usarla cada vez que tengamos que usar una coordenada, por ejemplo al llamar a Google Maps. Allí donde antes usábamos el bloque LocationSensor1.Latitude o LocationSensor.Longitude ahora usaremos los bloques call quitar_comas(LocationSensor.Latitude) o call quitar_comas(LocationSensor.Longitude). Fíjate cómo lo hemos usado en nuestro programa anterior:


 Buscando direcciones

Ahora vamos a aprender a localizar un punto en un mapa usando la dirección en lugar de las coordenadas.
Recupera el programa que hemos hecho antes "donde_estoy" y guárdalo de nuevo con la  opción "Save As" (guardar como) pero cambiando el nombre a: "buscando_direcciones"
Desde el Diseñador vamos a añadir un componente textbox debajo de la etiqueta etiqueta_direccion
Cambia el nombre del textbox por "nueva_direccion" y la propiedad Hint por "buscar dirección"
Cambia también el tamaño del font a 10 y la propiedad Height a 30. Así dejamos más espacio para el mapa de abajo.
Vamos el Editor de bloques.
En el evento boton_mapa.Click nos vamos a quedar únicamente con un bloque text join que tenga en el primer espacio la variable codigo_google y en el segundo espacio nuestra variable nueva_direccion.Text. Puedes borrar el segundo y tercer bloque text join que tenemos ahora y conservar la primera parte. Así:

En el evento boton_buscar_google.Click vamos a hacer algo parecido. Tenemos que quedarnos con dos bloques text join. En el primer espacio tendremos la variable "global codigo_google", en el segundo nueva_direccion.Text y en el último la variable "global nivel_zoom". Así:

Lo que hemos hecho es sustituir las variables de las coordenadas por la dirección que haya puesto el usuario en el textbox.

 Guardando Waypoints

Vamos a aprender a guardar un punto en el mapa para poder recuperarlo más tarde.
Un waypoint es un conjunto de coordenadas que identifican un punto en un mapa o espacio físico. Para localizar un punto sobre la superficie terrestre se usan los valores de latitud y longitud. Para la navegación aérea y otras aplicaciones también se usa el valor altitud.
El programa que vamos a hacer ahora nos permite guardar waypoints (coordenadas) de nuestra posición actual en una base de datos con el nombre que queramos. Podemos usar esta aplicación si vamos andando por la calle y encontramos algo interesante que queremos guardar para poder volver más tarde usando una ruta hasta ese punto.
Desde el Diseñador crea un nuevo proyecto y llámalo "waypoints" 
Desactiva la propiedad Scrollable del componente Screen.
Coge dos etiquetas y pon una debajo de la otra.
A la primera llámala etiqueta_coordenadas y cambia el texto por: "sin coordenadas"
A la segunda llámala etiqueta_dirección y cambia el texto por "sin dirección"
El componente LocationSensor que usaremos más adelante nos devolverá las coordenadas de nuestra posición actual que usaremos para actualizar estar etiquetas. Mientras este componente no nos de esta información mostraremos el mensaje "sin coordenadas"-
Coge un componente HorizontalArrangement y pon dentro, en este orden, los siguientes componentes:
7Un botón. Llámalo boton_posición_actual y cambia el texto por "Posición actual"
Otro botón. Llámalo boton_guardar. Cambia el texto por "Guardar".
Un componente ListPicker. Llámalo boton_mis_waypoints. Cambia el texto por "Mis Waypoints"
10 Cambia el tamaño de los fonts a 10 y la propiedad Height a 30 de todos estos componentes para que quepa el mapa en la pantalla.
11 Añade otro componente HorizontalArragement debajo del anterior y cambia su nombre a menu_guardar.
12 Mete dentro de este nuevo componente HorizontalArragement un textbox y un botón a la derecha.
13 Al textbox llámalo textbox_nombre_waypoint y en la propiedad Hint escribe "nombre del waypoint"
14 Al botón llámalo boton_guardar_waypoint y en el texto escribe: "Guardar"
15 Cambia el tamaño del font y la propiedad Height de ambos componentes como antes.
16 Y cambia la propiedad Visible del componente menu_guardar a Hidden (oculto)
17 Queremos que este menú sólo aparezca cuando el usuario ha pulsado el botón de guardar. Así ahorramos espacio en la pantalla.
18 Añade ahora un componente WebViewer. Cambia sus propiedades Width y Height a "Fill parent". Si quieres puedes hacer este componente más grande para que el mapa sea más grande también.
19 Añade un componente LocationSensor.
20 Añade un componente TinyDB.
21 Finalmente añade un componente ActivityStarter con las siguientes propiedades (puedes copiar y pegar el texto desde esta misma página):
22 Action - android.intent.action.VIEW
23 ActivityClass - com.google.android.maps.MapsActivity
24 ActivityPackage - com.google.android.apps.maps
El diseño final tiene que quedar así:

El funcionamiento del programa será el siguiente:
Al pulsar el botón "Posición actual" nuestro programa nos dará nuestras coordenadas actuales que podremos localizar en el mapa de debajo o en la aplicación Google Maps pulsando el botón "Google".
Si pulsamos el botón "Guardar" aparecerá un campo de texto para que las coordenadas actuales se guarden en la base de datos con el nombre que queramos.
Al pulsar el botón "Mis Waypoints" aparecerá una lista con las localizaciones que hayamos guardado con anterioridad. Al seleccionar una de ellas se actualizará el mapa o pulsando el botón "Google" se abrirá la aplicación de mapas de Google con la localización guardada. Con las coordenadas guardadas podemos iniciar una ruta hasta esa posición desde nuestra posición actual.
25 Vamos al Editor de bloques
26 Vamos a empezar definiendo todas las variables que vamos a usar en nuestro programa.
27 codigo_google - "http://www.google.com/maps/?q=" Esta variable la utilizamos para comunicarnos con Google Maps.
28 nivel_zoom - "&z=18". Esta variable nos permite cambiar el nivel del zoom de los mapas de Google.
29 lista_coordenadas - make a list. Esta es la lista donde vamos a guardar las coordenadas de cada localización (waypoint) que guardemos.
30 lista_waypoints - make a list. En esta lista guardaremos los nombres de los waypoints.
31 coordenadas_actuales - "". Variable de texto vacía donde guardaremos las coordenadas actuales.
32 localizado - false. Esta variable booleana nos dirá si tenemos ya las coordenadas de nuestra posición actual o todavía no. Recuerda que el sensor de localización de posición (LocationSensor / GPS) tarda un tiempo en determinar nuestra posición actual. Esta variable nos dirá si tenemos ya la información.
33 Coge el evento Screen.Initialize.
Recuerda que el primer paso es siempre recuperar la información que tenemos en la base de datos tal y como hemos aprendido antes. De esta forma recuperamos los waypoints que tuviésemos guardados.
Nuestra base de datos contendrá dos listas. lista_waypoints con el tag "waypoints" y lista_coordenadas con el tag "coordenadas". La lista_waypoints contendrá los nombres de los waypoints y la lista_coordenadas las coordenadas. Tal y como hemos aprendido antes usaremos el índice para relacionar el nombre del waypoint con las coordenadas correspondientes a ese waypoint.
Como siempre también nos vamos a asegurar de que existen datos antes de asignarlos a la variable correspondiente de lo contrario se produciría un error en nuestro programa.
34 Coge un bloque de control if then-do.
35 En el espacio test coloca un bloque lógico not, un bloque de texto "is text empty?" y un procedimiento "call TinyDB.GetValue" con el tag "waypoints" así:

Estamos pidiendo a la base de datos algún dato con el tag "waypoints". Si nos devuelve algún dato (no está vacía la respuesta) entonces podemos continuar porque significa que tenemos algún waypoint guardado.
En el espacio then-do recuperamos los datos de las dos listas y se las asignamos a las variables que tenemos preparadas.
36 Coge un bloque "set global lista_waypoints" y pégale un procedimiento "call TinyDB.GetValue" con el tag "waypoints".
De esta forma cogemos de la base de datos el valor que corresponde con el tag "waypoints" y como se supone que es una lista, se la asignamos a la variable lista_waypoints.
Ahora hacemos lo mismo con la lista de coordenadas.
37 Coge un bloque "set global lista_coordenadas" y pégale un procedimiento "call TinyDB.GetValue" con el tag "coordenadas".
Ya tenemos las dos listas con los datos que hemos obtenido de la base de datos. Si no hubiésemos encontrado nada, las listas estarían vacías.
Vamos con el botón para mostrar en el mapa nuestra posición actual.
38 Coge el evento boton_posicion_actual.Click
Primero comprobamos que tenemos las coordenadas de nuestra posición actual.
39 Coge un bloque de control if then.
En el espacio if comprobamos la variable localizado.
40 Pega la variable "global localizado" en el espacio if
Si la variable es verdadera (la condición se cumple) significa que tenemos las coordenadas.
41 Coge un bloque "call WebViewer.GoToUrl" y ponlo dentro del espacio then.
42 Crea un bloque de text join y pégalo al bloque anterior.
43 En el primer espacio pon la variable "global codigo_google"
44 En el segundo espacio pon la variable "global coordenadas_actuales"
Este bloque le pide al visor web que nos muestre la URL que le estamos pasando y que contiene las coordenadas de la posición actual.
45 Coge el evento LocationSensor.LocationChanged.
Este evento se activa cuando cambiamos la localización de nuestro dispositivo, es decir, cuando nos movemos. Por lo tanto, cada vez que se activa, nos dice las nuevas coordenadas de nuestra posición. Vamos a usar este evento para actualizar nuestra variable coordenadas_actuales y mostrar la información en las etiquetas de la pantalla.
46 Coge el bloque "set global coordenadas_actuales"
47 Crea un bloque "join" y pégalo al bloque anterior.
48 Pega al bloque "join" la variable LocationSensor.Latitude
49 En el segundo espacio text pega un bloque de texto con una coma, así ","
50 En el siguiente espacio text pega la variable LocationSensor.Longitude
Ahora nuestra variable coordenadas_actuales contendrá un valor, p. eje.: "40.343421,-3.334344"
Vamos con las etiquetas.
51 Coge el bloque "set etiqueta_coordenadas.Text" y pégale un bloque "text join".
52 En el primer espacio pon un bloque de texto que diga: "Coordenadas actuales: "
53 En el segundo pon nuestra variable coordenadas_actuales
54 Coge el bloque "set etiqueta_direccion.Text" y pégale un bloque LocationSensor.CurrentAddress 
Este bloque busca la dirección que corresponde a las coordenadas actuales.
Por último, como tenemos las coordenadas de la posición actual, vamos a cambiar la variable lógica localizado.
55 Pon un bloque "set global localizado" y pégale un bloque lógico true.
56 Ahora que tenemos las coordenadas de nuestra posición actual vamos a aprender a guardarlas.
57 Coge el evento boton_guardar.Click.
58 Vamos a comprobar si realmente tenemos las coordenadas.
59 Coge un bloque de control if then
60 En el espacio if comprobamos la variable localizado.
60 Pega la variable "global localizado" en el espacio if
Si tenemos las coordenadas primero limpiamos el textbox y mostramos el menú para guardar.
61 Coge un bloque "set textbox_nombre_waypoint" y pégale un bloque de texto vacío: "".
62 Coge un bloque "set menu_guardar.Visible" y pégale un bloque lógico true. Así mostramos el menú para guardar con el textbox y el botón para guardar.
Recuerda que este menú corresponde con el componente HorizontalArragement menu_guardar que contiene a su vez el textbox_nombre_waypoint y el botón boton_guardar_waypoint. Cuando el usuario haya puesto un nombre al waypoint pulsará el botón boton_guardar_waypoint así que necesitamos controlar este evento.
63 Coge el evento boton_guardar_waypoint.Click
En este punto tenemos dos datos. Por una parte tenemos las coordenadas actuales en la variable coordenadas_actuales y por otra parte el nombre que queremos usar en la variable textbox_nombre_waypoint.Text. Vamos a añadir cada dato a su lista correspondiente.
64 Coge dos bloques "add items to list" y ponlos dentro.
65 En el espacio list del primer bloque pon nuestra lista "global lista_waypoints" 
66 En el espacio item pon un bloque "textbox_nombre_waypoint.Text
Con esto añadimos el nombre a la lista de waypoints.
67 En el espacio list del segundo bloque pon nuestra lista "global lista_coordenadas"
68 En el espacio item pon la variable "global coordenadas_actuales"
69 Con esto añadimos las coordenadas a nuestra lista.
Ahora que hemos actualizado las listas con los nuevos datos sólo tenemos que guardarlas en la base de datos.
70 Coge dos procedimientos "call TinyDB.StoreValue" y ponlos debajo.
71 En el espacio tag del primer bloque por un bloque de texto con el texto: "waypoints"
72 En el espacio valueToStore pon nuestra lista "global lista_waypoints"
73 En el espacio tag del segundo bloque por un bloque de texto con el texto: "coordenadas"
74 En el espacio valueToStore pon nuestra lista "global lista_coordenadas"
Con esto guardamos ambas listas en la base de datos usando el tag correspondiente a cada lista.
Sólo queda ocultar el menú.
75 Coge un bloque "set menu_guardar.Visible" y pégale un bloque lógico false.
Vamos a recuperar waypoints para mostrarlos en el mapa.
76 Coge el evento boton_mis_waypoints.BeforePicking
77 Dentro pon un bloque "set boton_mis_waypoints.Elements" y pégale la variable "global lista_waypoints"
78 Con esto el componente ListPicker mostrará los nombres de los waypoints que tengamos en nuestra lista.
79 Coge ahora un evento boton_mis_waypoints.AfterPicking
80 Pon dentro un procedimiento "call WebViewer.GoToUrl"
81 Pega al bloque anterior un bloque de texto join.
82 En el primer espacio pon la variable "global codigo_google"
83 En el segundo espacio pon un bloque "select list item"
84 En el espacio list pon la variable "global lista_coordenadas"
85 En el espacio index pon la variable boton_mis_waypoints.SelectionIndex
Al hacer esto estamos seleccionando de la lista de coordenadas aquellas cuyo índice coincide con el nombre que ha seleccionado el usuario de la lista de waypoints.
En este caso estamos mostrando las coordenadas en el mapa dentro del componente WebViewer. Para mostrar las coordenadas en la aplicación de Google Maps en lugar de usar este bloque "WebViewer.GoToUrl" tendríamos que usar los dos siguientes bloques:
Un bloque "set ActivityStarter.DataUri" más la misma cadena de texto que hemos usado antes.
Y un bloque ActivityStarter.StartActivity
Tu programa completo debe de quedar así:

A esta aplicación sólo le faltaría un botón para borrar waypoints que ya no necesitamos. ¿Te atreves a hacerlo? Una pista: necesitamos otro componente ListPicker.

 Rutas

Vamos a completar nuestro programa de waypoints para que podamos mostrar la ruta desde nuestra posición actual hasta el waypoint que queramos de los que tenemos guardados.
Recupera el programa "waypoints" y grábalo (Save as) con el nombre "rutas"
Desde el Diseñador vamos a añadir un componente ListPicker dentro del componente HorizontalArragement a la derecha del botón Mis Waypoints.
A este ListPicker le vamos a llamar boton_rutas
Cambia el texto del componente por: "Rutas" y ajusta su tamaño.
Vamos al Editor de bloques.
Lo primero que vamos a hacer es definir un par de variables más que vamos a necesitar para informar a Google Maps de que queremos que nos muestre una ruta en lugar de una posición en el mapa.
6 Crea la variable codigo_google_ruta_origen con un bloque de texto con el texto: "http://maps.google.com/ maps?saddr="
Esta variable contiene la URL que necesita Google Maps además de las coordenadas de origen de la ruta que queremos. En nuestro caso contendrá nuestra posición actual desde la que comenzaramos la ruta hasta nuestro waypoint.
 Crea otra variable llamada codigo_google_ruta_destino con un bloque de texto con el texto: "&daddr="
Esta variable contendrá las coordenadas del destino de la ruta que queremos. Juntando ambos bloques construímos la URL definitiva que necesitamos pasar a Google Maps.
Ahora coge el evento boton_rutas.BeforePicking
Necesitamos tener la coordenadas actuales para poder hacer la ruta, así que necesitamos asegurarnos primero de que la variable localizado es verdadera.
Coge un bloque de control if then y en el campo test pon la variable localizado.
10 Ahora dentro del evento pon un bloque "set boton_rutas.Elements" y pégale la variable "global lista_waypoints"
11 Coge el evento boton_rutas.AfterPicking y copia dentro los bloques del evento boton_mis_waypoints.AfterPicking.
La URL que tenemos que montar consiste en los bloques codigo_google_ruta_origen + coordenadas_actuales + codigo_google_rutas_destino + coordenadas del destino. Este último dato lo sacamos de la lista de coordenadas uando el índice de la lista de waypoints, tal y como hemos hecho antes.
12 Crea un bloque de texto join y haz que tenga cuatro espacios.
13 En el primer espacio pon la variable codigo_google_ruta_origen
14 En el segundo la variable coordenadas_actuales.
15 En el tercero la variable codigo_google_ruta_destino.
16 En el último coge el bloque "select list item" que teníamos antes.
17 Pruébalo!
Recuerda que puedes usar el componente ActivityStarter para abrir Google Maps tal y como hemos aprendido antes.