Download A Map¶
In this guide you will learn how to get a list of the available country and region maps on the server and how to download a map for offline use.
Setup¶
First, get an API key token, see the Getting Started guide.
Download the Maps & Navigation SDK for Android archive fileDownload the DownloadingOnboardMap project
archive file or clone the project with Git
See the Configure Android Example guide.
Run the example¶
In Android Studio, from the File
menu, select Sync Project with Gradle Files
An android device should be connected via USB cable.
Press SHIFT+F10 to compile, install and run the example on the
android device.
Displays a list of maps on the server available for download. Automatically downloads a map.
How it works¶
You can open the MainActivity.kt file to see how the list of maps is obtained from the server and displayed, and then one of the maps is downloaded.
1private val progressListener = ProgressListener.create(
2 onStarted = {
3 progressBar?.visibility = View.VISIBLE
4 showStatusMessage("Started content store service.")
5 },
6 onCompleted = { errorCode, _ ->
7 progressBar?.visibility = View.GONE
8 showStatusMessage("Content store service completed with error code: $errorCode")
9 when (errorCode)
10 {
11 GemError.NoError ->
12 {
13 SdkCall.execute {
14 // No error encountered, we can handle the results.
15 val models = contentStore.getStoreContentList(EContentType.RoadMap)?.first
16 if (!models.isNullOrEmpty())
17 {
18 // The map items list is not empty or null.
19 val mapItem = models[0]
20 val itemName = mapItem.name
21 // Define a listener to the progress of the map download action.
22 val downloadProgressListener = ProgressListener.create(onStarted = {
23 showStatusMessage("Started downloading $itemName.")
24 },
25 onProgress = {
26 listView?.adapter?.notifyItemChanged(0)
27 },
28 onCompleted = { _, _ ->
29 listView?.adapter?.notifyItemChanged(0)
30 showStatusMessage("$itemName was downloaded.")
31 })
32 // Start downloading the first map item.
33 SdkCall.execute {
34 mapItem.asyncDownload(downloadProgressListener,
35 GemSdk.EDataSavePolicy.UseDefault, true)
36 }
37 }
38 displayList(models)
39 }
40 }
41 GemError.Cancel ->
42 {
43 // The action was cancelled.
44 }
45 else ->
46 {
47 // There was a problem at retrieving the content store items.
48 showDialog("Content store service error: ${GemError.getMessage(errorCode)}")
49 }
50 }
51 }
52)
This is the
progressListener
used to monitor the progress of obtaining
the list of maps available for download from the online content store server.onStarted
is called when the map list download starts, and onCompleted
is called when the map list download is complete.Once the map list is downloaded, the array of roadmaps is obtained from
the downloaded local copy of the map list:
val models = contentStore.getStoreContentList(EContentType.RoadMap)?.first
If the array is not empty, the first item (at index 0) is obtained:
val mapItem = models[0]
A progress listener is created right here:
val downloadProgressListener = ProgressListener.create(onStarted = {
overriding onProgress
and onCompleted
.
Then the download is started, and the progress listener just defined
is used to monitor the progress of downloading the map at index 0 in the list of maps.The downloaded map is stored on the device in a directory such as this:
/sdcard/Android/data/com.magiclane.examplename/files/Data/Maps/
. 1override fun onCreate(savedInstanceState: Bundle?)
2{
3 super.onCreate(savedInstanceState)
4 setContentView(R.layout.activity_main)
5 progressBar = findViewById(R.id.progressBar)
6 statusText = findViewById(R.id.status_text)
7 listView = findViewById<RecyclerView?>(R.id.list_view).apply {
8 layoutManager = LinearLayoutManager(this@MainActivity)
9 val separator = DividerItemDecoration(applicationContext, (layoutManager as LinearLayoutManager).orientation)
10 addItemDecoration(separator)
11 val lateralPadding = resources.getDimension(R.dimen.bigPadding).toInt()
12 setPadding(lateralPadding, 0, lateralPadding, 0)
13 itemAnimator = null
14 }
15 val loadMaps = {
16 mapsCatalogRequested = true
17 val loadMapsCatalog = {
18 SdkCall.execute {
19 // Call to the content store to asynchronously retrieve the list of maps.
20 contentStore.asyncGetStoreContentList(EContentType.RoadMap, progressListener)
21 }
22 }
23 val token = GemSdk.getTokenFromManifest(this)
24 if (!token.isNullOrEmpty() && (token != kDefaultToken))
25 {
26 loadMapsCatalog()
27 }
28 else
29 // if token is not present try to avoid content server requests limitation
30 // by delaying the request
31 {
32 progressBar?.visibility = View.VISIBLE
33 Handler(Looper.getMainLooper()).postDelayed({
34 loadMapsCatalog()
35 }, 3000)
36 }
37 }
38 SdkSettings.onMapDataReady = { it ->
39 mapReady = it
40 if (connected && mapReady && !mapsCatalogRequested)
41 {
42 loadMaps()
43 }
44 }
45 SdkSettings.onConnectionStatusUpdated = { it ->
46 connected = it
47 if (connected && mapReady && !mapsCatalogRequested)
48 {
49 loadMaps()
50 }
51 }
52 SdkSettings.onApiTokenRejected = {
53 showDialog("TOKEN REJECTED")
54 }
55 // This initialization step is mandatory for using the SDK without a map.
56 if (!GemSdk.initSdkWithDefaults(this))
57 {
58 // The SDK initialization was not completed.
59 finish()
60 }
61 if (!Util.isInternetConnected(this))
62 {
63 showDialog("You must be connected to internet!")
64 }
65}
MainActivity
overrides onCreate()
which checks that internet access
is available, and explicitly initializes the SDK, which is required for enabling
use of the SDK without a map:GemSdk.initSdkWithDefaults(this))
When the internet connection is detected, or when the SDK reports that map data
is ready, the
loadMaps()
function is called to request the list of maps
from the content store server.contentStore.asyncGetStoreContentList(EContentType.RoadMap, progressListener)
The list of maps is requested, and the progressListener
shown above is
passed in, to get notified when the list of maps has finished downloading.
At that point, as we have already seen above, the progress listener
automatically selects the first map (unless the list is empty) and
downloads it automatically.In a real world use case, the user would select which map to download.
1private fun displayList(models: ArrayList<ContentStoreItem>?)
2{
3 if (models != null)
4 {
5 val adapter = CustomAdapter(models)
6 listView?.adapter = adapter
7 }
8}
The progress listener also calls
displayList(models)
which uses a
CustomAdapter
to display a scrollable list of the maps available
on the server. The list displayed is the local copy that was
downloaded above.