Bienvenidos sean a este nuevo post, en el caso de hoy volveremos a una de las apps creadas anteriormente y en este caso es Mis Lugares al cual le agregaremos la opcion de Mapa para ello deberemos hacer una serie de modificaciones para poder implementarlo y para ello deberemos hacer algunos pasos, primero deberas tener la aplicacion Mis Lugares sino la tienes te recomiendo estos posts:

Anuncios

Nuestro siguiente paso sera utilizar la clave para Google Maps, la cual creamos en este post, te recomiendo crear una nueva pero esta vez para el paquete de Mis Lugares, utilicen el dominio que eligieron (en mi caso use com.tinchicus.mislugares) asi que deben crear uno nuevo y lo utilizan en este ejemplo, una vez generada deberemos implementar el complemento de google play para poder utilizar a google maps, para ello les recomiendo este post donde explico paso a paso como habilitar el componente de Google Play Services, una vez habilitado en nuestra app Mis Lugares deberemos hacer las siguientes modificaciones, para ello abriremos primero el archivo AndroidManifest.xml y agregaremos el siguiente bloque dentro del elemento application:

<meta-data
    android:name="com.google.android.gms.version"
    android:value="@integer/google_play_services_version" />
<meta-data
    android:name="com.google.android.maps.v2.API_KEY"
    android:value="AIzaSyCYvGZJmuAni3cS944NJrBn3pEoFMxRQAo" />

Esta nos permitira utilizar la API de Google Maps para ello debemos informarle la clave que generamos previamente, no utilicen la que informo en el ejemplo porque estas son unicas para cada usuario y puede generar un error, nuestra siguiente modificacion sera el siguiente bloque por fuera del elemento application:

Anuncios
    <permission
        android:name="org.example.mislugares.permission.MAPS_RECEIVE"
        android:protectionLevel="signature" />
    <uses-permission
        android:name="org.example.mislugares.permission.MAPS_RECEIVE" />
    <uses-permission
        android:name="org.example.mislugares.permission.READ_GSERVICES" />
    <uses-permission
        android:name="android.permission.INTERNET" />
    <uses-permission
        android:name="android.permission.ACCESS_NETWORK_STATE" />
    <uses-feature android:glEsVersion="0x00020000"
        android:required="true" />

Estas lineas se encargaran de conceder los permisos necesarios para nuestra app, Estos son para leer la memoria, tener acceso a la ubicacion (ACCESS_FINE_LOCATION, READ_GSERVICES) y tambien acceso a los mapas (MAPS_RECEIVE) la otra modificacion que deben realizar es reemplazar el nombre del paquete com.tinchicus.mislugares por el que hayan usado, p.e. com.example.mislugares, el resto puede quedar como aparece.

Con todas nuestras modificaciones realizadas procederemos a trabajar sobre nuestra app, para ello debemos crear un nuevo layout, para ello debemos hacer click con el boton derecho sobre la carpeta layout dentro del recurso res y seleccionar New -> Layout resource file, cuando aparezca el nuevo cuadro modifiquen el campo Name por mapa, en Root element modifiquenlo por RelativeLayout, el resto debe quedar como aparece y pulsen Ok, cuando se haya generado el nuevo layout lo modificaremos por el siguiente codigo:

<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout
    xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="match_parent">
    <fragment
        android:id="@+id/mapa"
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        class="com.google.android.gms.maps.SupportMapFragment" />
</RelativeLayout>

Este layout es simple y nos permitira mostrar el mapa, la parte que hara la magia es fragment, un elemento que vimos en este post, nuestro siguiente paso sera crear la clase Java para poder manipularlo, para ello haremos click con el boton derecho sobre el contenedor de clases Java y seleccionaremos New -> Java Class, en el cuadro que aparezca modifiquen el campo Name con Mapa, el resto debe quedar como aparece y pulsen Ok para cerrar el cuadro y generar la nueva clase. Al codigo existente reemplacenlo por el siguiente:

package org.example.mislugares;

import android.content.Intent;
import android.graphics.Bitmap;
import android.graphics.drawable.BitmapDrawable;
import android.os.Bundle;
import android.support.v4.app.FragmentActivity;

import com.google.android.gms.maps.CameraUpdateFactory;
import com.google.android.gms.maps.GoogleMap;
import com.google.android.gms.maps.OnMapReadyCallback;
import com.google.android.gms.maps.SupportMapFragment;
import com.google.android.gms.maps.model.BitmapDescriptorFactory;
import com.google.android.gms.maps.model.LatLng;
import com.google.android.gms.maps.model.Marker;
import com.google.android.gms.maps.model.MarkerOptions;

public class Mapa extends FragmentActivity
        implements GoogleMap.OnInfoWindowClickListener, OnMapReadyCallback {

    private GoogleMap mapa;

    @Override
    public void onCreate(Bundle savedInstanceState){
        super.onCreate(savedInstanceState);
        setContentView(R.layout.mapa);
        ((SupportMapFragment) getSupportFragmentManager()
                .findFragmentById(R.id.mapa)).getMapAsync(this);
    }

    @Override
    public void onInfoWindowClick(Marker marcador){
        for(int id=0;id < Lugares.vectorLugares.size(); id++){
            if(Lugares.vectorLugares.get(id).getNombre()
                    .equals(marcador.getTitle())){
                Intent intento = new Intent(this,VistaLugar.class);
                intento.putExtra("id",(long) id);
                startActivity(intento);
                break;
            }
        }
    }

    @Override
    public void onMapReady(GoogleMap map){
        mapa = map;
        mapa.setMapType(GoogleMap.MAP_TYPE_NORMAL);
        mapa.setMyLocationEnabled(true);
        mapa.getUiSettings().setZoomControlsEnabled(true);
        mapa.getUiSettings().setCompassEnabled(true);
        if(Lugares.vectorLugares.size() > 0) {
            GeoPunto p = Lugares.vectorLugares.get(0).getPosicion();
            mapa.moveCamera(CameraUpdateFactory.newLatLngZoom(
                    new LatLng(p.getLatitud(),p.getLongitud()),12));
        }
        for(Lugar lugar: Lugares.vectorLugares) {
            GeoPunto p = lugar.getPosicion();
            if (p != null && p.getLatitud() != 0) {
                BitmapDrawable iconoDrawable = (BitmapDrawable) getResources()
                        .getDrawable(lugar.getTipo().getRecurso());
                Bitmap iGrande = iconoDrawable.getBitmap();
                Bitmap icono = Bitmap.createScaledBitmap(iGrande,
                        iGrande.getWidth() / 7, iGrande.getHeight() / 7,
                        false);
                mapa.addMarker(new MarkerOptions()
                        .position(new LatLng(p.getLatitud(), p.getLongitud()))
                        .title(lugar.getNombre())
                        .snippet(lugar.getDireccion())
                        .icon(BitmapDescriptorFactory.fromBitmap(icono))
                );
            }
        }
    }
}
Anuncios

Este codigo parece dificil pero no lo es, primero haremos a nuestra clase heredera de la clase FragmentActivity y a su vez implementara dos clases una va a ser OnInfoWindowClickListener, la cual estara a atenta a cuando se haga click sobre alguno de los lugares, y la otra sera OnMapReadyCallback la cual se encargara de darnos la capacidad de utilizar la API de Google Maps, despues crearemos un objeto de la clase GoogleMap llamado mapa, en el metodo onCreate tendremos este bloque:

        ((SupportMapFragment) getSupportFragmentManager()
                .findFragmentById(R.id.mapa)).getMapAsync(this);

El cual se encargara de monitorear y representar a nuestro mapa, todos los elementos y acciones sobre ella, despues estara el metodo onInfoWindowClick() el cual se encargara de generar los datos de nuestro marcador, donde por medio de un bucle for obtendremos todos los lugares almacenados en Lugares y luego por medio del id iremos obteniendo los datos en base al lugar seleccionado, nuestro siguiente metodo sera onMapReady(), el cual se encarga de monitorear todo los cambios y acciones sobre el fragmento de mapa, con ello estableceremos algunos parametros, como la interfaz de usuario, o que muestre nuestra ubicacion, tambien obtendremos todos los datos almacenados en Lugares y los representara en pantalla, desde el icono hasta la ubicacion, tanto como el domicilio o el nombre del lugar.

Para nuestra siguiente modificacion debemos ir a AndroidManifest.xml donde agregaremos la siguiente linea dentro del elemento application:

<activity android:name=".Mapa" android:screenOrientation="portrait" />

Con esta accion crearemos a nuestra nueva actividad y seteara que la orientacion sea unicamente de tipo retrato (portrait), la cual evitara que se resetee nuestro mapa cuando movamos el dispositivo accidentalmente, nuestra siguiente accion sera modificar el menu del lugar para poder acceder a nuestra nueva actividad, para ello primero iremos al archivo menu_main.xml ubicado en el recurso res/menu/menu_main.xml y agregaremos el siguiente elemento:

Anuncios
<item android:title="mapa"
    android:id="@+id/menu_mapa"
    android:icon="@android:drawable/ic_menu_myplaces"
    android:orderInCategory="100"
    app:showAsAction="always" />

Este bloque se encargara de crear el item para nuestro menu, setearemos el nombre, el id y el icono, nuestra siguiente modficacion sera en la clase MainActivity donde agregaremos el siguiente bloque dentro del metodo onOptionsItemSelected():

if (id == R.id.menu_mapa){
    Intent intento = new Intent(this, Mapa.class);
    startActivity(intento);
}

Este bloque unicamente se encarga de detectar si el item antes creado fue pulsado, en caso de ser cierto procede a crear la nueva actividad relacionada con la clase Mapa y la ejecuta. Antes de continuar veamos como quedo nuestro archivo AndroidManifest.xml:

<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
    package="org.example.mislugares">

    <application
        android:allowBackup="true"
        android:icon="@mipmap/ic_launcher"
        android:label="@string/app_name"
        android:roundIcon="@mipmap/ic_launcher_round"
        android:supportsRtl="true"
        android:theme="@style/AppTheme">
        <activity android:name=".MainActivity">
            <intent-filter>
                <action android:name="android.intent.action.MAIN" />
                <action android:name="android.media.action.IMAGE_CAPTURE" />

                <category
                    android:name="android.intent.category.LAUNCHER" />
            </intent-filter>
        </activity>
        <activity android:name=".AcercaDe"
            android:label="Acerca De..."
            android:theme="@android:style/Theme.Dialog" />
        <activity android:name=".VistaLugar"
            android:label="@string/menu_buscar" />
        <activity android:name=".EdicionLugar"
            android:label="Editar" />
        <activity android:name=".Mapa" android:screenOrientation="portrait" />
        <meta-data
            android:name="com.google.android.gms.version"
            android:value="@integer/google_play_services_version" />
        <meta-data
            android:name="com.google.android.maps.v2.API_KEY"
            android:value="AIzaSyCYvGZJmuAni3cS944NJrBn3pEoFMxRQAo" />
    </application>
    <uses-permission
        android:name="android.permission.READ_EXTERNAL_STORAGE" />
    <uses-permission
        android:name="android.permission.ACCESS_FINE_LOCATION" />
    <permission
        android:name="org.example.mislugares.permission.MAPS_RECEIVE"
        android:protectionLevel="signature" />
    <uses-permission
        android:name="org.example.mislugares.permission.MAPS_RECEIVE" />
    <uses-permission
        android:name="org.example.mislugares.permission.READ_GSERVICES" />
    <uses-permission
        android:name="android.permission.INTERNET" />
    <uses-permission
        android:name="android.permission.ACCESS_NETWORK_STATE" />
    <uses-feature android:glEsVersion="0x00020000"
        android:required="true" />
</manifest>

Con todas estas modificaciones realizadas podemos finalmente probar nuestra app y obtendremos un resultado como se ve en el siguiente video

Como pueden ver en el video ahora tenemos una opcion para poder visualizar el mapa con nuestros lugares en el mismo y si hacemos click sobre alguno de ellos podemos ver la informacion pertinente.

Anuncios

En resumen, hemos visto como implementar SupportMapFragment en nuestra app llamada Mis Lugares, como hemos creado una opcion para mostrarla, como pudimos mostrar informacion adicional sobre la misma, como generar el icono y su ubicacion en el mapa, espero les haya sido util sigueme en Twitter o Facebook para recibir una notificacion cada vez que subo un nuevo post en este blog, nos vemos en el proximo post.

Tambien podes donar

Es para mantenimiento del sitio, gracias!

$1.00