Ubícate con Huawei Maps y Location Kit

Daniel Mendoza
Huawei Developers Latinoamérica
6 min readDec 7, 2020

¿Ya conoces Map Kit y Location Kit? Si esta es la primera vez que implementas estos kits, esta será una guía breve con Kotlin, pero primero, conozcamos un poco más acerca de estos kits.

Map Kit

  • Nos permite visualizar mapas interactivos en nuestras apps
  • Muestra en pantalla información sobre carreteras, ríos y puntos de interés
  • Soporta gestos de interacción del usuario

Location kit

  • Datos de geolocalización del usuario con un alto rango de precisión (hasta 99%).
  • Bajo consumo de energia
  • Sistema de posiciónamiento híbrido (GPS + WiFi + Bluetooth + Estación Base)

Pasos de implementación

  1. Crear una app en AppGallery Connect
  2. Conectar nuestro proyecto Android con AppGallery Connect
  3. Agregar las dependencias necesarias
  4. Agregar los permisos requeridos en el Android Manifest
  5. Agregar la navegación hacia la pantalla del mapa
  6. Implementar el mapa
  7. Programar una utilidad GPS
  8. Implementar Location Kit en el mapa
  9. Ejecutar la app

Creando la app en AGC

¿Cómo configuro mi app en AppGallery Connect? Para crear una app en AppGallery Connect debes crear primero un proyecto y agregarle una app. Un proyecto nuevo tendrá habilitadas por defecto las APIs de Map y Location.

Conectando nuestro proyecto android con AGC

Crea un nuevo proyecto de Android desde Android Studio y selecciona Kotlin como lenguaje de desarrollo. Genera la firma de tu app y configura su huella digital en AppGallery. Para más información sobre este proceso puedes realizar el Codelab.

Agregando las Dependencias

Para tener acceso a los kits de HMS debes agregar el repositorio Maven de Huawi al archivo build.gradle a nivel de proyecto.

repositories {google()jcenter()//TODO 1 : Add repomaven {url 'http://developer.huawei.com/repo/' }}

Cada kit de HMS debe ser agregado a la lista de dependencias del archivo build.gradle para poder usarse. El siguiente código incluye las dependencias de Map y Location.

//TODO 4 : Add plugin extension kotlinid 'kotlin-android-extensions'//TODO 5 : add plugin agconnectid 'com.huawei.agconnect'implementation 'com.huawei.hms:maps:5.0.3.302'implementation 'com.huawei.hms:location:4.0.4.300'

Agregando los permisos necesarios

Los kits de Maps y Location dependen de los permisos de Internet y Ubicación agrega los siguientes permisos a tu archivo Android Manifest.

<uses-permission android:name="android.permission.ACCESS_FINE_LOCATION" /><uses-permission android:name="android.permission.ACCESS_COARSE_LOCATION" /><uses-permission android:name="android.permission.INTERNET" /><uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" /><uses-permission android:name="com.huawei.appmarket.service.commondata.permission.GET_COMMON_DATA"/>

Navegando Hacia el Mapa

Suponiendo que la actividad que contiene el mapa es una de las muchas pantallas que puede desplegar tu aplicación, vamos a añadir un botón al MainActivity para navegar hacia nuestra MapActivity.

<Button
android:id="@+id/buttonMap"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="Button"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent" />

Al usar las kotlin extensions accederemos al botón al llamarlo mediante su id.

import kotlinx.android.synthetic.main.activity_main.*buttonMap.setOnClickListener {val intent = Intent(this, MapActivity::class.java)startActivity(intent)}

Programando el Map Activity

El SDK de Huawei maps nos devuelve un mapa de forma asíncrona, por lo que primero debemos definir una variable para recuperarlo cuándo esté listo.

private var hMap: HuaweiMap? = null

A partir de la versión 5 de MapKit, debemos especificar el API key de nuestra app antes de cargar el mapa. Esta key se puede obtener desde el archivo agconnect-services.json que te proporciona AppGallery Connect al crear tu proyecto.

private val KEY="CgB6e3x9MfG9UoNFEONJ5GQvShJkNwYqQh98MxgohKPS1/jINpMYbkFFO+Om1iT7yzbjjkiyIRvdeCN+rQ7PP6aT"

Ahora inicializa el MapKit con tu API key

MapsInitializer.setApiKey(KEY)

Ahora agrega los métodos de ciclo de vida de tu activity para controlar el ciclo de vida del mapa.

private fun initHuaweiMap(savedInstanceState: Bundle?) {var mapViewBundle: Bundle? = nullif (savedInstanceState != null) {mapViewBundle = savedInstanceState.getBundle(MAPVIEW_BUNDLE_KEY)}mapView?.apply {onCreate(mapViewBundle)getMapAsync(this@MapActivity)}}override fun onMapReady(map: HuaweiMap?) {if (map != null) {hMap = maphMap?.isMyLocationEnabled = true // Enable the my-location overlay.hMap?.uiSettings?.isMyLocationButtonEnabled = true // Enable the my-location icon.val location= LatLng(19.4978,-99.1269)val update= CameraUpdateFactory.newLatLngZoom(location, 10.0f)hMap!!.clear()hMap!!.animateCamera(update)}} override fun onStart() {mapView?.onStart()super.onStart()}override fun onStop() {mapView?.onStop()super.onStop()}override fun onPause() {mapView?.onPause()super.onPause()}override fun onDestroy() {mapView?.onDestroy()super.onDestroy()}override fun onResume() {mapView?.onResume()super.onResume()}override fun onLowMemory() {mapView?.onLowMemory()super.onLowMemory()}

Programando la utilidad GPS

Vamos a crear una clase GPS que contenga toda la funcionalidad de Location Kit.

public class GPS(val context: Context) : LocationCallback() {private val TAG = "GPS Tracker"var isStarted:Boolean=falsevar gpsEventListener:OnGPSEventListener? =nullprivate val fusedLocationProviderClient: FusedLocationProviderClient =LocationServices.getFusedLocationProviderClient(context)fun startLocationsRequest(interval: Long =1000) {val settingsClient: SettingsClient = LocationServices.getSettingsClient(context)val mLocationRequest = LocationRequest()mLocationRequest.interval = intervalmLocationRequest.priority = LocationRequest.PRIORITY_HIGH_ACCURACYval builder = LocationSettingsRequest.Builder()builder.addLocationRequest(mLocationRequest)val locationSettingsRequest = builder.build()settingsClient.checkLocationSettings(locationSettingsRequest).addOnSuccessListener {Log.i(TAG, "check location settings success")//request location updatesfusedLocationProviderClient.requestLocationUpdates(mLocationRequest,this,Looper.getMainLooper()).addOnSuccessListener{Log.i(TAG,"requestLocationUpdatesWithCallback onSuccess")isStarted=true}.addOnFailureListener{ e ->Log.e(TAG,"requestLocationUpdatesWithCallback onFailure:" + e.message)}}.addOnFailureListener { e ->Log.e(TAG, "checkLocationSetting onFailure:" + e.message)val apiException: ApiException = e as ApiExceptionwhen (apiException.statusCode) {LocationSettingsStatusCodes.RESOLUTION_REQUIRED -> {Log.e(TAG, "Resolution required")gpsEventListener?.onResolutionRequired(e)}}}}fun removeLocationUpdatesWithCallback() {try {fusedLocationProviderClient.removeLocationUpdates(this).addOnSuccessListener{isStarted=falseLog.i(TAG,"removeLocationUpdatesWithCallback onSuccess")}.addOnFailureListener{ e ->Log.e(TAG,"removeLocationUpdatesWithCallback onFailure:" + e.message)}} catch (e: Exception) {Log.e(TAG, "removeLocationUpdatesWithCallback exception:" + e.message)}}override fun onLocationResult(locationResult: LocationResult?) {if (locationResult != null) {val locations: List<Location> = locationResult.locationsval lastLocation=locationResult.lastLocationgpsEventListener?.onLastKnownLocation(lastLocation.latitude,lastLocation.longitude)if (locations.isNotEmpty()) {for (location in locations) {Log.e(TAG,"onLocationResult location[Longitude,Latitude,Accuracy]:" + location.getLongitude().toString() + "," + location.getLatitude().toString() + "," + location.getAccuracy())}}}}interface OnGPSEventListener {fun onResolutionRequired(e: Exception)fun onLastKnownLocation(lat:Double, lon:Double)}}

Agregando Location Kit a nuestro MapActivity

Ahora que tenemos nuestra clase GPS podemos usarla dentro de nuestra MapActivity, siempre y cuando el usuario conceda los permisos de ubicación.

private fun checkLocationPermissions(): Boolean {val location:Int = ContextCompat.checkSelfPermission(this, Manifest.permission.ACCESS_FINE_LOCATION) or ContextCompat.checkSelfPermission(this, Manifest.permission.ACCESS_COARSE_LOCATION)val backgroundLocation= if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.Q) {ContextCompat.checkSelfPermission(this, Manifest.permission.ACCESS_BACKGROUND_LOCATION)} else {PackageManager.PERMISSION_GRANTED}return location== PackageManager.PERMISSION_GRANTED&&backgroundLocation== PackageManager.PERMISSION_GRANTED}private fun requestLocationPermissions() {if (ContextCompat.checkSelfPermission(this@MapActivity,Manifest.permission.ACCESS_FINE_LOCATION) !==PackageManager.PERMISSION_GRANTED) {if (ActivityCompat.shouldShowRequestPermissionRationale(this@MapActivity,Manifest.permission.ACCESS_FINE_LOCATION)) {ActivityCompat.requestPermissions(this@MapActivity,arrayOf(Manifest.permission.ACCESS_FINE_LOCATION), 1)} else {ActivityCompat.requestPermissions(this@MapActivity,arrayOf(Manifest.permission.ACCESS_FINE_LOCATION), 1)}}}

Sobreescribe el método onRequestPermissionResult para obtener el resutlado de la solicitud.

override fun onRequestPermissionsResult(requestCode: Int,permissions: Array<out String>,grantResults: IntArray) {when (requestCode) {1 -> {if (grantResults.isNotEmpty() && grantResults[0] ==PackageManager.PERMISSION_GRANTED) {if ((ContextCompat.checkSelfPermission(this@MapActivity,Manifest.permission.ACCESS_FINE_LOCATION) ===PackageManager.PERMISSION_GRANTED)) {Toast.makeText(this, "Permission Granted", Toast.LENGTH_SHORT).show()}} else {Toast.makeText(this, "Permission Denied", Toast.LENGTH_SHORT).show()}return}}}

Si el resultado es positivo, podremos inicializar nuestra clase GPS

private lateinit var gps: GPS

Puedes añadir una verificación al método onCreate para saber si la app ya cuenta con los permisos.

if(checkLocationPermissions()){setupGPS()}else{requestLocationPermissions()}

Definamos un método para inicializar nuestra clase GPS

private fun setupGPS() {gps= GPS(this)gps.gpsEventListener=thisgps.startLocationsRequest()}

Corriendo la App

Al completar todos los pasos anteriores, serás capaz de visualizar tu ubicación en el mapa.

Referencias

https://developer.huawei.com/consumer/en/hms/huawei-MapKit/

https://developer.huawei.com/consumer/en/hms/huawei-locationkit/

--

--