[Huawei Developers] Freemind R:
This article is originally from HUAWEI Developer Forum

Forum link: https://forums.developer.huawei.com/forumPortal/en/home​

All About Maps

Let's talk about maps. I started an open source project called All About Maps (https://github.com/ulusoyca/AllAboutMaps). In this project I aim to demonstrate how we can implement the same map related use cases with different map providers in one codebase. We will use Mapbox Maps, Google Maps, and Huawei HMS Map Kit. This project uses following libraries and patterns:

MVVM pattern with Android Jetpack Libraries

Kotlin Coroutines for asynchronous operations

Dagger2 Dependency Injection

Android Clean Architecture

Note: The codebase changes by time. You can always find the latest code in develop branch. The code when this article is written can be seen by choosing the tag: episode_1-parse-gpx:

https://github.com/ulusoyca/AllAboutMaps/tree/episode_1-parse-gpx/

Motivation

Why do we need maps in our apps? What are the features a developer would expect from a map SDK? Let's try to list some:

Showing a coordinate on a map with camera options (zoom, tilt, latitude, longitude, bearing)

Adding symbols, photos, polylines, polygons to map

Handle user gestures (click, pinch, move events)

Showing maps with different map styles (Outdoor, Hybrid, Satallite, Winter, Dark etc.)

Data visualization (heatmaps, charts, clusters, time-lapse effect)

Offline map visualization (providing map tiles without network connectivity)

Generate snapshot image of a bounded region

We can probably add more items but I believe this is the list of features which all map provider companies would most likely provide. Knowing that we can achieve the same tasks with different map providers, we should not create huge dependencies to any specific provider in our codebase. When a product owner (PO) tells to developers to switch from Google Maps to Mapbox Maps, or Huawei Maps, developers should never see it as a big deal. It is software development. Business as usual.

One would probably think why a PO would want to switch from one map provider to another. In many cases, the reason is not the technical details. For example, Google Play Services may not be available in some devices or regions like China. Another case is when a company X which has a subscription to Mapbox, acquires company Y which uses Google Maps. In this case the transition to one provider is more efficient. Change in the terms of services, and pricing might be other motivations.

We need competition in the market! Let's switch easily when needed but how dependencies make things worse? Problematic dependencies in the codebase are usually created by developing software like there is no tomorrow. It is not always developers' fault. Tight schedules, anti-refactoring minded teams, unorganized plannings may cause careless coding and then eventually to technical depts. In this project, I aim to show how we can encapsulate the import lines below belonging to three different map providers to minimum number of classes with minimum lines:

import com.huawei.hms.maps.*
import com.google.android.gms.maps.*
import com.mapbox.mapboxsdk.maps.*

It should be noted that the way of achieving this in this post is just one proposal. There are always alternative and better ways of implementations. In the end, as software developers, we should deliver our tasks time-efficiently, without over-engineering.

About the project

In the home page of the project you will see the list of tutorials. Since this is the first blog post, there is only one item for now. To make our life easier with RecyclerViews, I use Epoxy library by Airbnb in the project. Once you click the buttons in the card, it will take to the detail page. Using bottom sheet we can switch between map providers. Note that Huawei Map Kit requires a Huawei mobile phone.

[IMG="https://communityfile-dre.op.hicloud.com/FileServer/getFile/cmtybbs/023/288/729/5190358000023288729.20200528181208.43728211170800647509226688196803:50510609105638:2800:FF46AE5633DF3E175A55299E511C2EC637ECC5A0C8C8C3FC0E6E05A3F5DAB354.png"]https://communityfile-dre.op.hicloud.com/FileServer/getFile/cmtybbs/023/288/729/5190358000023288729.20200528181208.43728211170800647509226688196803:50510609105638:2800:FF46AE5633DF3E175A55299E511C2EC637ECC5A0C8C8C3FC0E6E05A3F5DAB354.png[/IMG]

[IMG="https://communityfile-dre.op.hicloud.com/FileServer/getFile/cmtybbs/023/288/729/5190358000023288729.20200528181316.51224804603668884471265207983508:50510609105638:2800:E1B0F1CB707608D6807DD0F683D2D2748F057F04E230274F8BBE3548217A6E42.png"]https://communityfile-dre.op.hicloud.com/FileServer/getFile/cmtybbs/023/288/729/5190358000023288729.20200528181316.51224804603668884471265207983508:50510609105638:2800:E1B0F1CB707608D6807DD0F683D2D2748F057F04E230274F8BBE3548217A6E42.png[/IMG]

[IMG="https://communityfile-dre.op.hicloud.com/FileServer/getFile/cmtybbs/023/288/729/5190358000023288729.20200528181621.98830251350245671827800636421218:50510609105638:2800:9547C560702C416A3A91DE97A1471ED6AE7733C6AB7AB05283BDD3103707B9C8.png"]https://communityfile-dre.op.hicloud.com/FileServer/getFile/cmtybbs/023/288/729/5190358000023288729.20200528181621.98830251350245671827800636421218:50510609105638:2800:9547C560702C416A3A91DE97A1471ED6AE7733C6AB7AB05283BDD3103707B9C8.png[/IMG]

[IMG="https://communityfile-dre.op.hicloud.com/FileServer/getFile/cmtybbs/023/288/729/5190358000023288729.20200528181726.51298723360727393950247428425664:50510609105638:2800:A788AF387912104D48BF96B9F34C59DA6754FC5A90B5A23736B7BFB5894FE507.png"]https://communityfile-dre.op.hicloud.com/FileServer/getFile/cmtybbs/023/288/729/5190358000023288729.20200528181726.51298723360727393950247428425664:50510609105638:2800:A788AF387912104D48BF96B9F34C59DA6754FC5A90B5A23736B7BFB5894FE507.png[/IMG]

In this first blog post, we will parse the GPX file of 120 km route of Cappadocia Ultra Trail race and show the route and check points (food stations) on map. I finished this race in 23 hours 45 mins and you can also read my experience here (https://link.medium.com/uWmrWLAzR6). GPX is an open standart which contains route points that constructs a polyline and waypoints which are the attraction location. In this case, the waypoints represents the food and aid stations in the race. We will show the route with a polyline and waypoints with markers on map.

Architecture

Architecture is definitely not an overrated concept. Since the early days of Android, we have been seeking for the best architectural patterns that suits with Android development. We have heard of MVC, MVP, MVVM, MVI and many other patterns will emerge. The change and adaptation to a new pattern is inevitable by time. We should keep in mind some basic and commonly accepted concepts like SOLID principles, seperation of concerns, maintainability, readibility, testablity etc. so that we can switch to between patterns easily when needed.

Nowadays, widely accepted architecture in Android community is modularization with Clean Architecture. If you have time to invest more, I would strongly suggest Joe Birch's clean architecture tutorials. As Joe suggests in his tutorials, we do not have to apply every rule line by line but instead we take whatever we feel like is needed. Here is my take and how I modularized the All About Maps app:

[IMG="https://communityfile-dre.op.hicloud.com/FileServer/getFile/cmtybbs/023/288/729/5190358000023288729.20200528093432.25749549144393613483742856147692:50510609105638:2800:8EFD4D868ADF59C53FFE51AF1E4D2D483BB0A44C3FEF4A848778A806321E1D47.png"]https://communityfile-dre.op.hicloud.com/FileServer/getFile/cmtybbs/023/288/729/5190358000023288729.20200528093432.25749549144393613483742856147692:50510609105638:2800:8EFD4D868ADF59C53FFE51AF1E4D2D483BB0A44C3FEF4A848778A806321E1D47.png[/IMG]

Note that dependency injection with Dagger2 is the core of this implementation. If you are not familiar with the concept, I strongly suggest you to read the best Dagger2 tutorial in the wild Dagger2 world by Nimrod Dayan.

Domain Module

Many of us are excited to start implementation with UI to see the results immediately but we should patiently build our blocks. We shall start with the domain module since we will put our business logic and define the entities and user interactions there.

This is not the end. For full content, you can visit https://forums.developer.huawei.com/forumPortal/en/topicview?tid=0201260729166420263&fid=0101187876626530001