summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authortobrun <tobrun.van.nuland@gmail.com>2019-04-29 15:08:17 +0200
committertobrun <tobrun.van.nuland@gmail.com>2019-04-29 15:19:59 +0200
commit19efd5399aa303516dd081d1240197598a9f2d04 (patch)
tree36696fab7d2615363aadfe1fa28c2b156a7391d4
parentd22b88e6c02d4ad8264665911061675a2c977425 (diff)
downloadqtlocation-mapboxgl-upstream/tvn-offline-download.tar.gz
[android] - offline test, headless region downloadupstream/tvn-offline-download
-rw-r--r--platform/android/MapboxGLAndroidSDKTestApp/src/main/AndroidManifest.xml13
-rw-r--r--platform/android/MapboxGLAndroidSDKTestApp/src/main/java/com/mapbox/mapboxsdk/testapp/activity/offline/DownloadRegionActivity.kt313
-rw-r--r--platform/android/MapboxGLAndroidSDKTestApp/src/main/res/drawable/ic_pause_black_24dp.xml9
-rw-r--r--platform/android/MapboxGLAndroidSDKTestApp/src/main/res/layout/activity_region_download.xml216
-rw-r--r--platform/android/MapboxGLAndroidSDKTestApp/src/main/res/values/descriptions.xml1
-rw-r--r--platform/android/MapboxGLAndroidSDKTestApp/src/main/res/values/titles.xml1
-rw-r--r--platform/android/scripts/exclude-activity-gen.json3
7 files changed, 554 insertions, 2 deletions
diff --git a/platform/android/MapboxGLAndroidSDKTestApp/src/main/AndroidManifest.xml b/platform/android/MapboxGLAndroidSDKTestApp/src/main/AndroidManifest.xml
index 01f32b5406..18fbf33cc8 100644
--- a/platform/android/MapboxGLAndroidSDKTestApp/src/main/AndroidManifest.xml
+++ b/platform/android/MapboxGLAndroidSDKTestApp/src/main/AndroidManifest.xml
@@ -14,6 +14,7 @@
android:roundIcon="@drawable/ic_launcher_round"
android:supportsRtl="true"
android:theme="@style/AppTheme">
+
<activity
android:name=".activity.FeatureOverviewActivity"
android:label="@string/app_name"
@@ -953,7 +954,17 @@
android:name="android.support.PARENT_ACTIVITY"
android:value=".activity.FeatureOverviewActivity" />
</activity>
-
+ <activity
+ android:name=".activity.offline.DownloadRegionActivity"
+ android:description="@string/description_region"
+ android:label="@string/activity_region">
+ <meta-data
+ android:name="@string/category"
+ android:value="@string/category_offline" />
+ <meta-data
+ android:name="android.support.PARENT_ACTIVITY"
+ android:value=".activity.FeatureOverviewActivity" />
+ </activity>
<!-- For Instrumentation tests -->
<activity
android:name=".activity.style.RuntimeStyleTimingTestActivity"
diff --git a/platform/android/MapboxGLAndroidSDKTestApp/src/main/java/com/mapbox/mapboxsdk/testapp/activity/offline/DownloadRegionActivity.kt b/platform/android/MapboxGLAndroidSDKTestApp/src/main/java/com/mapbox/mapboxsdk/testapp/activity/offline/DownloadRegionActivity.kt
new file mode 100644
index 0000000000..7f90796f42
--- /dev/null
+++ b/platform/android/MapboxGLAndroidSDKTestApp/src/main/java/com/mapbox/mapboxsdk/testapp/activity/offline/DownloadRegionActivity.kt
@@ -0,0 +1,313 @@
+package com.mapbox.mapboxsdk.testapp.activity.offline
+
+import android.os.Bundle
+import android.os.Handler
+import android.support.v7.app.AppCompatActivity
+import android.view.View
+import android.widget.ArrayAdapter
+import android.widget.SeekBar
+import android.widget.TextView
+import android.widget.Toast
+import com.mapbox.mapboxsdk.constants.MapboxConstants
+import com.mapbox.mapboxsdk.geometry.LatLng
+import com.mapbox.mapboxsdk.geometry.LatLngBounds
+import com.mapbox.mapboxsdk.maps.Style
+import com.mapbox.mapboxsdk.offline.*
+import com.mapbox.mapboxsdk.testapp.R
+import kotlinx.android.synthetic.main.activity_region_download.*
+import timber.log.Timber
+import java.util.*
+import java.util.concurrent.TimeUnit
+
+/**
+ * Example showcasing how to download an offline region headless, allows to test pausing and resuming the download.
+ */
+class DownloadRegionActivity : AppCompatActivity(), OfflineRegion.OfflineRegionObserver {
+
+ companion object {
+ const val STATUS_UPDATE_TIMEOUT_MS = 10_000L
+ }
+
+ private val handler: Handler = Handler()
+ private lateinit var offlineManager: OfflineManager
+ private var offlineRegion: OfflineRegion? = null
+ private var downloading = false
+ private var previousCompletedResourceCount: Long = 0
+ private var previousUpdateTimestamp: Long = 0
+
+ override fun onCreate(savedInstanceState: Bundle?) {
+ super.onCreate(savedInstanceState)
+ setContentView(R.layout.activity_region_download)
+
+ offlineManager = OfflineManager.getInstance(this)
+ offlineManager.setOfflineMapboxTileCountLimit(Long.MAX_VALUE)
+ initUi()
+
+ deleteOldOfflineRegions {
+ container.visibility = View.VISIBLE
+ fab.visibility = View.VISIBLE
+ }
+ }
+
+ override fun onDestroy() {
+ handler.removeCallbacksAndMessages(null)
+ offlineRegion?.setObserver(null)
+ super.onDestroy()
+ }
+
+ private fun createOfflineRegion() {
+ val latitudeNorth = editTextLatNorth.text.toString().toDouble()
+ val longitudeEast = editTextLonEast.text.toString().toDouble()
+ val latitudeSouth = editTextLatSouth.text.toString().toDouble()
+ val longitudeWest = editTextLonWest.text.toString().toDouble()
+ val styleUrl = spinnerStyleUrl.selectedItem as String
+ val maxZoom = seekbarMaxZoom.progress.toFloat()
+ val minZoom = seekbarMinZoom.progress.toFloat()
+
+ if (!validCoordinates(latitudeNorth, longitudeEast, latitudeSouth, longitudeWest)) {
+ Toast.makeText(this, "coordinates need to be in valid range", Toast.LENGTH_LONG).show()
+ return
+ }
+
+ // create offline definition from data
+ val definition = OfflineTilePyramidRegionDefinition(
+ styleUrl,
+ LatLngBounds.Builder()
+ .include(LatLng(latitudeNorth, longitudeEast))
+ .include(LatLng(latitudeSouth, longitudeWest))
+ .build(),
+ minZoom.toDouble(),
+ maxZoom.toDouble(),
+ resources.displayMetrics.density
+ )
+
+ logMessage("Creating offline region")
+ offlineManager.createOfflineRegion(definition, byteArrayOf(), object : OfflineManager.CreateOfflineRegionCallback {
+ override fun onCreate(region: OfflineRegion) {
+ logMessage("Region with id ${region.id} created")
+ offlineRegion = region
+ startDownload(region)
+ fab.visibility = View.VISIBLE
+ }
+
+ override fun onError(error: String) {
+ logMessage("Failed to create offline region: $error")
+ }
+ })
+ }
+
+ private fun startDownload(region: OfflineRegion) {
+ downloading = true
+ fab.setImageResource(R.drawable.ic_pause_black_24dp)
+ logMessage("Downloading...")
+
+ region.setObserver(this)
+ region.setDownloadState(OfflineRegion.STATE_ACTIVE)
+
+ previousUpdateTimestamp = System.currentTimeMillis()
+ handler.postDelayed(object : Runnable {
+ override fun run() {
+ if (System.currentTimeMillis() > previousUpdateTimestamp + STATUS_UPDATE_TIMEOUT_MS) {
+ logMessage("FAILURE! No progress in ${TimeUnit.MILLISECONDS.toSeconds(STATUS_UPDATE_TIMEOUT_MS)} seconds")
+ } else {
+ handler.postDelayed(this, 1000)
+ }
+ }
+ }, 1000)
+ }
+
+ private fun pauseDownload(region: OfflineRegion) {
+ downloading = false
+ fab.setImageResource(R.drawable.ic_play_arrow_black_24dp)
+ handler.removeCallbacksAndMessages(null)
+ region.setDownloadState(OfflineRegion.STATE_INACTIVE)
+ "Paused".let {
+ logMessage(it)
+ download_status.text = it
+ }
+ }
+
+ override fun onStatusChanged(status: OfflineRegionStatus) {
+ if (status.isComplete) {
+ val statusText = "Completed"
+ logMessage("SUCCESS! $statusText")
+ download_status.text = statusText
+ offlineRegion?.setObserver(null)
+ handler.removeCallbacksAndMessages(null)
+ } else {
+ val statusText = "Downloaded ${status.completedResourceCount}/${status.requiredResourceCount}"
+ Timber.d(statusText)
+ download_status.text = statusText
+
+ if (status.completedResourceCount > status.requiredResourceCount &&
+ previousCompletedResourceCount <= status.requiredResourceCount) {
+ logMessage("FAILURE! Completed > required")
+ }
+ }
+
+ previousCompletedResourceCount = status.completedResourceCount
+ previousUpdateTimestamp = System.currentTimeMillis()
+ }
+
+ override fun onError(error: OfflineRegionError) {
+ logMessage("Error: $error")
+ }
+
+ override fun mapboxTileCountLimitExceeded(limit: Long) {
+ logMessage("Error: tile count limit exceeded")
+ }
+
+ protected fun logMessage(message: String) {
+ Timber.d(message)
+ logView.append(message)
+ logView.append("\n")
+ }
+
+ fun deleteOldOfflineRegions(onCompleted: () -> Unit) {
+ offlineManager.listOfflineRegions(object : OfflineManager.ListOfflineRegionsCallback {
+ override fun onList(offlineRegions: Array<out OfflineRegion>) {
+ val count = offlineRegions.size
+ var remainingCount = count
+ if (count > 0) {
+ logMessage("Deleting $count old region...")
+ offlineRegions.forEach {
+ it.delete(object : OfflineRegion.OfflineRegionDeleteCallback {
+ override fun onDelete() {
+ Timber.d("Deleted region with id ${it.id}")
+ onProcessed()
+ }
+
+ override fun onError(error: String) {
+ Timber.e("Failed to delete region: $error")
+ onProcessed()
+ }
+
+ private fun onProcessed() {
+ remainingCount--
+ if (remainingCount == 0) {
+ logMessage("Done deleting")
+ onCompleted()
+ }
+ }
+ })
+ }
+ } else {
+ onCompleted()
+ }
+ }
+
+ override fun onError(error: String) {
+ logMessage("Failed to list offline regions: $error")
+ onCompleted()
+ }
+ })
+ }
+
+ // ui
+
+ private val logView: TextView by lazy {
+ findViewById<TextView>(R.id.log_text)
+ }
+
+ private fun initUi() {
+ initEditTexts()
+ initSeekbars()
+ initSpinner()
+ initZoomLevelTextviews()
+ initSeekbarListeners()
+ initFab()
+ }
+
+ private fun initEditTexts() {
+ editTextLatNorth.setText("62.0")
+ editTextLonEast.setText("24.0")
+ editTextLatSouth.setText("60.0")
+ editTextLonWest.setText("22.5")
+ }
+
+ private fun initSeekbars() {
+ val maxZoom = MapboxConstants.MAXIMUM_ZOOM.toInt()
+ seekbarMinZoom.max = maxZoom
+ seekbarMinZoom.progress = 1
+ seekbarMaxZoom.max = maxZoom
+ seekbarMaxZoom.progress = 15
+ }
+
+ private fun initSpinner() {
+ val styles = ArrayList<String>()
+ styles.add(Style.MAPBOX_STREETS)
+ styles.add(Style.DARK)
+ styles.add(Style.LIGHT)
+ styles.add(Style.OUTDOORS)
+ val spinnerArrayAdapter = ArrayAdapter(this, android.R.layout.simple_spinner_item, styles)
+ spinnerArrayAdapter.setDropDownViewResource(android.R.layout.simple_spinner_dropdown_item)
+ spinnerStyleUrl.adapter = spinnerArrayAdapter
+ }
+
+ private fun initZoomLevelTextviews() {
+ textViewMaxText.text = String.format("Max zoom: %s", seekbarMaxZoom.progress)
+ textViewMinText.text = String.format("Min zoom: %s", seekbarMinZoom.progress)
+ }
+
+ private fun initFab() {
+ fab.setOnClickListener {
+ container.visibility = View.GONE
+ if (offlineRegion == null) {
+ fab.visibility = View.GONE
+ createOfflineRegion()
+ } else {
+ offlineRegion?.let {
+ if (downloading) {
+ pauseDownload(it)
+ } else {
+ startDownload(it)
+ }
+ }
+ }
+ }
+ }
+
+ private fun initSeekbarListeners() {
+ seekbarMaxZoom.setOnSeekBarChangeListener(object : SeekBar.OnSeekBarChangeListener {
+ override fun onProgressChanged(seekBar: SeekBar, progress: Int, fromUser: Boolean) {
+ textViewMaxText.text = String.format("Max zoom: %s", progress)
+ }
+
+ override fun onStartTrackingTouch(seekBar: SeekBar) {
+
+ }
+
+ override fun onStopTrackingTouch(seekBar: SeekBar) {
+
+ }
+ })
+
+ seekbarMinZoom.setOnSeekBarChangeListener(object : SeekBar.OnSeekBarChangeListener {
+ override fun onProgressChanged(seekBar: SeekBar, progress: Int, fromUser: Boolean) {
+ textViewMinText.text = String.format("Min zoom: %s", progress)
+ }
+
+ override fun onStartTrackingTouch(seekBar: SeekBar) {
+
+ }
+
+ override fun onStopTrackingTouch(seekBar: SeekBar) {
+
+ }
+ })
+ }
+
+ private fun validCoordinates(latitudeNorth: Double, longitudeEast: Double, latitudeSouth: Double,
+ longitudeWest: Double): Boolean {
+ if (latitudeNorth < -90 || latitudeNorth > 90) {
+ return false
+ } else if (longitudeEast < -180 || longitudeEast > 180) {
+ return false
+ } else if (latitudeSouth < -90 || latitudeSouth > 90) {
+ return false
+ } else if (longitudeWest < -180 || longitudeWest > 180) {
+ return false
+ }
+ return true
+ }
+}
diff --git a/platform/android/MapboxGLAndroidSDKTestApp/src/main/res/drawable/ic_pause_black_24dp.xml b/platform/android/MapboxGLAndroidSDKTestApp/src/main/res/drawable/ic_pause_black_24dp.xml
new file mode 100644
index 0000000000..bb28a6c415
--- /dev/null
+++ b/platform/android/MapboxGLAndroidSDKTestApp/src/main/res/drawable/ic_pause_black_24dp.xml
@@ -0,0 +1,9 @@
+<vector xmlns:android="http://schemas.android.com/apk/res/android"
+ android:width="24dp"
+ android:height="24dp"
+ android:viewportWidth="24.0"
+ android:viewportHeight="24.0">
+ <path
+ android:fillColor="#FF000000"
+ android:pathData="M6,19h4L10,5L6,5v14zM14,5v14h4L18,5h-4z"/>
+</vector>
diff --git a/platform/android/MapboxGLAndroidSDKTestApp/src/main/res/layout/activity_region_download.xml b/platform/android/MapboxGLAndroidSDKTestApp/src/main/res/layout/activity_region_download.xml
new file mode 100644
index 0000000000..4242da9fbd
--- /dev/null
+++ b/platform/android/MapboxGLAndroidSDKTestApp/src/main/res/layout/activity_region_download.xml
@@ -0,0 +1,216 @@
+<?xml version="1.0" encoding="utf-8"?>
+<android.support.constraint.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">
+
+ <android.support.v4.widget.NestedScrollView
+ android:id="@+id/container"
+ android:visibility="gone"
+ android:layout_width="match_parent"
+ android:layout_marginTop="8dp"
+ android:layout_height="match_parent">
+
+ <LinearLayout
+ android:layout_width="match_parent"
+ android:layout_height="match_parent"
+ android:orientation="vertical"
+ android:padding="16dp">
+
+ <LinearLayout
+ android:layout_width="match_parent"
+ android:layout_height="wrap_content"
+ android:layout_marginBottom="8dp"
+ android:orientation="horizontal"
+ android:weightSum="2">
+
+ <LinearLayout
+ android:layout_width="0dp"
+ android:layout_height="wrap_content"
+ android:layout_weight="1"
+ android:orientation="vertical">
+
+ <TextView
+ android:layout_width="match_parent"
+ android:layout_height="wrap_content"
+ android:layout_marginBottom="4dp"
+ android:text="Latitude north:"/>
+
+ <EditText
+ android:id="@+id/editTextLatNorth"
+ android:layout_width="match_parent"
+ android:layout_height="wrap_content"
+ android:ellipsize="end"
+ android:inputType="numberDecimal"
+ android:maxLines="1"/>
+
+ </LinearLayout>
+
+ <LinearLayout
+ android:layout_width="0dp"
+ android:layout_height="wrap_content"
+ android:layout_weight="1"
+ android:orientation="vertical">
+
+ <TextView
+ android:layout_width="match_parent"
+ android:layout_height="wrap_content"
+ android:layout_marginBottom="4dp"
+ android:text="Longitude east:"/>
+
+ <EditText
+ android:id="@+id/editTextLonEast"
+ android:layout_width="match_parent"
+ android:layout_height="wrap_content"
+ android:ellipsize="end"
+ android:inputType="numberDecimal"
+ android:maxLines="1"/>
+
+ </LinearLayout>
+
+ </LinearLayout>
+
+ <LinearLayout
+ android:layout_width="match_parent"
+ android:layout_height="wrap_content"
+ android:layout_marginBottom="8dp"
+ android:orientation="horizontal"
+ android:weightSum="2">
+
+ <LinearLayout
+ android:layout_width="0dp"
+ android:layout_height="wrap_content"
+ android:layout_weight="1"
+ android:orientation="vertical"
+ android:paddingRight="2dp">
+
+ <TextView
+ android:layout_width="match_parent"
+ android:layout_height="wrap_content"
+ android:layout_marginBottom="4dp"
+ android:text="Latitude south:"/>
+
+ <EditText
+ android:id="@+id/editTextLatSouth"
+ android:layout_width="match_parent"
+ android:layout_height="wrap_content"
+ android:ellipsize="end"
+ android:inputType="numberDecimal"
+ android:maxLines="1"/>
+
+ </LinearLayout>
+
+ <LinearLayout
+ android:layout_width="0dp"
+ android:layout_height="wrap_content"
+ android:layout_weight="1"
+ android:orientation="vertical"
+ android:paddingLeft="2dp">
+
+ <TextView
+ android:layout_width="match_parent"
+ android:layout_height="wrap_content"
+ android:layout_marginBottom="4dp"
+ android:text="Longitude west:"/>
+
+ <EditText
+ android:id="@+id/editTextLonWest"
+ android:layout_width="match_parent"
+ android:layout_height="wrap_content"
+ android:ellipsize="end"
+ android:inputType="numberDecimal"
+ android:maxLines="1"/>
+
+ </LinearLayout>
+
+ </LinearLayout>
+
+ <TextView
+ android:layout_width="match_parent"
+ android:layout_height="wrap_content"
+ android:layout_marginBottom="4dp"
+ android:text="Style url:"/>
+
+ <Spinner
+ android:id="@+id/spinnerStyleUrl"
+ android:layout_width="match_parent"
+ android:layout_height="wrap_content"
+ android:layout_marginBottom="8dp"/>
+
+ <TextView
+ android:id="@+id/textViewMinText"
+ android:layout_width="match_parent"
+ android:layout_height="wrap_content"
+ android:layout_marginBottom="4dp"/>
+
+ <SeekBar
+ android:id="@+id/seekbarMinZoom"
+ android:layout_width="match_parent"
+ android:layout_height="wrap_content"
+ android:layout_marginBottom="12dp"/>
+
+ <TextView
+ android:id="@+id/textViewMaxText"
+ android:layout_width="match_parent"
+ android:layout_height="wrap_content"
+ android:layout_marginBottom="4dp"/>
+
+ <SeekBar
+ android:id="@+id/seekbarMaxZoom"
+ android:layout_width="match_parent"
+ android:layout_height="wrap_content"
+ android:layout_marginBottom="12dp"/>
+
+ </LinearLayout>
+
+ </android.support.v4.widget.NestedScrollView>
+
+ <FrameLayout
+ android:layout_width="match_parent"
+ android:layout_height="match_parent">
+
+ <TextView
+ android:id="@+id/log_text"
+ android:layout_width="match_parent"
+ android:layout_height="match_parent"
+ android:textSize="8sp"
+ tools:text="Log text container"/>
+
+ </FrameLayout>
+
+ <FrameLayout android:layout_width="match_parent" android:layout_height="64dp"
+ app:layout_constraintStart_toStartOf="parent"
+ app:layout_constraintEnd_toEndOf="parent"
+ android:background="@color/primary"
+ android:id="@+id/bottom"
+ app:layout_constraintBottom_toBottomOf="parent">
+ <TextView
+ android:id="@+id/download_status"
+ android:layout_width="match_parent"
+ android:layout_height="match_parent"
+ android:gravity="center"
+ android:text="Not downloading"
+ android:textColor="@color/white"
+ android:textSize="16sp"/>
+
+ </FrameLayout>
+
+ <android.support.design.widget.FloatingActionButton
+ android:id="@+id/fab"
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:layout_margin="16dp"
+ android:visibility="gone"
+ app:layout_constraintEnd_toEndOf="@id/bottom"
+ android:background="@color/primary"
+ app:layout_constraintBottom_toBottomOf="@id/bottom"
+ app:layout_constraintBottom_toTopOf="@id/bottom"
+ android:src="@drawable/ic_play_arrow_black_24dp"
+ android:tint="@android:color/white"
+ android:layout_marginBottom="64dp"
+ app:backgroundTint="@color/primary"/>
+
+
+</android.support.constraint.ConstraintLayout> \ No newline at end of file
diff --git a/platform/android/MapboxGLAndroidSDKTestApp/src/main/res/values/descriptions.xml b/platform/android/MapboxGLAndroidSDKTestApp/src/main/res/values/descriptions.xml
index cc2577fb5e..be8dae57a0 100644
--- a/platform/android/MapboxGLAndroidSDKTestApp/src/main/res/values/descriptions.xml
+++ b/platform/android/MapboxGLAndroidSDKTestApp/src/main/res/values/descriptions.xml
@@ -18,6 +18,7 @@
<string name="description_map_padding">Map Padding example</string>
<string name="description_debug_mode">Debug Mode</string>
<string name="description_offline">Offline Map example</string>
+ <string name="description_region">Download an offline region.</string>
<string name="description_update_metadata">Update metadata example</string>
<string name="description_offline_region_delete">Delete region example</string>
<string name="description_change_resources_cache_path">Change resources cache path example</string>
diff --git a/platform/android/MapboxGLAndroidSDKTestApp/src/main/res/values/titles.xml b/platform/android/MapboxGLAndroidSDKTestApp/src/main/res/values/titles.xml
index e5f7381918..027198c71b 100644
--- a/platform/android/MapboxGLAndroidSDKTestApp/src/main/res/values/titles.xml
+++ b/platform/android/MapboxGLAndroidSDKTestApp/src/main/res/values/titles.xml
@@ -83,4 +83,5 @@
<string name="activity_nested_viewpager">Nested ViewPager</string>
<string name="activity_performance_measurement">Performance Measurement</string>
<string name="activity_physical_circle">Physical Unit Circle</string>
+ <string name="activity_region">Download region</string>
</resources> \ No newline at end of file
diff --git a/platform/android/scripts/exclude-activity-gen.json b/platform/android/scripts/exclude-activity-gen.json
index a6070edccf..f6156eb0ea 100644
--- a/platform/android/scripts/exclude-activity-gen.json
+++ b/platform/android/scripts/exclude-activity-gen.json
@@ -50,5 +50,6 @@
"EspressoTestActivity",
"FragmentBackStackActivity",
"ChildFragmentMapInDialogActivity",
- "PerformanceMeasurementActivity"
+ "PerformanceMeasurementActivity",
+ "DownloadRegionActivity"
]