Trabajar con la muestra de Core Map y Location
Published: 2021-03-10 16:17:27

![Alt text of image](https://miro.medium.com/max/1050/1*E_M3iMzMgivQPz8GRda00A.png)
Si bien los usos de un servicio Huawei Core podrían ser muy poderosos para lograr un mejor compromiso y mejorar la experiencia del usuario, es solo un pequeño paso para el mejor uso que se puede hacer con las herramientas proporcionadas por HMS Core. Dado que algunos de nuestros kits son altamente sinérgicos, alojarlos en la misma aplicación, o incluso en la misma actividad, es más fácil de lo que parece.
En esta publicación estaremos revisando una implementación fácil para los mapas que se muestra como una guía rápida para las combinaciones dentro de la misma actividad, la pantalla mostrará el mapa directamente en la ubicación de los usuarios, siempre y cuando den el permiso, y la direcciones reales obtenidas del servicio de Huawei.
Desarrollo
Los primeros pasos siempre serán los mismos para la integración de servicios, ya que aquí se explica, es más fácil para el desarrollador verificarlo directamente aquí:
https://developer.huawei.com/consumer/en/codelab/HMSPreparation/index.html#0

Después de estos primeros pasos de generar la aplicación en la consola, obtendremos el archivo gradle a nivel de la aplicación que usamos estas dependencias, ya que puede verificar los mapas, ubicaciones y bibliotecas de sitios más actualizados, usaremos las versiones 4.0.1
```
dependencies {
    implementation fileTree(dir: 'libs', include: ['*.jar'])

    implementation 'androidx.appcompat:appcompat:1.1.0'
    implementation 'androidx.constraintlayout:constraintlayout:1.1.3'
    testImplementation 'junit:junit:4.12'
    androidTestImplementation 'androidx.test.ext:junit:1.1.1'
    androidTestImplementation 'androidx.test.espresso:espresso-core:3.2.0'

    implementation 'com.huawei.hms:maps:4.0.1.301'
    implementation 'com.huawei.hms:location:4.0.1.300'
    implementation 'com.huawei.hms:site:4.0.1.300'
}
```
Importante considerar chequear en la consola que la app tiene habilitados estos tres servicios, esto puede afectar el resultado final de este proyecto, luego de verificar dentro del proyecto que la compilación es exitosa, el siguiente paso será generar una nueva actividad la cual contienen el mapa en sí, en este ejemplo estamos usando la actividad principal.
Una vez que tengamos la actividad principal para el mapa, el diseño será rápido considerando que la mayoría de los elementos son administrados directamente por el servicio, solo necesitaremos un Diseño de Vista de Mapa y una Vista de Texto, en este caso la configuración para este ejemplo es lo siguiente dentro de un diseño de restricción:
```
<?xml version="1.0" encoding="utf-8"?>
 <androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
     xmlns:app="http://schemas.android.com/apk/res-auto"
     xmlns:tools="http://schemas.android.com/tools"
     android:layout_width="match_parent"
     android:layout_height="match_parent"
     tools:context=".MainActivity">
 
     <com.huawei.hms.maps.MapView
         android:id="@+id/mapView"
         android:layout_width="match_parent"
         android:layout_height="match_parent"
         app:cameraTargetLat="48.893478"
         app:cameraTargetLng="2.334595"
         app:cameraZoom="10"
         app:layout_constraintEnd_toEndOf="parent"
         app:layout_constraintHorizontal_bias="1.0"
         app:layout_constraintStart_toStartOf="parent"
         app:layout_constraintTop_toTopOf="parent">
     </com.huawei.hms.maps.MapView>
 
     <TextView
         android:id="@+id/locationText"
         android:layout_width="match_parent"
         android:layout_height="100dp"
         android:background="#FFFFFF"
         android:text="TextView"
         android:textAlignment="center"
         android:textSize="24sp"
         android:visibility="visible"
         app:layout_constraintBottom_toBottomOf="parent"
  />
 
 </androidx.constraintlayout.widget.ConstraintLayout>
```
Una vez finalizado el diseño, ahora nos ocuparemos del lado de los permisos, ya que en las últimas versiones de los sdks se requiere tener el permiso explícito del usuario para obtener su ubicación, usaremos un método fácil para esta instancia, el método utiliza una Lista de los permisos de String declarados como una variable final estática, solicitando los siguientes permisos, no siendo todos imperativos, pero los recomendados para el mejor rendimiento:
```
private static final String[] RUNTIME_PERMISSIONS = {
         Manifest.permission.WRITE_EXTERNAL_STORAGE,
         Manifest.permission.READ_EXTERNAL_STORAGE,
         Manifest.permission.ACCESS_COARSE_LOCATION,
         Manifest.permission.ACCESS_FINE_LOCATION,
         Manifest.permission.INTERNET
 };
```
Además la función que usaremos es sencilla, ya que su única finalidad es comprobar si el usuario ya dio el permiso, y en caso de que no lo sea, volver a pedir el permiso, comprobando cada uno de los permisos en caso es necesario
```
private static boolean hasPermissions(Context context, String... permissions) {
     if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M && permissions != null) {
         for (String permission : permissions) {
             if (ActivityCompat.checkSelfPermission(context, permission) != PackageManager.PERMISSION_GRANTED) {
                 return false;
             }
         }
     }
     return true;
 }
```
En este ejemplo específico, este método se llama en la parte OnCreate del ciclo de vida de la aplicación, aquí también invocaremos el paquete de mapas para las instancias anteriores guardadas en caso de que las haya, y para obtener el cliente del proveedor de ubicación, ya que estos dos es básico para esta actividad, para la generación de mapas y obtención de información de los servicios
```
mFusedLocationProviderClient = LocationServices.getFusedLocationProviderClient(this);
 
 if (!hasPermissions(this, RUNTIME_PERMISSIONS)) {
     ActivityCompat.requestPermissions(this, RUNTIME_PERMISSIONS, REQUEST_CODE);
 }
 
 mMapView = findViewById(R.id.mapView);
 Bundle mapViewBundle = null;
 if (savedInstanceState != null) {
     mapViewBundle = savedInstanceState.getBundle(MAPVIEW_BUNDLE_KEY);
 }
 mMapView.onCreate(mapViewBundle);
 mMapView.getMapAsync(this);
 setLastLocation();
```
La última función que se muestra aquí para OnCreate es la que nos permitirá obtener las direcciones y la ubicación actual para el usuario, y esta fácil implementación nos permite generar esta función más interesante que es buena para nuestro mapa y mejora la funcionalidad simple de ella.
```
private void setLastLocation() {
     try {
         LocationRequest locReq = new LocationRequest();
         locReq.setNeedAddress(true);
         Task<HWLocation> lastLocation = mFusedLocationProviderClient.getLastLocationWithAddress(locReq);
         if (lastLocation == null) {
             Log.i(TAG, "setLastLocation got null location");
             return;
         }
         lastLocation.addOnSuccessListener(new OnSuccessListener<HWLocation>() {
             @Override
             public void onSuccess(HWLocation location) {
                 if (location == null) {
                     Log.i(TAG, "setLastLocation got null location");
                     return;
                 }
                 double latitude = location.getLatitude();
                 double longitude = location.getLongitude();
                 LatLng latLng1 = new LatLng(latitude, longitude);
                 CameraUpdate cameraUpdateLocation = CameraUpdateFactory.newLatLng(latLng1);
                 float zoom = 16.0f;
                 CameraUpdate cameraUpdateZoom = CameraUpdateFactory.zoomTo(zoom);
                 hMap.moveCamera(cameraUpdateLocation);
                 hMap.moveCamera(cameraUpdateZoom);
                 String address = location.getFeatureName() + " " + location.getStreet() + ", " +
                         location.getCity() + ", " + location.getState();
                 TextView locationText = findViewById(R.id.locationText);
                 locationText.setText(address);
             }
         }).addOnFailureListener(new OnFailureListener() {
             @Override
             public void onFailure(Exception e) {
                 Log.e(TAG, "setLastLocation onFailure:" + e.getMessage());
             }
         });
     } catch (Exception e) {
         Log.e(TAG, "setLastLocation exception:" + e.getMessage());
     }
 }
```
Finalmente, para que lo verifique, puede encontrar el código aquí en este repositorio público y disfrutar de esta sencilla integración que puede ser muy útil para muchos casos en una implementación de mapa simple con las características de ubicación incluidas.
https://github.com/NprezB/HuaweiMapIntegation