[android] fixing ktlint issues
This commit is contained in:
@@ -18,310 +18,310 @@ import org.junit.Test
|
||||
|
||||
class IndicatorLocationLayerRendererTest {
|
||||
|
||||
private val style: Style = mockk(relaxUnitFun = true)
|
||||
private val layerSourceProvider: LayerSourceProvider = mockk(relaxUnitFun = true)
|
||||
private val layer: Layer = mockk(relaxUnitFun = true)
|
||||
private val style: Style = mockk(relaxUnitFun = true)
|
||||
private val layerSourceProvider: LayerSourceProvider = mockk(relaxUnitFun = true)
|
||||
private val layer: Layer = mockk(relaxUnitFun = true)
|
||||
|
||||
private lateinit var locationLayerRenderer: IndicatorLocationLayerRenderer
|
||||
private lateinit var locationLayerRenderer: IndicatorLocationLayerRenderer
|
||||
|
||||
@Before
|
||||
fun setup() {
|
||||
every { style.removeLayer(any<Layer>()) } returns true
|
||||
locationLayerRenderer = IndicatorLocationLayerRenderer(layerSourceProvider)
|
||||
every { layerSourceProvider.generateLocationComponentLayer() } returns layer
|
||||
locationLayerRenderer.initializeComponents(style)
|
||||
}
|
||||
|
||||
@Test
|
||||
fun sanity() {
|
||||
Assert.assertNotNull(locationLayerRenderer)
|
||||
}
|
||||
|
||||
@Test
|
||||
fun initializeComponents_withLocation() {
|
||||
val newLayer: Layer = mockk(relaxUnitFun = true)
|
||||
every { layerSourceProvider.generateLocationComponentLayer() } returns newLayer
|
||||
val latLng = LatLng(10.0, 20.0)
|
||||
val bearing = 11f
|
||||
val accuracy = 65f
|
||||
locationLayerRenderer.setLatLng(latLng)
|
||||
locationLayerRenderer.setGpsBearing(bearing)
|
||||
locationLayerRenderer.setAccuracyRadius(accuracy)
|
||||
|
||||
locationLayerRenderer.initializeComponents(mockk())
|
||||
|
||||
verify { newLayer.setProperties(LocationPropertyFactory.location(latLng.toLocationArray())) }
|
||||
verify { newLayer.setProperties(LocationPropertyFactory.bearing(bearing.toDouble())) }
|
||||
verify { newLayer.setProperties(LocationPropertyFactory.accuracyRadius(accuracy)) }
|
||||
}
|
||||
|
||||
@Test
|
||||
fun addLayers() {
|
||||
val positionManager: LocationComponentPositionManager = mockk(relaxUnitFun = true)
|
||||
|
||||
locationLayerRenderer.addLayers(positionManager)
|
||||
|
||||
verify { positionManager.addLayerToMap(layer) }
|
||||
}
|
||||
|
||||
@Test
|
||||
fun removeLayers() {
|
||||
locationLayerRenderer.removeLayers()
|
||||
|
||||
verify { style.removeLayer(layer) }
|
||||
}
|
||||
|
||||
@Test
|
||||
fun hide() {
|
||||
locationLayerRenderer.hide()
|
||||
|
||||
verify { layer.setProperties(LocationPropertyFactory.visibility(Property.NONE)) }
|
||||
}
|
||||
|
||||
@Test
|
||||
fun show() {
|
||||
locationLayerRenderer.show(RenderMode.NORMAL, false)
|
||||
|
||||
verify { layer.setProperties(LocationPropertyFactory.visibility(Property.VISIBLE)) }
|
||||
}
|
||||
|
||||
@Test
|
||||
fun show_normal_notStale() {
|
||||
locationLayerRenderer.show(RenderMode.NORMAL, false)
|
||||
|
||||
verify {
|
||||
layer.setProperties(
|
||||
LocationPropertyFactory.topImage(FOREGROUND_ICON),
|
||||
LocationPropertyFactory.bearingImage(BACKGROUND_ICON),
|
||||
LocationPropertyFactory.shadowImage(SHADOW_ICON)
|
||||
)
|
||||
@Before
|
||||
fun setup() {
|
||||
every { style.removeLayer(any<Layer>()) } returns true
|
||||
locationLayerRenderer = IndicatorLocationLayerRenderer(layerSourceProvider)
|
||||
every { layerSourceProvider.generateLocationComponentLayer() } returns layer
|
||||
locationLayerRenderer.initializeComponents(style)
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
fun show_compass_notStale() {
|
||||
locationLayerRenderer.show(RenderMode.COMPASS, false)
|
||||
|
||||
verify {
|
||||
layer.setProperties(
|
||||
LocationPropertyFactory.topImage(FOREGROUND_ICON),
|
||||
LocationPropertyFactory.bearingImage(BEARING_ICON),
|
||||
LocationPropertyFactory.shadowImage(SHADOW_ICON)
|
||||
)
|
||||
@Test
|
||||
fun sanity() {
|
||||
Assert.assertNotNull(locationLayerRenderer)
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
fun show_gps_notStale() {
|
||||
locationLayerRenderer.show(RenderMode.GPS, false)
|
||||
@Test
|
||||
fun initializeComponents_withLocation() {
|
||||
val newLayer: Layer = mockk(relaxUnitFun = true)
|
||||
every { layerSourceProvider.generateLocationComponentLayer() } returns newLayer
|
||||
val latLng = LatLng(10.0, 20.0)
|
||||
val bearing = 11f
|
||||
val accuracy = 65f
|
||||
locationLayerRenderer.setLatLng(latLng)
|
||||
locationLayerRenderer.setGpsBearing(bearing)
|
||||
locationLayerRenderer.setAccuracyRadius(accuracy)
|
||||
|
||||
verify {
|
||||
layer.setProperties(
|
||||
LocationPropertyFactory.topImage(""),
|
||||
LocationPropertyFactory.bearingImage(FOREGROUND_ICON),
|
||||
LocationPropertyFactory.shadowImage(BACKGROUND_ICON)
|
||||
)
|
||||
locationLayerRenderer.initializeComponents(mockk())
|
||||
|
||||
verify { newLayer.setProperties(LocationPropertyFactory.location(latLng.toLocationArray())) }
|
||||
verify { newLayer.setProperties(LocationPropertyFactory.bearing(bearing.toDouble())) }
|
||||
verify { newLayer.setProperties(LocationPropertyFactory.accuracyRadius(accuracy)) }
|
||||
}
|
||||
verify { layer.setProperties(LocationPropertyFactory.accuracyRadius(0f)) }
|
||||
}
|
||||
|
||||
@Test
|
||||
fun show_normal_stale() {
|
||||
locationLayerRenderer.show(RenderMode.NORMAL, true)
|
||||
@Test
|
||||
fun addLayers() {
|
||||
val positionManager: LocationComponentPositionManager = mockk(relaxUnitFun = true)
|
||||
|
||||
verify {
|
||||
layer.setProperties(
|
||||
LocationPropertyFactory.topImage(FOREGROUND_STALE_ICON),
|
||||
LocationPropertyFactory.bearingImage(BACKGROUND_STALE_ICON),
|
||||
LocationPropertyFactory.shadowImage(SHADOW_ICON)
|
||||
)
|
||||
locationLayerRenderer.addLayers(positionManager)
|
||||
|
||||
verify { positionManager.addLayerToMap(layer) }
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
fun show_compass_stale() {
|
||||
locationLayerRenderer.show(RenderMode.COMPASS, true)
|
||||
@Test
|
||||
fun removeLayers() {
|
||||
locationLayerRenderer.removeLayers()
|
||||
|
||||
verify {
|
||||
layer.setProperties(
|
||||
LocationPropertyFactory.topImage(FOREGROUND_STALE_ICON),
|
||||
LocationPropertyFactory.bearingImage(BEARING_STALE_ICON),
|
||||
LocationPropertyFactory.shadowImage(SHADOW_ICON)
|
||||
)
|
||||
verify { style.removeLayer(layer) }
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
fun show_gps_stale() {
|
||||
locationLayerRenderer.show(RenderMode.GPS, true)
|
||||
@Test
|
||||
fun hide() {
|
||||
locationLayerRenderer.hide()
|
||||
|
||||
verify {
|
||||
layer.setProperties(
|
||||
LocationPropertyFactory.topImage(""),
|
||||
LocationPropertyFactory.bearingImage(FOREGROUND_STALE_ICON),
|
||||
LocationPropertyFactory.shadowImage(BACKGROUND_STALE_ICON)
|
||||
)
|
||||
verify { layer.setProperties(LocationPropertyFactory.visibility(Property.NONE)) }
|
||||
}
|
||||
verify { layer.setProperties(LocationPropertyFactory.accuracyRadius(0f)) }
|
||||
}
|
||||
|
||||
@Test
|
||||
fun styleAccuracy() {
|
||||
val colorArray = ColorUtils.colorToRgbaArray(Color.RED)
|
||||
val exp = Expression.rgba(colorArray[0], colorArray[1], colorArray[2], 0.7f)
|
||||
@Test
|
||||
fun show() {
|
||||
locationLayerRenderer.show(RenderMode.NORMAL, false)
|
||||
|
||||
locationLayerRenderer.styleAccuracy(0.7f, Color.RED)
|
||||
|
||||
verify {
|
||||
layer.setProperties(
|
||||
LocationPropertyFactory.accuracyRadiusColor(exp),
|
||||
LocationPropertyFactory.accuracyRadiusBorderColor(exp)
|
||||
)
|
||||
verify { layer.setProperties(LocationPropertyFactory.visibility(Property.VISIBLE)) }
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
fun setLatLng() {
|
||||
val latLng = LatLng(10.0, 20.0)
|
||||
locationLayerRenderer.setLatLng(latLng)
|
||||
@Test
|
||||
fun show_normal_notStale() {
|
||||
locationLayerRenderer.show(RenderMode.NORMAL, false)
|
||||
|
||||
verify { layer.setProperties(LocationPropertyFactory.location(latLng.toLocationArray())) }
|
||||
}
|
||||
|
||||
@Test
|
||||
fun setGpsBearing() {
|
||||
val bearing = 30.0
|
||||
locationLayerRenderer.setGpsBearing(bearing.toFloat())
|
||||
|
||||
verify { layer.setProperties(LocationPropertyFactory.bearing(bearing)) }
|
||||
}
|
||||
|
||||
@Test
|
||||
fun setCompassBearing() {
|
||||
val bearing = 30.0
|
||||
locationLayerRenderer.setCompassBearing(bearing.toFloat())
|
||||
|
||||
verify { layer.setProperties(LocationPropertyFactory.bearing(bearing)) }
|
||||
}
|
||||
|
||||
@Test
|
||||
fun setAccuracyRadius() {
|
||||
val radius = 40f
|
||||
locationLayerRenderer.setAccuracyRadius(radius)
|
||||
|
||||
verify { layer.setProperties(LocationPropertyFactory.accuracyRadius(radius)) }
|
||||
}
|
||||
|
||||
@Test
|
||||
fun styleScaling() {
|
||||
val exp = Expression.literal("")
|
||||
locationLayerRenderer.styleScaling(exp)
|
||||
|
||||
verify {
|
||||
layer.setProperties(
|
||||
LocationPropertyFactory.shadowImageSize(exp),
|
||||
LocationPropertyFactory.bearingImageSize(exp),
|
||||
LocationPropertyFactory.topImageSize(exp)
|
||||
)
|
||||
verify {
|
||||
layer.setProperties(
|
||||
LocationPropertyFactory.topImage(FOREGROUND_ICON),
|
||||
LocationPropertyFactory.bearingImage(BACKGROUND_ICON),
|
||||
LocationPropertyFactory.shadowImage(SHADOW_ICON)
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
fun setLocationStale() {
|
||||
locationLayerRenderer.setLocationStale(true, RenderMode.NORMAL)
|
||||
@Test
|
||||
fun show_compass_notStale() {
|
||||
locationLayerRenderer.show(RenderMode.COMPASS, false)
|
||||
|
||||
verify {
|
||||
layer.setProperties(
|
||||
LocationPropertyFactory.topImage(FOREGROUND_STALE_ICON),
|
||||
LocationPropertyFactory.bearingImage(BACKGROUND_STALE_ICON),
|
||||
LocationPropertyFactory.shadowImage(SHADOW_ICON)
|
||||
)
|
||||
verify {
|
||||
layer.setProperties(
|
||||
LocationPropertyFactory.topImage(FOREGROUND_ICON),
|
||||
LocationPropertyFactory.bearingImage(BEARING_ICON),
|
||||
LocationPropertyFactory.shadowImage(SHADOW_ICON)
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
fun addBitmaps_shadow() {
|
||||
addBitmaps(withShadow = true, renderMode = RenderMode.NORMAL)
|
||||
@Test
|
||||
fun show_gps_notStale() {
|
||||
locationLayerRenderer.show(RenderMode.GPS, false)
|
||||
|
||||
verify { style.addImage(SHADOW_ICON, shadowBitmap) }
|
||||
}
|
||||
verify {
|
||||
layer.setProperties(
|
||||
LocationPropertyFactory.topImage(""),
|
||||
LocationPropertyFactory.bearingImage(FOREGROUND_ICON),
|
||||
LocationPropertyFactory.shadowImage(BACKGROUND_ICON)
|
||||
)
|
||||
}
|
||||
verify { layer.setProperties(LocationPropertyFactory.accuracyRadius(0f)) }
|
||||
}
|
||||
|
||||
@Test
|
||||
fun addBitmaps_noShadow() {
|
||||
addBitmaps(withShadow = false, renderMode = RenderMode.NORMAL)
|
||||
@Test
|
||||
fun show_normal_stale() {
|
||||
locationLayerRenderer.show(RenderMode.NORMAL, true)
|
||||
|
||||
verify { style.removeImage(SHADOW_ICON) }
|
||||
}
|
||||
verify {
|
||||
layer.setProperties(
|
||||
LocationPropertyFactory.topImage(FOREGROUND_STALE_ICON),
|
||||
LocationPropertyFactory.bearingImage(BACKGROUND_STALE_ICON),
|
||||
LocationPropertyFactory.shadowImage(SHADOW_ICON)
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
fun addBitmaps_normal() {
|
||||
addBitmaps(withShadow = true, renderMode = RenderMode.NORMAL)
|
||||
@Test
|
||||
fun show_compass_stale() {
|
||||
locationLayerRenderer.show(RenderMode.COMPASS, true)
|
||||
|
||||
verify { style.addImage(FOREGROUND_ICON, foregroundBitmap) }
|
||||
verify { style.addImage(FOREGROUND_STALE_ICON, foregroundStaleBitmap) }
|
||||
verify { style.addImage(BACKGROUND_ICON, backgroundBitmap) }
|
||||
verify { style.addImage(BACKGROUND_STALE_ICON, backgroundStaleBitmap) }
|
||||
verify { style.addImage(BEARING_ICON, bearingBitmap) }
|
||||
}
|
||||
verify {
|
||||
layer.setProperties(
|
||||
LocationPropertyFactory.topImage(FOREGROUND_STALE_ICON),
|
||||
LocationPropertyFactory.bearingImage(BEARING_STALE_ICON),
|
||||
LocationPropertyFactory.shadowImage(SHADOW_ICON)
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
fun addBitmaps_compass() {
|
||||
every { bearingBitmap.width } returns 40
|
||||
every { bearingBitmap.height } returns 40
|
||||
every { bearingBitmap.config } returns mockk()
|
||||
every { backgroundBitmap.width } returns 20
|
||||
every { backgroundBitmap.height } returns 10
|
||||
@Test
|
||||
fun show_gps_stale() {
|
||||
locationLayerRenderer.show(RenderMode.GPS, true)
|
||||
|
||||
val mergedBitmap = mockk<Bitmap>()
|
||||
mockkStatic(BitmapUtils::class)
|
||||
every { BitmapUtils.mergeBitmap(bearingBitmap, backgroundBitmap, 10f, 15f) } returns mergedBitmap
|
||||
verify {
|
||||
layer.setProperties(
|
||||
LocationPropertyFactory.topImage(""),
|
||||
LocationPropertyFactory.bearingImage(FOREGROUND_STALE_ICON),
|
||||
LocationPropertyFactory.shadowImage(BACKGROUND_STALE_ICON)
|
||||
)
|
||||
}
|
||||
verify { layer.setProperties(LocationPropertyFactory.accuracyRadius(0f)) }
|
||||
}
|
||||
|
||||
every { bearingBitmap.width } returns 40
|
||||
every { bearingBitmap.height } returns 40
|
||||
every { bearingBitmap.config } returns mockk()
|
||||
every { backgroundStaleBitmap.width } returns 30
|
||||
every { backgroundStaleBitmap.height } returns 10
|
||||
@Test
|
||||
fun styleAccuracy() {
|
||||
val colorArray = ColorUtils.colorToRgbaArray(Color.RED)
|
||||
val exp = Expression.rgba(colorArray[0], colorArray[1], colorArray[2], 0.7f)
|
||||
|
||||
val mergedStaleBitmap = mockk<Bitmap>()
|
||||
every { BitmapUtils.mergeBitmap(bearingBitmap, backgroundStaleBitmap, 5f, 15f) } returns mergedStaleBitmap
|
||||
locationLayerRenderer.styleAccuracy(0.7f, Color.RED)
|
||||
|
||||
addBitmaps(withShadow = true, renderMode = RenderMode.COMPASS)
|
||||
verify {
|
||||
layer.setProperties(
|
||||
LocationPropertyFactory.accuracyRadiusColor(exp),
|
||||
LocationPropertyFactory.accuracyRadiusBorderColor(exp)
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
verify { style.addImage(BEARING_ICON, mergedBitmap) }
|
||||
verify { style.addImage(BEARING_STALE_ICON, mergedStaleBitmap) }
|
||||
@Test
|
||||
fun setLatLng() {
|
||||
val latLng = LatLng(10.0, 20.0)
|
||||
locationLayerRenderer.setLatLng(latLng)
|
||||
|
||||
unmockkStatic(BitmapUtils::class)
|
||||
}
|
||||
verify { layer.setProperties(LocationPropertyFactory.location(latLng.toLocationArray())) }
|
||||
}
|
||||
|
||||
@Test
|
||||
fun addBitmaps_gps() {
|
||||
addBitmaps(withShadow = true, renderMode = RenderMode.GPS)
|
||||
@Test
|
||||
fun setGpsBearing() {
|
||||
val bearing = 30.0
|
||||
locationLayerRenderer.setGpsBearing(bearing.toFloat())
|
||||
|
||||
verify { style.addImage(FOREGROUND_ICON, foregroundBitmap) }
|
||||
verify { style.addImage(FOREGROUND_STALE_ICON, foregroundStaleBitmap) }
|
||||
verify { style.addImage(BACKGROUND_ICON, backgroundBitmap) }
|
||||
verify { style.addImage(BACKGROUND_STALE_ICON, backgroundStaleBitmap) }
|
||||
verify { style.addImage(BEARING_ICON, bearingBitmap) }
|
||||
}
|
||||
verify { layer.setProperties(LocationPropertyFactory.bearing(bearing)) }
|
||||
}
|
||||
|
||||
private val shadowBitmap = mockk<Bitmap>()
|
||||
private val backgroundBitmap = mockk<Bitmap>()
|
||||
private val backgroundStaleBitmap = mockk<Bitmap>()
|
||||
private val bearingBitmap = mockk<Bitmap>()
|
||||
private val foregroundBitmap = mockk<Bitmap>()
|
||||
private val foregroundStaleBitmap = mockk<Bitmap>()
|
||||
@Test
|
||||
fun setCompassBearing() {
|
||||
val bearing = 30.0
|
||||
locationLayerRenderer.setCompassBearing(bearing.toFloat())
|
||||
|
||||
private fun addBitmaps(withShadow: Boolean, @RenderMode.Mode renderMode: Int) {
|
||||
locationLayerRenderer.addBitmaps(
|
||||
renderMode,
|
||||
if (withShadow) shadowBitmap else null,
|
||||
backgroundBitmap,
|
||||
backgroundStaleBitmap,
|
||||
bearingBitmap,
|
||||
foregroundBitmap,
|
||||
foregroundStaleBitmap
|
||||
)
|
||||
}
|
||||
verify { layer.setProperties(LocationPropertyFactory.bearing(bearing)) }
|
||||
}
|
||||
|
||||
private fun LatLng.toLocationArray() = arrayOf(latitude, longitude, 0.0)
|
||||
}
|
||||
@Test
|
||||
fun setAccuracyRadius() {
|
||||
val radius = 40f
|
||||
locationLayerRenderer.setAccuracyRadius(radius)
|
||||
|
||||
verify { layer.setProperties(LocationPropertyFactory.accuracyRadius(radius)) }
|
||||
}
|
||||
|
||||
@Test
|
||||
fun styleScaling() {
|
||||
val exp = Expression.literal("")
|
||||
locationLayerRenderer.styleScaling(exp)
|
||||
|
||||
verify {
|
||||
layer.setProperties(
|
||||
LocationPropertyFactory.shadowImageSize(exp),
|
||||
LocationPropertyFactory.bearingImageSize(exp),
|
||||
LocationPropertyFactory.topImageSize(exp)
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
fun setLocationStale() {
|
||||
locationLayerRenderer.setLocationStale(true, RenderMode.NORMAL)
|
||||
|
||||
verify {
|
||||
layer.setProperties(
|
||||
LocationPropertyFactory.topImage(FOREGROUND_STALE_ICON),
|
||||
LocationPropertyFactory.bearingImage(BACKGROUND_STALE_ICON),
|
||||
LocationPropertyFactory.shadowImage(SHADOW_ICON)
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
fun addBitmaps_shadow() {
|
||||
addBitmaps(withShadow = true, renderMode = RenderMode.NORMAL)
|
||||
|
||||
verify { style.addImage(SHADOW_ICON, shadowBitmap) }
|
||||
}
|
||||
|
||||
@Test
|
||||
fun addBitmaps_noShadow() {
|
||||
addBitmaps(withShadow = false, renderMode = RenderMode.NORMAL)
|
||||
|
||||
verify { style.removeImage(SHADOW_ICON) }
|
||||
}
|
||||
|
||||
@Test
|
||||
fun addBitmaps_normal() {
|
||||
addBitmaps(withShadow = true, renderMode = RenderMode.NORMAL)
|
||||
|
||||
verify { style.addImage(FOREGROUND_ICON, foregroundBitmap) }
|
||||
verify { style.addImage(FOREGROUND_STALE_ICON, foregroundStaleBitmap) }
|
||||
verify { style.addImage(BACKGROUND_ICON, backgroundBitmap) }
|
||||
verify { style.addImage(BACKGROUND_STALE_ICON, backgroundStaleBitmap) }
|
||||
verify { style.addImage(BEARING_ICON, bearingBitmap) }
|
||||
}
|
||||
|
||||
@Test
|
||||
fun addBitmaps_compass() {
|
||||
every { bearingBitmap.width } returns 40
|
||||
every { bearingBitmap.height } returns 40
|
||||
every { bearingBitmap.config } returns mockk()
|
||||
every { backgroundBitmap.width } returns 20
|
||||
every { backgroundBitmap.height } returns 10
|
||||
|
||||
val mergedBitmap = mockk<Bitmap>()
|
||||
mockkStatic(BitmapUtils::class)
|
||||
every { BitmapUtils.mergeBitmap(bearingBitmap, backgroundBitmap, 10f, 15f) } returns mergedBitmap
|
||||
|
||||
every { bearingBitmap.width } returns 40
|
||||
every { bearingBitmap.height } returns 40
|
||||
every { bearingBitmap.config } returns mockk()
|
||||
every { backgroundStaleBitmap.width } returns 30
|
||||
every { backgroundStaleBitmap.height } returns 10
|
||||
|
||||
val mergedStaleBitmap = mockk<Bitmap>()
|
||||
every { BitmapUtils.mergeBitmap(bearingBitmap, backgroundStaleBitmap, 5f, 15f) } returns mergedStaleBitmap
|
||||
|
||||
addBitmaps(withShadow = true, renderMode = RenderMode.COMPASS)
|
||||
|
||||
verify { style.addImage(BEARING_ICON, mergedBitmap) }
|
||||
verify { style.addImage(BEARING_STALE_ICON, mergedStaleBitmap) }
|
||||
|
||||
unmockkStatic(BitmapUtils::class)
|
||||
}
|
||||
|
||||
@Test
|
||||
fun addBitmaps_gps() {
|
||||
addBitmaps(withShadow = true, renderMode = RenderMode.GPS)
|
||||
|
||||
verify { style.addImage(FOREGROUND_ICON, foregroundBitmap) }
|
||||
verify { style.addImage(FOREGROUND_STALE_ICON, foregroundStaleBitmap) }
|
||||
verify { style.addImage(BACKGROUND_ICON, backgroundBitmap) }
|
||||
verify { style.addImage(BACKGROUND_STALE_ICON, backgroundStaleBitmap) }
|
||||
verify { style.addImage(BEARING_ICON, bearingBitmap) }
|
||||
}
|
||||
|
||||
private val shadowBitmap = mockk<Bitmap>()
|
||||
private val backgroundBitmap = mockk<Bitmap>()
|
||||
private val backgroundStaleBitmap = mockk<Bitmap>()
|
||||
private val bearingBitmap = mockk<Bitmap>()
|
||||
private val foregroundBitmap = mockk<Bitmap>()
|
||||
private val foregroundStaleBitmap = mockk<Bitmap>()
|
||||
|
||||
private fun addBitmaps(withShadow: Boolean, @RenderMode.Mode renderMode: Int) {
|
||||
locationLayerRenderer.addBitmaps(
|
||||
renderMode,
|
||||
if (withShadow) shadowBitmap else null,
|
||||
backgroundBitmap,
|
||||
backgroundStaleBitmap,
|
||||
bearingBitmap,
|
||||
foregroundBitmap,
|
||||
foregroundStaleBitmap
|
||||
)
|
||||
}
|
||||
|
||||
private fun LatLng.toLocationArray() = arrayOf(latitude, longitude, 0.0)
|
||||
}
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@@ -14,117 +14,117 @@ import org.mockito.junit.MockitoJUnitRunner
|
||||
@RunWith(MockitoJUnitRunner::class)
|
||||
class LocationComponentPositionManagerTest {
|
||||
|
||||
private lateinit var style: Style
|
||||
private lateinit var layer: Layer
|
||||
private lateinit var style: Style
|
||||
private lateinit var layer: Layer
|
||||
|
||||
@Before
|
||||
fun setup() {
|
||||
style = mockk(relaxed = true)
|
||||
layer = mockk(relaxed = true)
|
||||
}
|
||||
@Before
|
||||
fun setup() {
|
||||
style = mockk(relaxed = true)
|
||||
layer = mockk(relaxed = true)
|
||||
}
|
||||
|
||||
@Test
|
||||
fun update_noChange_null() {
|
||||
val positionManager = LocationComponentPositionManager(style, null, null)
|
||||
val requiresUpdate = positionManager.update(null, null)
|
||||
assertFalse(requiresUpdate)
|
||||
}
|
||||
@Test
|
||||
fun update_noChange_null() {
|
||||
val positionManager = LocationComponentPositionManager(style, null, null)
|
||||
val requiresUpdate = positionManager.update(null, null)
|
||||
assertFalse(requiresUpdate)
|
||||
}
|
||||
|
||||
@Test
|
||||
fun update_noChange_above() {
|
||||
val positionManager = LocationComponentPositionManager(style, "above", null)
|
||||
val requiresUpdate = positionManager.update("above", null)
|
||||
assertFalse(requiresUpdate)
|
||||
}
|
||||
@Test
|
||||
fun update_noChange_above() {
|
||||
val positionManager = LocationComponentPositionManager(style, "above", null)
|
||||
val requiresUpdate = positionManager.update("above", null)
|
||||
assertFalse(requiresUpdate)
|
||||
}
|
||||
|
||||
@Test
|
||||
fun update_noChange_below() {
|
||||
val positionManager = LocationComponentPositionManager(style, null, "below")
|
||||
val requiresUpdate = positionManager.update(null, "below")
|
||||
assertFalse(requiresUpdate)
|
||||
}
|
||||
@Test
|
||||
fun update_noChange_below() {
|
||||
val positionManager = LocationComponentPositionManager(style, null, "below")
|
||||
val requiresUpdate = positionManager.update(null, "below")
|
||||
assertFalse(requiresUpdate)
|
||||
}
|
||||
|
||||
@Test
|
||||
fun update_fromNull_above() {
|
||||
val positionManager = LocationComponentPositionManager(style, null, null)
|
||||
val requiresUpdate = positionManager.update("above", null)
|
||||
assertTrue(requiresUpdate)
|
||||
}
|
||||
@Test
|
||||
fun update_fromNull_above() {
|
||||
val positionManager = LocationComponentPositionManager(style, null, null)
|
||||
val requiresUpdate = positionManager.update("above", null)
|
||||
assertTrue(requiresUpdate)
|
||||
}
|
||||
|
||||
@Test
|
||||
fun update_fromNull_below() {
|
||||
val positionManager = LocationComponentPositionManager(style, null, null)
|
||||
val requiresUpdate = positionManager.update(null, "below")
|
||||
assertTrue(requiresUpdate)
|
||||
}
|
||||
@Test
|
||||
fun update_fromNull_below() {
|
||||
val positionManager = LocationComponentPositionManager(style, null, null)
|
||||
val requiresUpdate = positionManager.update(null, "below")
|
||||
assertTrue(requiresUpdate)
|
||||
}
|
||||
|
||||
@Test
|
||||
fun update_toNull_above() {
|
||||
val positionManager = LocationComponentPositionManager(style, "above", null)
|
||||
val requiresUpdate = positionManager.update(null, null)
|
||||
assertTrue(requiresUpdate)
|
||||
}
|
||||
@Test
|
||||
fun update_toNull_above() {
|
||||
val positionManager = LocationComponentPositionManager(style, "above", null)
|
||||
val requiresUpdate = positionManager.update(null, null)
|
||||
assertTrue(requiresUpdate)
|
||||
}
|
||||
|
||||
@Test
|
||||
fun update_toNull_below() {
|
||||
val positionManager = LocationComponentPositionManager(style, null, "below")
|
||||
val requiresUpdate = positionManager.update(null, null)
|
||||
assertTrue(requiresUpdate)
|
||||
}
|
||||
@Test
|
||||
fun update_toNull_below() {
|
||||
val positionManager = LocationComponentPositionManager(style, null, "below")
|
||||
val requiresUpdate = positionManager.update(null, null)
|
||||
assertTrue(requiresUpdate)
|
||||
}
|
||||
|
||||
@Test
|
||||
fun update_fromValue_above() {
|
||||
val positionManager = LocationComponentPositionManager(style, "above1", null)
|
||||
val requiresUpdate = positionManager.update("above2", null)
|
||||
assertTrue(requiresUpdate)
|
||||
}
|
||||
@Test
|
||||
fun update_fromValue_above() {
|
||||
val positionManager = LocationComponentPositionManager(style, "above1", null)
|
||||
val requiresUpdate = positionManager.update("above2", null)
|
||||
assertTrue(requiresUpdate)
|
||||
}
|
||||
|
||||
@Test
|
||||
fun update_fromValue_below() {
|
||||
val positionManager = LocationComponentPositionManager(style, null, "below1")
|
||||
val requiresUpdate = positionManager.update(null, "below2")
|
||||
assertTrue(requiresUpdate)
|
||||
}
|
||||
@Test
|
||||
fun update_fromValue_below() {
|
||||
val positionManager = LocationComponentPositionManager(style, null, "below1")
|
||||
val requiresUpdate = positionManager.update(null, "below2")
|
||||
assertTrue(requiresUpdate)
|
||||
}
|
||||
|
||||
@Test
|
||||
fun addLayer_noModifier() {
|
||||
val positionManager = LocationComponentPositionManager(style, null, null)
|
||||
positionManager.addLayerToMap(layer)
|
||||
@Test
|
||||
fun addLayer_noModifier() {
|
||||
val positionManager = LocationComponentPositionManager(style, null, null)
|
||||
positionManager.addLayerToMap(layer)
|
||||
|
||||
verify { style.addLayer(layer) }
|
||||
}
|
||||
verify { style.addLayer(layer) }
|
||||
}
|
||||
|
||||
@Test
|
||||
fun addLayer_above() {
|
||||
val positionManager = LocationComponentPositionManager(style, "above", null)
|
||||
positionManager.addLayerToMap(layer)
|
||||
@Test
|
||||
fun addLayer_above() {
|
||||
val positionManager = LocationComponentPositionManager(style, "above", null)
|
||||
positionManager.addLayerToMap(layer)
|
||||
|
||||
verify { style.addLayerAbove(layer, "above") }
|
||||
}
|
||||
verify { style.addLayerAbove(layer, "above") }
|
||||
}
|
||||
|
||||
@Test
|
||||
fun addLayer_below() {
|
||||
val positionManager = LocationComponentPositionManager(style, null, "below")
|
||||
positionManager.addLayerToMap(layer)
|
||||
@Test
|
||||
fun addLayer_below() {
|
||||
val positionManager = LocationComponentPositionManager(style, null, "below")
|
||||
positionManager.addLayerToMap(layer)
|
||||
|
||||
verify { style.addLayerBelow(layer, "below") }
|
||||
}
|
||||
verify { style.addLayerBelow(layer, "below") }
|
||||
}
|
||||
|
||||
@Test
|
||||
fun addLayer_afterUpdate_above() {
|
||||
val positionManager = LocationComponentPositionManager(style, null, null)
|
||||
positionManager.update("above", null)
|
||||
positionManager.addLayerToMap(layer)
|
||||
@Test
|
||||
fun addLayer_afterUpdate_above() {
|
||||
val positionManager = LocationComponentPositionManager(style, null, null)
|
||||
positionManager.update("above", null)
|
||||
positionManager.addLayerToMap(layer)
|
||||
|
||||
verify { style.addLayerAbove(layer, "above") }
|
||||
}
|
||||
verify { style.addLayerAbove(layer, "above") }
|
||||
}
|
||||
|
||||
@Test
|
||||
fun addLayer_afterUpdate_below() {
|
||||
val positionManager = LocationComponentPositionManager(style, null, null)
|
||||
positionManager.update(null, "below")
|
||||
positionManager.addLayerToMap(layer)
|
||||
@Test
|
||||
fun addLayer_afterUpdate_below() {
|
||||
val positionManager = LocationComponentPositionManager(style, null, null)
|
||||
positionManager.update(null, "below")
|
||||
positionManager.addLayerToMap(layer)
|
||||
|
||||
verify { style.addLayerBelow(layer, "below") }
|
||||
}
|
||||
}
|
||||
verify { style.addLayerBelow(layer, "below") }
|
||||
}
|
||||
}
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@@ -11,33 +11,33 @@ import org.robolectric.RobolectricTestRunner
|
||||
@RunWith(RobolectricTestRunner::class)
|
||||
class MapboxAnimatorTest {
|
||||
|
||||
@Test
|
||||
fun fps_unlimited() {
|
||||
val valueAnimator = mockk<ValueAnimator>()
|
||||
every { valueAnimator.animatedValue } answers { 5f }
|
||||
val listener = mockk<MapboxAnimator.AnimationsValueChangeListener<Float>>()
|
||||
every { listener.onNewAnimationValue(any()) } answers {}
|
||||
val mapboxAnimator = MapboxFloatAnimator(floatArrayOf(0f, 10f).toTypedArray(), listener, Int.MAX_VALUE)
|
||||
@Test
|
||||
fun fps_unlimited() {
|
||||
val valueAnimator = mockk<ValueAnimator>()
|
||||
every { valueAnimator.animatedValue } answers { 5f }
|
||||
val listener = mockk<MapboxAnimator.AnimationsValueChangeListener<Float>>()
|
||||
every { listener.onNewAnimationValue(any()) } answers {}
|
||||
val mapboxAnimator = MapboxFloatAnimator(floatArrayOf(0f, 10f).toTypedArray(), listener, Int.MAX_VALUE)
|
||||
|
||||
for (i in 0 until 5)
|
||||
mapboxAnimator.onAnimationUpdate(valueAnimator)
|
||||
for (i in 0 until 5)
|
||||
mapboxAnimator.onAnimationUpdate(valueAnimator)
|
||||
|
||||
verify(exactly = 5) { listener.onNewAnimationValue(5f) }
|
||||
}
|
||||
|
||||
@Test
|
||||
fun fps_limited() {
|
||||
val valueAnimator = mockk<ValueAnimator>()
|
||||
every { valueAnimator.animatedValue } answers { 5f }
|
||||
val listener = mockk<MapboxAnimator.AnimationsValueChangeListener<Float>>()
|
||||
every { listener.onNewAnimationValue(any()) } answers {}
|
||||
val mapboxAnimator = MapboxFloatAnimator(floatArrayOf(0f, 10f).toTypedArray(), listener, 5)
|
||||
|
||||
for (i in 0 until 5) {
|
||||
mapboxAnimator.onAnimationUpdate(valueAnimator)
|
||||
Thread.sleep(150)
|
||||
verify(exactly = 5) { listener.onNewAnimationValue(5f) }
|
||||
}
|
||||
|
||||
verify(exactly = 3) { listener.onNewAnimationValue(5f) }
|
||||
}
|
||||
}
|
||||
@Test
|
||||
fun fps_limited() {
|
||||
val valueAnimator = mockk<ValueAnimator>()
|
||||
every { valueAnimator.animatedValue } answers { 5f }
|
||||
val listener = mockk<MapboxAnimator.AnimationsValueChangeListener<Float>>()
|
||||
every { listener.onNewAnimationValue(any()) } answers {}
|
||||
val mapboxAnimator = MapboxFloatAnimator(floatArrayOf(0f, 10f).toTypedArray(), listener, 5)
|
||||
|
||||
for (i in 0 until 5) {
|
||||
mapboxAnimator.onAnimationUpdate(valueAnimator)
|
||||
Thread.sleep(150)
|
||||
}
|
||||
|
||||
verify(exactly = 3) { listener.onNewAnimationValue(5f) }
|
||||
}
|
||||
}
|
||||
|
||||
@@ -10,84 +10,84 @@ import org.robolectric.RobolectricTestRunner
|
||||
@RunWith(RobolectricTestRunner::class)
|
||||
class LoggerTest {
|
||||
|
||||
private val logger: LoggerDefinition = mockk(relaxed = true)
|
||||
private val logger: LoggerDefinition = mockk(relaxed = true)
|
||||
|
||||
@Before
|
||||
fun setUp() {
|
||||
Logger.setLoggerDefinition(logger)
|
||||
}
|
||||
@Before
|
||||
fun setUp() {
|
||||
Logger.setLoggerDefinition(logger)
|
||||
}
|
||||
|
||||
@Test
|
||||
fun verbosityLogLevel() {
|
||||
Logger.setVerbosity(Logger.VERBOSE)
|
||||
Logger.v(TAG, MESSAGE)
|
||||
verify { logger.v(TAG, MESSAGE) }
|
||||
}
|
||||
@Test
|
||||
fun verbosityLogLevel() {
|
||||
Logger.setVerbosity(Logger.VERBOSE)
|
||||
Logger.v(TAG, MESSAGE)
|
||||
verify { logger.v(TAG, MESSAGE) }
|
||||
}
|
||||
|
||||
@Test
|
||||
fun verbosityLogLevelIgnore() {
|
||||
Logger.setVerbosity(Logger.DEBUG)
|
||||
Logger.v(TAG, MESSAGE)
|
||||
verify(exactly = 0) { logger.v(TAG, MESSAGE) }
|
||||
}
|
||||
@Test
|
||||
fun verbosityLogLevelIgnore() {
|
||||
Logger.setVerbosity(Logger.DEBUG)
|
||||
Logger.v(TAG, MESSAGE)
|
||||
verify(exactly = 0) { logger.v(TAG, MESSAGE) }
|
||||
}
|
||||
|
||||
@Test
|
||||
fun debugLogLevel() {
|
||||
Logger.setVerbosity(Logger.VERBOSE)
|
||||
Logger.d(TAG, MESSAGE)
|
||||
verify { logger.d(TAG, MESSAGE) }
|
||||
}
|
||||
@Test
|
||||
fun debugLogLevel() {
|
||||
Logger.setVerbosity(Logger.VERBOSE)
|
||||
Logger.d(TAG, MESSAGE)
|
||||
verify { logger.d(TAG, MESSAGE) }
|
||||
}
|
||||
|
||||
@Test
|
||||
fun debugLogLevelIgnore() {
|
||||
Logger.setVerbosity(Logger.WARN)
|
||||
Logger.d(TAG, MESSAGE)
|
||||
verify(exactly = 0) { logger.d(TAG, MESSAGE) }
|
||||
}
|
||||
@Test
|
||||
fun debugLogLevelIgnore() {
|
||||
Logger.setVerbosity(Logger.WARN)
|
||||
Logger.d(TAG, MESSAGE)
|
||||
verify(exactly = 0) { logger.d(TAG, MESSAGE) }
|
||||
}
|
||||
|
||||
@Test
|
||||
fun warnLogLevel() {
|
||||
Logger.setVerbosity(Logger.WARN)
|
||||
Logger.w(TAG, MESSAGE)
|
||||
verify { logger.w(TAG, MESSAGE) }
|
||||
}
|
||||
@Test
|
||||
fun warnLogLevel() {
|
||||
Logger.setVerbosity(Logger.WARN)
|
||||
Logger.w(TAG, MESSAGE)
|
||||
verify { logger.w(TAG, MESSAGE) }
|
||||
}
|
||||
|
||||
@Test
|
||||
fun warnLogLevelIgnore() {
|
||||
Logger.setVerbosity(Logger.ERROR)
|
||||
Logger.w(TAG, MESSAGE)
|
||||
verify(exactly = 0) { logger.w(TAG, MESSAGE) }
|
||||
}
|
||||
@Test
|
||||
fun warnLogLevelIgnore() {
|
||||
Logger.setVerbosity(Logger.ERROR)
|
||||
Logger.w(TAG, MESSAGE)
|
||||
verify(exactly = 0) { logger.w(TAG, MESSAGE) }
|
||||
}
|
||||
|
||||
@Test
|
||||
fun errorLogLevel() {
|
||||
Logger.setVerbosity(Logger.ERROR)
|
||||
Logger.e(TAG, MESSAGE)
|
||||
verify { logger.e(TAG, MESSAGE) }
|
||||
}
|
||||
@Test
|
||||
fun errorLogLevel() {
|
||||
Logger.setVerbosity(Logger.ERROR)
|
||||
Logger.e(TAG, MESSAGE)
|
||||
verify { logger.e(TAG, MESSAGE) }
|
||||
}
|
||||
|
||||
@Test
|
||||
fun errorLogLevelIgnore() {
|
||||
Logger.setVerbosity(Logger.NONE)
|
||||
Logger.e(TAG, MESSAGE)
|
||||
verify(exactly = 0) { logger.e(TAG, MESSAGE) }
|
||||
}
|
||||
@Test
|
||||
fun errorLogLevelIgnore() {
|
||||
Logger.setVerbosity(Logger.NONE)
|
||||
Logger.e(TAG, MESSAGE)
|
||||
verify(exactly = 0) { logger.e(TAG, MESSAGE) }
|
||||
}
|
||||
|
||||
@Test
|
||||
fun noneLogLevelIgnore() {
|
||||
Logger.setVerbosity(Logger.NONE)
|
||||
Logger.v(TAG, MESSAGE)
|
||||
Logger.d(TAG, MESSAGE)
|
||||
Logger.w(TAG, MESSAGE)
|
||||
Logger.e(TAG, MESSAGE)
|
||||
verify(exactly = 0) { logger.v(TAG, MESSAGE) }
|
||||
verify(exactly = 0) { logger.d(TAG, MESSAGE) }
|
||||
verify(exactly = 0) { logger.w(TAG, MESSAGE) }
|
||||
verify(exactly = 0) { logger.e(TAG, MESSAGE) }
|
||||
}
|
||||
@Test
|
||||
fun noneLogLevelIgnore() {
|
||||
Logger.setVerbosity(Logger.NONE)
|
||||
Logger.v(TAG, MESSAGE)
|
||||
Logger.d(TAG, MESSAGE)
|
||||
Logger.w(TAG, MESSAGE)
|
||||
Logger.e(TAG, MESSAGE)
|
||||
verify(exactly = 0) { logger.v(TAG, MESSAGE) }
|
||||
verify(exactly = 0) { logger.d(TAG, MESSAGE) }
|
||||
verify(exactly = 0) { logger.w(TAG, MESSAGE) }
|
||||
verify(exactly = 0) { logger.e(TAG, MESSAGE) }
|
||||
}
|
||||
|
||||
companion object {
|
||||
const val TAG: String = "TAG"
|
||||
const val MESSAGE: String = "message"
|
||||
}
|
||||
}
|
||||
companion object {
|
||||
const val TAG: String = "TAG"
|
||||
const val MESSAGE: String = "message"
|
||||
}
|
||||
}
|
||||
|
||||
@@ -16,86 +16,86 @@ import org.robolectric.RobolectricTestRunner
|
||||
@RunWith(RobolectricTestRunner::class)
|
||||
class MapboxMapOptionsAttrsTest {
|
||||
|
||||
@RelaxedMockK
|
||||
private lateinit var options: MapboxMapOptions
|
||||
@RelaxedMockK
|
||||
private lateinit var options: MapboxMapOptions
|
||||
|
||||
@RelaxedMockK
|
||||
private lateinit var typedArray: TypedArray
|
||||
@RelaxedMockK
|
||||
private lateinit var typedArray: TypedArray
|
||||
|
||||
@RelaxedMockK
|
||||
private lateinit var context: Context
|
||||
@RelaxedMockK
|
||||
private lateinit var context: Context
|
||||
|
||||
@RelaxedMockK
|
||||
private lateinit var resources: Resources
|
||||
@RelaxedMockK
|
||||
private lateinit var resources: Resources
|
||||
|
||||
@Before
|
||||
fun setUp() {
|
||||
MockKAnnotations.init(this)
|
||||
every {
|
||||
context.resources
|
||||
}.returns(resources)
|
||||
}
|
||||
|
||||
@Test
|
||||
fun enabledLocalIdeographFontFamily() {
|
||||
mockEnableLocalIdeograph(enabled = true)
|
||||
|
||||
val options = MapboxMapOptions.createFromAttributes(options, context, typedArray)
|
||||
|
||||
verify(exactly = 1) {
|
||||
options.localIdeographFontFamily(any())
|
||||
@Before
|
||||
fun setUp() {
|
||||
MockKAnnotations.init(this)
|
||||
every {
|
||||
context.resources
|
||||
}.returns(resources)
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
fun localIdeographFontFamily() {
|
||||
mockEnableLocalIdeograph(enabled = true)
|
||||
@Test
|
||||
fun enabledLocalIdeographFontFamily() {
|
||||
mockEnableLocalIdeograph(enabled = true)
|
||||
|
||||
val font = "foo"
|
||||
mockLocalIdeographString(font)
|
||||
val options = MapboxMapOptions.createFromAttributes(options, context, typedArray)
|
||||
|
||||
val options = MapboxMapOptions.createFromAttributes(options, context, typedArray)
|
||||
|
||||
verify(exactly = 1) {
|
||||
options.localIdeographFontFamily(font)
|
||||
verify(exactly = 1) {
|
||||
options.localIdeographFontFamily(any())
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
fun localIdeographFontFamilies() {
|
||||
mockEnableLocalIdeograph(enabled = true)
|
||||
@Test
|
||||
fun localIdeographFontFamily() {
|
||||
mockEnableLocalIdeograph(enabled = true)
|
||||
|
||||
val fonts = arrayOf("foo", "bar")
|
||||
mockLocalIdeographStringArray(fonts)
|
||||
val font = "foo"
|
||||
mockLocalIdeographString(font)
|
||||
|
||||
val options = MapboxMapOptions.createFromAttributes(options, context, typedArray)
|
||||
val options = MapboxMapOptions.createFromAttributes(options, context, typedArray)
|
||||
|
||||
verify(exactly = 1) {
|
||||
options.localIdeographFontFamily(*fonts)
|
||||
verify(exactly = 1) {
|
||||
options.localIdeographFontFamily(font)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private fun mockEnableLocalIdeograph(enabled: Boolean) {
|
||||
every {
|
||||
typedArray.getBoolean(R.styleable.mapbox_MapView_mapbox_localIdeographEnabled, true)
|
||||
}.returns(enabled)
|
||||
}
|
||||
@Test
|
||||
fun localIdeographFontFamilies() {
|
||||
mockEnableLocalIdeograph(enabled = true)
|
||||
|
||||
private fun mockLocalIdeographString(font: String) {
|
||||
every {
|
||||
typedArray.getString(R.styleable.mapbox_MapView_mapbox_localIdeographFontFamily)
|
||||
}.returns(font)
|
||||
}
|
||||
val fonts = arrayOf("foo", "bar")
|
||||
mockLocalIdeographStringArray(fonts)
|
||||
|
||||
private fun mockLocalIdeographStringArray(fonts: Array<String>) {
|
||||
val resId = 9000
|
||||
val options = MapboxMapOptions.createFromAttributes(options, context, typedArray)
|
||||
|
||||
every {
|
||||
typedArray.getResourceId(R.styleable.mapbox_MapView_mapbox_localIdeographFontFamilies, 0)
|
||||
}.returns(resId)
|
||||
verify(exactly = 1) {
|
||||
options.localIdeographFontFamily(*fonts)
|
||||
}
|
||||
}
|
||||
|
||||
every {
|
||||
resources.getStringArray(resId)
|
||||
}.returns(fonts)
|
||||
}
|
||||
}
|
||||
private fun mockEnableLocalIdeograph(enabled: Boolean) {
|
||||
every {
|
||||
typedArray.getBoolean(R.styleable.mapbox_MapView_mapbox_localIdeographEnabled, true)
|
||||
}.returns(enabled)
|
||||
}
|
||||
|
||||
private fun mockLocalIdeographString(font: String) {
|
||||
every {
|
||||
typedArray.getString(R.styleable.mapbox_MapView_mapbox_localIdeographFontFamily)
|
||||
}.returns(font)
|
||||
}
|
||||
|
||||
private fun mockLocalIdeographStringArray(fonts: Array<String>) {
|
||||
val resId = 9000
|
||||
|
||||
every {
|
||||
typedArray.getResourceId(R.styleable.mapbox_MapView_mapbox_localIdeographFontFamilies, 0)
|
||||
}.returns(resId)
|
||||
|
||||
every {
|
||||
resources.getStringArray(resId)
|
||||
}.returns(fonts)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -16,211 +16,211 @@ import org.robolectric.RobolectricTestRunner
|
||||
@RunWith(RobolectricTestRunner::class)
|
||||
class MapboxMapTest {
|
||||
|
||||
private lateinit var mapboxMap: MapboxMap
|
||||
private lateinit var mapboxMap: MapboxMap
|
||||
|
||||
private lateinit var nativeMapView: NativeMap
|
||||
private lateinit var nativeMapView: NativeMap
|
||||
|
||||
private lateinit var transform: Transform
|
||||
private lateinit var transform: Transform
|
||||
|
||||
private lateinit var cameraChangeDispatcher: CameraChangeDispatcher
|
||||
private lateinit var cameraChangeDispatcher: CameraChangeDispatcher
|
||||
|
||||
private lateinit var developerAnimationListener: MapboxMap.OnDeveloperAnimationListener
|
||||
private lateinit var developerAnimationListener: MapboxMap.OnDeveloperAnimationListener
|
||||
|
||||
@Before
|
||||
fun setup() {
|
||||
cameraChangeDispatcher = spyk()
|
||||
developerAnimationListener = mockk(relaxed = true)
|
||||
nativeMapView = mockk(relaxed = true)
|
||||
transform = mockk(relaxed = true)
|
||||
mapboxMap = MapboxMap(nativeMapView, transform, mockk(relaxed = true), null, null, cameraChangeDispatcher, listOf(developerAnimationListener))
|
||||
every { nativeMapView.isDestroyed } returns false
|
||||
every { nativeMapView.nativePtr } returns 5
|
||||
mapboxMap.injectLocationComponent(spyk())
|
||||
mapboxMap.setStyle(Style.MAPBOX_STREETS)
|
||||
mapboxMap.onFinishLoadingStyle()
|
||||
}
|
||||
@Before
|
||||
fun setup() {
|
||||
cameraChangeDispatcher = spyk()
|
||||
developerAnimationListener = mockk(relaxed = true)
|
||||
nativeMapView = mockk(relaxed = true)
|
||||
transform = mockk(relaxed = true)
|
||||
mapboxMap = MapboxMap(nativeMapView, transform, mockk(relaxed = true), null, null, cameraChangeDispatcher, listOf(developerAnimationListener))
|
||||
every { nativeMapView.isDestroyed } returns false
|
||||
every { nativeMapView.nativePtr } returns 5
|
||||
mapboxMap.injectLocationComponent(spyk())
|
||||
mapboxMap.setStyle(Style.MAPBOX_STREETS)
|
||||
mapboxMap.onFinishLoadingStyle()
|
||||
}
|
||||
|
||||
@Test
|
||||
fun testTransitionOptions() {
|
||||
val expected = TransitionOptions(100, 200)
|
||||
mapboxMap.style?.transition = expected
|
||||
verify { nativeMapView.transitionOptions = expected }
|
||||
}
|
||||
@Test
|
||||
fun testTransitionOptions() {
|
||||
val expected = TransitionOptions(100, 200)
|
||||
mapboxMap.style?.transition = expected
|
||||
verify { nativeMapView.transitionOptions = expected }
|
||||
}
|
||||
|
||||
@Test
|
||||
fun testMoveCamera() {
|
||||
val callback = mockk<MapboxMap.CancelableCallback>()
|
||||
val target = LatLng(1.0, 2.0)
|
||||
val expected = CameraPosition.Builder().target(target).build()
|
||||
val update = CameraUpdateFactory.newCameraPosition(expected)
|
||||
mapboxMap.moveCamera(update, callback)
|
||||
verify { transform.moveCamera(mapboxMap, update, callback) }
|
||||
verify { developerAnimationListener.onDeveloperAnimationStarted() }
|
||||
}
|
||||
@Test
|
||||
fun testMoveCamera() {
|
||||
val callback = mockk<MapboxMap.CancelableCallback>()
|
||||
val target = LatLng(1.0, 2.0)
|
||||
val expected = CameraPosition.Builder().target(target).build()
|
||||
val update = CameraUpdateFactory.newCameraPosition(expected)
|
||||
mapboxMap.moveCamera(update, callback)
|
||||
verify { transform.moveCamera(mapboxMap, update, callback) }
|
||||
verify { developerAnimationListener.onDeveloperAnimationStarted() }
|
||||
}
|
||||
|
||||
@Test
|
||||
fun testEaseCamera() {
|
||||
val callback = mockk<MapboxMap.CancelableCallback>()
|
||||
val target = LatLng(1.0, 2.0)
|
||||
val expected = CameraPosition.Builder().target(target).build()
|
||||
val update = CameraUpdateFactory.newCameraPosition(expected)
|
||||
mapboxMap.easeCamera(update, callback)
|
||||
verify { transform.easeCamera(mapboxMap, update, MapboxConstants.ANIMATION_DURATION, true, callback) }
|
||||
verify { developerAnimationListener.onDeveloperAnimationStarted() }
|
||||
}
|
||||
@Test
|
||||
fun testEaseCamera() {
|
||||
val callback = mockk<MapboxMap.CancelableCallback>()
|
||||
val target = LatLng(1.0, 2.0)
|
||||
val expected = CameraPosition.Builder().target(target).build()
|
||||
val update = CameraUpdateFactory.newCameraPosition(expected)
|
||||
mapboxMap.easeCamera(update, callback)
|
||||
verify { transform.easeCamera(mapboxMap, update, MapboxConstants.ANIMATION_DURATION, true, callback) }
|
||||
verify { developerAnimationListener.onDeveloperAnimationStarted() }
|
||||
}
|
||||
|
||||
@Test
|
||||
fun testAnimateCamera() {
|
||||
val callback = mockk<MapboxMap.CancelableCallback>()
|
||||
val target = LatLng(1.0, 2.0)
|
||||
val expected = CameraPosition.Builder().target(target).build()
|
||||
val update = CameraUpdateFactory.newCameraPosition(expected)
|
||||
mapboxMap.animateCamera(update, callback)
|
||||
verify { transform.animateCamera(mapboxMap, update, MapboxConstants.ANIMATION_DURATION, callback) }
|
||||
verify { developerAnimationListener.onDeveloperAnimationStarted() }
|
||||
}
|
||||
@Test
|
||||
fun testAnimateCamera() {
|
||||
val callback = mockk<MapboxMap.CancelableCallback>()
|
||||
val target = LatLng(1.0, 2.0)
|
||||
val expected = CameraPosition.Builder().target(target).build()
|
||||
val update = CameraUpdateFactory.newCameraPosition(expected)
|
||||
mapboxMap.animateCamera(update, callback)
|
||||
verify { transform.animateCamera(mapboxMap, update, MapboxConstants.ANIMATION_DURATION, callback) }
|
||||
verify { developerAnimationListener.onDeveloperAnimationStarted() }
|
||||
}
|
||||
|
||||
@Test
|
||||
fun testScrollBy() {
|
||||
mapboxMap.scrollBy(100f, 200f)
|
||||
verify { nativeMapView.moveBy(100.0, 200.0, 0) }
|
||||
verify { developerAnimationListener.onDeveloperAnimationStarted() }
|
||||
}
|
||||
@Test
|
||||
fun testScrollBy() {
|
||||
mapboxMap.scrollBy(100f, 200f)
|
||||
verify { nativeMapView.moveBy(100.0, 200.0, 0) }
|
||||
verify { developerAnimationListener.onDeveloperAnimationStarted() }
|
||||
}
|
||||
|
||||
@Test
|
||||
fun testResetNorth() {
|
||||
mapboxMap.resetNorth()
|
||||
verify { transform.resetNorth() }
|
||||
verify { developerAnimationListener.onDeveloperAnimationStarted() }
|
||||
}
|
||||
@Test
|
||||
fun testResetNorth() {
|
||||
mapboxMap.resetNorth()
|
||||
verify { transform.resetNorth() }
|
||||
verify { developerAnimationListener.onDeveloperAnimationStarted() }
|
||||
}
|
||||
|
||||
@Test
|
||||
fun testFocalBearing() {
|
||||
mapboxMap.setFocalBearing(35.0, 100f, 200f, 1000)
|
||||
verify { transform.setBearing(35.0, 100f, 200f, 1000) }
|
||||
verify { developerAnimationListener.onDeveloperAnimationStarted() }
|
||||
}
|
||||
@Test
|
||||
fun testFocalBearing() {
|
||||
mapboxMap.setFocalBearing(35.0, 100f, 200f, 1000)
|
||||
verify { transform.setBearing(35.0, 100f, 200f, 1000) }
|
||||
verify { developerAnimationListener.onDeveloperAnimationStarted() }
|
||||
}
|
||||
|
||||
@Test
|
||||
fun testMinZoom() {
|
||||
mapboxMap.setMinZoomPreference(10.0)
|
||||
verify { transform.minZoom = 10.0 }
|
||||
}
|
||||
@Test
|
||||
fun testMinZoom() {
|
||||
mapboxMap.setMinZoomPreference(10.0)
|
||||
verify { transform.minZoom = 10.0 }
|
||||
}
|
||||
|
||||
@Test
|
||||
fun testMaxZoom() {
|
||||
mapboxMap.setMaxZoomPreference(10.0)
|
||||
verify { transform.maxZoom = 10.0 }
|
||||
}
|
||||
@Test
|
||||
fun testMaxZoom() {
|
||||
mapboxMap.setMaxZoomPreference(10.0)
|
||||
verify { transform.maxZoom = 10.0 }
|
||||
}
|
||||
|
||||
@Test
|
||||
fun testMinPitch() {
|
||||
mapboxMap.setMinPitchPreference(10.0)
|
||||
verify { transform.minPitch = 10.0 }
|
||||
}
|
||||
@Test
|
||||
fun testMinPitch() {
|
||||
mapboxMap.setMinPitchPreference(10.0)
|
||||
verify { transform.minPitch = 10.0 }
|
||||
}
|
||||
|
||||
@Test
|
||||
fun testMaxPitch() {
|
||||
mapboxMap.setMaxPitchPreference(10.0)
|
||||
verify { transform.maxPitch = 10.0 }
|
||||
}
|
||||
@Test
|
||||
fun testMaxPitch() {
|
||||
mapboxMap.setMaxPitchPreference(10.0)
|
||||
verify { transform.maxPitch = 10.0 }
|
||||
}
|
||||
|
||||
@Test
|
||||
fun testFpsListener() {
|
||||
val fpsChangedListener = mockk<MapboxMap.OnFpsChangedListener>()
|
||||
mapboxMap.onFpsChangedListener = fpsChangedListener
|
||||
assertEquals("Listener should match", fpsChangedListener, mapboxMap.onFpsChangedListener)
|
||||
}
|
||||
@Test
|
||||
fun testFpsListener() {
|
||||
val fpsChangedListener = mockk<MapboxMap.OnFpsChangedListener>()
|
||||
mapboxMap.onFpsChangedListener = fpsChangedListener
|
||||
assertEquals("Listener should match", fpsChangedListener, mapboxMap.onFpsChangedListener)
|
||||
}
|
||||
|
||||
@Test
|
||||
fun testTilePrefetch() {
|
||||
mapboxMap.prefetchesTiles = true
|
||||
verify { nativeMapView.prefetchTiles = true }
|
||||
}
|
||||
@Test
|
||||
fun testTilePrefetch() {
|
||||
mapboxMap.prefetchesTiles = true
|
||||
verify { nativeMapView.prefetchTiles = true }
|
||||
}
|
||||
|
||||
@Test
|
||||
fun testGetPrefetchZoomDelta() {
|
||||
every { nativeMapView.prefetchZoomDelta } answers { 3 }
|
||||
assertEquals(3, mapboxMap.prefetchZoomDelta)
|
||||
}
|
||||
@Test
|
||||
fun testGetPrefetchZoomDelta() {
|
||||
every { nativeMapView.prefetchZoomDelta } answers { 3 }
|
||||
assertEquals(3, mapboxMap.prefetchZoomDelta)
|
||||
}
|
||||
|
||||
@Test
|
||||
fun testSetPrefetchZoomDelta() {
|
||||
mapboxMap.prefetchZoomDelta = 2
|
||||
verify { nativeMapView.prefetchZoomDelta = 2 }
|
||||
}
|
||||
@Test
|
||||
fun testSetPrefetchZoomDelta() {
|
||||
mapboxMap.prefetchZoomDelta = 2
|
||||
verify { nativeMapView.prefetchZoomDelta = 2 }
|
||||
}
|
||||
|
||||
@Test
|
||||
fun testCameraForLatLngBounds() {
|
||||
val bounds = LatLngBounds.Builder().include(LatLng()).include(LatLng(1.0, 1.0)).build()
|
||||
mapboxMap.setLatLngBoundsForCameraTarget(bounds)
|
||||
verify { nativeMapView.setLatLngBounds(bounds) }
|
||||
}
|
||||
@Test
|
||||
fun testCameraForLatLngBounds() {
|
||||
val bounds = LatLngBounds.Builder().include(LatLng()).include(LatLng(1.0, 1.0)).build()
|
||||
mapboxMap.setLatLngBoundsForCameraTarget(bounds)
|
||||
verify { nativeMapView.setLatLngBounds(bounds) }
|
||||
}
|
||||
|
||||
@Test(expected = IllegalArgumentException::class)
|
||||
fun testAnimateCameraChecksDurationPositive() {
|
||||
mapboxMap.animateCamera(CameraUpdateFactory.newLatLng(LatLng(30.0, 30.0)), 0, null)
|
||||
}
|
||||
@Test(expected = IllegalArgumentException::class)
|
||||
fun testAnimateCameraChecksDurationPositive() {
|
||||
mapboxMap.animateCamera(CameraUpdateFactory.newLatLng(LatLng(30.0, 30.0)), 0, null)
|
||||
}
|
||||
|
||||
@Test(expected = IllegalArgumentException::class)
|
||||
fun testEaseCameraChecksDurationPositive() {
|
||||
mapboxMap.easeCamera(CameraUpdateFactory.newLatLng(LatLng(30.0, 30.0)), 0, null)
|
||||
}
|
||||
@Test(expected = IllegalArgumentException::class)
|
||||
fun testEaseCameraChecksDurationPositive() {
|
||||
mapboxMap.easeCamera(CameraUpdateFactory.newLatLng(LatLng(30.0, 30.0)), 0, null)
|
||||
}
|
||||
|
||||
@Test
|
||||
fun testGetNativeMapPtr() {
|
||||
assertEquals(5, mapboxMap.nativeMapPtr)
|
||||
}
|
||||
@Test
|
||||
fun testGetNativeMapPtr() {
|
||||
assertEquals(5, mapboxMap.nativeMapPtr)
|
||||
}
|
||||
|
||||
@Test
|
||||
fun testNativeMapIsNotCalledOnStateSave() {
|
||||
clearMocks(nativeMapView)
|
||||
mapboxMap.onSaveInstanceState(mockk(relaxed = true))
|
||||
verify { nativeMapView wasNot Called }
|
||||
}
|
||||
@Test
|
||||
fun testNativeMapIsNotCalledOnStateSave() {
|
||||
clearMocks(nativeMapView)
|
||||
mapboxMap.onSaveInstanceState(mockk(relaxed = true))
|
||||
verify { nativeMapView wasNot Called }
|
||||
}
|
||||
|
||||
@Test
|
||||
fun testCameraChangeDispatcherCleared() {
|
||||
mapboxMap.onDestroy()
|
||||
verify { cameraChangeDispatcher.onDestroy() }
|
||||
}
|
||||
@Test
|
||||
fun testCameraChangeDispatcherCleared() {
|
||||
mapboxMap.onDestroy()
|
||||
verify { cameraChangeDispatcher.onDestroy() }
|
||||
}
|
||||
|
||||
@Test
|
||||
fun testStyleClearedOnDestroy() {
|
||||
val style = mockk<Style>(relaxed = true)
|
||||
val builder = mockk<Style.Builder>(relaxed = true)
|
||||
every { builder.build(nativeMapView) } returns style
|
||||
mapboxMap.setStyle(builder)
|
||||
@Test
|
||||
fun testStyleClearedOnDestroy() {
|
||||
val style = mockk<Style>(relaxed = true)
|
||||
val builder = mockk<Style.Builder>(relaxed = true)
|
||||
every { builder.build(nativeMapView) } returns style
|
||||
mapboxMap.setStyle(builder)
|
||||
|
||||
mapboxMap.onDestroy()
|
||||
verify(exactly = 1) { style.clear() }
|
||||
}
|
||||
mapboxMap.onDestroy()
|
||||
verify(exactly = 1) { style.clear() }
|
||||
}
|
||||
|
||||
@Test
|
||||
fun testStyleCallbackNotCalledWhenPreviousFailed() {
|
||||
val style = mockk<Style>(relaxed = true)
|
||||
val builder = mockk<Style.Builder>(relaxed = true)
|
||||
every { builder.build(nativeMapView) } returns style
|
||||
val onStyleLoadedListener = mockk<Style.OnStyleLoaded>(relaxed = true)
|
||||
@Test
|
||||
fun testStyleCallbackNotCalledWhenPreviousFailed() {
|
||||
val style = mockk<Style>(relaxed = true)
|
||||
val builder = mockk<Style.Builder>(relaxed = true)
|
||||
every { builder.build(nativeMapView) } returns style
|
||||
val onStyleLoadedListener = mockk<Style.OnStyleLoaded>(relaxed = true)
|
||||
|
||||
mapboxMap.setStyle(builder, onStyleLoadedListener)
|
||||
mapboxMap.onFailLoadingStyle()
|
||||
mapboxMap.setStyle(builder, onStyleLoadedListener)
|
||||
mapboxMap.onFinishLoadingStyle()
|
||||
verify(exactly = 1) { onStyleLoadedListener.onStyleLoaded(style) }
|
||||
}
|
||||
mapboxMap.setStyle(builder, onStyleLoadedListener)
|
||||
mapboxMap.onFailLoadingStyle()
|
||||
mapboxMap.setStyle(builder, onStyleLoadedListener)
|
||||
mapboxMap.onFinishLoadingStyle()
|
||||
verify(exactly = 1) { onStyleLoadedListener.onStyleLoaded(style) }
|
||||
}
|
||||
|
||||
@Test
|
||||
fun testStyleCallbackNotCalledWhenPreviousNotFinished() {
|
||||
// regression test for #14337
|
||||
val style = mockk<Style>(relaxed = true)
|
||||
val builder = mockk<Style.Builder>(relaxed = true)
|
||||
every { builder.build(nativeMapView) } returns style
|
||||
val onStyleLoadedListener = mockk<Style.OnStyleLoaded>(relaxed = true)
|
||||
@Test
|
||||
fun testStyleCallbackNotCalledWhenPreviousNotFinished() {
|
||||
// regression test for #14337
|
||||
val style = mockk<Style>(relaxed = true)
|
||||
val builder = mockk<Style.Builder>(relaxed = true)
|
||||
every { builder.build(nativeMapView) } returns style
|
||||
val onStyleLoadedListener = mockk<Style.OnStyleLoaded>(relaxed = true)
|
||||
|
||||
mapboxMap.setStyle(builder, onStyleLoadedListener)
|
||||
mapboxMap.setStyle(builder, onStyleLoadedListener)
|
||||
mapboxMap.onFinishLoadingStyle()
|
||||
verify(exactly = 1) { onStyleLoadedListener.onStyleLoaded(style) }
|
||||
}
|
||||
}
|
||||
mapboxMap.setStyle(builder, onStyleLoadedListener)
|
||||
mapboxMap.setStyle(builder, onStyleLoadedListener)
|
||||
mapboxMap.onFinishLoadingStyle()
|
||||
verify(exactly = 1) { onStyleLoadedListener.onStyleLoaded(style) }
|
||||
}
|
||||
}
|
||||
|
||||
@@ -155,9 +155,11 @@ class StyleBuilderTest {
|
||||
drawable.intrinsicHeight = 1
|
||||
val builder = Style.Builder()
|
||||
builder.withImage("id", drawable)
|
||||
assertTrue(BitmapUtils.equals(
|
||||
assertTrue(
|
||||
BitmapUtils.equals(
|
||||
BitmapUtils.getBitmapFromDrawable(drawable)!!,
|
||||
builder.images[0].bitmap)
|
||||
builder.images[0].bitmap
|
||||
)
|
||||
)
|
||||
assertEquals("id", builder.images[0].id)
|
||||
assertEquals(false, builder.images[0].sdf)
|
||||
@@ -170,9 +172,11 @@ class StyleBuilderTest {
|
||||
drawable.intrinsicHeight = 1
|
||||
val builder = Style.Builder()
|
||||
builder.withImage("id", drawable, true)
|
||||
assertTrue(BitmapUtils.equals(
|
||||
assertTrue(
|
||||
BitmapUtils.equals(
|
||||
BitmapUtils.getBitmapFromDrawable(drawable)!!,
|
||||
builder.images[0].bitmap)
|
||||
builder.images[0].bitmap
|
||||
)
|
||||
)
|
||||
assertEquals("id", builder.images[0].id)
|
||||
assertEquals(true, builder.images[0].sdf)
|
||||
@@ -188,15 +192,19 @@ class StyleBuilderTest {
|
||||
drawable2.intrinsicHeight = 1
|
||||
val builder = Style.Builder()
|
||||
builder.withDrawableImages(Pair<String, Drawable>("id1", drawable1), Pair<String, Drawable>("id2", drawable2))
|
||||
assertTrue(BitmapUtils.equals(
|
||||
assertTrue(
|
||||
BitmapUtils.equals(
|
||||
BitmapUtils.getBitmapFromDrawable(drawable1)!!,
|
||||
builder.images[0].bitmap)
|
||||
builder.images[0].bitmap
|
||||
)
|
||||
)
|
||||
assertEquals("id1", builder.images[0].id)
|
||||
assertEquals(false, builder.images[0].sdf)
|
||||
assertTrue(BitmapUtils.equals(
|
||||
assertTrue(
|
||||
BitmapUtils.equals(
|
||||
BitmapUtils.getBitmapFromDrawable(drawable2)!!,
|
||||
builder.images[1].bitmap)
|
||||
builder.images[1].bitmap
|
||||
)
|
||||
)
|
||||
assertEquals("id2", builder.images[1].id)
|
||||
assertEquals(false, builder.images[1].sdf)
|
||||
@@ -212,15 +220,19 @@ class StyleBuilderTest {
|
||||
drawable2.intrinsicHeight = 1
|
||||
val builder = Style.Builder()
|
||||
builder.withDrawableImages(true, Pair<String, Drawable>("id1", drawable1), Pair<String, Drawable>("id2", drawable2))
|
||||
assertTrue(BitmapUtils.equals(
|
||||
assertTrue(
|
||||
BitmapUtils.equals(
|
||||
BitmapUtils.getBitmapFromDrawable(drawable1)!!,
|
||||
builder.images[0].bitmap)
|
||||
builder.images[0].bitmap
|
||||
)
|
||||
)
|
||||
assertEquals("id1", builder.images[0].id)
|
||||
assertEquals(true, builder.images[0].sdf)
|
||||
assertTrue(BitmapUtils.equals(
|
||||
assertTrue(
|
||||
BitmapUtils.equals(
|
||||
BitmapUtils.getBitmapFromDrawable(drawable2)!!,
|
||||
builder.images[1].bitmap)
|
||||
builder.images[1].bitmap
|
||||
)
|
||||
)
|
||||
assertEquals("id2", builder.images[1].id)
|
||||
assertEquals(true, builder.images[1].sdf)
|
||||
@@ -234,4 +246,4 @@ class StyleBuilderTest {
|
||||
assertEquals(100, builder.transitionOptions.duration)
|
||||
assertEquals(200, builder.transitionOptions.delay)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -405,4 +405,4 @@ class StyleTest {
|
||||
Assert.assertEquals("Layer that failed to be added shouldn't be cached", layer1, mapboxMap.style!!.getLayer("layer1"))
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -12,191 +12,191 @@ import org.robolectric.RobolectricTestRunner
|
||||
@RunWith(RobolectricTestRunner::class)
|
||||
class TransformTest {
|
||||
|
||||
private lateinit var mapView: MapView
|
||||
private lateinit var nativeMapView: NativeMap
|
||||
private lateinit var transform: Transform
|
||||
private lateinit var cameraChangeDispatcher: CameraChangeDispatcher
|
||||
private lateinit var mapView: MapView
|
||||
private lateinit var nativeMapView: NativeMap
|
||||
private lateinit var transform: Transform
|
||||
private lateinit var cameraChangeDispatcher: CameraChangeDispatcher
|
||||
|
||||
@Before
|
||||
fun setup() {
|
||||
cameraChangeDispatcher = spyk()
|
||||
mapView = mockk()
|
||||
nativeMapView = mockk()
|
||||
transform = Transform(mapView, nativeMapView, cameraChangeDispatcher)
|
||||
every { nativeMapView.isDestroyed } returns false
|
||||
every { nativeMapView.cameraPosition } returns CameraPosition.DEFAULT
|
||||
every { nativeMapView.cancelTransitions() } answers {}
|
||||
every { nativeMapView.jumpTo(any(), any(), any(), any(), any()) } answers {}
|
||||
every { nativeMapView.easeTo(any(), any(), any(), any(), any(), any(), any()) } answers {}
|
||||
every { nativeMapView.flyTo(any(), any(), any(), any(), any(), any()) } answers {}
|
||||
every { nativeMapView.minZoom = any() } answers {}
|
||||
every { nativeMapView.maxZoom = any() } answers {}
|
||||
every { nativeMapView.minPitch = any() } answers {}
|
||||
every { nativeMapView.maxPitch = any() } answers {}
|
||||
}
|
||||
|
||||
@Test
|
||||
fun testMoveCamera() {
|
||||
val mapboxMap = mockk<MapboxMap>()
|
||||
every { mapboxMap.cameraPosition } answers { CameraPosition.DEFAULT }
|
||||
|
||||
val callback = mockk<MapboxMap.CancelableCallback>()
|
||||
every { callback.onFinish() } answers {}
|
||||
|
||||
val target = LatLng(1.0, 2.0)
|
||||
val expected = CameraPosition.Builder().target(target).build()
|
||||
val update = CameraUpdateFactory.newCameraPosition(expected)
|
||||
|
||||
transform.cameraPosition
|
||||
every { nativeMapView.cameraPosition } returns expected
|
||||
transform.moveCamera(mapboxMap, update, callback)
|
||||
|
||||
verify { cameraChangeDispatcher.onCameraMove() }
|
||||
verify { nativeMapView.jumpTo(target, -1.0, -1.0, -1.0, null) }
|
||||
verify { callback.onFinish() }
|
||||
}
|
||||
|
||||
@Test
|
||||
fun testMoveCameraToSamePosition() {
|
||||
val mapboxMap = mockk<MapboxMap>()
|
||||
every { mapboxMap.cameraPosition } answers { CameraPosition.DEFAULT }
|
||||
|
||||
val callback = mockk<MapboxMap.CancelableCallback>()
|
||||
every { callback.onFinish() } answers {}
|
||||
|
||||
val expected = CameraPosition.DEFAULT
|
||||
val update = CameraUpdateFactory.newCameraPosition(expected)
|
||||
|
||||
transform.moveCamera(mapboxMap, update, null) // Initialize camera position
|
||||
transform.moveCamera(mapboxMap, update, callback)
|
||||
|
||||
verify(exactly = 1, verifyBlock = { nativeMapView.jumpTo(any(), any(), any(), any(), any()) })
|
||||
verify { callback.onFinish() }
|
||||
}
|
||||
|
||||
@Test
|
||||
fun testEaseCamera() {
|
||||
val mapboxMap = mockk<MapboxMap>()
|
||||
every { mapboxMap.cameraPosition } answers { CameraPosition.DEFAULT }
|
||||
|
||||
every { mapView.addOnCameraDidChangeListener(any()) } answers { transform.onCameraDidChange(true) }
|
||||
every { mapView.removeOnCameraDidChangeListener(any()) } answers {}
|
||||
|
||||
val callback = mockk<MapboxMap.CancelableCallback>()
|
||||
every { callback.onFinish() } answers {}
|
||||
|
||||
val target = LatLng(1.0, 2.0)
|
||||
val expected = CameraPosition.Builder().target(target).build()
|
||||
val update = CameraUpdateFactory.newCameraPosition(expected)
|
||||
|
||||
transform.easeCamera(mapboxMap, update, 100, false, callback)
|
||||
|
||||
verify { nativeMapView.easeTo(target, -1.0, -1.0, -1.0, null, 100, false) }
|
||||
verify { callback.onFinish() }
|
||||
}
|
||||
|
||||
@Test
|
||||
fun testEaseCameraToSamePosition() {
|
||||
val mapboxMap = mockk<MapboxMap>()
|
||||
every { mapboxMap.cameraPosition } answers { CameraPosition.DEFAULT }
|
||||
|
||||
val callback = mockk<MapboxMap.CancelableCallback>()
|
||||
every { callback.onFinish() } answers {}
|
||||
|
||||
val expected = CameraPosition.DEFAULT
|
||||
val update = CameraUpdateFactory.newCameraPosition(expected)
|
||||
transform.moveCamera(mapboxMap, update, null)
|
||||
|
||||
transform.easeCamera(mapboxMap, update, 100, false, callback)
|
||||
|
||||
verify(exactly = 0, verifyBlock = { nativeMapView.easeTo(any(), any(), any(), any(), any(), any(), any()) })
|
||||
verify { callback.onFinish() }
|
||||
}
|
||||
|
||||
@Test
|
||||
fun testAnimateCamera() {
|
||||
val mapboxMap = mockk<MapboxMap>()
|
||||
every { mapboxMap.cameraPosition } answers { CameraPosition.DEFAULT }
|
||||
|
||||
every { mapView.addOnCameraDidChangeListener(any()) } answers { transform.onCameraDidChange(true) }
|
||||
every { mapView.removeOnCameraDidChangeListener(any()) } answers {}
|
||||
|
||||
val callback = mockk<MapboxMap.CancelableCallback>()
|
||||
every { callback.onFinish() } answers {}
|
||||
|
||||
val target = LatLng(1.0, 2.0)
|
||||
val expected = CameraPosition.Builder().target(target).build()
|
||||
val update = CameraUpdateFactory.newCameraPosition(expected)
|
||||
|
||||
transform.animateCamera(mapboxMap, update, 100, callback)
|
||||
|
||||
verify { nativeMapView.flyTo(target, -1.0, -1.0, -1.0, null, 100) }
|
||||
verify { callback.onFinish() }
|
||||
}
|
||||
|
||||
@Test
|
||||
fun testAnimateCameraToSamePosition() {
|
||||
val mapboxMap = mockk<MapboxMap>()
|
||||
every { mapboxMap.cameraPosition } answers { CameraPosition.DEFAULT }
|
||||
|
||||
val callback = mockk<MapboxMap.CancelableCallback>()
|
||||
every { callback.onFinish() } answers {}
|
||||
|
||||
val expected = CameraPosition.DEFAULT
|
||||
val update = CameraUpdateFactory.newCameraPosition(expected)
|
||||
transform.moveCamera(mapboxMap, update, null)
|
||||
|
||||
transform.animateCamera(mapboxMap, update, 100, callback)
|
||||
|
||||
verify(exactly = 0, verifyBlock = { nativeMapView.flyTo(any(), any(), any(), any(), any(), any()) })
|
||||
verify { callback.onFinish() }
|
||||
}
|
||||
|
||||
@Test
|
||||
fun testMinZoom() {
|
||||
transform.minZoom = 10.0
|
||||
verify { nativeMapView.minZoom = 10.0 }
|
||||
}
|
||||
|
||||
@Test
|
||||
fun testMaxZoom() {
|
||||
transform.maxZoom = 10.0
|
||||
verify { nativeMapView.maxZoom = 10.0 }
|
||||
}
|
||||
|
||||
@Test
|
||||
fun testMinPitch() {
|
||||
transform.minPitch = 10.0
|
||||
verify { nativeMapView.minPitch = 10.0 }
|
||||
}
|
||||
|
||||
@Test
|
||||
fun testMaxPitch() {
|
||||
transform.maxPitch = 10.0
|
||||
verify { nativeMapView.maxPitch = 10.0 }
|
||||
}
|
||||
|
||||
@Test
|
||||
fun testCancelNotInvokedFromOnFinish() {
|
||||
val slot = slot<MapView.OnCameraDidChangeListener>()
|
||||
every { mapView.addOnCameraDidChangeListener(capture(slot)) } answers { slot.captured.onCameraDidChange(true) }
|
||||
every { mapView.removeOnCameraDidChangeListener(any()) } answers {}
|
||||
// regression test for https://github.com/mapbox/mapbox-gl-native/issues/13735
|
||||
val mapboxMap = mockk<MapboxMap>()
|
||||
every { mapboxMap.cameraPosition } answers { CameraPosition.DEFAULT }
|
||||
|
||||
val target = LatLng(1.0, 2.0)
|
||||
val expected = CameraPosition.Builder().target(target).build()
|
||||
|
||||
val callback = object : MapboxMap.CancelableCallback {
|
||||
override fun onCancel() {
|
||||
throw IllegalStateException("onCancel shouldn't be called from onFinish")
|
||||
}
|
||||
|
||||
override fun onFinish() {
|
||||
transform.animateCamera(mapboxMap, CameraUpdateFactory.newCameraPosition(expected), 500, null)
|
||||
}
|
||||
@Before
|
||||
fun setup() {
|
||||
cameraChangeDispatcher = spyk()
|
||||
mapView = mockk()
|
||||
nativeMapView = mockk()
|
||||
transform = Transform(mapView, nativeMapView, cameraChangeDispatcher)
|
||||
every { nativeMapView.isDestroyed } returns false
|
||||
every { nativeMapView.cameraPosition } returns CameraPosition.DEFAULT
|
||||
every { nativeMapView.cancelTransitions() } answers {}
|
||||
every { nativeMapView.jumpTo(any(), any(), any(), any(), any()) } answers {}
|
||||
every { nativeMapView.easeTo(any(), any(), any(), any(), any(), any(), any()) } answers {}
|
||||
every { nativeMapView.flyTo(any(), any(), any(), any(), any(), any()) } answers {}
|
||||
every { nativeMapView.minZoom = any() } answers {}
|
||||
every { nativeMapView.maxZoom = any() } answers {}
|
||||
every { nativeMapView.minPitch = any() } answers {}
|
||||
every { nativeMapView.maxPitch = any() } answers {}
|
||||
}
|
||||
transform.animateCamera(mapboxMap, CameraUpdateFactory.newCameraPosition(expected), 500, callback)
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
fun testMoveCamera() {
|
||||
val mapboxMap = mockk<MapboxMap>()
|
||||
every { mapboxMap.cameraPosition } answers { CameraPosition.DEFAULT }
|
||||
|
||||
val callback = mockk<MapboxMap.CancelableCallback>()
|
||||
every { callback.onFinish() } answers {}
|
||||
|
||||
val target = LatLng(1.0, 2.0)
|
||||
val expected = CameraPosition.Builder().target(target).build()
|
||||
val update = CameraUpdateFactory.newCameraPosition(expected)
|
||||
|
||||
transform.cameraPosition
|
||||
every { nativeMapView.cameraPosition } returns expected
|
||||
transform.moveCamera(mapboxMap, update, callback)
|
||||
|
||||
verify { cameraChangeDispatcher.onCameraMove() }
|
||||
verify { nativeMapView.jumpTo(target, -1.0, -1.0, -1.0, null) }
|
||||
verify { callback.onFinish() }
|
||||
}
|
||||
|
||||
@Test
|
||||
fun testMoveCameraToSamePosition() {
|
||||
val mapboxMap = mockk<MapboxMap>()
|
||||
every { mapboxMap.cameraPosition } answers { CameraPosition.DEFAULT }
|
||||
|
||||
val callback = mockk<MapboxMap.CancelableCallback>()
|
||||
every { callback.onFinish() } answers {}
|
||||
|
||||
val expected = CameraPosition.DEFAULT
|
||||
val update = CameraUpdateFactory.newCameraPosition(expected)
|
||||
|
||||
transform.moveCamera(mapboxMap, update, null) // Initialize camera position
|
||||
transform.moveCamera(mapboxMap, update, callback)
|
||||
|
||||
verify(exactly = 1, verifyBlock = { nativeMapView.jumpTo(any(), any(), any(), any(), any()) })
|
||||
verify { callback.onFinish() }
|
||||
}
|
||||
|
||||
@Test
|
||||
fun testEaseCamera() {
|
||||
val mapboxMap = mockk<MapboxMap>()
|
||||
every { mapboxMap.cameraPosition } answers { CameraPosition.DEFAULT }
|
||||
|
||||
every { mapView.addOnCameraDidChangeListener(any()) } answers { transform.onCameraDidChange(true) }
|
||||
every { mapView.removeOnCameraDidChangeListener(any()) } answers {}
|
||||
|
||||
val callback = mockk<MapboxMap.CancelableCallback>()
|
||||
every { callback.onFinish() } answers {}
|
||||
|
||||
val target = LatLng(1.0, 2.0)
|
||||
val expected = CameraPosition.Builder().target(target).build()
|
||||
val update = CameraUpdateFactory.newCameraPosition(expected)
|
||||
|
||||
transform.easeCamera(mapboxMap, update, 100, false, callback)
|
||||
|
||||
verify { nativeMapView.easeTo(target, -1.0, -1.0, -1.0, null, 100, false) }
|
||||
verify { callback.onFinish() }
|
||||
}
|
||||
|
||||
@Test
|
||||
fun testEaseCameraToSamePosition() {
|
||||
val mapboxMap = mockk<MapboxMap>()
|
||||
every { mapboxMap.cameraPosition } answers { CameraPosition.DEFAULT }
|
||||
|
||||
val callback = mockk<MapboxMap.CancelableCallback>()
|
||||
every { callback.onFinish() } answers {}
|
||||
|
||||
val expected = CameraPosition.DEFAULT
|
||||
val update = CameraUpdateFactory.newCameraPosition(expected)
|
||||
transform.moveCamera(mapboxMap, update, null)
|
||||
|
||||
transform.easeCamera(mapboxMap, update, 100, false, callback)
|
||||
|
||||
verify(exactly = 0, verifyBlock = { nativeMapView.easeTo(any(), any(), any(), any(), any(), any(), any()) })
|
||||
verify { callback.onFinish() }
|
||||
}
|
||||
|
||||
@Test
|
||||
fun testAnimateCamera() {
|
||||
val mapboxMap = mockk<MapboxMap>()
|
||||
every { mapboxMap.cameraPosition } answers { CameraPosition.DEFAULT }
|
||||
|
||||
every { mapView.addOnCameraDidChangeListener(any()) } answers { transform.onCameraDidChange(true) }
|
||||
every { mapView.removeOnCameraDidChangeListener(any()) } answers {}
|
||||
|
||||
val callback = mockk<MapboxMap.CancelableCallback>()
|
||||
every { callback.onFinish() } answers {}
|
||||
|
||||
val target = LatLng(1.0, 2.0)
|
||||
val expected = CameraPosition.Builder().target(target).build()
|
||||
val update = CameraUpdateFactory.newCameraPosition(expected)
|
||||
|
||||
transform.animateCamera(mapboxMap, update, 100, callback)
|
||||
|
||||
verify { nativeMapView.flyTo(target, -1.0, -1.0, -1.0, null, 100) }
|
||||
verify { callback.onFinish() }
|
||||
}
|
||||
|
||||
@Test
|
||||
fun testAnimateCameraToSamePosition() {
|
||||
val mapboxMap = mockk<MapboxMap>()
|
||||
every { mapboxMap.cameraPosition } answers { CameraPosition.DEFAULT }
|
||||
|
||||
val callback = mockk<MapboxMap.CancelableCallback>()
|
||||
every { callback.onFinish() } answers {}
|
||||
|
||||
val expected = CameraPosition.DEFAULT
|
||||
val update = CameraUpdateFactory.newCameraPosition(expected)
|
||||
transform.moveCamera(mapboxMap, update, null)
|
||||
|
||||
transform.animateCamera(mapboxMap, update, 100, callback)
|
||||
|
||||
verify(exactly = 0, verifyBlock = { nativeMapView.flyTo(any(), any(), any(), any(), any(), any()) })
|
||||
verify { callback.onFinish() }
|
||||
}
|
||||
|
||||
@Test
|
||||
fun testMinZoom() {
|
||||
transform.minZoom = 10.0
|
||||
verify { nativeMapView.minZoom = 10.0 }
|
||||
}
|
||||
|
||||
@Test
|
||||
fun testMaxZoom() {
|
||||
transform.maxZoom = 10.0
|
||||
verify { nativeMapView.maxZoom = 10.0 }
|
||||
}
|
||||
|
||||
@Test
|
||||
fun testMinPitch() {
|
||||
transform.minPitch = 10.0
|
||||
verify { nativeMapView.minPitch = 10.0 }
|
||||
}
|
||||
|
||||
@Test
|
||||
fun testMaxPitch() {
|
||||
transform.maxPitch = 10.0
|
||||
verify { nativeMapView.maxPitch = 10.0 }
|
||||
}
|
||||
|
||||
@Test
|
||||
fun testCancelNotInvokedFromOnFinish() {
|
||||
val slot = slot<MapView.OnCameraDidChangeListener>()
|
||||
every { mapView.addOnCameraDidChangeListener(capture(slot)) } answers { slot.captured.onCameraDidChange(true) }
|
||||
every { mapView.removeOnCameraDidChangeListener(any()) } answers {}
|
||||
// regression test for https://github.com/mapbox/mapbox-gl-native/issues/13735
|
||||
val mapboxMap = mockk<MapboxMap>()
|
||||
every { mapboxMap.cameraPosition } answers { CameraPosition.DEFAULT }
|
||||
|
||||
val target = LatLng(1.0, 2.0)
|
||||
val expected = CameraPosition.Builder().target(target).build()
|
||||
|
||||
val callback = object : MapboxMap.CancelableCallback {
|
||||
override fun onCancel() {
|
||||
throw IllegalStateException("onCancel shouldn't be called from onFinish")
|
||||
}
|
||||
|
||||
override fun onFinish() {
|
||||
transform.animateCamera(mapboxMap, CameraUpdateFactory.newCameraPosition(expected), 500, null)
|
||||
}
|
||||
}
|
||||
transform.animateCamera(mapboxMap, CameraUpdateFactory.newCameraPosition(expected), 500, callback)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -13,55 +13,55 @@ import org.robolectric.RobolectricTestRunner
|
||||
@RunWith(RobolectricTestRunner::class)
|
||||
class HttpRequestUrlTest {
|
||||
|
||||
@Before
|
||||
fun setUp() {
|
||||
MapboxInjector.inject(mockk(relaxed = true), "pk.foobar", "foobar")
|
||||
}
|
||||
@Before
|
||||
fun setUp() {
|
||||
MapboxInjector.inject(mockk(relaxed = true), "pk.foobar", "foobar")
|
||||
}
|
||||
|
||||
@Test
|
||||
fun testOfflineFlagMapboxCom() {
|
||||
val expected = "http://mapbox.com/path/of/no/return.pbf?offline=true"
|
||||
val actual = HttpRequestUrl.buildResourceUrl("mapbox.com", "http://mapbox.com/path/of/no/return.pbf", 0, true)
|
||||
assertEquals(expected, actual)
|
||||
}
|
||||
@Test
|
||||
fun testOfflineFlagMapboxCom() {
|
||||
val expected = "http://mapbox.com/path/of/no/return.pbf?offline=true"
|
||||
val actual = HttpRequestUrl.buildResourceUrl("mapbox.com", "http://mapbox.com/path/of/no/return.pbf", 0, true)
|
||||
assertEquals(expected, actual)
|
||||
}
|
||||
|
||||
@Test
|
||||
fun testOfflineFlagMapboxCn() {
|
||||
val expected = "http://mapbox.cn/path/of/no/return.pbf?offline=true"
|
||||
val actual = HttpRequestUrl.buildResourceUrl("mapbox.cn", "http://mapbox.cn/path/of/no/return.pbf", 0, true)
|
||||
assertEquals(expected, actual)
|
||||
}
|
||||
@Test
|
||||
fun testOfflineFlagMapboxCn() {
|
||||
val expected = "http://mapbox.cn/path/of/no/return.pbf?offline=true"
|
||||
val actual = HttpRequestUrl.buildResourceUrl("mapbox.cn", "http://mapbox.cn/path/of/no/return.pbf", 0, true)
|
||||
assertEquals(expected, actual)
|
||||
}
|
||||
|
||||
@Test
|
||||
fun testOfflineFlagInvalidHost() {
|
||||
val expected = "http://foobar.com/path/of/no/return.pbf"
|
||||
val actual = HttpRequestUrl.buildResourceUrl("foobar.com", "http://foobar.com/path/of/no/return.pbf", 0, true)
|
||||
assertEquals(expected, actual)
|
||||
}
|
||||
@Test
|
||||
fun testOfflineFlagInvalidHost() {
|
||||
val expected = "http://foobar.com/path/of/no/return.pbf"
|
||||
val actual = HttpRequestUrl.buildResourceUrl("foobar.com", "http://foobar.com/path/of/no/return.pbf", 0, true)
|
||||
assertEquals(expected, actual)
|
||||
}
|
||||
|
||||
@Test
|
||||
fun testOnlineMapboxCom() {
|
||||
val expected = "http://mapbox.com/path/of/no/return.pbf?sku=foobar"
|
||||
val actual = HttpRequestUrl.buildResourceUrl("mapbox.com", "http://mapbox.com/path/of/no/return.pbf", 0, false)
|
||||
assertEquals(expected, actual)
|
||||
}
|
||||
@Test
|
||||
fun testOnlineMapboxCom() {
|
||||
val expected = "http://mapbox.com/path/of/no/return.pbf?sku=foobar"
|
||||
val actual = HttpRequestUrl.buildResourceUrl("mapbox.com", "http://mapbox.com/path/of/no/return.pbf", 0, false)
|
||||
assertEquals(expected, actual)
|
||||
}
|
||||
|
||||
@Test
|
||||
fun testOnlineMapboxCn() {
|
||||
val expected = "http://mapbox.cn/path/of/no/return.pbf?sku=foobar"
|
||||
val actual = HttpRequestUrl.buildResourceUrl("mapbox.cn", "http://mapbox.cn/path/of/no/return.pbf", 0, false)
|
||||
assertEquals(expected, actual)
|
||||
}
|
||||
@Test
|
||||
fun testOnlineMapboxCn() {
|
||||
val expected = "http://mapbox.cn/path/of/no/return.pbf?sku=foobar"
|
||||
val actual = HttpRequestUrl.buildResourceUrl("mapbox.cn", "http://mapbox.cn/path/of/no/return.pbf", 0, false)
|
||||
assertEquals(expected, actual)
|
||||
}
|
||||
|
||||
@Test
|
||||
fun testOnlineInvalidHost() {
|
||||
val expected = "http://foobar.com/path/of/no/return.pbf"
|
||||
val actual = HttpRequestUrl.buildResourceUrl("foobar.com", "http://foobar.com/path/of/no/return.pbf", 0, false)
|
||||
assertEquals(expected, actual)
|
||||
}
|
||||
@Test
|
||||
fun testOnlineInvalidHost() {
|
||||
val expected = "http://foobar.com/path/of/no/return.pbf"
|
||||
val actual = HttpRequestUrl.buildResourceUrl("foobar.com", "http://foobar.com/path/of/no/return.pbf", 0, false)
|
||||
assertEquals(expected, actual)
|
||||
}
|
||||
|
||||
@After
|
||||
fun tearDown() {
|
||||
MapboxInjector.clear()
|
||||
}
|
||||
}
|
||||
@After
|
||||
fun tearDown() {
|
||||
MapboxInjector.clear()
|
||||
}
|
||||
}
|
||||
|
||||
@@ -11,25 +11,27 @@ import org.robolectric.RobolectricTestRunner
|
||||
@RunWith(RobolectricTestRunner::class)
|
||||
class HttpRequestUtilTest {
|
||||
|
||||
@Test
|
||||
fun replaceHttpClient() {
|
||||
MapboxInjector.inject(mockk(relaxed = true), "")
|
||||
@Test
|
||||
fun replaceHttpClient() {
|
||||
MapboxInjector.inject(mockk(relaxed = true), "")
|
||||
|
||||
assertEquals(HttpRequestImpl.DEFAULT_CLIENT, HttpRequestImpl.client)
|
||||
assertEquals(HttpRequestImpl.DEFAULT_CLIENT, HttpRequestImpl.client)
|
||||
|
||||
val httpMock = mockk<OkHttpClient>()
|
||||
HttpRequestUtil.setOkHttpClient(httpMock)
|
||||
assertEquals("Http client should have set to the mocked client",
|
||||
httpMock,
|
||||
HttpRequestImpl.client
|
||||
)
|
||||
val httpMock = mockk<OkHttpClient>()
|
||||
HttpRequestUtil.setOkHttpClient(httpMock)
|
||||
assertEquals(
|
||||
"Http client should have set to the mocked client",
|
||||
httpMock,
|
||||
HttpRequestImpl.client
|
||||
)
|
||||
|
||||
HttpRequestUtil.setOkHttpClient(null)
|
||||
assertEquals("Http client should have been reset to the default client",
|
||||
HttpRequestImpl.DEFAULT_CLIENT,
|
||||
HttpRequestImpl.client
|
||||
)
|
||||
HttpRequestUtil.setOkHttpClient(null)
|
||||
assertEquals(
|
||||
"Http client should have been reset to the default client",
|
||||
HttpRequestImpl.DEFAULT_CLIENT,
|
||||
HttpRequestImpl.client
|
||||
)
|
||||
|
||||
MapboxInjector.clear()
|
||||
}
|
||||
}
|
||||
MapboxInjector.clear()
|
||||
}
|
||||
}
|
||||
|
||||
@@ -6,17 +6,17 @@ import org.junit.Test
|
||||
|
||||
class ColorUtilsTest {
|
||||
|
||||
@Test
|
||||
fun rgbaToColor_decimalComponent() {
|
||||
val input = "rgba(255,128.0000952303,0,0.7)"
|
||||
val result = ColorUtils.rgbaToColor(input)
|
||||
Assert.assertEquals(Color.argb(255, 128, 0, (0.7 * 255).toInt()), result)
|
||||
}
|
||||
@Test
|
||||
fun rgbaToColor_decimalComponent() {
|
||||
val input = "rgba(255,128.0000952303,0,0.7)"
|
||||
val result = ColorUtils.rgbaToColor(input)
|
||||
Assert.assertEquals(Color.argb(255, 128, 0, (0.7 * 255).toInt()), result)
|
||||
}
|
||||
|
||||
@Test
|
||||
fun rgbaToColor_decimalComponent_floor() {
|
||||
val input = "rgba(255,128.70123,0,0.7)"
|
||||
val result = ColorUtils.rgbaToColor(input)
|
||||
Assert.assertEquals(Color.argb(255, 128, 0, (0.7 * 255).toInt()), result)
|
||||
}
|
||||
}
|
||||
@Test
|
||||
fun rgbaToColor_decimalComponent_floor() {
|
||||
val input = "rgba(255,128.70123,0,0.7)"
|
||||
val result = ColorUtils.rgbaToColor(input)
|
||||
Assert.assertEquals(Color.argb(255, 128, 0, (0.7 * 255).toInt()), result)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -7,69 +7,79 @@ import com.intellij.psi.PsiType
|
||||
import org.jetbrains.uast.*
|
||||
|
||||
class KeepDetector : Detector(), SourceCodeScanner, FileScanner {
|
||||
companion object {
|
||||
private val DETECTOR_CLASS = KeepDetector::class.java
|
||||
private val DETECTOR_SCOPE = Scope.JAVA_FILE_SCOPE
|
||||
private val IMPLEMENTATION = Implementation(DETECTOR_CLASS, DETECTOR_SCOPE)
|
||||
companion object {
|
||||
private val DETECTOR_CLASS = KeepDetector::class.java
|
||||
private val DETECTOR_SCOPE = Scope.JAVA_FILE_SCOPE
|
||||
private val IMPLEMENTATION = Implementation(DETECTOR_CLASS, DETECTOR_SCOPE)
|
||||
|
||||
private const val ISSUE_ID = "KeepMissing"
|
||||
private const val ISSUE_DESCRIPTION = "Element cannot be minified."
|
||||
private const val ISSUE_EXPLANATION = "This class, method or field might contain native references. " +
|
||||
"It has to be annotated with @Keep if it cannot be obfuscated/removed, otherwise, the warning should be suppressed. " +
|
||||
"There can also be another methods/fields of this class that cannot be obfuscated/removed, " +
|
||||
"look closely for any methods that are referenced from the JNI context."
|
||||
private val ISSUE_CATEGORY = Category.CORRECTNESS
|
||||
private const val ISSUE_PRIORITY = 9
|
||||
private val ISSUE_SEVERITY = Severity.ERROR
|
||||
private const val ISSUE_ID = "KeepMissing"
|
||||
private const val ISSUE_DESCRIPTION = "Element cannot be minified."
|
||||
private const val ISSUE_EXPLANATION = "This class, method or field might contain native references. " +
|
||||
"It has to be annotated with @Keep if it cannot be obfuscated/removed, otherwise, the warning should be suppressed. " +
|
||||
"There can also be another methods/fields of this class that cannot be obfuscated/removed, " +
|
||||
"look closely for any methods that are referenced from the JNI context."
|
||||
private val ISSUE_CATEGORY = Category.CORRECTNESS
|
||||
private const val ISSUE_PRIORITY = 9
|
||||
private val ISSUE_SEVERITY = Severity.ERROR
|
||||
|
||||
var ISSUE_NOT_KEPT = Issue.create(
|
||||
ISSUE_ID,
|
||||
ISSUE_DESCRIPTION,
|
||||
ISSUE_EXPLANATION,
|
||||
ISSUE_CATEGORY,
|
||||
ISSUE_PRIORITY,
|
||||
ISSUE_SEVERITY,
|
||||
IMPLEMENTATION
|
||||
)
|
||||
}
|
||||
|
||||
override fun getApplicableUastTypes(): List<Class<out UElement>>? =
|
||||
listOf(UMethod::class.java, UField::class.java)
|
||||
|
||||
override fun createUastHandler(context: JavaContext): UElementHandler? = KeepHandler(context)
|
||||
|
||||
class KeepHandler(private val context: JavaContext) : UElementHandler() {
|
||||
|
||||
override fun visitMethod(node: UMethod) {
|
||||
if (node.hasModifier(JvmModifier.NATIVE) && checkKeepAnnotation(node)) {
|
||||
context.report(ISSUE_NOT_KEPT, node,
|
||||
context.getNameLocation(node),
|
||||
"This method contains native references and will be minified.")
|
||||
} else if (node.isConstructor &&
|
||||
node.parameterList.parameters.find { it.type == PsiType.LONG && it.name!!.contains("native") } != null &&
|
||||
checkKeepAnnotation(node)) {
|
||||
context.report(ISSUE_NOT_KEPT, node,
|
||||
context.getNameLocation(node as UElement),
|
||||
"This constructor might contain native references and will be minified. " +
|
||||
"Either suppress the warning or use @Keep.")
|
||||
}
|
||||
var ISSUE_NOT_KEPT = Issue.create(
|
||||
ISSUE_ID,
|
||||
ISSUE_DESCRIPTION,
|
||||
ISSUE_EXPLANATION,
|
||||
ISSUE_CATEGORY,
|
||||
ISSUE_PRIORITY,
|
||||
ISSUE_SEVERITY,
|
||||
IMPLEMENTATION
|
||||
)
|
||||
}
|
||||
|
||||
override fun visitField(node: UField) {
|
||||
if (node.type == PsiType.LONG && node.name.contains("native") && checkKeepAnnotation(node)) {
|
||||
context.report(ISSUE_NOT_KEPT, node,
|
||||
context.getNameLocation(node as UElement),
|
||||
"This field might contain native references and will be minified. " +
|
||||
"Either suppress the warning or use @Keep.")
|
||||
}
|
||||
}
|
||||
override fun getApplicableUastTypes(): List<Class<out UElement>>? =
|
||||
listOf(UMethod::class.java, UField::class.java)
|
||||
|
||||
private fun checkKeepAnnotation(uAnnotated: UAnnotated): Boolean {
|
||||
return !hasKeepAnnotation(uAnnotated) && !hasKeepAnnotation(uAnnotated.getContainingUClass()!!)
|
||||
}
|
||||
override fun createUastHandler(context: JavaContext): UElementHandler? = KeepHandler(context)
|
||||
|
||||
private fun hasKeepAnnotation(uAnnotated: UAnnotated): Boolean {
|
||||
return uAnnotated.findAnnotation("androidx.annotation.Keep") != null
|
||||
class KeepHandler(private val context: JavaContext) : UElementHandler() {
|
||||
|
||||
override fun visitMethod(node: UMethod) {
|
||||
if (node.hasModifier(JvmModifier.NATIVE) && checkKeepAnnotation(node)) {
|
||||
context.report(
|
||||
ISSUE_NOT_KEPT,
|
||||
node,
|
||||
context.getNameLocation(node),
|
||||
"This method contains native references and will be minified."
|
||||
)
|
||||
} else if (node.isConstructor &&
|
||||
node.parameterList.parameters.find { it.type == PsiType.LONG && it.name!!.contains("native") } != null &&
|
||||
checkKeepAnnotation(node)
|
||||
) {
|
||||
context.report(
|
||||
ISSUE_NOT_KEPT,
|
||||
node,
|
||||
context.getNameLocation(node as UElement),
|
||||
"This constructor might contain native references and will be minified. " +
|
||||
"Either suppress the warning or use @Keep."
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
override fun visitField(node: UField) {
|
||||
if (node.type == PsiType.LONG && node.name.contains("native") && checkKeepAnnotation(node)) {
|
||||
context.report(
|
||||
ISSUE_NOT_KEPT,
|
||||
node,
|
||||
context.getNameLocation(node as UElement),
|
||||
"This field might contain native references and will be minified. " +
|
||||
"Either suppress the warning or use @Keep."
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
private fun checkKeepAnnotation(uAnnotated: UAnnotated): Boolean {
|
||||
return !hasKeepAnnotation(uAnnotated) && !hasKeepAnnotation(uAnnotated.getContainingUClass()!!)
|
||||
}
|
||||
|
||||
private fun hasKeepAnnotation(uAnnotated: UAnnotated): Boolean {
|
||||
return uAnnotated.findAnnotation("androidx.annotation.Keep") != null
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -5,9 +5,9 @@ import com.android.tools.lint.detector.api.CURRENT_API
|
||||
import com.android.tools.lint.detector.api.Issue
|
||||
|
||||
class MapboxIssueRegistry : IssueRegistry() {
|
||||
override val issues: List<Issue>
|
||||
get() = listOf(KeepDetector.ISSUE_NOT_KEPT)
|
||||
override val issues: List<Issue>
|
||||
get() = listOf(KeepDetector.ISSUE_NOT_KEPT)
|
||||
|
||||
override val api: Int
|
||||
get() = CURRENT_API
|
||||
}
|
||||
override val api: Int
|
||||
get() = CURRENT_API
|
||||
}
|
||||
|
||||
@@ -9,20 +9,24 @@ import org.robolectric.RobolectricTestRunner
|
||||
@RunWith(RobolectricTestRunner::class)
|
||||
class KeepDetectorTest {
|
||||
|
||||
@Test
|
||||
fun correctClassName() {
|
||||
lint()
|
||||
.allowMissingSdk()
|
||||
.files(java("""
|
||||
@Test
|
||||
fun correctClassName() {
|
||||
lint()
|
||||
.allowMissingSdk()
|
||||
.files(
|
||||
java(
|
||||
"""
|
||||
|package foo;
|
||||
|
|
||||
|import android.support.annotation.Keep;
|
||||
|
|
||||
|@Keep
|
||||
|class TestClass {
|
||||
|}""".trimMargin()))
|
||||
.issues(KeepDetector.ISSUE_NOT_KEPT)
|
||||
.run()
|
||||
.expectClean()
|
||||
}
|
||||
}
|
||||
|}""".trimMargin()
|
||||
)
|
||||
)
|
||||
.issues(KeepDetector.ISSUE_NOT_KEPT)
|
||||
.run()
|
||||
.expectClean()
|
||||
}
|
||||
}
|
||||
|
||||
@@ -12,4 +12,4 @@ abstract class AppCenter {
|
||||
open fun afterTest() {
|
||||
reportHelper.label(javaClass.simpleName)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -3,8 +3,8 @@ package com.mapbox.mapboxsdk
|
||||
import com.mapbox.mapboxsdk.testapp.MapboxApplication
|
||||
|
||||
class InstrumentationApplication : MapboxApplication() {
|
||||
override fun initializeLeakCanary(): Boolean {
|
||||
// do not initialize leak canary during instrumentation tests
|
||||
return true
|
||||
}
|
||||
}
|
||||
override fun initializeLeakCanary(): Boolean {
|
||||
// do not initialize leak canary during instrumentation tests
|
||||
return true
|
||||
}
|
||||
}
|
||||
|
||||
@@ -5,7 +5,7 @@ import android.content.Context
|
||||
import androidx.test.runner.AndroidJUnitRunner
|
||||
|
||||
class InstrumentationRunner : AndroidJUnitRunner() {
|
||||
override fun newApplication(cl: ClassLoader?, className: String?, context: Context?): Application {
|
||||
return super.newApplication(cl, InstrumentationApplication::class.java.name, context)
|
||||
}
|
||||
}
|
||||
override fun newApplication(cl: ClassLoader?, className: String?, context: Context?): Application {
|
||||
return super.newApplication(cl, InstrumentationApplication::class.java.name, context)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -16,171 +16,171 @@ import org.junit.runner.RunWith
|
||||
@RunWith(AndroidJUnit4::class)
|
||||
class CameraUpdateFactoryTest : BaseTest() {
|
||||
|
||||
override fun getActivityClass(): Class<*> {
|
||||
return DeviceIndependentTestActivity::class.java
|
||||
}
|
||||
override fun getActivityClass(): Class<*> {
|
||||
return DeviceIndependentTestActivity::class.java
|
||||
}
|
||||
|
||||
@Test
|
||||
@UiThreadTest
|
||||
fun testLatLngBoundsUntiltedUnrotated() {
|
||||
mapboxMap.cameraPosition = CameraPosition.Builder()
|
||||
.target(LatLng(60.0, 24.0))
|
||||
.bearing(0.0)
|
||||
.tilt(0.0)
|
||||
.build()
|
||||
@Test
|
||||
@UiThreadTest
|
||||
fun testLatLngBoundsUntiltedUnrotated() {
|
||||
mapboxMap.cameraPosition = CameraPosition.Builder()
|
||||
.target(LatLng(60.0, 24.0))
|
||||
.bearing(0.0)
|
||||
.tilt(0.0)
|
||||
.build()
|
||||
|
||||
val bounds: LatLngBounds = LatLngBounds.Builder()
|
||||
.include(LatLng(62.0, 26.0))
|
||||
.include(LatLng(58.0, 22.0))
|
||||
.build()
|
||||
val bounds: LatLngBounds = LatLngBounds.Builder()
|
||||
.include(LatLng(62.0, 26.0))
|
||||
.include(LatLng(58.0, 22.0))
|
||||
.build()
|
||||
|
||||
mapboxMap.moveCamera(CameraUpdateFactory.newLatLngBounds(bounds, 0))
|
||||
mapboxMap.moveCamera(CameraUpdateFactory.newLatLngBounds(bounds, 0))
|
||||
|
||||
val cameraPosition = mapboxMap.cameraPosition
|
||||
assertEquals("latitude should match:", 60.0, cameraPosition.target.latitude, 0.1)
|
||||
assertEquals("longitude should match:", 24.0, cameraPosition.target.longitude, 0.1)
|
||||
assertEquals("bearing should match:", 0.0, cameraPosition.bearing, 0.1)
|
||||
assertEquals("zoom should match", 5.5, cameraPosition.zoom, 0.1)
|
||||
assertEquals("tilt should match:", 0.0, cameraPosition.tilt, 0.1)
|
||||
}
|
||||
val cameraPosition = mapboxMap.cameraPosition
|
||||
assertEquals("latitude should match:", 60.0, cameraPosition.target.latitude, 0.1)
|
||||
assertEquals("longitude should match:", 24.0, cameraPosition.target.longitude, 0.1)
|
||||
assertEquals("bearing should match:", 0.0, cameraPosition.bearing, 0.1)
|
||||
assertEquals("zoom should match", 5.5, cameraPosition.zoom, 0.1)
|
||||
assertEquals("tilt should match:", 0.0, cameraPosition.tilt, 0.1)
|
||||
}
|
||||
|
||||
@Test
|
||||
@UiThreadTest
|
||||
fun testLatLngBoundsTilted() {
|
||||
mapboxMap.cameraPosition = CameraPosition.Builder()
|
||||
.target(LatLng(60.0, 24.0))
|
||||
.bearing(0.0)
|
||||
.tilt(45.0)
|
||||
.build()
|
||||
@Test
|
||||
@UiThreadTest
|
||||
fun testLatLngBoundsTilted() {
|
||||
mapboxMap.cameraPosition = CameraPosition.Builder()
|
||||
.target(LatLng(60.0, 24.0))
|
||||
.bearing(0.0)
|
||||
.tilt(45.0)
|
||||
.build()
|
||||
|
||||
val bounds: LatLngBounds = LatLngBounds.Builder()
|
||||
.include(LatLng(62.0, 26.0))
|
||||
.include(LatLng(58.0, 22.0))
|
||||
.build()
|
||||
val bounds: LatLngBounds = LatLngBounds.Builder()
|
||||
.include(LatLng(62.0, 26.0))
|
||||
.include(LatLng(58.0, 22.0))
|
||||
.build()
|
||||
|
||||
mapboxMap.moveCamera(CameraUpdateFactory.newLatLngBounds(bounds, 0))
|
||||
mapboxMap.moveCamera(CameraUpdateFactory.newLatLngBounds(bounds, 0))
|
||||
|
||||
val cameraPosition = mapboxMap.cameraPosition
|
||||
assertEquals("latitude should match:", 60.0, cameraPosition.target.latitude, 0.1)
|
||||
assertEquals("longitude should match:", 24.0, cameraPosition.target.longitude, 0.1)
|
||||
assertEquals("bearing should match:", 0.0, cameraPosition.bearing, 0.1)
|
||||
assertEquals("zoom should match", 6.0, cameraPosition.zoom, 0.1)
|
||||
assertEquals("tilt should match:", 45.0, cameraPosition.tilt, 0.1)
|
||||
}
|
||||
val cameraPosition = mapboxMap.cameraPosition
|
||||
assertEquals("latitude should match:", 60.0, cameraPosition.target.latitude, 0.1)
|
||||
assertEquals("longitude should match:", 24.0, cameraPosition.target.longitude, 0.1)
|
||||
assertEquals("bearing should match:", 0.0, cameraPosition.bearing, 0.1)
|
||||
assertEquals("zoom should match", 6.0, cameraPosition.zoom, 0.1)
|
||||
assertEquals("tilt should match:", 45.0, cameraPosition.tilt, 0.1)
|
||||
}
|
||||
|
||||
@Test
|
||||
@UiThreadTest
|
||||
fun testLatLngBoundsRotated() {
|
||||
mapboxMap.cameraPosition = CameraPosition.Builder()
|
||||
.target(LatLng(60.0, 24.0))
|
||||
.bearing(30.0)
|
||||
.tilt(0.0)
|
||||
.build()
|
||||
@Test
|
||||
@UiThreadTest
|
||||
fun testLatLngBoundsRotated() {
|
||||
mapboxMap.cameraPosition = CameraPosition.Builder()
|
||||
.target(LatLng(60.0, 24.0))
|
||||
.bearing(30.0)
|
||||
.tilt(0.0)
|
||||
.build()
|
||||
|
||||
val bounds: LatLngBounds = LatLngBounds.Builder()
|
||||
.include(LatLng(62.0, 26.0))
|
||||
.include(LatLng(58.0, 22.0))
|
||||
.build()
|
||||
val bounds: LatLngBounds = LatLngBounds.Builder()
|
||||
.include(LatLng(62.0, 26.0))
|
||||
.include(LatLng(58.0, 22.0))
|
||||
.build()
|
||||
|
||||
mapboxMap.moveCamera(CameraUpdateFactory.newLatLngBounds(bounds, 0))
|
||||
mapboxMap.moveCamera(CameraUpdateFactory.newLatLngBounds(bounds, 0))
|
||||
|
||||
val cameraPosition = mapboxMap.cameraPosition
|
||||
assertEquals("latitude should match:", 60.0, cameraPosition.target.latitude, 0.1)
|
||||
assertEquals("longitude should match:", 24.0, cameraPosition.target.longitude, 0.1)
|
||||
assertEquals("bearing should match:", 30.0, cameraPosition.bearing, 0.1)
|
||||
assertEquals("zoom should match", 5.3, cameraPosition.zoom, 0.1)
|
||||
assertEquals("tilt should match:", 0.0, cameraPosition.tilt, 0.1)
|
||||
}
|
||||
val cameraPosition = mapboxMap.cameraPosition
|
||||
assertEquals("latitude should match:", 60.0, cameraPosition.target.latitude, 0.1)
|
||||
assertEquals("longitude should match:", 24.0, cameraPosition.target.longitude, 0.1)
|
||||
assertEquals("bearing should match:", 30.0, cameraPosition.bearing, 0.1)
|
||||
assertEquals("zoom should match", 5.3, cameraPosition.zoom, 0.1)
|
||||
assertEquals("tilt should match:", 0.0, cameraPosition.tilt, 0.1)
|
||||
}
|
||||
|
||||
@Test
|
||||
@UiThreadTest
|
||||
fun testLatLngBoundsTiltedRotated() {
|
||||
mapboxMap.cameraPosition = CameraPosition.Builder()
|
||||
.target(LatLng(60.0, 24.0))
|
||||
.bearing(30.0)
|
||||
.tilt(45.0)
|
||||
.build()
|
||||
@Test
|
||||
@UiThreadTest
|
||||
fun testLatLngBoundsTiltedRotated() {
|
||||
mapboxMap.cameraPosition = CameraPosition.Builder()
|
||||
.target(LatLng(60.0, 24.0))
|
||||
.bearing(30.0)
|
||||
.tilt(45.0)
|
||||
.build()
|
||||
|
||||
val bounds: LatLngBounds = LatLngBounds.Builder()
|
||||
.include(LatLng(62.0, 26.0))
|
||||
.include(LatLng(58.0, 22.0))
|
||||
.build()
|
||||
val bounds: LatLngBounds = LatLngBounds.Builder()
|
||||
.include(LatLng(62.0, 26.0))
|
||||
.include(LatLng(58.0, 22.0))
|
||||
.build()
|
||||
|
||||
mapboxMap.moveCamera(CameraUpdateFactory.newLatLngBounds(bounds, 0))
|
||||
mapboxMap.moveCamera(CameraUpdateFactory.newLatLngBounds(bounds, 0))
|
||||
|
||||
val cameraPosition = mapboxMap.cameraPosition
|
||||
assertEquals("latitude should match:", 60.0, cameraPosition.target.latitude, 0.1)
|
||||
assertEquals("longitude should match:", 24.0, cameraPosition.target.longitude, 0.1)
|
||||
assertEquals("bearing should match:", 30.0, cameraPosition.bearing, 0.1)
|
||||
assertEquals("zoom should match", 5.6, cameraPosition.zoom, 0.1)
|
||||
assertEquals("tilt should match:", 45.0, cameraPosition.tilt, 0.1)
|
||||
}
|
||||
val cameraPosition = mapboxMap.cameraPosition
|
||||
assertEquals("latitude should match:", 60.0, cameraPosition.target.latitude, 0.1)
|
||||
assertEquals("longitude should match:", 24.0, cameraPosition.target.longitude, 0.1)
|
||||
assertEquals("bearing should match:", 30.0, cameraPosition.bearing, 0.1)
|
||||
assertEquals("zoom should match", 5.6, cameraPosition.zoom, 0.1)
|
||||
assertEquals("tilt should match:", 45.0, cameraPosition.tilt, 0.1)
|
||||
}
|
||||
|
||||
@Test
|
||||
@UiThreadTest
|
||||
fun testLatLngBoundsWithProvidedTiltAndRotation() {
|
||||
mapboxMap.cameraPosition = CameraPosition.Builder()
|
||||
.target(LatLng(60.0, 24.0))
|
||||
.bearing(0.0)
|
||||
.tilt(0.0)
|
||||
.build()
|
||||
@Test
|
||||
@UiThreadTest
|
||||
fun testLatLngBoundsWithProvidedTiltAndRotation() {
|
||||
mapboxMap.cameraPosition = CameraPosition.Builder()
|
||||
.target(LatLng(60.0, 24.0))
|
||||
.bearing(0.0)
|
||||
.tilt(0.0)
|
||||
.build()
|
||||
|
||||
val bounds: LatLngBounds = LatLngBounds.Builder()
|
||||
.include(LatLng(62.0, 26.0))
|
||||
.include(LatLng(58.0, 22.0))
|
||||
.build()
|
||||
val bounds: LatLngBounds = LatLngBounds.Builder()
|
||||
.include(LatLng(62.0, 26.0))
|
||||
.include(LatLng(58.0, 22.0))
|
||||
.build()
|
||||
|
||||
mapboxMap.moveCamera(CameraUpdateFactory.newLatLngBounds(bounds, 30.0, 40.0, 0))
|
||||
mapboxMap.moveCamera(CameraUpdateFactory.newLatLngBounds(bounds, 30.0, 40.0, 0))
|
||||
|
||||
val cameraPosition = mapboxMap.cameraPosition
|
||||
assertEquals("latitude should match:", 60.0, cameraPosition.target.latitude, 0.1)
|
||||
assertEquals("longitude should match:", 24.0, cameraPosition.target.longitude, 0.1)
|
||||
assertEquals("bearing should match:", 30.0, cameraPosition.bearing, 0.1)
|
||||
assertEquals("zoom should match", 5.6, cameraPosition.zoom, 0.1)
|
||||
assertEquals("tilt should match:", 40.0, cameraPosition.tilt, 0.1)
|
||||
}
|
||||
val cameraPosition = mapboxMap.cameraPosition
|
||||
assertEquals("latitude should match:", 60.0, cameraPosition.target.latitude, 0.1)
|
||||
assertEquals("longitude should match:", 24.0, cameraPosition.target.longitude, 0.1)
|
||||
assertEquals("bearing should match:", 30.0, cameraPosition.bearing, 0.1)
|
||||
assertEquals("zoom should match", 5.6, cameraPosition.zoom, 0.1)
|
||||
assertEquals("tilt should match:", 40.0, cameraPosition.tilt, 0.1)
|
||||
}
|
||||
|
||||
@Test
|
||||
@UiThreadTest
|
||||
fun withPadding_cameraInvalidated_paddingPersisting() {
|
||||
val initialCameraPosition = mapboxMap.cameraPosition
|
||||
val initialPoint = mapboxMap.projection.toScreenLocation(initialCameraPosition.target)
|
||||
@Test
|
||||
@UiThreadTest
|
||||
fun withPadding_cameraInvalidated_paddingPersisting() {
|
||||
val initialCameraPosition = mapboxMap.cameraPosition
|
||||
val initialPoint = mapboxMap.projection.toScreenLocation(initialCameraPosition.target)
|
||||
|
||||
val bottomPadding = mapView.height / 4
|
||||
val leftPadding = mapView.width / 4
|
||||
val padding = doubleArrayOf(leftPadding.toDouble(), 0.0, 0.0, bottomPadding.toDouble())
|
||||
mapboxMap.moveCamera(CameraUpdateFactory.paddingTo(leftPadding.toDouble(), 0.0, 0.0, bottomPadding.toDouble()))
|
||||
val bottomPadding = mapView.height / 4
|
||||
val leftPadding = mapView.width / 4
|
||||
val padding = doubleArrayOf(leftPadding.toDouble(), 0.0, 0.0, bottomPadding.toDouble())
|
||||
mapboxMap.moveCamera(CameraUpdateFactory.paddingTo(leftPadding.toDouble(), 0.0, 0.0, bottomPadding.toDouble()))
|
||||
|
||||
Assert.assertArrayEquals(intArrayOf(leftPadding, 0, 0, bottomPadding), mapboxMap.padding)
|
||||
Assert.assertArrayEquals(intArrayOf(leftPadding, 0, 0, bottomPadding), mapboxMap.padding)
|
||||
|
||||
val resultingCameraPosition = mapboxMap.cameraPosition
|
||||
assertEquals(initialCameraPosition.target, resultingCameraPosition.target)
|
||||
assertEquals(
|
||||
PointF(initialPoint.x + leftPadding / 2, initialPoint.y - bottomPadding / 2),
|
||||
mapboxMap.projection.toScreenLocation(resultingCameraPosition.target)
|
||||
)
|
||||
Assert.assertArrayEquals(padding, resultingCameraPosition.padding, 0.0001)
|
||||
}
|
||||
val resultingCameraPosition = mapboxMap.cameraPosition
|
||||
assertEquals(initialCameraPosition.target, resultingCameraPosition.target)
|
||||
assertEquals(
|
||||
PointF(initialPoint.x + leftPadding / 2, initialPoint.y - bottomPadding / 2),
|
||||
mapboxMap.projection.toScreenLocation(resultingCameraPosition.target)
|
||||
)
|
||||
Assert.assertArrayEquals(padding, resultingCameraPosition.padding, 0.0001)
|
||||
}
|
||||
|
||||
@Test
|
||||
@UiThreadTest
|
||||
fun withLatLngPadding_cameraInvalidated_paddingPersisting() {
|
||||
val expectedTarget = LatLng(2.0, 2.0)
|
||||
@Test
|
||||
@UiThreadTest
|
||||
fun withLatLngPadding_cameraInvalidated_paddingPersisting() {
|
||||
val expectedTarget = LatLng(2.0, 2.0)
|
||||
|
||||
val topPadding = mapView.height / 4
|
||||
val rightPadding = mapView.width / 4
|
||||
val padding = doubleArrayOf(0.0, topPadding.toDouble(), rightPadding.toDouble(), 0.0)
|
||||
mapboxMap.moveCamera(CameraUpdateFactory.newLatLngPadding(expectedTarget, 0.0, topPadding.toDouble(), rightPadding.toDouble(), 0.0))
|
||||
val topPadding = mapView.height / 4
|
||||
val rightPadding = mapView.width / 4
|
||||
val padding = doubleArrayOf(0.0, topPadding.toDouble(), rightPadding.toDouble(), 0.0)
|
||||
mapboxMap.moveCamera(CameraUpdateFactory.newLatLngPadding(expectedTarget, 0.0, topPadding.toDouble(), rightPadding.toDouble(), 0.0))
|
||||
|
||||
Assert.assertArrayEquals(intArrayOf(0, topPadding, rightPadding, 0), mapboxMap.padding)
|
||||
Assert.assertArrayEquals(intArrayOf(0, topPadding, rightPadding, 0), mapboxMap.padding)
|
||||
|
||||
val resultingCameraPosition = mapboxMap.cameraPosition
|
||||
assertEquals(expectedTarget.latitude, resultingCameraPosition.target.latitude, 0.1)
|
||||
assertEquals(expectedTarget.longitude, resultingCameraPosition.target.longitude, 0.1)
|
||||
val resultingCameraPosition = mapboxMap.cameraPosition
|
||||
assertEquals(expectedTarget.latitude, resultingCameraPosition.target.latitude, 0.1)
|
||||
assertEquals(expectedTarget.longitude, resultingCameraPosition.target.longitude, 0.1)
|
||||
|
||||
val centerLatLng = mapboxMap.projection.fromScreenLocation(PointF((mapView.width / 2).toFloat(), (mapView.height / 2).toFloat()))
|
||||
assertTrue(centerLatLng.latitude > resultingCameraPosition.target.latitude)
|
||||
assertTrue(centerLatLng.longitude > resultingCameraPosition.target.longitude)
|
||||
Assert.assertArrayEquals(padding, resultingCameraPosition.padding, 0.0001)
|
||||
}
|
||||
}
|
||||
val centerLatLng = mapboxMap.projection.fromScreenLocation(PointF((mapView.width / 2).toFloat(), (mapView.height / 2).toFloat()))
|
||||
assertTrue(centerLatLng.latitude > resultingCameraPosition.target.latitude)
|
||||
assertTrue(centerLatLng.longitude > resultingCameraPosition.target.longitude)
|
||||
Assert.assertArrayEquals(padding, resultingCameraPosition.padding, 0.0001)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -12,12 +12,12 @@ const val TIMEOUT_UI_SEARCH_WAIT = 5000L
|
||||
|
||||
abstract class BaseIntegrationTest : AppCenter() {
|
||||
|
||||
protected lateinit var device: UiDevice
|
||||
protected lateinit var device: UiDevice
|
||||
|
||||
@Before
|
||||
open fun beforeTest() {
|
||||
device = UiDevice.getInstance(InstrumentationRegistry.getInstrumentation())
|
||||
}
|
||||
@Before
|
||||
open fun beforeTest() {
|
||||
device = UiDevice.getInstance(InstrumentationRegistry.getInstrumentation())
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -27,14 +27,14 @@ abstract class BaseIntegrationTest : AppCenter() {
|
||||
* <p>
|
||||
*/
|
||||
fun UiDevice.launchActivity(context: Context, clazz: Class<*>) {
|
||||
val applicationPackage = InstrumentationRegistry.getInstrumentation().targetContext.packageName
|
||||
val intent = Intent(context, clazz)
|
||||
intent.addFlags(FLAG_ACTIVITY_NEW_TASK)
|
||||
InstrumentationRegistry.getInstrumentation().context.startActivity(intent)
|
||||
wait(Until.hasObject(By.pkg(applicationPackage).depth(0)), TIMEOUT_UI_SEARCH_WAIT)
|
||||
val applicationPackage = InstrumentationRegistry.getInstrumentation().targetContext.packageName
|
||||
val intent = Intent(context, clazz)
|
||||
intent.addFlags(FLAG_ACTIVITY_NEW_TASK)
|
||||
InstrumentationRegistry.getInstrumentation().context.startActivity(intent)
|
||||
wait(Until.hasObject(By.pkg(applicationPackage).depth(0)), TIMEOUT_UI_SEARCH_WAIT)
|
||||
}
|
||||
|
||||
fun UiDevice.scrollRecyclerViewTo(recycleItem: String) {
|
||||
val appView = UiScrollable(UiSelector().scrollable(true))
|
||||
appView.scrollIntoView(UiSelector().text(recycleItem))
|
||||
}
|
||||
val appView = UiScrollable(UiSelector().scrollable(true))
|
||||
appView.scrollIntoView(UiSelector().text(recycleItem))
|
||||
}
|
||||
|
||||
@@ -15,31 +15,31 @@ import org.junit.runner.RunWith
|
||||
@RunWith(AndroidJUnit4::class)
|
||||
class FragmentBackStackTest : BaseIntegrationTest() {
|
||||
|
||||
@get:Rule
|
||||
var activityRule: ActivityTestRule<FragmentBackStackActivity> = ActivityTestRule(FragmentBackStackActivity::class.java)
|
||||
@get:Rule
|
||||
var activityRule: ActivityTestRule<FragmentBackStackActivity> = ActivityTestRule(FragmentBackStackActivity::class.java)
|
||||
|
||||
@Test
|
||||
@LargeTest
|
||||
fun backPressedOnBackStackResumed() {
|
||||
device.waitForIdle()
|
||||
clickReplaceFragmentButton()
|
||||
device.pressHome()
|
||||
device.waitForIdle()
|
||||
device.launchActivity(activityRule.activity.applicationContext, FragmentBackStackActivity::class.java)
|
||||
backPressBackStack()
|
||||
device.waitForIdle()
|
||||
}
|
||||
@Test
|
||||
@LargeTest
|
||||
fun backPressedOnBackStackResumed() {
|
||||
device.waitForIdle()
|
||||
clickReplaceFragmentButton()
|
||||
device.pressHome()
|
||||
device.waitForIdle()
|
||||
device.launchActivity(activityRule.activity.applicationContext, FragmentBackStackActivity::class.java)
|
||||
backPressBackStack()
|
||||
device.waitForIdle()
|
||||
}
|
||||
|
||||
private fun clickReplaceFragmentButton() {
|
||||
device.findObject(UiSelector().description(textDescription)).click()
|
||||
}
|
||||
private fun clickReplaceFragmentButton() {
|
||||
device.findObject(UiSelector().description(textDescription)).click()
|
||||
}
|
||||
|
||||
private fun backPressBackStack() {
|
||||
device.pressBack() // pops fragment, showing map
|
||||
device.pressBack() // finish activity
|
||||
}
|
||||
private fun backPressBackStack() {
|
||||
device.pressBack() // pops fragment, showing map
|
||||
device.pressBack() // finish activity
|
||||
}
|
||||
|
||||
private companion object {
|
||||
const val textDescription = "btn_change_fragment"
|
||||
}
|
||||
}
|
||||
private companion object {
|
||||
const val textDescription = "btn_change_fragment"
|
||||
}
|
||||
}
|
||||
|
||||
@@ -14,16 +14,16 @@ import org.junit.runner.RunWith
|
||||
@RunWith(AndroidJUnit4::class)
|
||||
class GLSurfaceViewReopenTest : BaseIntegrationTest() {
|
||||
|
||||
@get:Rule
|
||||
var activityRule: ActivityTestRule<SimpleMapActivity> = ActivityTestRule(SimpleMapActivity::class.java)
|
||||
@get:Rule
|
||||
var activityRule: ActivityTestRule<SimpleMapActivity> = ActivityTestRule(SimpleMapActivity::class.java)
|
||||
|
||||
@Test
|
||||
@LargeTest
|
||||
fun reopenSimpleMapActivity() {
|
||||
device.waitForIdle()
|
||||
device.pressHome()
|
||||
device.waitForIdle()
|
||||
device.launchActivity(activityRule.activity, SimpleMapActivity::class.java)
|
||||
device.waitForIdle()
|
||||
}
|
||||
}
|
||||
@Test
|
||||
@LargeTest
|
||||
fun reopenSimpleMapActivity() {
|
||||
device.waitForIdle()
|
||||
device.pressHome()
|
||||
device.waitForIdle()
|
||||
device.launchActivity(activityRule.activity, SimpleMapActivity::class.java)
|
||||
device.waitForIdle()
|
||||
}
|
||||
}
|
||||
|
||||
@@ -14,16 +14,16 @@ import org.junit.runner.RunWith
|
||||
@RunWith(AndroidJUnit4::class)
|
||||
class GLSurfaceViewReuseTest : BaseIntegrationTest() {
|
||||
|
||||
@get:Rule
|
||||
var activityRule: ActivityTestRule<GLSurfaceRecyclerViewActivity> = ActivityTestRule(GLSurfaceRecyclerViewActivity::class.java)
|
||||
@get:Rule
|
||||
var activityRule: ActivityTestRule<GLSurfaceRecyclerViewActivity> = ActivityTestRule(GLSurfaceRecyclerViewActivity::class.java)
|
||||
|
||||
@Test
|
||||
@LargeTest
|
||||
fun scrollRecyclerView() {
|
||||
device.waitForIdle()
|
||||
device.scrollRecyclerViewTo("Twenty-one")
|
||||
device.waitForIdle()
|
||||
device.scrollRecyclerViewTo("One")
|
||||
device.waitForIdle()
|
||||
}
|
||||
}
|
||||
@Test
|
||||
@LargeTest
|
||||
fun scrollRecyclerView() {
|
||||
device.waitForIdle()
|
||||
device.scrollRecyclerViewTo("Twenty-one")
|
||||
device.waitForIdle()
|
||||
device.scrollRecyclerViewTo("One")
|
||||
device.waitForIdle()
|
||||
}
|
||||
}
|
||||
|
||||
@@ -11,22 +11,22 @@ import org.junit.runner.RunWith
|
||||
@RunWith(AndroidJUnit4::class)
|
||||
class OrientationChangeTest : BaseIntegrationTest() {
|
||||
|
||||
@get:Rule
|
||||
var activityRule: ActivityTestRule<SimpleMapActivity> = ActivityTestRule(SimpleMapActivity::class.java)
|
||||
@get:Rule
|
||||
var activityRule: ActivityTestRule<SimpleMapActivity> = ActivityTestRule(SimpleMapActivity::class.java)
|
||||
|
||||
@Test
|
||||
@LargeTest
|
||||
fun rotateSimpleMap() {
|
||||
device.setOrientationLeft()
|
||||
device.waitForIdle()
|
||||
device.setOrientationNatural()
|
||||
device.waitForIdle()
|
||||
device.setOrientationRight()
|
||||
device.waitForIdle()
|
||||
device.setOrientationNatural()
|
||||
device.setOrientationLeft()
|
||||
device.setOrientationNatural()
|
||||
device.setOrientationRight()
|
||||
device.setOrientationNatural()
|
||||
}
|
||||
}
|
||||
@Test
|
||||
@LargeTest
|
||||
fun rotateSimpleMap() {
|
||||
device.setOrientationLeft()
|
||||
device.waitForIdle()
|
||||
device.setOrientationNatural()
|
||||
device.waitForIdle()
|
||||
device.setOrientationRight()
|
||||
device.waitForIdle()
|
||||
device.setOrientationNatural()
|
||||
device.setOrientationLeft()
|
||||
device.setOrientationNatural()
|
||||
device.setOrientationRight()
|
||||
device.setOrientationNatural()
|
||||
}
|
||||
}
|
||||
|
||||
@@ -14,17 +14,17 @@ import org.junit.runner.RunWith
|
||||
@RunWith(AndroidJUnit4::class)
|
||||
class QueryRenderedFeaturesBoxCountTest : BaseIntegrationTest() {
|
||||
|
||||
@get:Rule
|
||||
var activityRule: ActivityTestRule<QueryRenderedFeaturesBoxCountActivity> =
|
||||
ActivityTestRule(QueryRenderedFeaturesBoxCountActivity::class.java)
|
||||
@get:Rule
|
||||
var activityRule: ActivityTestRule<QueryRenderedFeaturesBoxCountActivity> =
|
||||
ActivityTestRule(QueryRenderedFeaturesBoxCountActivity::class.java)
|
||||
|
||||
@Test
|
||||
@LargeTest
|
||||
fun reopenQueryRendererFeaturesActivity() {
|
||||
device.waitForIdle()
|
||||
device.pressHome()
|
||||
device.waitForIdle()
|
||||
device.launchActivity(activityRule.activity, QueryRenderedFeaturesBoxCountActivity::class.java)
|
||||
device.waitForIdle()
|
||||
}
|
||||
}
|
||||
@Test
|
||||
@LargeTest
|
||||
fun reopenQueryRendererFeaturesActivity() {
|
||||
device.waitForIdle()
|
||||
device.pressHome()
|
||||
device.waitForIdle()
|
||||
device.launchActivity(activityRule.activity, QueryRenderedFeaturesBoxCountActivity::class.java)
|
||||
device.waitForIdle()
|
||||
}
|
||||
}
|
||||
|
||||
@@ -14,16 +14,16 @@ import org.junit.runner.RunWith
|
||||
@RunWith(AndroidJUnit4::class)
|
||||
class TextureViewReopenTest : BaseIntegrationTest() {
|
||||
|
||||
@get:Rule
|
||||
var activityRule: ActivityTestRule<TextureViewDebugModeActivity> = ActivityTestRule(TextureViewDebugModeActivity::class.java)
|
||||
@get:Rule
|
||||
var activityRule: ActivityTestRule<TextureViewDebugModeActivity> = ActivityTestRule(TextureViewDebugModeActivity::class.java)
|
||||
|
||||
@Test
|
||||
@LargeTest
|
||||
fun reopenTextureViewDebugActivity() {
|
||||
device.waitForIdle()
|
||||
device.pressHome()
|
||||
device.waitForIdle()
|
||||
device.launchActivity(activityRule.activity, TextureViewDebugModeActivity::class.java)
|
||||
device.waitForIdle()
|
||||
}
|
||||
}
|
||||
@Test
|
||||
@LargeTest
|
||||
fun reopenTextureViewDebugActivity() {
|
||||
device.waitForIdle()
|
||||
device.pressHome()
|
||||
device.waitForIdle()
|
||||
device.launchActivity(activityRule.activity, TextureViewDebugModeActivity::class.java)
|
||||
device.waitForIdle()
|
||||
}
|
||||
}
|
||||
|
||||
@@ -14,16 +14,16 @@ import org.junit.runner.RunWith
|
||||
@RunWith(AndroidJUnit4::class)
|
||||
class TextureViewReuseTest : BaseIntegrationTest() {
|
||||
|
||||
@get:Rule
|
||||
var activityRule: ActivityTestRule<TextureRecyclerViewActivity> = ActivityTestRule(TextureRecyclerViewActivity::class.java)
|
||||
@get:Rule
|
||||
var activityRule: ActivityTestRule<TextureRecyclerViewActivity> = ActivityTestRule(TextureRecyclerViewActivity::class.java)
|
||||
|
||||
@Test
|
||||
@LargeTest
|
||||
fun scrollRecyclerView() {
|
||||
device.waitForIdle()
|
||||
device.scrollRecyclerViewTo("Twenty-one")
|
||||
device.waitForIdle()
|
||||
device.scrollRecyclerViewTo("One")
|
||||
device.waitForIdle()
|
||||
}
|
||||
}
|
||||
@Test
|
||||
@LargeTest
|
||||
fun scrollRecyclerView() {
|
||||
device.waitForIdle()
|
||||
device.scrollRecyclerViewTo("Twenty-one")
|
||||
device.waitForIdle()
|
||||
device.scrollRecyclerViewTo("One")
|
||||
device.waitForIdle()
|
||||
}
|
||||
}
|
||||
|
||||
@@ -15,22 +15,22 @@ import org.junit.runner.RunWith
|
||||
@RunWith(AndroidJUnit4::class)
|
||||
class ViewPagerScrollTest : BaseIntegrationTest() {
|
||||
|
||||
@get:Rule
|
||||
var activityRule: ActivityTestRule<ViewPagerActivity> = ActivityTestRule(ViewPagerActivity::class.java)
|
||||
@get:Rule
|
||||
var activityRule: ActivityTestRule<ViewPagerActivity> = ActivityTestRule(ViewPagerActivity::class.java)
|
||||
|
||||
@Test
|
||||
@LargeTest
|
||||
fun scrollViewPager() {
|
||||
for (i in 1..4) {
|
||||
clickTab(i)
|
||||
@Test
|
||||
@LargeTest
|
||||
fun scrollViewPager() {
|
||||
for (i in 1..4) {
|
||||
clickTab(i)
|
||||
}
|
||||
|
||||
for (i in 3 downTo 0) {
|
||||
clickTab(i)
|
||||
}
|
||||
}
|
||||
|
||||
for (i in 3 downTo 0) {
|
||||
clickTab(i)
|
||||
private fun clickTab(index: Int) {
|
||||
device.findObject(UiSelector().text("Page $index")).click()
|
||||
}
|
||||
}
|
||||
|
||||
private fun clickTab(index: Int) {
|
||||
device.findObject(UiSelector().text("Page $index")).click()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
@@ -11,28 +11,29 @@ import com.mapbox.mapboxsdk.maps.Style
|
||||
import org.hamcrest.Matcher
|
||||
|
||||
class LocationComponentAction(
|
||||
private val mapboxMap: MapboxMap,
|
||||
private val onPerformLocationComponentAction: OnPerformLocationComponentAction
|
||||
private val mapboxMap: MapboxMap,
|
||||
private val onPerformLocationComponentAction: OnPerformLocationComponentAction
|
||||
) : ViewAction {
|
||||
|
||||
override fun getConstraints(): Matcher<View> {
|
||||
return isDisplayed()
|
||||
}
|
||||
override fun getConstraints(): Matcher<View> {
|
||||
return isDisplayed()
|
||||
}
|
||||
|
||||
override fun getDescription(): String {
|
||||
return javaClass.simpleName
|
||||
}
|
||||
override fun getDescription(): String {
|
||||
return javaClass.simpleName
|
||||
}
|
||||
|
||||
override fun perform(uiController: UiController, view: View) {
|
||||
onPerformLocationComponentAction.onLocationComponentAction(
|
||||
mapboxMap.locationComponent,
|
||||
mapboxMap,
|
||||
mapboxMap.style!!,
|
||||
uiController,
|
||||
view.context)
|
||||
}
|
||||
override fun perform(uiController: UiController, view: View) {
|
||||
onPerformLocationComponentAction.onLocationComponentAction(
|
||||
mapboxMap.locationComponent,
|
||||
mapboxMap,
|
||||
mapboxMap.style!!,
|
||||
uiController,
|
||||
view.context
|
||||
)
|
||||
}
|
||||
|
||||
interface OnPerformLocationComponentAction {
|
||||
fun onLocationComponentAction(component: LocationComponent, mapboxMap: MapboxMap, style: Style, uiController: UiController, context: Context)
|
||||
}
|
||||
}
|
||||
interface OnPerformLocationComponentAction {
|
||||
fun onLocationComponentAction(component: LocationComponent, mapboxMap: MapboxMap, style: Style, uiController: UiController, context: Context)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -14,66 +14,69 @@ import com.mapbox.mapboxsdk.style.layers.Property
|
||||
import com.mapbox.mapboxsdk.style.sources.GeoJsonSource
|
||||
|
||||
fun MapboxMap.querySourceFeatures(sourceId: String): List<Feature> {
|
||||
return this.style!!.getSourceAs<GeoJsonSource>(sourceId)?.querySourceFeatures(null) ?: emptyList()
|
||||
return this.style!!.getSourceAs<GeoJsonSource>(sourceId)?.querySourceFeatures(null) ?: emptyList()
|
||||
}
|
||||
|
||||
fun MapboxMap.queryRenderedFeatures(location: Location, layerId: String): List<Feature> {
|
||||
val latLng = LatLng(location.latitude, location.longitude)
|
||||
val point = this.projection.toScreenLocation(latLng)
|
||||
return this.queryRenderedFeatures(point, layerId)
|
||||
val latLng = LatLng(location.latitude, location.longitude)
|
||||
val point = this.projection.toScreenLocation(latLng)
|
||||
return this.queryRenderedFeatures(point, layerId)
|
||||
}
|
||||
|
||||
fun MapboxMap.isLayerVisible(layerId: String): Boolean {
|
||||
return this.style!!.getLayer(layerId)?.visibility?.value?.equals(Property.VISIBLE)!!
|
||||
return this.style!!.getLayer(layerId)?.visibility?.value?.equals(Property.VISIBLE)!!
|
||||
}
|
||||
|
||||
class MapboxTestingUtils {
|
||||
companion object {
|
||||
companion object {
|
||||
|
||||
/**
|
||||
* Used to increase style load time for stress testing.
|
||||
*/
|
||||
const val MAPBOX_HEAVY_STYLE = "asset://heavy_style.json"
|
||||
/**
|
||||
* Used to increase style load time for stress testing.
|
||||
*/
|
||||
const val MAPBOX_HEAVY_STYLE = "asset://heavy_style.json"
|
||||
|
||||
private const val DATA_PUSH_INTERVAL = 1L
|
||||
private const val DATA_PUSH_INTERVAL = 1L
|
||||
|
||||
/**
|
||||
* Pushes data updates every [DATA_PUSH_INTERVAL] milliseconds until the style has been loaded,
|
||||
* checked with [StyleChangeIdlingResource].
|
||||
*/
|
||||
fun pushSourceUpdates(styleChangeIdlingResource: StyleChangeIdlingResource, update: () -> Unit) {
|
||||
val mainHandler = Handler(Looper.getMainLooper())
|
||||
val runnable = object : Runnable {
|
||||
override fun run() {
|
||||
update.invoke()
|
||||
if (!styleChangeIdlingResource.isIdleNow) {
|
||||
mainHandler.postDelayed(this, DATA_PUSH_INTERVAL)
|
||||
}
|
||||
/**
|
||||
* Pushes data updates every [DATA_PUSH_INTERVAL] milliseconds until the style has been loaded,
|
||||
* checked with [StyleChangeIdlingResource].
|
||||
*/
|
||||
fun pushSourceUpdates(styleChangeIdlingResource: StyleChangeIdlingResource, update: () -> Unit) {
|
||||
val mainHandler = Handler(Looper.getMainLooper())
|
||||
val runnable = object : Runnable {
|
||||
override fun run() {
|
||||
update.invoke()
|
||||
if (!styleChangeIdlingResource.isIdleNow) {
|
||||
mainHandler.postDelayed(this, DATA_PUSH_INTERVAL)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (!styleChangeIdlingResource.isIdleNow) {
|
||||
if (Looper.myLooper() == Looper.getMainLooper()) {
|
||||
runnable.run()
|
||||
} else {
|
||||
mainHandler.post(runnable)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (!styleChangeIdlingResource.isIdleNow) {
|
||||
if (Looper.myLooper() == Looper.getMainLooper()) {
|
||||
runnable.run()
|
||||
} else {
|
||||
mainHandler.post(runnable)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fun MapboxMap.addImageFromDrawable(string: String, drawable: Drawable) {
|
||||
val bitmapFromDrawable = getBitmapFromDrawable(drawable)
|
||||
this.style!!.addImage(string, bitmapFromDrawable)
|
||||
val bitmapFromDrawable = getBitmapFromDrawable(drawable)
|
||||
this.style!!.addImage(string, bitmapFromDrawable)
|
||||
}
|
||||
|
||||
private fun getBitmapFromDrawable(drawable: Drawable): Bitmap {
|
||||
if (drawable is BitmapDrawable) return drawable.bitmap
|
||||
val bitmap = Bitmap.createBitmap(drawable.intrinsicWidth,
|
||||
drawable.intrinsicHeight, Bitmap.Config.ARGB_8888)
|
||||
val canvas = Canvas(bitmap)
|
||||
drawable.setBounds(0, 0, canvas.width, canvas.height)
|
||||
drawable.draw(canvas)
|
||||
return bitmap
|
||||
}
|
||||
if (drawable is BitmapDrawable) return drawable.bitmap
|
||||
val bitmap = Bitmap.createBitmap(
|
||||
drawable.intrinsicWidth,
|
||||
drawable.intrinsicHeight,
|
||||
Bitmap.Config.ARGB_8888
|
||||
)
|
||||
val canvas = Canvas(bitmap)
|
||||
drawable.setBounds(0, 0, canvas.width, canvas.height)
|
||||
drawable.draw(canvas)
|
||||
return bitmap
|
||||
}
|
||||
|
||||
@@ -11,30 +11,30 @@ import com.mapbox.mapboxsdk.maps.Style
|
||||
*/
|
||||
class StyleChangeIdlingResource : IdlingResource {
|
||||
|
||||
private var callback: IdlingResource.ResourceCallback? = null
|
||||
private var isIdle = true
|
||||
private var callback: IdlingResource.ResourceCallback? = null
|
||||
private var isIdle = true
|
||||
|
||||
override fun getName(): String {
|
||||
return javaClass.simpleName
|
||||
}
|
||||
|
||||
override fun isIdleNow(): Boolean {
|
||||
return isIdle
|
||||
}
|
||||
|
||||
override fun registerIdleTransitionCallback(callback: IdlingResource.ResourceCallback?) {
|
||||
this.callback = callback
|
||||
}
|
||||
|
||||
private fun setIdle() {
|
||||
isIdle = true
|
||||
callback?.onTransitionToIdle()
|
||||
}
|
||||
|
||||
fun waitForStyle(mapboxMap: MapboxMap, styleUrl: String) {
|
||||
isIdle = false
|
||||
mapboxMap.setStyle(Style.Builder().fromUri(styleUrl)) {
|
||||
setIdle()
|
||||
override fun getName(): String {
|
||||
return javaClass.simpleName
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
override fun isIdleNow(): Boolean {
|
||||
return isIdle
|
||||
}
|
||||
|
||||
override fun registerIdleTransitionCallback(callback: IdlingResource.ResourceCallback?) {
|
||||
this.callback = callback
|
||||
}
|
||||
|
||||
private fun setIdle() {
|
||||
isIdle = true
|
||||
callback?.onTransitionToIdle()
|
||||
}
|
||||
|
||||
fun waitForStyle(mapboxMap: MapboxMap, styleUrl: String) {
|
||||
isIdle = false
|
||||
mapboxMap.setStyle(Style.Builder().fromUri(styleUrl)) {
|
||||
setIdle()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -24,4 +24,4 @@ abstract class BaseLayerTest : AppCenter() {
|
||||
fun setupLayer(layer: Layer) {
|
||||
nativeMapView.addLayer(layer)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -13,143 +13,143 @@ import org.hamcrest.Matcher
|
||||
|
||||
object GesturesUiTestUtils {
|
||||
|
||||
private const val DEFAULT_GESTURE_DURATION = 500L
|
||||
private const val DEFAULT_GESTURE_DURATION = 500L
|
||||
|
||||
fun pinch(
|
||||
startSpan: Float,
|
||||
endSpan: Float,
|
||||
center: PointF? = null,
|
||||
duration: Long = DEFAULT_GESTURE_DURATION
|
||||
): ViewAction {
|
||||
return object : ViewAction {
|
||||
override fun getConstraints(): Matcher<View> {
|
||||
return ViewMatchers.isEnabled()
|
||||
}
|
||||
fun pinch(
|
||||
startSpan: Float,
|
||||
endSpan: Float,
|
||||
center: PointF? = null,
|
||||
duration: Long = DEFAULT_GESTURE_DURATION
|
||||
): ViewAction {
|
||||
return object : ViewAction {
|
||||
override fun getConstraints(): Matcher<View> {
|
||||
return ViewMatchers.isEnabled()
|
||||
}
|
||||
|
||||
override fun getDescription(): String = "Pinch $startSpan -> $endSpan"
|
||||
override fun getDescription(): String = "Pinch $startSpan -> $endSpan"
|
||||
|
||||
override fun perform(uiController: UiController, view: View) {
|
||||
var middlePosition = center
|
||||
if (middlePosition == null) {
|
||||
middlePosition = getCenterPointF(view)
|
||||
override fun perform(uiController: UiController, view: View) {
|
||||
var middlePosition = center
|
||||
if (middlePosition == null) {
|
||||
middlePosition = getCenterPointF(view)
|
||||
}
|
||||
|
||||
val startPoint1 = PointF(middlePosition.x - startSpan / 2f, middlePosition.y)
|
||||
val startPoint2 = PointF(middlePosition.x + startSpan / 2f, middlePosition.y)
|
||||
val endPoint1 = PointF(middlePosition.x - endSpan / 2f, middlePosition.y)
|
||||
val endPoint2 = PointF(middlePosition.x + endSpan / 2f, middlePosition.y)
|
||||
|
||||
performPinch(uiController, startPoint1, startPoint2, endPoint1, endPoint2, duration)
|
||||
}
|
||||
}
|
||||
|
||||
val startPoint1 = PointF(middlePosition.x - startSpan / 2f, middlePosition.y)
|
||||
val startPoint2 = PointF(middlePosition.x + startSpan / 2f, middlePosition.y)
|
||||
val endPoint1 = PointF(middlePosition.x - endSpan / 2f, middlePosition.y)
|
||||
val endPoint2 = PointF(middlePosition.x + endSpan / 2f, middlePosition.y)
|
||||
|
||||
performPinch(uiController, startPoint1, startPoint2, endPoint1, endPoint2, duration)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fun quickScale(
|
||||
deltaY: Float,
|
||||
startPoint: PointF? = null,
|
||||
withVelocity: Boolean = true,
|
||||
duration: Long = DEFAULT_GESTURE_DURATION,
|
||||
interrupt: Boolean = false
|
||||
): ViewAction {
|
||||
return object : ViewAction {
|
||||
override fun getConstraints(): Matcher<View> = ViewMatchers.isEnabled()
|
||||
fun quickScale(
|
||||
deltaY: Float,
|
||||
startPoint: PointF? = null,
|
||||
withVelocity: Boolean = true,
|
||||
duration: Long = DEFAULT_GESTURE_DURATION,
|
||||
interrupt: Boolean = false
|
||||
): ViewAction {
|
||||
return object : ViewAction {
|
||||
override fun getConstraints(): Matcher<View> = ViewMatchers.isEnabled()
|
||||
|
||||
override fun getDescription(): String = "quick scale ${deltaY}Y"
|
||||
override fun getDescription(): String = "quick scale ${deltaY}Y"
|
||||
|
||||
override fun perform(uiController: UiController, view: View) {
|
||||
var middlePosition = startPoint
|
||||
if (middlePosition == null) {
|
||||
middlePosition = getCenterPointF(view)
|
||||
override fun perform(uiController: UiController, view: View) {
|
||||
var middlePosition = startPoint
|
||||
if (middlePosition == null) {
|
||||
middlePosition = getCenterPointF(view)
|
||||
}
|
||||
|
||||
val endPoint = PointF(middlePosition.x, middlePosition.y + deltaY)
|
||||
|
||||
performQuickScale(uiController, middlePosition, endPoint, withVelocity, duration, interrupt)
|
||||
}
|
||||
}
|
||||
|
||||
val endPoint = PointF(middlePosition.x, middlePosition.y + deltaY)
|
||||
|
||||
performQuickScale(uiController, middlePosition, endPoint, withVelocity, duration, interrupt)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fun move(
|
||||
deltaX: Float,
|
||||
deltaY: Float,
|
||||
startPoint: PointF? = null,
|
||||
withVelocity: Boolean = true,
|
||||
duration: Long = DEFAULT_GESTURE_DURATION
|
||||
): ViewAction {
|
||||
return object : ViewAction {
|
||||
override fun getConstraints(): Matcher<View> = ViewMatchers.isEnabled()
|
||||
fun move(
|
||||
deltaX: Float,
|
||||
deltaY: Float,
|
||||
startPoint: PointF? = null,
|
||||
withVelocity: Boolean = true,
|
||||
duration: Long = DEFAULT_GESTURE_DURATION
|
||||
): ViewAction {
|
||||
return object : ViewAction {
|
||||
override fun getConstraints(): Matcher<View> = ViewMatchers.isEnabled()
|
||||
|
||||
override fun getDescription(): String = "move ${deltaX}X, ${deltaY}Y"
|
||||
override fun getDescription(): String = "move ${deltaX}X, ${deltaY}Y"
|
||||
|
||||
override fun perform(uiController: UiController, view: View) {
|
||||
var middlePosition = startPoint
|
||||
if (middlePosition == null) {
|
||||
middlePosition = getCenterPointF(view)
|
||||
override fun perform(uiController: UiController, view: View) {
|
||||
var middlePosition = startPoint
|
||||
if (middlePosition == null) {
|
||||
middlePosition = getCenterPointF(view)
|
||||
}
|
||||
|
||||
val endPoint = PointF(middlePosition.x + deltaX, middlePosition.y + deltaY)
|
||||
|
||||
performMove(uiController, middlePosition, endPoint, withVelocity, duration)
|
||||
}
|
||||
}
|
||||
|
||||
val endPoint = PointF(middlePosition.x + deltaX, middlePosition.y + deltaY)
|
||||
|
||||
performMove(uiController, middlePosition, endPoint, withVelocity, duration)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private fun getCenterPointF(view: View): PointF {
|
||||
val locationOnScreen = IntArray(2)
|
||||
view.getLocationOnScreen(locationOnScreen)
|
||||
val viewHeight = view.height * view.scaleY
|
||||
val viewWidth = view.width * view.scaleX
|
||||
return PointF(
|
||||
(locationOnScreen[0] + viewWidth / 2).toInt().toFloat(),
|
||||
(locationOnScreen[1] + viewHeight / 2).toInt().toFloat()
|
||||
)
|
||||
}
|
||||
private fun getCenterPointF(view: View): PointF {
|
||||
val locationOnScreen = IntArray(2)
|
||||
view.getLocationOnScreen(locationOnScreen)
|
||||
val viewHeight = view.height * view.scaleY
|
||||
val viewWidth = view.width * view.scaleX
|
||||
return PointF(
|
||||
(locationOnScreen[0] + viewWidth / 2).toInt().toFloat(),
|
||||
(locationOnScreen[1] + viewHeight / 2).toInt().toFloat()
|
||||
)
|
||||
}
|
||||
|
||||
// https://stackoverflow.com/a/46443628/9126211
|
||||
private fun performPinch(
|
||||
uiController: UiController,
|
||||
startPoint1: PointF,
|
||||
startPoint2: PointF,
|
||||
endPoint1: PointF,
|
||||
endPoint2: PointF,
|
||||
duration: Long
|
||||
) {
|
||||
val eventMinInterval: Long = 10
|
||||
val startTime = SystemClock.uptimeMillis()
|
||||
var eventTime = startTime
|
||||
var event: MotionEvent
|
||||
var eventX1: Float = startPoint1.x
|
||||
var eventY1: Float = startPoint1.y
|
||||
var eventX2: Float = startPoint2.x
|
||||
var eventY2: Float = startPoint2.y
|
||||
// https://stackoverflow.com/a/46443628/9126211
|
||||
private fun performPinch(
|
||||
uiController: UiController,
|
||||
startPoint1: PointF,
|
||||
startPoint2: PointF,
|
||||
endPoint1: PointF,
|
||||
endPoint2: PointF,
|
||||
duration: Long
|
||||
) {
|
||||
val eventMinInterval: Long = 10
|
||||
val startTime = SystemClock.uptimeMillis()
|
||||
var eventTime = startTime
|
||||
var event: MotionEvent
|
||||
var eventX1: Float = startPoint1.x
|
||||
var eventY1: Float = startPoint1.y
|
||||
var eventX2: Float = startPoint2.x
|
||||
var eventY2: Float = startPoint2.y
|
||||
|
||||
// Specify the property for the two touch points
|
||||
val properties = arrayOfNulls<MotionEvent.PointerProperties>(2)
|
||||
val pp1 = MotionEvent.PointerProperties()
|
||||
pp1.id = 0
|
||||
pp1.toolType = MotionEvent.TOOL_TYPE_FINGER
|
||||
val pp2 = MotionEvent.PointerProperties()
|
||||
pp2.id = 1
|
||||
pp2.toolType = MotionEvent.TOOL_TYPE_FINGER
|
||||
// Specify the property for the two touch points
|
||||
val properties = arrayOfNulls<MotionEvent.PointerProperties>(2)
|
||||
val pp1 = MotionEvent.PointerProperties()
|
||||
pp1.id = 0
|
||||
pp1.toolType = MotionEvent.TOOL_TYPE_FINGER
|
||||
val pp2 = MotionEvent.PointerProperties()
|
||||
pp2.id = 1
|
||||
pp2.toolType = MotionEvent.TOOL_TYPE_FINGER
|
||||
|
||||
properties[0] = pp1
|
||||
properties[1] = pp2
|
||||
properties[0] = pp1
|
||||
properties[1] = pp2
|
||||
|
||||
// Specify the coordinations of the two touch points
|
||||
// NOTE: you MUST set the pressure and size value, or it doesn't work
|
||||
val pointerCoords = arrayOfNulls<MotionEvent.PointerCoords>(2)
|
||||
val pc1 = MotionEvent.PointerCoords()
|
||||
pc1.x = eventX1
|
||||
pc1.y = eventY1
|
||||
pc1.pressure = 1f
|
||||
pc1.size = 1f
|
||||
val pc2 = MotionEvent.PointerCoords()
|
||||
pc2.x = eventX2
|
||||
pc2.y = eventY2
|
||||
pc2.pressure = 1f
|
||||
pc2.size = 1f
|
||||
pointerCoords[0] = pc1
|
||||
pointerCoords[1] = pc2
|
||||
// Specify the coordinations of the two touch points
|
||||
// NOTE: you MUST set the pressure and size value, or it doesn't work
|
||||
val pointerCoords = arrayOfNulls<MotionEvent.PointerCoords>(2)
|
||||
val pc1 = MotionEvent.PointerCoords()
|
||||
pc1.x = eventX1
|
||||
pc1.y = eventY1
|
||||
pc1.pressure = 1f
|
||||
pc1.size = 1f
|
||||
val pc2 = MotionEvent.PointerCoords()
|
||||
pc2.x = eventX2
|
||||
pc2.y = eventY2
|
||||
pc2.pressure = 1f
|
||||
pc2.size = 1f
|
||||
pointerCoords[0] = pc1
|
||||
pointerCoords[1] = pc2
|
||||
|
||||
/*
|
||||
* Events sequence of zoom gesture:
|
||||
@@ -162,118 +162,119 @@ object GesturesUiTestUtils {
|
||||
* 6. Send ACTION_UP of one end point
|
||||
*/
|
||||
|
||||
try {
|
||||
// Step 1
|
||||
event = MotionEvent.obtain(
|
||||
startTime, eventTime,
|
||||
MotionEvent.ACTION_DOWN, 1, properties,
|
||||
pointerCoords, 0, 0, 1f, 1f, 0, 0, 0, 0
|
||||
)
|
||||
injectMotionEventToUiController(uiController, event)
|
||||
try {
|
||||
// Step 1
|
||||
event = MotionEvent.obtain(
|
||||
startTime, eventTime,
|
||||
MotionEvent.ACTION_DOWN, 1, properties,
|
||||
pointerCoords, 0, 0, 1f, 1f, 0, 0, 0, 0
|
||||
)
|
||||
injectMotionEventToUiController(uiController, event)
|
||||
|
||||
// Step 2
|
||||
event = MotionEvent.obtain(
|
||||
startTime, eventTime,
|
||||
MotionEvent.ACTION_POINTER_DOWN + (pp2.id shl MotionEvent.ACTION_POINTER_INDEX_SHIFT), 2,
|
||||
properties, pointerCoords, 0, 0, 1f, 1f, 0, 0, 0, 0
|
||||
)
|
||||
injectMotionEventToUiController(uiController, event)
|
||||
// Step 2
|
||||
event = MotionEvent.obtain(
|
||||
startTime, eventTime,
|
||||
MotionEvent.ACTION_POINTER_DOWN + (pp2.id shl MotionEvent.ACTION_POINTER_INDEX_SHIFT), 2,
|
||||
properties, pointerCoords, 0, 0, 1f, 1f, 0, 0, 0, 0
|
||||
)
|
||||
injectMotionEventToUiController(uiController, event)
|
||||
|
||||
// Step 3, 4
|
||||
val moveEventNumber = duration / eventMinInterval
|
||||
// Step 3, 4
|
||||
val moveEventNumber = duration / eventMinInterval
|
||||
|
||||
val stepX1: Float
|
||||
val stepY1: Float
|
||||
val stepX2: Float
|
||||
val stepY2: Float
|
||||
val stepX1: Float
|
||||
val stepY1: Float
|
||||
val stepX2: Float
|
||||
val stepY2: Float
|
||||
|
||||
stepX1 = (endPoint1.x - startPoint1.x) / moveEventNumber
|
||||
stepY1 = (endPoint1.y - startPoint1.y) / moveEventNumber
|
||||
stepX2 = (endPoint2.x - startPoint2.x) / moveEventNumber
|
||||
stepY2 = (endPoint2.y - startPoint2.y) / moveEventNumber
|
||||
stepX1 = (endPoint1.x - startPoint1.x) / moveEventNumber
|
||||
stepY1 = (endPoint1.y - startPoint1.y) / moveEventNumber
|
||||
stepX2 = (endPoint2.x - startPoint2.x) / moveEventNumber
|
||||
stepY2 = (endPoint2.y - startPoint2.y) / moveEventNumber
|
||||
|
||||
for (i in 0 until moveEventNumber) {
|
||||
// Update the move events
|
||||
eventTime += eventMinInterval
|
||||
eventX1 += stepX1
|
||||
eventY1 += stepY1
|
||||
eventX2 += stepX2
|
||||
eventY2 += stepY2
|
||||
for (i in 0 until moveEventNumber) {
|
||||
// Update the move events
|
||||
eventTime += eventMinInterval
|
||||
eventX1 += stepX1
|
||||
eventY1 += stepY1
|
||||
eventX2 += stepX2
|
||||
eventY2 += stepY2
|
||||
|
||||
pc1.x = eventX1
|
||||
pc1.y = eventY1
|
||||
pc2.x = eventX2
|
||||
pc2.y = eventY2
|
||||
|
||||
pointerCoords[0] = pc1
|
||||
pointerCoords[1] = pc2
|
||||
|
||||
event = MotionEvent.obtain(
|
||||
startTime, eventTime,
|
||||
MotionEvent.ACTION_MOVE, 2, properties,
|
||||
pointerCoords, 0, 0, 1f, 1f, 0, 0, 0, 0
|
||||
)
|
||||
injectMotionEventToUiController(uiController, event)
|
||||
}
|
||||
|
||||
// Step 5
|
||||
pc1.x = endPoint1.x
|
||||
pc1.y = endPoint1.y
|
||||
pc2.x = endPoint2.x
|
||||
pc2.y = endPoint2.y
|
||||
pointerCoords[0] = pc1
|
||||
pointerCoords[1] = pc2
|
||||
|
||||
eventTime += eventMinInterval
|
||||
event = MotionEvent.obtain(
|
||||
startTime, eventTime,
|
||||
MotionEvent.ACTION_POINTER_UP + (pp2.id shl MotionEvent.ACTION_POINTER_INDEX_SHIFT), 2, properties,
|
||||
pointerCoords, 0, 0, 1f, 1f, 0, 0, 0, 0
|
||||
)
|
||||
injectMotionEventToUiController(uiController, event)
|
||||
|
||||
// Step 6
|
||||
eventTime += eventMinInterval
|
||||
event = MotionEvent.obtain(
|
||||
startTime, eventTime,
|
||||
MotionEvent.ACTION_UP, 1, properties,
|
||||
pointerCoords, 0, 0, 1f, 1f, 0, 0, 0, 0
|
||||
)
|
||||
injectMotionEventToUiController(uiController, event)
|
||||
} catch (ex: InjectEventSecurityException) {
|
||||
throw RuntimeException("Could not perform pinch", ex)
|
||||
}
|
||||
}
|
||||
|
||||
private fun performQuickScale(
|
||||
uiController: UiController,
|
||||
startPoint: PointF,
|
||||
endPoint: PointF,
|
||||
withVelocity: Boolean,
|
||||
duration: Long,
|
||||
interrupt: Boolean
|
||||
) {
|
||||
val eventMinInterval: Long = 10
|
||||
|
||||
val tapDownMinInterval: Long = 40 // ViewConfiguration#DOUBLE_TAP_MIN_TIME = 40
|
||||
val startTime = SystemClock.uptimeMillis()
|
||||
var eventTime = startTime
|
||||
var event: MotionEvent
|
||||
var eventX1: Float = startPoint.x
|
||||
var eventY1: Float = startPoint.y
|
||||
|
||||
var properties = arrayOfNulls<MotionEvent.PointerProperties>(1)
|
||||
val pp1 = MotionEvent.PointerProperties()
|
||||
pp1.id = 0
|
||||
pp1.toolType = MotionEvent.TOOL_TYPE_FINGER
|
||||
properties[0] = pp1
|
||||
|
||||
var pointerCoords = arrayOfNulls<MotionEvent.PointerCoords>(1)
|
||||
val pc1 = MotionEvent.PointerCoords()
|
||||
pc1.x = eventX1
|
||||
pc1.y = eventY1
|
||||
pc2.x = eventX2
|
||||
pc2.y = eventY2
|
||||
|
||||
pc1.pressure = 1f
|
||||
pc1.size = 1f
|
||||
pointerCoords[0] = pc1
|
||||
pointerCoords[1] = pc2
|
||||
|
||||
event = MotionEvent.obtain(
|
||||
startTime, eventTime,
|
||||
MotionEvent.ACTION_MOVE, 2, properties,
|
||||
pointerCoords, 0, 0, 1f, 1f, 0, 0, 0, 0
|
||||
)
|
||||
injectMotionEventToUiController(uiController, event)
|
||||
}
|
||||
|
||||
// Step 5
|
||||
pc1.x = endPoint1.x
|
||||
pc1.y = endPoint1.y
|
||||
pc2.x = endPoint2.x
|
||||
pc2.y = endPoint2.y
|
||||
pointerCoords[0] = pc1
|
||||
pointerCoords[1] = pc2
|
||||
|
||||
eventTime += eventMinInterval
|
||||
event = MotionEvent.obtain(
|
||||
startTime, eventTime,
|
||||
MotionEvent.ACTION_POINTER_UP + (pp2.id shl MotionEvent.ACTION_POINTER_INDEX_SHIFT), 2, properties,
|
||||
pointerCoords, 0, 0, 1f, 1f, 0, 0, 0, 0
|
||||
)
|
||||
injectMotionEventToUiController(uiController, event)
|
||||
|
||||
// Step 6
|
||||
eventTime += eventMinInterval
|
||||
event = MotionEvent.obtain(
|
||||
startTime, eventTime,
|
||||
MotionEvent.ACTION_UP, 1, properties,
|
||||
pointerCoords, 0, 0, 1f, 1f, 0, 0, 0, 0
|
||||
)
|
||||
injectMotionEventToUiController(uiController, event)
|
||||
} catch (ex: InjectEventSecurityException) {
|
||||
throw RuntimeException("Could not perform pinch", ex)
|
||||
}
|
||||
}
|
||||
|
||||
private fun performQuickScale(
|
||||
uiController: UiController,
|
||||
startPoint: PointF,
|
||||
endPoint: PointF,
|
||||
withVelocity: Boolean,
|
||||
duration: Long,
|
||||
interrupt: Boolean
|
||||
) {
|
||||
val eventMinInterval: Long = 10
|
||||
val tapDownMinInterval: Long = 40 // ViewConfiguration#DOUBLE_TAP_MIN_TIME = 40
|
||||
val startTime = SystemClock.uptimeMillis()
|
||||
var eventTime = startTime
|
||||
var event: MotionEvent
|
||||
var eventX1: Float = startPoint.x
|
||||
var eventY1: Float = startPoint.y
|
||||
|
||||
var properties = arrayOfNulls<MotionEvent.PointerProperties>(1)
|
||||
val pp1 = MotionEvent.PointerProperties()
|
||||
pp1.id = 0
|
||||
pp1.toolType = MotionEvent.TOOL_TYPE_FINGER
|
||||
properties[0] = pp1
|
||||
|
||||
var pointerCoords = arrayOfNulls<MotionEvent.PointerCoords>(1)
|
||||
val pc1 = MotionEvent.PointerCoords()
|
||||
pc1.x = eventX1
|
||||
pc1.y = eventY1
|
||||
pc1.pressure = 1f
|
||||
pc1.size = 1f
|
||||
pointerCoords[0] = pc1
|
||||
|
||||
/*
|
||||
* Events sequence of quick scale gesture:
|
||||
@@ -284,145 +285,145 @@ object GesturesUiTestUtils {
|
||||
* 4. Send ACTION_MOVE with updated middle points (x,y), until reach the end points
|
||||
* 5. Send ACTION_UP of one end point
|
||||
*/
|
||||
try {
|
||||
// Step 1
|
||||
event = MotionEvent.obtain(
|
||||
startTime, eventTime,
|
||||
MotionEvent.ACTION_DOWN, 1, properties,
|
||||
pointerCoords, 0, 0, 1f, 1f, 0, 0, 0, 0
|
||||
)
|
||||
injectMotionEventToUiController(uiController, event)
|
||||
try {
|
||||
// Step 1
|
||||
event = MotionEvent.obtain(
|
||||
startTime, eventTime,
|
||||
MotionEvent.ACTION_DOWN, 1, properties,
|
||||
pointerCoords, 0, 0, 1f, 1f, 0, 0, 0, 0
|
||||
)
|
||||
injectMotionEventToUiController(uiController, event)
|
||||
|
||||
// Step 2
|
||||
eventTime += eventMinInterval
|
||||
event = MotionEvent.obtain(
|
||||
startTime, eventTime,
|
||||
MotionEvent.ACTION_UP, 1, properties,
|
||||
pointerCoords, 0, 0, 1f, 1f, 0, 0, 0, 0
|
||||
)
|
||||
injectMotionEventToUiController(uiController, event)
|
||||
// Step 2
|
||||
eventTime += eventMinInterval
|
||||
event = MotionEvent.obtain(
|
||||
startTime, eventTime,
|
||||
MotionEvent.ACTION_UP, 1, properties,
|
||||
pointerCoords, 0, 0, 1f, 1f, 0, 0, 0, 0
|
||||
)
|
||||
injectMotionEventToUiController(uiController, event)
|
||||
|
||||
// Step 3
|
||||
eventTime += tapDownMinInterval
|
||||
event = MotionEvent.obtain(
|
||||
startTime, eventTime,
|
||||
MotionEvent.ACTION_DOWN, 1, properties,
|
||||
pointerCoords, 0, 0, 1f, 1f, 0, 0, 0, 0
|
||||
)
|
||||
injectMotionEventToUiController(uiController, event)
|
||||
// Step 3
|
||||
eventTime += tapDownMinInterval
|
||||
event = MotionEvent.obtain(
|
||||
startTime, eventTime,
|
||||
MotionEvent.ACTION_DOWN, 1, properties,
|
||||
pointerCoords, 0, 0, 1f, 1f, 0, 0, 0, 0
|
||||
)
|
||||
injectMotionEventToUiController(uiController, event)
|
||||
|
||||
// Step 4
|
||||
val moveEventNumber = duration / eventMinInterval
|
||||
// Step 4
|
||||
val moveEventNumber = duration / eventMinInterval
|
||||
|
||||
val stepX1: Float
|
||||
val stepY1: Float
|
||||
val stepX1: Float
|
||||
val stepY1: Float
|
||||
|
||||
stepX1 = (endPoint.x - startPoint.x) / moveEventNumber
|
||||
stepY1 = (endPoint.y - startPoint.y) / moveEventNumber
|
||||
stepX1 = (endPoint.x - startPoint.x) / moveEventNumber
|
||||
stepY1 = (endPoint.y - startPoint.y) / moveEventNumber
|
||||
|
||||
var interrupted = false
|
||||
var interrupted = false
|
||||
|
||||
for (i in 0 until moveEventNumber) {
|
||||
// Update the move events
|
||||
eventTime += eventMinInterval
|
||||
eventX1 += stepX1
|
||||
eventY1 += stepY1
|
||||
for (i in 0 until moveEventNumber) {
|
||||
// Update the move events
|
||||
eventTime += eventMinInterval
|
||||
eventX1 += stepX1
|
||||
eventY1 += stepY1
|
||||
|
||||
pc1.x = eventX1
|
||||
pc1.y = eventY1
|
||||
|
||||
pointerCoords[0] = pc1
|
||||
|
||||
event = MotionEvent.obtain(
|
||||
startTime, eventTime,
|
||||
MotionEvent.ACTION_MOVE, if (interrupted) 2 else 1, properties,
|
||||
pointerCoords, 0, 0, 1f, 1f, 0, 0, 0, 0
|
||||
)
|
||||
injectMotionEventToUiController(uiController, event)
|
||||
|
||||
if (interrupt && i == moveEventNumber / 2) {
|
||||
// Specify the property for the two touch points
|
||||
properties = arrayOfNulls<MotionEvent.PointerProperties>(2)
|
||||
val pp2 = MotionEvent.PointerProperties()
|
||||
pp2.id = 1
|
||||
pp2.toolType = MotionEvent.TOOL_TYPE_FINGER
|
||||
|
||||
properties[0] = pp1
|
||||
properties[1] = pp2
|
||||
|
||||
// Specify the coordinations of the two touch points
|
||||
// NOTE: you MUST set the pressure and size value, or it doesn't work
|
||||
pointerCoords = arrayOfNulls<MotionEvent.PointerCoords>(2)
|
||||
val pc2 = MotionEvent.PointerCoords()
|
||||
pc2.x = startPoint.x
|
||||
pc2.y = startPoint.y
|
||||
pc2.pressure = 1f
|
||||
pc2.size = 1f
|
||||
pointerCoords[0] = pc1
|
||||
pointerCoords[1] = pc2
|
||||
|
||||
eventTime += eventMinInterval
|
||||
event = MotionEvent.obtain(
|
||||
startTime, eventTime,
|
||||
MotionEvent.ACTION_POINTER_DOWN + (pp2.id shl MotionEvent.ACTION_POINTER_INDEX_SHIFT), 2,
|
||||
properties, pointerCoords, 0, 0, 1f, 1f, 0, 0, 0, 0
|
||||
)
|
||||
injectMotionEventToUiController(uiController, event)
|
||||
interrupted = true
|
||||
}
|
||||
}
|
||||
|
||||
if (!withVelocity) {
|
||||
eventTime += eventMinInterval
|
||||
event = MotionEvent.obtain(
|
||||
startTime, eventTime,
|
||||
MotionEvent.ACTION_MOVE, 1, properties,
|
||||
pointerCoords, 0, 0, 1f, 1f, 0, 0, 0, 0
|
||||
)
|
||||
injectMotionEventToUiController(uiController, event)
|
||||
}
|
||||
|
||||
// Step 5
|
||||
eventTime += eventMinInterval
|
||||
event = MotionEvent.obtain(
|
||||
startTime, eventTime,
|
||||
MotionEvent.ACTION_UP, 1, properties,
|
||||
pointerCoords, 0, 0, 1f, 1f, 0, 0, 0, 0
|
||||
)
|
||||
injectMotionEventToUiController(uiController, event)
|
||||
} catch (ex: InjectEventSecurityException) {
|
||||
throw RuntimeException("Could not perform quick scale", ex)
|
||||
}
|
||||
}
|
||||
|
||||
private fun performMove(
|
||||
uiController: UiController,
|
||||
startPoint: PointF,
|
||||
endPoint: PointF,
|
||||
withVelocity: Boolean,
|
||||
duration: Long
|
||||
) {
|
||||
val eventMinInterval: Long = 10
|
||||
val startTime = SystemClock.uptimeMillis()
|
||||
var eventTime = startTime
|
||||
var event: MotionEvent
|
||||
var eventX1: Float = startPoint.x
|
||||
var eventY1: Float = startPoint.y
|
||||
|
||||
val properties = arrayOfNulls<MotionEvent.PointerProperties>(1)
|
||||
val pp1 = MotionEvent.PointerProperties()
|
||||
pp1.id = 0
|
||||
pp1.toolType = MotionEvent.TOOL_TYPE_FINGER
|
||||
properties[0] = pp1
|
||||
|
||||
val pointerCoords = arrayOfNulls<MotionEvent.PointerCoords>(1)
|
||||
val pc1 = MotionEvent.PointerCoords()
|
||||
pc1.x = eventX1
|
||||
pc1.y = eventY1
|
||||
|
||||
pc1.pressure = 1f
|
||||
pc1.size = 1f
|
||||
pointerCoords[0] = pc1
|
||||
|
||||
event = MotionEvent.obtain(
|
||||
startTime, eventTime,
|
||||
MotionEvent.ACTION_MOVE, if (interrupted) 2 else 1, properties,
|
||||
pointerCoords, 0, 0, 1f, 1f, 0, 0, 0, 0
|
||||
)
|
||||
injectMotionEventToUiController(uiController, event)
|
||||
|
||||
if (interrupt && i == moveEventNumber / 2) {
|
||||
// Specify the property for the two touch points
|
||||
properties = arrayOfNulls<MotionEvent.PointerProperties>(2)
|
||||
val pp2 = MotionEvent.PointerProperties()
|
||||
pp2.id = 1
|
||||
pp2.toolType = MotionEvent.TOOL_TYPE_FINGER
|
||||
|
||||
properties[0] = pp1
|
||||
properties[1] = pp2
|
||||
|
||||
// Specify the coordinations of the two touch points
|
||||
// NOTE: you MUST set the pressure and size value, or it doesn't work
|
||||
pointerCoords = arrayOfNulls<MotionEvent.PointerCoords>(2)
|
||||
val pc2 = MotionEvent.PointerCoords()
|
||||
pc2.x = startPoint.x
|
||||
pc2.y = startPoint.y
|
||||
pc2.pressure = 1f
|
||||
pc2.size = 1f
|
||||
pointerCoords[0] = pc1
|
||||
pointerCoords[1] = pc2
|
||||
|
||||
eventTime += eventMinInterval
|
||||
event = MotionEvent.obtain(
|
||||
startTime, eventTime,
|
||||
MotionEvent.ACTION_POINTER_DOWN + (pp2.id shl MotionEvent.ACTION_POINTER_INDEX_SHIFT), 2,
|
||||
properties, pointerCoords, 0, 0, 1f, 1f, 0, 0, 0, 0
|
||||
)
|
||||
injectMotionEventToUiController(uiController, event)
|
||||
interrupted = true
|
||||
}
|
||||
}
|
||||
|
||||
if (!withVelocity) {
|
||||
eventTime += eventMinInterval
|
||||
event = MotionEvent.obtain(
|
||||
startTime, eventTime,
|
||||
MotionEvent.ACTION_MOVE, 1, properties,
|
||||
pointerCoords, 0, 0, 1f, 1f, 0, 0, 0, 0
|
||||
)
|
||||
injectMotionEventToUiController(uiController, event)
|
||||
}
|
||||
|
||||
// Step 5
|
||||
eventTime += eventMinInterval
|
||||
event = MotionEvent.obtain(
|
||||
startTime, eventTime,
|
||||
MotionEvent.ACTION_UP, 1, properties,
|
||||
pointerCoords, 0, 0, 1f, 1f, 0, 0, 0, 0
|
||||
)
|
||||
injectMotionEventToUiController(uiController, event)
|
||||
} catch (ex: InjectEventSecurityException) {
|
||||
throw RuntimeException("Could not perform quick scale", ex)
|
||||
}
|
||||
}
|
||||
|
||||
private fun performMove(
|
||||
uiController: UiController,
|
||||
startPoint: PointF,
|
||||
endPoint: PointF,
|
||||
withVelocity: Boolean,
|
||||
duration: Long
|
||||
) {
|
||||
val eventMinInterval: Long = 10
|
||||
val startTime = SystemClock.uptimeMillis()
|
||||
var eventTime = startTime
|
||||
var event: MotionEvent
|
||||
var eventX1: Float = startPoint.x
|
||||
var eventY1: Float = startPoint.y
|
||||
|
||||
val properties = arrayOfNulls<MotionEvent.PointerProperties>(1)
|
||||
val pp1 = MotionEvent.PointerProperties()
|
||||
pp1.id = 0
|
||||
pp1.toolType = MotionEvent.TOOL_TYPE_FINGER
|
||||
properties[0] = pp1
|
||||
|
||||
val pointerCoords = arrayOfNulls<MotionEvent.PointerCoords>(1)
|
||||
val pc1 = MotionEvent.PointerCoords()
|
||||
pc1.x = eventX1
|
||||
pc1.y = eventY1
|
||||
pc1.pressure = 1f
|
||||
pc1.size = 1f
|
||||
pointerCoords[0] = pc1
|
||||
|
||||
/*
|
||||
* Events sequence of move gesture:
|
||||
*
|
||||
@@ -430,87 +431,87 @@ object GesturesUiTestUtils {
|
||||
* 2. Send ACTION_MOVE with updated middle points (x,y), until reach the end points
|
||||
* 3. Send ACTION_UP
|
||||
*/
|
||||
try {
|
||||
// Step 1
|
||||
event = MotionEvent.obtain(
|
||||
startTime, eventTime,
|
||||
MotionEvent.ACTION_DOWN, 1, properties,
|
||||
pointerCoords, 0, 0, 1f, 1f, 0, 0, 0, 0
|
||||
)
|
||||
injectMotionEventToUiController(uiController, event)
|
||||
try {
|
||||
// Step 1
|
||||
event = MotionEvent.obtain(
|
||||
startTime, eventTime,
|
||||
MotionEvent.ACTION_DOWN, 1, properties,
|
||||
pointerCoords, 0, 0, 1f, 1f, 0, 0, 0, 0
|
||||
)
|
||||
injectMotionEventToUiController(uiController, event)
|
||||
|
||||
// Step 2
|
||||
val moveEventNumber = duration / eventMinInterval
|
||||
// Step 2
|
||||
val moveEventNumber = duration / eventMinInterval
|
||||
|
||||
val stepX1: Float
|
||||
val stepY1: Float
|
||||
val stepX1: Float
|
||||
val stepY1: Float
|
||||
|
||||
stepX1 = (endPoint.x - startPoint.x) / moveEventNumber
|
||||
stepY1 = (endPoint.y - startPoint.y) / moveEventNumber
|
||||
stepX1 = (endPoint.x - startPoint.x) / moveEventNumber
|
||||
stepY1 = (endPoint.y - startPoint.y) / moveEventNumber
|
||||
|
||||
for (i in 0 until moveEventNumber) {
|
||||
// Update the move events
|
||||
eventTime += eventMinInterval
|
||||
eventX1 += stepX1
|
||||
eventY1 += stepY1
|
||||
for (i in 0 until moveEventNumber) {
|
||||
// Update the move events
|
||||
eventTime += eventMinInterval
|
||||
eventX1 += stepX1
|
||||
eventY1 += stepY1
|
||||
|
||||
pc1.x = eventX1
|
||||
pc1.y = eventY1
|
||||
pc1.x = eventX1
|
||||
pc1.y = eventY1
|
||||
|
||||
pointerCoords[0] = pc1
|
||||
pointerCoords[0] = pc1
|
||||
|
||||
event = MotionEvent.obtain(
|
||||
startTime, eventTime,
|
||||
MotionEvent.ACTION_MOVE, 1, properties,
|
||||
pointerCoords, 0, 0, 1f, 1f, 0, 0, 0, 0
|
||||
)
|
||||
injectMotionEventToUiController(uiController, event)
|
||||
}
|
||||
event = MotionEvent.obtain(
|
||||
startTime, eventTime,
|
||||
MotionEvent.ACTION_MOVE, 1, properties,
|
||||
pointerCoords, 0, 0, 1f, 1f, 0, 0, 0, 0
|
||||
)
|
||||
injectMotionEventToUiController(uiController, event)
|
||||
}
|
||||
|
||||
if (!withVelocity) {
|
||||
eventTime += eventMinInterval
|
||||
event = MotionEvent.obtain(
|
||||
startTime, eventTime,
|
||||
MotionEvent.ACTION_MOVE, 1, properties,
|
||||
pointerCoords, 0, 0, 1f, 1f, 0, 0, 0, 0
|
||||
)
|
||||
injectMotionEventToUiController(uiController, event)
|
||||
}
|
||||
if (!withVelocity) {
|
||||
eventTime += eventMinInterval
|
||||
event = MotionEvent.obtain(
|
||||
startTime, eventTime,
|
||||
MotionEvent.ACTION_MOVE, 1, properties,
|
||||
pointerCoords, 0, 0, 1f, 1f, 0, 0, 0, 0
|
||||
)
|
||||
injectMotionEventToUiController(uiController, event)
|
||||
}
|
||||
|
||||
// Step 3
|
||||
eventTime += eventMinInterval
|
||||
event = MotionEvent.obtain(
|
||||
startTime, eventTime,
|
||||
MotionEvent.ACTION_UP, 1, properties,
|
||||
pointerCoords, 0, 0, 1f, 1f, 0, 0, 0, 0
|
||||
)
|
||||
injectMotionEventToUiController(uiController, event)
|
||||
} catch (ex: InjectEventSecurityException) {
|
||||
throw RuntimeException("Could not perform quick scale", ex)
|
||||
// Step 3
|
||||
eventTime += eventMinInterval
|
||||
event = MotionEvent.obtain(
|
||||
startTime, eventTime,
|
||||
MotionEvent.ACTION_UP, 1, properties,
|
||||
pointerCoords, 0, 0, 1f, 1f, 0, 0, 0, 0
|
||||
)
|
||||
injectMotionEventToUiController(uiController, event)
|
||||
} catch (ex: InjectEventSecurityException) {
|
||||
throw RuntimeException("Could not perform quick scale", ex)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Safely call uiController.injectMotionEvent(event): Detect any error and "convert" it to an
|
||||
* IllegalStateException
|
||||
*/
|
||||
@Throws(InjectEventSecurityException::class)
|
||||
private fun injectMotionEventToUiController(uiController: UiController, event: MotionEvent) {
|
||||
val injectEventSucceeded = uiController.injectMotionEvent(event)
|
||||
if (!injectEventSucceeded) {
|
||||
throw IllegalStateException("Error performing event $event")
|
||||
/**
|
||||
* Safely call uiController.injectMotionEvent(event): Detect any error and "convert" it to an
|
||||
* IllegalStateException
|
||||
*/
|
||||
@Throws(InjectEventSecurityException::class)
|
||||
private fun injectMotionEventToUiController(uiController: UiController, event: MotionEvent) {
|
||||
val injectEventSucceeded = uiController.injectMotionEvent(event)
|
||||
if (!injectEventSucceeded) {
|
||||
throw IllegalStateException("Error performing event $event")
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fun Int.loopFor(millis: Long) {
|
||||
Espresso.onView(ViewMatchers.withId(this)).perform(object : ViewAction {
|
||||
override fun getDescription(): String = "waiting for $millis"
|
||||
Espresso.onView(ViewMatchers.withId(this)).perform(object : ViewAction {
|
||||
override fun getDescription(): String = "waiting for $millis"
|
||||
|
||||
override fun getConstraints(): Matcher<View> = ViewMatchers.isEnabled()
|
||||
override fun getConstraints(): Matcher<View> = ViewMatchers.isEnabled()
|
||||
|
||||
override fun perform(uiController: UiController?, view: View?) {
|
||||
uiController?.loopMainThreadForAtLeast(millis)
|
||||
}
|
||||
})
|
||||
}
|
||||
override fun perform(uiController: UiController?, view: View?) {
|
||||
uiController?.loopMainThreadForAtLeast(millis)
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
@@ -16,178 +16,178 @@ import org.junit.Before
|
||||
import org.junit.Test
|
||||
|
||||
class MapGestureDetectorTest : BaseTest() {
|
||||
override fun getActivityClass() = SimpleMapActivity::class.java
|
||||
override fun getActivityClass() = SimpleMapActivity::class.java
|
||||
|
||||
private var maxWidth: Int = 0
|
||||
private var maxHeight: Int = 0
|
||||
private var maxWidth: Int = 0
|
||||
private var maxHeight: Int = 0
|
||||
|
||||
@Before
|
||||
fun setup() {
|
||||
maxWidth = mapView.width
|
||||
maxHeight = mapView.height
|
||||
}
|
||||
|
||||
@Test
|
||||
fun sanity_quickZoom() {
|
||||
validateTestSetup()
|
||||
var initialZoom: Double? = null
|
||||
rule.runOnUiThread {
|
||||
initialZoom = mapboxMap.cameraPosition.zoom
|
||||
}
|
||||
onView(withId(R.id.mapView)).perform(quickScale(maxHeight / 2f, withVelocity = false))
|
||||
rule.runOnUiThread {
|
||||
Assert.assertTrue(mapboxMap.cameraPosition.zoom > initialZoom!!)
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
fun quickZoomDisabled_phantomQuickZoom_moveStillEnabled_15091() {
|
||||
// regression test for https://github.com/mapbox/mapbox-gl-native/issues/15091
|
||||
validateTestSetup()
|
||||
var initialCameraPosition: CameraPosition? = null
|
||||
rule.runOnUiThread {
|
||||
// zoom in so we can move vertically
|
||||
mapboxMap.moveCamera(CameraUpdateFactory.zoomTo(4.0))
|
||||
initialCameraPosition = mapboxMap.cameraPosition
|
||||
mapboxMap.uiSettings.isQuickZoomGesturesEnabled = false
|
||||
@Before
|
||||
fun setup() {
|
||||
maxWidth = mapView.width
|
||||
maxHeight = mapView.height
|
||||
}
|
||||
|
||||
onView(withId(R.id.mapView)).perform(quickScale(maxHeight / 2f))
|
||||
rule.runOnUiThread {
|
||||
// camera did not move
|
||||
Assert.assertEquals(initialCameraPosition!!, mapboxMap.cameraPosition)
|
||||
@Test
|
||||
fun sanity_quickZoom() {
|
||||
validateTestSetup()
|
||||
var initialZoom: Double? = null
|
||||
rule.runOnUiThread {
|
||||
initialZoom = mapboxMap.cameraPosition.zoom
|
||||
}
|
||||
onView(withId(R.id.mapView)).perform(quickScale(maxHeight / 2f, withVelocity = false))
|
||||
rule.runOnUiThread {
|
||||
Assert.assertTrue(mapboxMap.cameraPosition.zoom > initialZoom!!)
|
||||
}
|
||||
}
|
||||
|
||||
// move to expected target
|
||||
onView(withId(R.id.mapView)).perform(move(-maxWidth / 2f, -maxHeight / 2f, withVelocity = false))
|
||||
rule.runOnUiThread {
|
||||
Assert.assertNotEquals(initialCameraPosition!!.target.latitude, mapboxMap.cameraPosition.target.latitude, 1.0)
|
||||
Assert.assertNotEquals(initialCameraPosition!!.target.longitude, mapboxMap.cameraPosition.target.longitude, 1.0)
|
||||
}
|
||||
}
|
||||
@Test
|
||||
fun quickZoomDisabled_phantomQuickZoom_moveStillEnabled_15091() {
|
||||
// regression test for https://github.com/mapbox/mapbox-gl-native/issues/15091
|
||||
validateTestSetup()
|
||||
var initialCameraPosition: CameraPosition? = null
|
||||
rule.runOnUiThread {
|
||||
// zoom in so we can move vertically
|
||||
mapboxMap.moveCamera(CameraUpdateFactory.zoomTo(4.0))
|
||||
initialCameraPosition = mapboxMap.cameraPosition
|
||||
mapboxMap.uiSettings.isQuickZoomGesturesEnabled = false
|
||||
}
|
||||
|
||||
@Test
|
||||
fun quickZoom_doNotMove_14227() {
|
||||
// test for https://github.com/mapbox/mapbox-gl-native/issues/14227
|
||||
validateTestSetup()
|
||||
var initialTarget: LatLng? = null
|
||||
rule.runOnUiThread {
|
||||
initialTarget = mapboxMap.cameraPosition.target
|
||||
onView(withId(R.id.mapView)).perform(quickScale(maxHeight / 2f))
|
||||
rule.runOnUiThread {
|
||||
// camera did not move
|
||||
Assert.assertEquals(initialCameraPosition!!, mapboxMap.cameraPosition)
|
||||
}
|
||||
|
||||
// move to expected target
|
||||
onView(withId(R.id.mapView)).perform(move(-maxWidth / 2f, -maxHeight / 2f, withVelocity = false))
|
||||
rule.runOnUiThread {
|
||||
Assert.assertNotEquals(initialCameraPosition!!.target.latitude, mapboxMap.cameraPosition.target.latitude, 1.0)
|
||||
Assert.assertNotEquals(initialCameraPosition!!.target.longitude, mapboxMap.cameraPosition.target.longitude, 1.0)
|
||||
}
|
||||
}
|
||||
|
||||
onView(withId(R.id.mapView)).perform(quickScale(maxHeight / 2f))
|
||||
rule.runOnUiThread {
|
||||
// camera did not move
|
||||
Assert.assertEquals(initialTarget!!.latitude, mapboxMap.cameraPosition.target.latitude, 1.0)
|
||||
Assert.assertEquals(initialTarget!!.longitude, mapboxMap.cameraPosition.target.longitude, 1.0)
|
||||
}
|
||||
}
|
||||
@Test
|
||||
fun quickZoom_doNotMove_14227() {
|
||||
// test for https://github.com/mapbox/mapbox-gl-native/issues/14227
|
||||
validateTestSetup()
|
||||
var initialTarget: LatLng? = null
|
||||
rule.runOnUiThread {
|
||||
initialTarget = mapboxMap.cameraPosition.target
|
||||
}
|
||||
|
||||
@Test
|
||||
fun quickZoom_interrupted_moveStillEnabled_14598() {
|
||||
// test for https://github.com/mapbox/mapbox-gl-native/issues/14598
|
||||
validateTestSetup()
|
||||
onView(withId(R.id.mapView)).perform(quickScale(maxHeight / 2f, interrupt = true))
|
||||
|
||||
var initialCameraPosition: CameraPosition? = null
|
||||
rule.runOnUiThread {
|
||||
// zoom in so we can move vertically
|
||||
mapboxMap.moveCamera(CameraUpdateFactory.zoomTo(4.0))
|
||||
initialCameraPosition = mapboxMap.cameraPosition
|
||||
mapboxMap.uiSettings.isQuickZoomGesturesEnabled = false
|
||||
onView(withId(R.id.mapView)).perform(quickScale(maxHeight / 2f))
|
||||
rule.runOnUiThread {
|
||||
// camera did not move
|
||||
Assert.assertEquals(initialTarget!!.latitude, mapboxMap.cameraPosition.target.latitude, 1.0)
|
||||
Assert.assertEquals(initialTarget!!.longitude, mapboxMap.cameraPosition.target.longitude, 1.0)
|
||||
}
|
||||
}
|
||||
|
||||
// move to expected target
|
||||
onView(withId(R.id.mapView)).perform(move(-maxWidth / 2f, -maxHeight / 2f, withVelocity = false))
|
||||
rule.runOnUiThread {
|
||||
Assert.assertNotEquals(initialCameraPosition!!.target.latitude, mapboxMap.cameraPosition.target.latitude, 1.0)
|
||||
Assert.assertNotEquals(initialCameraPosition!!.target.longitude, mapboxMap.cameraPosition.target.longitude, 1.0)
|
||||
}
|
||||
}
|
||||
@Test
|
||||
fun quickZoom_interrupted_moveStillEnabled_14598() {
|
||||
// test for https://github.com/mapbox/mapbox-gl-native/issues/14598
|
||||
validateTestSetup()
|
||||
onView(withId(R.id.mapView)).perform(quickScale(maxHeight / 2f, interrupt = true))
|
||||
|
||||
@Test
|
||||
fun quickZoom_ignoreDoubleTap() {
|
||||
// test for https://github.com/mapbox/mapbox-gl-native/issues/14013
|
||||
validateTestSetup()
|
||||
var initialZoom: Double? = null
|
||||
rule.runOnUiThread {
|
||||
mapboxMap.moveCamera(CameraUpdateFactory.zoomTo(2.0))
|
||||
initialZoom = mapboxMap.cameraPosition.zoom
|
||||
}
|
||||
onView(withId(R.id.mapView)).perform(quickScale(-(mapboxMap.gesturesManager.standardScaleGestureDetector.spanSinceStartThreshold * 2), withVelocity = false, duration = 1000L))
|
||||
R.id.mapView.loopFor(MapboxConstants.ANIMATION_DURATION.toLong())
|
||||
rule.runOnUiThread {
|
||||
Assert.assertTrue(mapboxMap.cameraPosition.zoom < initialZoom!!)
|
||||
}
|
||||
}
|
||||
var initialCameraPosition: CameraPosition? = null
|
||||
rule.runOnUiThread {
|
||||
// zoom in so we can move vertically
|
||||
mapboxMap.moveCamera(CameraUpdateFactory.zoomTo(4.0))
|
||||
initialCameraPosition = mapboxMap.cameraPosition
|
||||
mapboxMap.uiSettings.isQuickZoomGesturesEnabled = false
|
||||
}
|
||||
|
||||
@Test
|
||||
fun doubleTap_minimalMovement() {
|
||||
validateTestSetup()
|
||||
var initialZoom: Double? = null
|
||||
rule.runOnUiThread {
|
||||
initialZoom = mapboxMap.cameraPosition.zoom
|
||||
}
|
||||
onView(withId(R.id.mapView)).perform(quickScale(mapboxMap.gesturesManager.standardScaleGestureDetector.spanSinceStartThreshold / 2, withVelocity = false, duration = 50L))
|
||||
R.id.mapView.loopFor(MapboxConstants.ANIMATION_DURATION.toLong())
|
||||
rule.runOnUiThread {
|
||||
Assert.assertEquals(initialZoom!! + 1, mapboxMap.cameraPosition.zoom, 0.1)
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
fun doubleTap_overMaxThreshold_ignore_14013() {
|
||||
// test for https://github.com/mapbox/mapbox-gl-native/issues/14013
|
||||
validateTestSetup()
|
||||
var initialZoom: Double? = null
|
||||
rule.runOnUiThread {
|
||||
initialZoom = mapboxMap.cameraPosition.zoom
|
||||
mapboxMap.uiSettings.isQuickZoomGesturesEnabled = false
|
||||
}
|
||||
onView(withId(R.id.mapView)).perform(quickScale(mapboxMap.gesturesManager.standardScaleGestureDetector.spanSinceStartThreshold * 2, withVelocity = false, duration = 50L))
|
||||
R.id.mapView.loopFor(MapboxConstants.ANIMATION_DURATION.toLong())
|
||||
rule.runOnUiThread {
|
||||
Assert.assertEquals(initialZoom!!, mapboxMap.cameraPosition.zoom, 0.01)
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
fun doubleTap_interrupted_moveStillEnabled() {
|
||||
validateTestSetup()
|
||||
|
||||
rule.runOnUiThread {
|
||||
mapboxMap.moveCamera(CameraUpdateFactory.zoomTo(4.0))
|
||||
// move to expected target
|
||||
onView(withId(R.id.mapView)).perform(move(-maxWidth / 2f, -maxHeight / 2f, withVelocity = false))
|
||||
rule.runOnUiThread {
|
||||
Assert.assertNotEquals(initialCameraPosition!!.target.latitude, mapboxMap.cameraPosition.target.latitude, 1.0)
|
||||
Assert.assertNotEquals(initialCameraPosition!!.target.longitude, mapboxMap.cameraPosition.target.longitude, 1.0)
|
||||
}
|
||||
}
|
||||
|
||||
onView(withId(R.id.mapView)).perform(quickScale(mapboxMap.gesturesManager.standardScaleGestureDetector.spanSinceStartThreshold / 2, withVelocity = false, duration = 50L, interrupt = true))
|
||||
|
||||
var initialCameraPosition: CameraPosition? = null
|
||||
rule.runOnUiThread {
|
||||
// zoom in so we can move vertically
|
||||
mapboxMap.moveCamera(CameraUpdateFactory.zoomTo(4.0))
|
||||
initialCameraPosition = mapboxMap.cameraPosition
|
||||
mapboxMap.uiSettings.isQuickZoomGesturesEnabled = false
|
||||
@Test
|
||||
fun quickZoom_ignoreDoubleTap() {
|
||||
// test for https://github.com/mapbox/mapbox-gl-native/issues/14013
|
||||
validateTestSetup()
|
||||
var initialZoom: Double? = null
|
||||
rule.runOnUiThread {
|
||||
mapboxMap.moveCamera(CameraUpdateFactory.zoomTo(2.0))
|
||||
initialZoom = mapboxMap.cameraPosition.zoom
|
||||
}
|
||||
onView(withId(R.id.mapView)).perform(quickScale(-(mapboxMap.gesturesManager.standardScaleGestureDetector.spanSinceStartThreshold * 2), withVelocity = false, duration = 1000L))
|
||||
R.id.mapView.loopFor(MapboxConstants.ANIMATION_DURATION.toLong())
|
||||
rule.runOnUiThread {
|
||||
Assert.assertTrue(mapboxMap.cameraPosition.zoom < initialZoom!!)
|
||||
}
|
||||
}
|
||||
|
||||
// move to expected target
|
||||
onView(withId(R.id.mapView)).perform(move(-maxWidth / 2f, -maxHeight / 2f, withVelocity = false))
|
||||
rule.runOnUiThread {
|
||||
Assert.assertNotEquals(initialCameraPosition!!.target.latitude, mapboxMap.cameraPosition.target.latitude, 1.0)
|
||||
Assert.assertNotEquals(initialCameraPosition!!.target.longitude, mapboxMap.cameraPosition.target.longitude, 1.0)
|
||||
@Test
|
||||
fun doubleTap_minimalMovement() {
|
||||
validateTestSetup()
|
||||
var initialZoom: Double? = null
|
||||
rule.runOnUiThread {
|
||||
initialZoom = mapboxMap.cameraPosition.zoom
|
||||
}
|
||||
onView(withId(R.id.mapView)).perform(quickScale(mapboxMap.gesturesManager.standardScaleGestureDetector.spanSinceStartThreshold / 2, withVelocity = false, duration = 50L))
|
||||
R.id.mapView.loopFor(MapboxConstants.ANIMATION_DURATION.toLong())
|
||||
rule.runOnUiThread {
|
||||
Assert.assertEquals(initialZoom!! + 1, mapboxMap.cameraPosition.zoom, 0.1)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
fun quickZoom_roundTripping() {
|
||||
validateTestSetup()
|
||||
rule.runOnUiThread {
|
||||
mapboxMap.moveCamera(CameraUpdateFactory.newLatLngZoom(LatLng(51.0, 16.0), 3.0))
|
||||
@Test
|
||||
fun doubleTap_overMaxThreshold_ignore_14013() {
|
||||
// test for https://github.com/mapbox/mapbox-gl-native/issues/14013
|
||||
validateTestSetup()
|
||||
var initialZoom: Double? = null
|
||||
rule.runOnUiThread {
|
||||
initialZoom = mapboxMap.cameraPosition.zoom
|
||||
mapboxMap.uiSettings.isQuickZoomGesturesEnabled = false
|
||||
}
|
||||
onView(withId(R.id.mapView)).perform(quickScale(mapboxMap.gesturesManager.standardScaleGestureDetector.spanSinceStartThreshold * 2, withVelocity = false, duration = 50L))
|
||||
R.id.mapView.loopFor(MapboxConstants.ANIMATION_DURATION.toLong())
|
||||
rule.runOnUiThread {
|
||||
Assert.assertEquals(initialZoom!!, mapboxMap.cameraPosition.zoom, 0.01)
|
||||
}
|
||||
}
|
||||
onView(withId(R.id.mapView)).perform(quickScale(300f, withVelocity = false, duration = 750L))
|
||||
onView(withId(R.id.mapView)).perform(quickScale(-300f, withVelocity = false, duration = 750L))
|
||||
|
||||
rule.runOnUiThread {
|
||||
Assert.assertEquals(3.0, mapboxMap.cameraPosition.zoom, 0.0001)
|
||||
@Test
|
||||
fun doubleTap_interrupted_moveStillEnabled() {
|
||||
validateTestSetup()
|
||||
|
||||
rule.runOnUiThread {
|
||||
mapboxMap.moveCamera(CameraUpdateFactory.zoomTo(4.0))
|
||||
}
|
||||
|
||||
onView(withId(R.id.mapView)).perform(quickScale(mapboxMap.gesturesManager.standardScaleGestureDetector.spanSinceStartThreshold / 2, withVelocity = false, duration = 50L, interrupt = true))
|
||||
|
||||
var initialCameraPosition: CameraPosition? = null
|
||||
rule.runOnUiThread {
|
||||
// zoom in so we can move vertically
|
||||
mapboxMap.moveCamera(CameraUpdateFactory.zoomTo(4.0))
|
||||
initialCameraPosition = mapboxMap.cameraPosition
|
||||
mapboxMap.uiSettings.isQuickZoomGesturesEnabled = false
|
||||
}
|
||||
|
||||
// move to expected target
|
||||
onView(withId(R.id.mapView)).perform(move(-maxWidth / 2f, -maxHeight / 2f, withVelocity = false))
|
||||
rule.runOnUiThread {
|
||||
Assert.assertNotEquals(initialCameraPosition!!.target.latitude, mapboxMap.cameraPosition.target.latitude, 1.0)
|
||||
Assert.assertNotEquals(initialCameraPosition!!.target.longitude, mapboxMap.cameraPosition.target.longitude, 1.0)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
fun quickZoom_roundTripping() {
|
||||
validateTestSetup()
|
||||
rule.runOnUiThread {
|
||||
mapboxMap.moveCamera(CameraUpdateFactory.newLatLngZoom(LatLng(51.0, 16.0), 3.0))
|
||||
}
|
||||
onView(withId(R.id.mapView)).perform(quickScale(300f, withVelocity = false, duration = 750L))
|
||||
onView(withId(R.id.mapView)).perform(quickScale(-300f, withVelocity = false, duration = 750L))
|
||||
|
||||
rule.runOnUiThread {
|
||||
Assert.assertEquals(3.0, mapboxMap.cameraPosition.zoom, 0.0001)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -155,12 +155,12 @@ class NativeMapViewTest : AppCenter() {
|
||||
@UiThreadTest
|
||||
fun testJumpTo() {
|
||||
val expected = CameraPosition.Builder()
|
||||
.bearing(BEARING_TEST)
|
||||
.target(LATLNG_TEST)
|
||||
.tilt(PITCH_TEST)
|
||||
.zoom(ZOOM_TEST)
|
||||
.padding(PADDING_TEST)
|
||||
.build()
|
||||
.bearing(BEARING_TEST)
|
||||
.target(LATLNG_TEST)
|
||||
.tilt(PITCH_TEST)
|
||||
.zoom(ZOOM_TEST)
|
||||
.padding(PADDING_TEST)
|
||||
.build()
|
||||
// verify that the lazily set padding is ignored when a value is provided with the camera
|
||||
nativeMapView.contentPadding = doubleArrayOf(1.0, 2.0, 3.0, 4.0)
|
||||
nativeMapView.jumpTo(LATLNG_TEST, ZOOM_TEST, PITCH_TEST, BEARING_TEST, PADDING_TEST)
|
||||
@@ -179,7 +179,7 @@ class NativeMapViewTest : AppCenter() {
|
||||
val expected = LATLNG_TEST
|
||||
nativeMapView.setLatLng(LATLNG_TEST, 0)
|
||||
val actual = nativeMapView.latLngForPixel(
|
||||
PointF((WIDTH / 2).toFloat(), (HEIGHT / 2).toFloat())
|
||||
PointF((WIDTH / 2).toFloat(), (HEIGHT / 2).toFloat())
|
||||
)
|
||||
assertEquals("Latitude should match", expected.latitude, actual.latitude, DELTA_BIG)
|
||||
assertEquals("Longitude should match", expected.longitude, actual.longitude, DELTA_BIG)
|
||||
@@ -224,18 +224,18 @@ class NativeMapViewTest : AppCenter() {
|
||||
@Test
|
||||
@UiThreadTest
|
||||
fun testPrefetchZoomDelta() {
|
||||
val expected = 2
|
||||
nativeMapView.prefetchZoomDelta = 2
|
||||
val actual = nativeMapView.prefetchZoomDelta
|
||||
assertEquals("Prefetch zoom delta should match", expected, actual)
|
||||
val expected = 2
|
||||
nativeMapView.prefetchZoomDelta = 2
|
||||
val actual = nativeMapView.prefetchZoomDelta
|
||||
assertEquals("Prefetch zoom delta should match", expected, actual)
|
||||
}
|
||||
|
||||
@Test
|
||||
@UiThreadTest
|
||||
fun testPrefetchZoomDeltaDefault() {
|
||||
val expected = 4
|
||||
val actual = nativeMapView.prefetchZoomDelta
|
||||
assertEquals("Prefetch zoom delta should match", expected, actual)
|
||||
val expected = 4
|
||||
val actual = nativeMapView.prefetchZoomDelta
|
||||
assertEquals("Prefetch zoom delta should match", expected, actual)
|
||||
}
|
||||
|
||||
@Test
|
||||
@@ -268,23 +268,23 @@ class NativeMapViewTest : AppCenter() {
|
||||
assertEquals("Max zoom should match", expected, actual)
|
||||
}
|
||||
|
||||
@Test
|
||||
@UiThreadTest
|
||||
fun testSetMinPitch() {
|
||||
val expected = 60.0
|
||||
nativeMapView.minPitch = expected
|
||||
val actual = nativeMapView.minPitch
|
||||
assertEquals("Min Pitch should match", expected, actual, 0.01)
|
||||
}
|
||||
@Test
|
||||
@UiThreadTest
|
||||
fun testSetMinPitch() {
|
||||
val expected = 60.0
|
||||
nativeMapView.minPitch = expected
|
||||
val actual = nativeMapView.minPitch
|
||||
assertEquals("Min Pitch should match", expected, actual, 0.01)
|
||||
}
|
||||
|
||||
@Test
|
||||
@UiThreadTest
|
||||
fun testSetMaxPitch() {
|
||||
val expected = 60.0
|
||||
nativeMapView.maxPitch = expected
|
||||
val actual = nativeMapView.maxPitch
|
||||
assertEquals("Max Pitch should match", expected, actual, 0.01)
|
||||
}
|
||||
@Test
|
||||
@UiThreadTest
|
||||
fun testSetMaxPitch() {
|
||||
val expected = 60.0
|
||||
nativeMapView.maxPitch = expected
|
||||
val actual = nativeMapView.maxPitch
|
||||
assertEquals("Max Pitch should match", expected, actual, 0.01)
|
||||
}
|
||||
|
||||
@Test
|
||||
@UiThreadTest
|
||||
@@ -307,12 +307,12 @@ class NativeMapViewTest : AppCenter() {
|
||||
@UiThreadTest
|
||||
fun testFlyTo() {
|
||||
val expected = CameraPosition.Builder()
|
||||
.zoom(12.0)
|
||||
.tilt(30.0)
|
||||
.target(LatLng(12.0, 14.0))
|
||||
.bearing(20.0)
|
||||
.padding(PADDING_TEST)
|
||||
.build()
|
||||
.zoom(12.0)
|
||||
.tilt(30.0)
|
||||
.target(LatLng(12.0, 14.0))
|
||||
.bearing(20.0)
|
||||
.padding(PADDING_TEST)
|
||||
.build()
|
||||
// verify that the lazily set padding is ignored when a value is provided with the camera
|
||||
nativeMapView.contentPadding = doubleArrayOf(1.0, 2.0, 3.0, 4.0)
|
||||
nativeMapView.flyTo(expected.target, expected.zoom, expected.bearing, expected.tilt, PADDING_TEST, 0)
|
||||
@@ -329,12 +329,12 @@ class NativeMapViewTest : AppCenter() {
|
||||
@UiThreadTest
|
||||
fun testEaseTo() {
|
||||
val expected = CameraPosition.Builder()
|
||||
.zoom(12.0)
|
||||
.tilt(30.0)
|
||||
.target(LatLng(12.0, 14.0))
|
||||
.bearing(20.0)
|
||||
.padding(PADDING_TEST)
|
||||
.build()
|
||||
.zoom(12.0)
|
||||
.tilt(30.0)
|
||||
.target(LatLng(12.0, 14.0))
|
||||
.bearing(20.0)
|
||||
.padding(PADDING_TEST)
|
||||
.build()
|
||||
// verify that the lazily set padding is ignored when a value is provided with the camera
|
||||
nativeMapView.contentPadding = doubleArrayOf(1.0, 2.0, 3.0, 4.0)
|
||||
nativeMapView.easeTo(expected.target, expected.zoom, expected.bearing, expected.tilt, PADDING_TEST, 0, false)
|
||||
@@ -351,12 +351,12 @@ class NativeMapViewTest : AppCenter() {
|
||||
@UiThreadTest
|
||||
fun testResetPosition() {
|
||||
val expected = CameraPosition.Builder()
|
||||
.zoom(0.0)
|
||||
.tilt(0.0)
|
||||
.target(LatLng(0.0, 0.0))
|
||||
.bearing(0.0)
|
||||
.padding(PADDING_TEST)
|
||||
.build()
|
||||
.zoom(0.0)
|
||||
.tilt(0.0)
|
||||
.target(LatLng(0.0, 0.0))
|
||||
.bearing(0.0)
|
||||
.padding(PADDING_TEST)
|
||||
.build()
|
||||
nativeMapView.jumpTo(LatLng(1.0, 2.0), 12.0, 23.0, 1.0, PADDING_TEST)
|
||||
nativeMapView.resetPosition()
|
||||
val actual = nativeMapView.cameraPosition
|
||||
@@ -372,16 +372,16 @@ class NativeMapViewTest : AppCenter() {
|
||||
@UiThreadTest
|
||||
fun testGetCameraForLatLngBounds() {
|
||||
val expected = CameraPosition.Builder()
|
||||
.zoom(3.5258764777024005)
|
||||
.tilt(0.0)
|
||||
.target(LatLng(23.182767623652808, 13.999999999994088))
|
||||
.bearing(0.0)
|
||||
.build()
|
||||
.zoom(3.5258764777024005)
|
||||
.tilt(0.0)
|
||||
.target(LatLng(23.182767623652808, 13.999999999994088))
|
||||
.bearing(0.0)
|
||||
.build()
|
||||
val actual = nativeMapView.getCameraForLatLngBounds(
|
||||
LatLngBounds.from(30.0, 16.0, 16.0, 12.0),
|
||||
intArrayOf(0, 0, 0, 0),
|
||||
0.0,
|
||||
0.0
|
||||
LatLngBounds.from(30.0, 16.0, 16.0, 12.0),
|
||||
intArrayOf(0, 0, 0, 0),
|
||||
0.0,
|
||||
0.0
|
||||
)
|
||||
assertEquals("Bearing should match", expected.bearing, actual.bearing, TestConstants.BEARING_DELTA)
|
||||
assertEquals("Latitude should match", expected.target.latitude, actual.target.latitude, TestConstants.LAT_LNG_DELTA)
|
||||
@@ -394,11 +394,11 @@ class NativeMapViewTest : AppCenter() {
|
||||
@UiThreadTest
|
||||
fun testMoveBy() {
|
||||
val expected = CameraPosition.Builder()
|
||||
.zoom(0.0)
|
||||
.tilt(0.0)
|
||||
.target(LatLng(4.21494310024160, -4.218749958739409))
|
||||
.bearing(0.0)
|
||||
.build()
|
||||
.zoom(0.0)
|
||||
.tilt(0.0)
|
||||
.target(LatLng(4.21494310024160, -4.218749958739409))
|
||||
.bearing(0.0)
|
||||
.build()
|
||||
nativeMapView.moveBy(12.0, 12.0, 0)
|
||||
val actual = nativeMapView.cameraPosition
|
||||
assertEquals("Bearing should match", expected.bearing, actual.bearing, TestConstants.BEARING_DELTA)
|
||||
@@ -436,4 +436,4 @@ class NativeMapViewTest : AppCenter() {
|
||||
// no-op
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -30,4 +30,4 @@ class TransformTest : EspressoTest() {
|
||||
assertEquals("Camera position should match", expectedCameraPosition, actualCameraPosition)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -14,505 +14,507 @@ import org.junit.Test
|
||||
|
||||
class VisibleRegionTest : BaseTest() {
|
||||
|
||||
override fun getActivityClass(): Class<*> {
|
||||
return PixelTestActivity::class.java
|
||||
}
|
||||
|
||||
override
|
||||
fun beforeTest() {
|
||||
super.beforeTest()
|
||||
mapView = (rule.activity as PixelTestActivity).mapView
|
||||
}
|
||||
|
||||
@Test
|
||||
fun visibleRegionTest() {
|
||||
validateTestSetup()
|
||||
invoke(mapboxMap) { _: UiController, mapboxMap: MapboxMap ->
|
||||
mapboxMap.moveCamera(CameraUpdateFactory.newLatLngZoom(LatLng(0.0, 0.0), 8.0))
|
||||
val latLngs = listOf(
|
||||
mapboxMap.getLatLngFromScreenCoords(0f, 0f),
|
||||
mapboxMap.getLatLngFromScreenCoords(mapView.width / 2f, 0f),
|
||||
mapboxMap.getLatLngFromScreenCoords(mapView.width.toFloat(), 0f),
|
||||
mapboxMap.getLatLngFromScreenCoords(mapView.width.toFloat(), mapView.height / 2f),
|
||||
mapboxMap.getLatLngFromScreenCoords(mapView.width.toFloat(), mapView.height.toFloat()),
|
||||
mapboxMap.getLatLngFromScreenCoords(mapView.width / 2f, mapView.height.toFloat()),
|
||||
mapboxMap.getLatLngFromScreenCoords(0f, mapView.height.toFloat()),
|
||||
mapboxMap.getLatLngFromScreenCoords(0f, mapView.height / 2f),
|
||||
mapboxMap.getLatLngFromScreenCoords(mapView.width / 2f, mapView.height / 2f)
|
||||
)
|
||||
val visibleRegion = mapboxMap.projection.visibleRegion
|
||||
assertTrue(latLngs.all { visibleRegion.latLngBounds.contains(it) })
|
||||
override fun getActivityClass(): Class<*> {
|
||||
return PixelTestActivity::class.java
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
fun paddedVisibleRegionTest() {
|
||||
validateTestSetup()
|
||||
invoke(mapboxMap) { _: UiController, mapboxMap: MapboxMap ->
|
||||
mapboxMap.moveCamera(CameraUpdateFactory.newLatLngZoom(LatLng(0.0, 0.0), 8.0))
|
||||
val latLngs = listOf(
|
||||
mapboxMap.getLatLngFromScreenCoords(0f, 0f),
|
||||
mapboxMap.getLatLngFromScreenCoords(mapView.width / 2f, 0f),
|
||||
mapboxMap.getLatLngFromScreenCoords(mapView.width.toFloat(), 0f),
|
||||
mapboxMap.getLatLngFromScreenCoords(mapView.width.toFloat(), mapView.height / 2f),
|
||||
mapboxMap.getLatLngFromScreenCoords(mapView.width.toFloat(), mapView.height.toFloat()),
|
||||
mapboxMap.getLatLngFromScreenCoords(mapView.width / 2f, mapView.height.toFloat()),
|
||||
mapboxMap.getLatLngFromScreenCoords(0f, mapView.height.toFloat()),
|
||||
mapboxMap.getLatLngFromScreenCoords(0f, mapView.height / 2f),
|
||||
mapboxMap.getLatLngFromScreenCoords(mapView.width / 2f, mapView.height / 2f)
|
||||
)
|
||||
|
||||
mapboxMap.setPadding(
|
||||
mapView.width / 4,
|
||||
mapView.height / 4,
|
||||
mapView.width / 4,
|
||||
mapView.height / 4)
|
||||
|
||||
val visibleRegion = mapboxMap.projection.getVisibleRegion(false)
|
||||
val filtered = latLngs.filter { visibleRegion.latLngBounds.contains(it) }
|
||||
assertTrue(filtered.size == 1)
|
||||
assertTrue(filtered.contains(mapboxMap.getLatLngFromScreenCoords(mapView.width / 2f, mapView.height / 2f)))
|
||||
override
|
||||
fun beforeTest() {
|
||||
super.beforeTest()
|
||||
mapView = (rule.activity as PixelTestActivity).mapView
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
fun paddedLeftVisibleRegionTest() {
|
||||
validateTestSetup()
|
||||
invoke(mapboxMap) { _: UiController, mapboxMap: MapboxMap ->
|
||||
mapboxMap.moveCamera(CameraUpdateFactory.newLatLngZoom(LatLng(0.0, 0.0), 8.0))
|
||||
val latLngs = listOf(
|
||||
mapboxMap.getLatLngFromScreenCoords(0f, 0f),
|
||||
mapboxMap.getLatLngFromScreenCoords(mapView.width / 2f, 0f),
|
||||
mapboxMap.getLatLngFromScreenCoords(mapView.width.toFloat(), 0f),
|
||||
mapboxMap.getLatLngFromScreenCoords(mapView.width.toFloat(), mapView.height / 2f),
|
||||
mapboxMap.getLatLngFromScreenCoords(mapView.width.toFloat(), mapView.height.toFloat()),
|
||||
mapboxMap.getLatLngFromScreenCoords(mapView.width / 2f, mapView.height.toFloat()),
|
||||
mapboxMap.getLatLngFromScreenCoords(0f, mapView.height.toFloat()),
|
||||
mapboxMap.getLatLngFromScreenCoords(0f, mapView.height / 2f),
|
||||
mapboxMap.getLatLngFromScreenCoords(mapView.width / 2f, mapView.height / 2f)
|
||||
)
|
||||
|
||||
mapboxMap.setPadding(mapView.width / 4, 0, 0, 0)
|
||||
|
||||
val visibleRegion = mapboxMap.projection.getVisibleRegion(false)
|
||||
val filtered = latLngs.filter { visibleRegion.latLngBounds.contains(it) }
|
||||
assertTrue(filtered.size == 6)
|
||||
assertFalse(filtered.contains(mapboxMap.getLatLngFromScreenCoords(0f, mapView.height / 2f)))
|
||||
@Test
|
||||
fun visibleRegionTest() {
|
||||
validateTestSetup()
|
||||
invoke(mapboxMap) { _: UiController, mapboxMap: MapboxMap ->
|
||||
mapboxMap.moveCamera(CameraUpdateFactory.newLatLngZoom(LatLng(0.0, 0.0), 8.0))
|
||||
val latLngs = listOf(
|
||||
mapboxMap.getLatLngFromScreenCoords(0f, 0f),
|
||||
mapboxMap.getLatLngFromScreenCoords(mapView.width / 2f, 0f),
|
||||
mapboxMap.getLatLngFromScreenCoords(mapView.width.toFloat(), 0f),
|
||||
mapboxMap.getLatLngFromScreenCoords(mapView.width.toFloat(), mapView.height / 2f),
|
||||
mapboxMap.getLatLngFromScreenCoords(mapView.width.toFloat(), mapView.height.toFloat()),
|
||||
mapboxMap.getLatLngFromScreenCoords(mapView.width / 2f, mapView.height.toFloat()),
|
||||
mapboxMap.getLatLngFromScreenCoords(0f, mapView.height.toFloat()),
|
||||
mapboxMap.getLatLngFromScreenCoords(0f, mapView.height / 2f),
|
||||
mapboxMap.getLatLngFromScreenCoords(mapView.width / 2f, mapView.height / 2f)
|
||||
)
|
||||
val visibleRegion = mapboxMap.projection.visibleRegion
|
||||
assertTrue(latLngs.all { visibleRegion.latLngBounds.contains(it) })
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
fun paddedTopVisibleRegionTest() {
|
||||
validateTestSetup()
|
||||
invoke(mapboxMap) { _: UiController, mapboxMap: MapboxMap ->
|
||||
mapboxMap.moveCamera(CameraUpdateFactory.newLatLngZoom(LatLng(0.0, 0.0), 8.0))
|
||||
val latLngs = listOf(
|
||||
mapboxMap.getLatLngFromScreenCoords(0f, 0f),
|
||||
mapboxMap.getLatLngFromScreenCoords(mapView.width / 2f, 0f),
|
||||
mapboxMap.getLatLngFromScreenCoords(mapView.width.toFloat(), 0f),
|
||||
mapboxMap.getLatLngFromScreenCoords(mapView.width.toFloat(), mapView.height / 2f),
|
||||
mapboxMap.getLatLngFromScreenCoords(mapView.width.toFloat(), mapView.height.toFloat()),
|
||||
mapboxMap.getLatLngFromScreenCoords(mapView.width / 2f, mapView.height.toFloat()),
|
||||
mapboxMap.getLatLngFromScreenCoords(0f, mapView.height.toFloat()),
|
||||
mapboxMap.getLatLngFromScreenCoords(0f, mapView.height / 2f),
|
||||
mapboxMap.getLatLngFromScreenCoords(mapView.width / 2f, mapView.height / 2f)
|
||||
)
|
||||
@Test
|
||||
fun paddedVisibleRegionTest() {
|
||||
validateTestSetup()
|
||||
invoke(mapboxMap) { _: UiController, mapboxMap: MapboxMap ->
|
||||
mapboxMap.moveCamera(CameraUpdateFactory.newLatLngZoom(LatLng(0.0, 0.0), 8.0))
|
||||
val latLngs = listOf(
|
||||
mapboxMap.getLatLngFromScreenCoords(0f, 0f),
|
||||
mapboxMap.getLatLngFromScreenCoords(mapView.width / 2f, 0f),
|
||||
mapboxMap.getLatLngFromScreenCoords(mapView.width.toFloat(), 0f),
|
||||
mapboxMap.getLatLngFromScreenCoords(mapView.width.toFloat(), mapView.height / 2f),
|
||||
mapboxMap.getLatLngFromScreenCoords(mapView.width.toFloat(), mapView.height.toFloat()),
|
||||
mapboxMap.getLatLngFromScreenCoords(mapView.width / 2f, mapView.height.toFloat()),
|
||||
mapboxMap.getLatLngFromScreenCoords(0f, mapView.height.toFloat()),
|
||||
mapboxMap.getLatLngFromScreenCoords(0f, mapView.height / 2f),
|
||||
mapboxMap.getLatLngFromScreenCoords(mapView.width / 2f, mapView.height / 2f)
|
||||
)
|
||||
|
||||
mapboxMap.setPadding(0, mapView.height / 4, 0, 0)
|
||||
mapboxMap.setPadding(
|
||||
mapView.width / 4,
|
||||
mapView.height / 4,
|
||||
mapView.width / 4,
|
||||
mapView.height / 4
|
||||
)
|
||||
|
||||
val visibleRegion = mapboxMap.projection.getVisibleRegion(false)
|
||||
val filtered = latLngs.filter { visibleRegion.latLngBounds.contains(it) }
|
||||
assertTrue(filtered.size == 6)
|
||||
assertFalse(filtered.contains(mapboxMap.getLatLngFromScreenCoords(mapView.width / 2f, 0f)))
|
||||
val visibleRegion = mapboxMap.projection.getVisibleRegion(false)
|
||||
val filtered = latLngs.filter { visibleRegion.latLngBounds.contains(it) }
|
||||
assertTrue(filtered.size == 1)
|
||||
assertTrue(filtered.contains(mapboxMap.getLatLngFromScreenCoords(mapView.width / 2f, mapView.height / 2f)))
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
fun paddedRightVisibleRegionTest() {
|
||||
validateTestSetup()
|
||||
invoke(mapboxMap) { _: UiController, mapboxMap: MapboxMap ->
|
||||
mapboxMap.moveCamera(CameraUpdateFactory.newLatLngZoom(LatLng(0.0, 0.0), 8.0))
|
||||
val latLngs = listOf(
|
||||
mapboxMap.getLatLngFromScreenCoords(0f, 0f),
|
||||
mapboxMap.getLatLngFromScreenCoords(mapView.width / 2f, 0f),
|
||||
mapboxMap.getLatLngFromScreenCoords(mapView.width.toFloat(), 0f),
|
||||
mapboxMap.getLatLngFromScreenCoords(mapView.width.toFloat(), mapView.height / 2f),
|
||||
mapboxMap.getLatLngFromScreenCoords(mapView.width.toFloat(), mapView.height.toFloat()),
|
||||
mapboxMap.getLatLngFromScreenCoords(mapView.width / 2f, mapView.height.toFloat()),
|
||||
mapboxMap.getLatLngFromScreenCoords(0f, mapView.height.toFloat()),
|
||||
mapboxMap.getLatLngFromScreenCoords(0f, mapView.height / 2f),
|
||||
mapboxMap.getLatLngFromScreenCoords(mapView.width / 2f, mapView.height / 2f)
|
||||
)
|
||||
@Test
|
||||
fun paddedLeftVisibleRegionTest() {
|
||||
validateTestSetup()
|
||||
invoke(mapboxMap) { _: UiController, mapboxMap: MapboxMap ->
|
||||
mapboxMap.moveCamera(CameraUpdateFactory.newLatLngZoom(LatLng(0.0, 0.0), 8.0))
|
||||
val latLngs = listOf(
|
||||
mapboxMap.getLatLngFromScreenCoords(0f, 0f),
|
||||
mapboxMap.getLatLngFromScreenCoords(mapView.width / 2f, 0f),
|
||||
mapboxMap.getLatLngFromScreenCoords(mapView.width.toFloat(), 0f),
|
||||
mapboxMap.getLatLngFromScreenCoords(mapView.width.toFloat(), mapView.height / 2f),
|
||||
mapboxMap.getLatLngFromScreenCoords(mapView.width.toFloat(), mapView.height.toFloat()),
|
||||
mapboxMap.getLatLngFromScreenCoords(mapView.width / 2f, mapView.height.toFloat()),
|
||||
mapboxMap.getLatLngFromScreenCoords(0f, mapView.height.toFloat()),
|
||||
mapboxMap.getLatLngFromScreenCoords(0f, mapView.height / 2f),
|
||||
mapboxMap.getLatLngFromScreenCoords(mapView.width / 2f, mapView.height / 2f)
|
||||
)
|
||||
|
||||
mapboxMap.setPadding(0, 0, mapView.width / 4, 0)
|
||||
mapboxMap.setPadding(mapView.width / 4, 0, 0, 0)
|
||||
|
||||
val visibleRegion = mapboxMap.projection.getVisibleRegion(false)
|
||||
val filtered = latLngs.filter { visibleRegion.latLngBounds.contains(it) }
|
||||
assertTrue(filtered.size == 6)
|
||||
assertFalse(filtered.contains(mapboxMap.getLatLngFromScreenCoords(mapView.width.toFloat(), mapView.height / 2f)))
|
||||
val visibleRegion = mapboxMap.projection.getVisibleRegion(false)
|
||||
val filtered = latLngs.filter { visibleRegion.latLngBounds.contains(it) }
|
||||
assertTrue(filtered.size == 6)
|
||||
assertFalse(filtered.contains(mapboxMap.getLatLngFromScreenCoords(0f, mapView.height / 2f)))
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
fun paddedBottomVisibleRegionTest() {
|
||||
validateTestSetup()
|
||||
invoke(mapboxMap) { _: UiController, mapboxMap: MapboxMap ->
|
||||
mapboxMap.moveCamera(CameraUpdateFactory.newLatLngZoom(LatLng(0.0, 0.0), 8.0))
|
||||
val latLngs = listOf(
|
||||
mapboxMap.getLatLngFromScreenCoords(0f, 0f),
|
||||
mapboxMap.getLatLngFromScreenCoords(mapView.width / 2f, 0f),
|
||||
mapboxMap.getLatLngFromScreenCoords(mapView.width.toFloat(), 0f),
|
||||
mapboxMap.getLatLngFromScreenCoords(mapView.width.toFloat(), mapView.height / 2f),
|
||||
mapboxMap.getLatLngFromScreenCoords(mapView.width.toFloat(), mapView.height.toFloat()),
|
||||
mapboxMap.getLatLngFromScreenCoords(mapView.width / 2f, mapView.height.toFloat()),
|
||||
mapboxMap.getLatLngFromScreenCoords(0f, mapView.height.toFloat()),
|
||||
mapboxMap.getLatLngFromScreenCoords(0f, mapView.height / 2f),
|
||||
mapboxMap.getLatLngFromScreenCoords(mapView.width / 2f, mapView.height / 2f)
|
||||
)
|
||||
@Test
|
||||
fun paddedTopVisibleRegionTest() {
|
||||
validateTestSetup()
|
||||
invoke(mapboxMap) { _: UiController, mapboxMap: MapboxMap ->
|
||||
mapboxMap.moveCamera(CameraUpdateFactory.newLatLngZoom(LatLng(0.0, 0.0), 8.0))
|
||||
val latLngs = listOf(
|
||||
mapboxMap.getLatLngFromScreenCoords(0f, 0f),
|
||||
mapboxMap.getLatLngFromScreenCoords(mapView.width / 2f, 0f),
|
||||
mapboxMap.getLatLngFromScreenCoords(mapView.width.toFloat(), 0f),
|
||||
mapboxMap.getLatLngFromScreenCoords(mapView.width.toFloat(), mapView.height / 2f),
|
||||
mapboxMap.getLatLngFromScreenCoords(mapView.width.toFloat(), mapView.height.toFloat()),
|
||||
mapboxMap.getLatLngFromScreenCoords(mapView.width / 2f, mapView.height.toFloat()),
|
||||
mapboxMap.getLatLngFromScreenCoords(0f, mapView.height.toFloat()),
|
||||
mapboxMap.getLatLngFromScreenCoords(0f, mapView.height / 2f),
|
||||
mapboxMap.getLatLngFromScreenCoords(mapView.width / 2f, mapView.height / 2f)
|
||||
)
|
||||
|
||||
mapboxMap.setPadding(0, 0, 0, mapView.height / 4)
|
||||
mapboxMap.setPadding(0, mapView.height / 4, 0, 0)
|
||||
|
||||
val visibleRegion = mapboxMap.projection.getVisibleRegion(false)
|
||||
val filtered = latLngs.filter { visibleRegion.latLngBounds.contains(it) }
|
||||
assertTrue(filtered.size == 6)
|
||||
assertFalse(filtered.contains(mapboxMap.getLatLngFromScreenCoords(mapView.width / 2f, mapView.height.toFloat())))
|
||||
val visibleRegion = mapboxMap.projection.getVisibleRegion(false)
|
||||
val filtered = latLngs.filter { visibleRegion.latLngBounds.contains(it) }
|
||||
assertTrue(filtered.size == 6)
|
||||
assertFalse(filtered.contains(mapboxMap.getLatLngFromScreenCoords(mapView.width / 2f, 0f)))
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
fun visibleRegionOverDatelineTest() {
|
||||
validateTestSetup()
|
||||
invoke(mapboxMap) { _: UiController, mapboxMap: MapboxMap ->
|
||||
mapboxMap.moveCamera(CameraUpdateFactory.newLatLngZoom(LatLng(0.0, 180.0), 8.0))
|
||||
val latLngs = listOf(
|
||||
mapboxMap.getLatLngFromScreenCoords(0f, 0f),
|
||||
mapboxMap.getLatLngFromScreenCoords(mapView.width / 2f, 0f),
|
||||
mapboxMap.getLatLngFromScreenCoords(mapView.width.toFloat(), 0f)
|
||||
.also { it.longitude += 360 },
|
||||
mapboxMap.getLatLngFromScreenCoords(mapView.width.toFloat(), mapView.height / 2f)
|
||||
.also { it.longitude += 360 },
|
||||
mapboxMap.getLatLngFromScreenCoords(mapView.width.toFloat(), mapView.height.toFloat())
|
||||
.also { it.longitude += 360 },
|
||||
mapboxMap.getLatLngFromScreenCoords(mapView.width / 2f, mapView.height.toFloat()),
|
||||
mapboxMap.getLatLngFromScreenCoords(0f, mapView.height.toFloat()),
|
||||
mapboxMap.getLatLngFromScreenCoords(0f, mapView.height / 2f),
|
||||
mapboxMap.getLatLngFromScreenCoords(mapView.width / 2f, mapView.height / 2f)
|
||||
)
|
||||
val visibleRegion = mapboxMap.projection.visibleRegion
|
||||
assertTrue(latLngs.all { visibleRegion.latLngBounds.contains(it) })
|
||||
@Test
|
||||
fun paddedRightVisibleRegionTest() {
|
||||
validateTestSetup()
|
||||
invoke(mapboxMap) { _: UiController, mapboxMap: MapboxMap ->
|
||||
mapboxMap.moveCamera(CameraUpdateFactory.newLatLngZoom(LatLng(0.0, 0.0), 8.0))
|
||||
val latLngs = listOf(
|
||||
mapboxMap.getLatLngFromScreenCoords(0f, 0f),
|
||||
mapboxMap.getLatLngFromScreenCoords(mapView.width / 2f, 0f),
|
||||
mapboxMap.getLatLngFromScreenCoords(mapView.width.toFloat(), 0f),
|
||||
mapboxMap.getLatLngFromScreenCoords(mapView.width.toFloat(), mapView.height / 2f),
|
||||
mapboxMap.getLatLngFromScreenCoords(mapView.width.toFloat(), mapView.height.toFloat()),
|
||||
mapboxMap.getLatLngFromScreenCoords(mapView.width / 2f, mapView.height.toFloat()),
|
||||
mapboxMap.getLatLngFromScreenCoords(0f, mapView.height.toFloat()),
|
||||
mapboxMap.getLatLngFromScreenCoords(0f, mapView.height / 2f),
|
||||
mapboxMap.getLatLngFromScreenCoords(mapView.width / 2f, mapView.height / 2f)
|
||||
)
|
||||
|
||||
mapboxMap.setPadding(0, 0, mapView.width / 4, 0)
|
||||
|
||||
val visibleRegion = mapboxMap.projection.getVisibleRegion(false)
|
||||
val filtered = latLngs.filter { visibleRegion.latLngBounds.contains(it) }
|
||||
assertTrue(filtered.size == 6)
|
||||
assertFalse(filtered.contains(mapboxMap.getLatLngFromScreenCoords(mapView.width.toFloat(), mapView.height / 2f)))
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
fun paddedVisibleRegionOverDatelineTest() {
|
||||
validateTestSetup()
|
||||
invoke(mapboxMap) { _: UiController, mapboxMap: MapboxMap ->
|
||||
mapboxMap.moveCamera(CameraUpdateFactory.newLatLngZoom(LatLng(0.0, 180.0), 8.0))
|
||||
val latLngs = listOf(
|
||||
mapboxMap.getLatLngFromScreenCoords(0f, 0f),
|
||||
mapboxMap.getLatLngFromScreenCoords(mapView.width / 2f, 0f),
|
||||
mapboxMap.getLatLngFromScreenCoords(mapView.width.toFloat(), 0f),
|
||||
mapboxMap.getLatLngFromScreenCoords(mapView.width.toFloat(), mapView.height / 2f),
|
||||
mapboxMap.getLatLngFromScreenCoords(mapView.width.toFloat(), mapView.height.toFloat()),
|
||||
mapboxMap.getLatLngFromScreenCoords(mapView.width / 2f, mapView.height.toFloat()),
|
||||
mapboxMap.getLatLngFromScreenCoords(0f, mapView.height.toFloat()),
|
||||
mapboxMap.getLatLngFromScreenCoords(0f, mapView.height / 2f),
|
||||
mapboxMap.getLatLngFromScreenCoords(mapView.width / 2f, mapView.height / 2f)
|
||||
)
|
||||
@Test
|
||||
fun paddedBottomVisibleRegionTest() {
|
||||
validateTestSetup()
|
||||
invoke(mapboxMap) { _: UiController, mapboxMap: MapboxMap ->
|
||||
mapboxMap.moveCamera(CameraUpdateFactory.newLatLngZoom(LatLng(0.0, 0.0), 8.0))
|
||||
val latLngs = listOf(
|
||||
mapboxMap.getLatLngFromScreenCoords(0f, 0f),
|
||||
mapboxMap.getLatLngFromScreenCoords(mapView.width / 2f, 0f),
|
||||
mapboxMap.getLatLngFromScreenCoords(mapView.width.toFloat(), 0f),
|
||||
mapboxMap.getLatLngFromScreenCoords(mapView.width.toFloat(), mapView.height / 2f),
|
||||
mapboxMap.getLatLngFromScreenCoords(mapView.width.toFloat(), mapView.height.toFloat()),
|
||||
mapboxMap.getLatLngFromScreenCoords(mapView.width / 2f, mapView.height.toFloat()),
|
||||
mapboxMap.getLatLngFromScreenCoords(0f, mapView.height.toFloat()),
|
||||
mapboxMap.getLatLngFromScreenCoords(0f, mapView.height / 2f),
|
||||
mapboxMap.getLatLngFromScreenCoords(mapView.width / 2f, mapView.height / 2f)
|
||||
)
|
||||
|
||||
mapboxMap.setPadding(
|
||||
mapView.width / 4,
|
||||
mapView.height / 4,
|
||||
mapView.width / 4,
|
||||
mapView.height / 4)
|
||||
mapboxMap.setPadding(0, 0, 0, mapView.height / 4)
|
||||
|
||||
val visibleRegion = mapboxMap.projection.getVisibleRegion(false)
|
||||
val filtered = latLngs.filter { visibleRegion.latLngBounds.contains(it) }
|
||||
assertTrue(filtered.size == 1)
|
||||
assertTrue(filtered.contains(mapboxMap.getLatLngFromScreenCoords(mapView.width / 2f, mapView.height / 2f)))
|
||||
val visibleRegion = mapboxMap.projection.getVisibleRegion(false)
|
||||
val filtered = latLngs.filter { visibleRegion.latLngBounds.contains(it) }
|
||||
assertTrue(filtered.size == 6)
|
||||
assertFalse(filtered.contains(mapboxMap.getLatLngFromScreenCoords(mapView.width / 2f, mapView.height.toFloat())))
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
fun paddedLeftVisibleRegionOverDatelineTest() {
|
||||
validateTestSetup()
|
||||
invoke(mapboxMap) { _: UiController, mapboxMap: MapboxMap ->
|
||||
mapboxMap.moveCamera(CameraUpdateFactory.newLatLngZoom(LatLng(0.0, 180.0), 8.0))
|
||||
val latLngs = listOf(
|
||||
mapboxMap.getLatLngFromScreenCoords(0f, 0f),
|
||||
mapboxMap.getLatLngFromScreenCoords(mapView.width / 2f, 0f),
|
||||
mapboxMap.getLatLngFromScreenCoords(mapView.width.toFloat(), 0f)
|
||||
.also { it.longitude += 360 },
|
||||
mapboxMap.getLatLngFromScreenCoords(mapView.width.toFloat(), mapView.height / 2f)
|
||||
.also { it.longitude += 360 },
|
||||
mapboxMap.getLatLngFromScreenCoords(mapView.width.toFloat(), mapView.height.toFloat())
|
||||
.also { it.longitude += 360 },
|
||||
mapboxMap.getLatLngFromScreenCoords(mapView.width / 2f, mapView.height.toFloat()),
|
||||
mapboxMap.getLatLngFromScreenCoords(0f, mapView.height.toFloat()),
|
||||
mapboxMap.getLatLngFromScreenCoords(0f, mapView.height / 2f),
|
||||
mapboxMap.getLatLngFromScreenCoords(mapView.width / 2f, mapView.height / 2f)
|
||||
)
|
||||
|
||||
mapboxMap.setPadding(mapView.width / 4, 0, 0, 0)
|
||||
|
||||
val visibleRegion = mapboxMap.projection.getVisibleRegion(false)
|
||||
val filtered = latLngs.filter { visibleRegion.latLngBounds.contains(it) }
|
||||
assertTrue(filtered.size == 6)
|
||||
assertFalse(filtered.contains(mapboxMap.getLatLngFromScreenCoords(0f, mapView.height / 2f)))
|
||||
@Test
|
||||
fun visibleRegionOverDatelineTest() {
|
||||
validateTestSetup()
|
||||
invoke(mapboxMap) { _: UiController, mapboxMap: MapboxMap ->
|
||||
mapboxMap.moveCamera(CameraUpdateFactory.newLatLngZoom(LatLng(0.0, 180.0), 8.0))
|
||||
val latLngs = listOf(
|
||||
mapboxMap.getLatLngFromScreenCoords(0f, 0f),
|
||||
mapboxMap.getLatLngFromScreenCoords(mapView.width / 2f, 0f),
|
||||
mapboxMap.getLatLngFromScreenCoords(mapView.width.toFloat(), 0f)
|
||||
.also { it.longitude += 360 },
|
||||
mapboxMap.getLatLngFromScreenCoords(mapView.width.toFloat(), mapView.height / 2f)
|
||||
.also { it.longitude += 360 },
|
||||
mapboxMap.getLatLngFromScreenCoords(mapView.width.toFloat(), mapView.height.toFloat())
|
||||
.also { it.longitude += 360 },
|
||||
mapboxMap.getLatLngFromScreenCoords(mapView.width / 2f, mapView.height.toFloat()),
|
||||
mapboxMap.getLatLngFromScreenCoords(0f, mapView.height.toFloat()),
|
||||
mapboxMap.getLatLngFromScreenCoords(0f, mapView.height / 2f),
|
||||
mapboxMap.getLatLngFromScreenCoords(mapView.width / 2f, mapView.height / 2f)
|
||||
)
|
||||
val visibleRegion = mapboxMap.projection.visibleRegion
|
||||
assertTrue(latLngs.all { visibleRegion.latLngBounds.contains(it) })
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
fun paddedTopVisibleRegionOverDatelineTest() {
|
||||
validateTestSetup()
|
||||
invoke(mapboxMap) { ui: UiController, mapboxMap: MapboxMap ->
|
||||
mapboxMap.moveCamera(CameraUpdateFactory.newLatLngZoom(LatLng(0.0, 180.0), 8.0))
|
||||
ui.loopMainThreadForAtLeast(5000)
|
||||
val latLngs = listOf(
|
||||
mapboxMap.getLatLngFromScreenCoords(0f, 0f),
|
||||
mapboxMap.getLatLngFromScreenCoords(mapView.width / 2f, 0f),
|
||||
mapboxMap.getLatLngFromScreenCoords(mapView.width.toFloat(), 0f)
|
||||
.also { it.longitude += 360 },
|
||||
mapboxMap.getLatLngFromScreenCoords(mapView.width.toFloat(), mapView.height / 2f)
|
||||
.also { it.longitude += 360 },
|
||||
mapboxMap.getLatLngFromScreenCoords(mapView.width.toFloat(), mapView.height.toFloat())
|
||||
.also { it.longitude += 360 },
|
||||
mapboxMap.getLatLngFromScreenCoords(mapView.width / 2f, mapView.height.toFloat()),
|
||||
mapboxMap.getLatLngFromScreenCoords(0f, mapView.height.toFloat()),
|
||||
mapboxMap.getLatLngFromScreenCoords(0f, mapView.height / 2f),
|
||||
mapboxMap.getLatLngFromScreenCoords(mapView.width / 2f, mapView.height / 2f)
|
||||
)
|
||||
@Test
|
||||
fun paddedVisibleRegionOverDatelineTest() {
|
||||
validateTestSetup()
|
||||
invoke(mapboxMap) { _: UiController, mapboxMap: MapboxMap ->
|
||||
mapboxMap.moveCamera(CameraUpdateFactory.newLatLngZoom(LatLng(0.0, 180.0), 8.0))
|
||||
val latLngs = listOf(
|
||||
mapboxMap.getLatLngFromScreenCoords(0f, 0f),
|
||||
mapboxMap.getLatLngFromScreenCoords(mapView.width / 2f, 0f),
|
||||
mapboxMap.getLatLngFromScreenCoords(mapView.width.toFloat(), 0f),
|
||||
mapboxMap.getLatLngFromScreenCoords(mapView.width.toFloat(), mapView.height / 2f),
|
||||
mapboxMap.getLatLngFromScreenCoords(mapView.width.toFloat(), mapView.height.toFloat()),
|
||||
mapboxMap.getLatLngFromScreenCoords(mapView.width / 2f, mapView.height.toFloat()),
|
||||
mapboxMap.getLatLngFromScreenCoords(0f, mapView.height.toFloat()),
|
||||
mapboxMap.getLatLngFromScreenCoords(0f, mapView.height / 2f),
|
||||
mapboxMap.getLatLngFromScreenCoords(mapView.width / 2f, mapView.height / 2f)
|
||||
)
|
||||
|
||||
mapboxMap.setPadding(0, mapView.height / 4, 0, 0)
|
||||
mapboxMap.setPadding(
|
||||
mapView.width / 4,
|
||||
mapView.height / 4,
|
||||
mapView.width / 4,
|
||||
mapView.height / 4
|
||||
)
|
||||
|
||||
val visibleRegion = mapboxMap.projection.getVisibleRegion(false)
|
||||
val filtered = latLngs.filter { visibleRegion.latLngBounds.contains(it) }
|
||||
assertTrue(filtered.size == 6)
|
||||
assertFalse(filtered.contains(mapboxMap.getLatLngFromScreenCoords(mapView.width / 2f, 0f)))
|
||||
val visibleRegion = mapboxMap.projection.getVisibleRegion(false)
|
||||
val filtered = latLngs.filter { visibleRegion.latLngBounds.contains(it) }
|
||||
assertTrue(filtered.size == 1)
|
||||
assertTrue(filtered.contains(mapboxMap.getLatLngFromScreenCoords(mapView.width / 2f, mapView.height / 2f)))
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
fun paddedRightVisibleRegionOverDatelineTest() {
|
||||
validateTestSetup()
|
||||
invoke(mapboxMap) { _: UiController, mapboxMap: MapboxMap ->
|
||||
mapboxMap.moveCamera(CameraUpdateFactory.newLatLngZoom(LatLng(0.0, 180.0), 8.0))
|
||||
val latLngs = listOf(
|
||||
mapboxMap.getLatLngFromScreenCoords(0f, 0f),
|
||||
mapboxMap.getLatLngFromScreenCoords(mapView.width / 2f, 0f),
|
||||
mapboxMap.getLatLngFromScreenCoords(mapView.width.toFloat(), 0f)
|
||||
.also { it.longitude += 360 },
|
||||
mapboxMap.getLatLngFromScreenCoords(mapView.width.toFloat(), mapView.height / 2f)
|
||||
.also { it.longitude += 360 },
|
||||
mapboxMap.getLatLngFromScreenCoords(mapView.width.toFloat(), mapView.height.toFloat())
|
||||
.also { it.longitude += 360 },
|
||||
mapboxMap.getLatLngFromScreenCoords(mapView.width / 2f, mapView.height.toFloat()),
|
||||
mapboxMap.getLatLngFromScreenCoords(0f, mapView.height.toFloat()),
|
||||
mapboxMap.getLatLngFromScreenCoords(0f, mapView.height / 2f),
|
||||
mapboxMap.getLatLngFromScreenCoords(mapView.width / 2f, mapView.height / 2f)
|
||||
)
|
||||
@Test
|
||||
fun paddedLeftVisibleRegionOverDatelineTest() {
|
||||
validateTestSetup()
|
||||
invoke(mapboxMap) { _: UiController, mapboxMap: MapboxMap ->
|
||||
mapboxMap.moveCamera(CameraUpdateFactory.newLatLngZoom(LatLng(0.0, 180.0), 8.0))
|
||||
val latLngs = listOf(
|
||||
mapboxMap.getLatLngFromScreenCoords(0f, 0f),
|
||||
mapboxMap.getLatLngFromScreenCoords(mapView.width / 2f, 0f),
|
||||
mapboxMap.getLatLngFromScreenCoords(mapView.width.toFloat(), 0f)
|
||||
.also { it.longitude += 360 },
|
||||
mapboxMap.getLatLngFromScreenCoords(mapView.width.toFloat(), mapView.height / 2f)
|
||||
.also { it.longitude += 360 },
|
||||
mapboxMap.getLatLngFromScreenCoords(mapView.width.toFloat(), mapView.height.toFloat())
|
||||
.also { it.longitude += 360 },
|
||||
mapboxMap.getLatLngFromScreenCoords(mapView.width / 2f, mapView.height.toFloat()),
|
||||
mapboxMap.getLatLngFromScreenCoords(0f, mapView.height.toFloat()),
|
||||
mapboxMap.getLatLngFromScreenCoords(0f, mapView.height / 2f),
|
||||
mapboxMap.getLatLngFromScreenCoords(mapView.width / 2f, mapView.height / 2f)
|
||||
)
|
||||
|
||||
mapboxMap.setPadding(0, 0, mapView.width / 4, 0)
|
||||
mapboxMap.setPadding(mapView.width / 4, 0, 0, 0)
|
||||
|
||||
val visibleRegion = mapboxMap.projection.getVisibleRegion(false)
|
||||
val filtered = latLngs.filter { visibleRegion.latLngBounds.contains(it) }
|
||||
assertTrue(filtered.size == 6)
|
||||
assertFalse(filtered.contains(mapboxMap.getLatLngFromScreenCoords(mapView.width.toFloat(), mapView.height / 2f)))
|
||||
val visibleRegion = mapboxMap.projection.getVisibleRegion(false)
|
||||
val filtered = latLngs.filter { visibleRegion.latLngBounds.contains(it) }
|
||||
assertTrue(filtered.size == 6)
|
||||
assertFalse(filtered.contains(mapboxMap.getLatLngFromScreenCoords(0f, mapView.height / 2f)))
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
fun paddedBottomVisibleRegionOverDatelineTest() {
|
||||
validateTestSetup()
|
||||
invoke(mapboxMap) { _: UiController, mapboxMap: MapboxMap ->
|
||||
mapboxMap.moveCamera(CameraUpdateFactory.newLatLngZoom(LatLng(0.0, 180.0), 8.0))
|
||||
val latLngs = listOf(
|
||||
mapboxMap.getLatLngFromScreenCoords(0f, 0f),
|
||||
mapboxMap.getLatLngFromScreenCoords(mapView.width / 2f, 0f),
|
||||
mapboxMap.getLatLngFromScreenCoords(mapView.width.toFloat(), 0f)
|
||||
.also { it.longitude += 360 },
|
||||
mapboxMap.getLatLngFromScreenCoords(mapView.width.toFloat(), mapView.height / 2f)
|
||||
.also { it.longitude += 360 },
|
||||
mapboxMap.getLatLngFromScreenCoords(mapView.width.toFloat(), mapView.height.toFloat())
|
||||
.also { it.longitude += 360 },
|
||||
mapboxMap.getLatLngFromScreenCoords(mapView.width / 2f, mapView.height.toFloat()),
|
||||
mapboxMap.getLatLngFromScreenCoords(0f, mapView.height.toFloat()),
|
||||
mapboxMap.getLatLngFromScreenCoords(0f, mapView.height / 2f),
|
||||
mapboxMap.getLatLngFromScreenCoords(mapView.width / 2f, mapView.height / 2f)
|
||||
)
|
||||
@Test
|
||||
fun paddedTopVisibleRegionOverDatelineTest() {
|
||||
validateTestSetup()
|
||||
invoke(mapboxMap) { ui: UiController, mapboxMap: MapboxMap ->
|
||||
mapboxMap.moveCamera(CameraUpdateFactory.newLatLngZoom(LatLng(0.0, 180.0), 8.0))
|
||||
ui.loopMainThreadForAtLeast(5000)
|
||||
val latLngs = listOf(
|
||||
mapboxMap.getLatLngFromScreenCoords(0f, 0f),
|
||||
mapboxMap.getLatLngFromScreenCoords(mapView.width / 2f, 0f),
|
||||
mapboxMap.getLatLngFromScreenCoords(mapView.width.toFloat(), 0f)
|
||||
.also { it.longitude += 360 },
|
||||
mapboxMap.getLatLngFromScreenCoords(mapView.width.toFloat(), mapView.height / 2f)
|
||||
.also { it.longitude += 360 },
|
||||
mapboxMap.getLatLngFromScreenCoords(mapView.width.toFloat(), mapView.height.toFloat())
|
||||
.also { it.longitude += 360 },
|
||||
mapboxMap.getLatLngFromScreenCoords(mapView.width / 2f, mapView.height.toFloat()),
|
||||
mapboxMap.getLatLngFromScreenCoords(0f, mapView.height.toFloat()),
|
||||
mapboxMap.getLatLngFromScreenCoords(0f, mapView.height / 2f),
|
||||
mapboxMap.getLatLngFromScreenCoords(mapView.width / 2f, mapView.height / 2f)
|
||||
)
|
||||
|
||||
mapboxMap.setPadding(0, 0, 0, mapView.height / 4)
|
||||
mapboxMap.setPadding(0, mapView.height / 4, 0, 0)
|
||||
|
||||
val visibleRegion = mapboxMap.projection.getVisibleRegion(false)
|
||||
val filtered = latLngs.filter { visibleRegion.latLngBounds.contains(it) }
|
||||
assertTrue(filtered.size == 6)
|
||||
assertFalse(filtered.contains(mapboxMap.getLatLngFromScreenCoords(mapView.width / 2f, mapView.height.toFloat())))
|
||||
val visibleRegion = mapboxMap.projection.getVisibleRegion(false)
|
||||
val filtered = latLngs.filter { visibleRegion.latLngBounds.contains(it) }
|
||||
assertTrue(filtered.size == 6)
|
||||
assertFalse(filtered.contains(mapboxMap.getLatLngFromScreenCoords(mapView.width / 2f, 0f)))
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
fun visibleRotatedRegionTest() {
|
||||
validateTestSetup()
|
||||
invoke(mapboxMap) { _: UiController, mapboxMap: MapboxMap ->
|
||||
mapboxMap.moveCamera(CameraUpdateFactory.newLatLngZoom(LatLng(0.0, 0.0), 8.0))
|
||||
val d = Math.min(mapboxMap.width, mapboxMap.height) / 4
|
||||
val latLngs = listOf(
|
||||
mapboxMap.getLatLngFromScreenCoords(mapView.width / 2f, mapView.height / 2f),
|
||||
mapboxMap.getLatLngFromScreenCoords(mapView.width / 2f - d / 2f, mapView.height / 2f),
|
||||
mapboxMap.getLatLngFromScreenCoords(mapView.width / 2f + d / 2f, mapView.height / 2f),
|
||||
mapboxMap.getLatLngFromScreenCoords(mapView.width / 2f, mapView.height / 2f - d / 2f),
|
||||
mapboxMap.getLatLngFromScreenCoords(mapView.width / 2f, mapView.height / 2f + d / 2f)
|
||||
)
|
||||
@Test
|
||||
fun paddedRightVisibleRegionOverDatelineTest() {
|
||||
validateTestSetup()
|
||||
invoke(mapboxMap) { _: UiController, mapboxMap: MapboxMap ->
|
||||
mapboxMap.moveCamera(CameraUpdateFactory.newLatLngZoom(LatLng(0.0, 180.0), 8.0))
|
||||
val latLngs = listOf(
|
||||
mapboxMap.getLatLngFromScreenCoords(0f, 0f),
|
||||
mapboxMap.getLatLngFromScreenCoords(mapView.width / 2f, 0f),
|
||||
mapboxMap.getLatLngFromScreenCoords(mapView.width.toFloat(), 0f)
|
||||
.also { it.longitude += 360 },
|
||||
mapboxMap.getLatLngFromScreenCoords(mapView.width.toFloat(), mapView.height / 2f)
|
||||
.also { it.longitude += 360 },
|
||||
mapboxMap.getLatLngFromScreenCoords(mapView.width.toFloat(), mapView.height.toFloat())
|
||||
.also { it.longitude += 360 },
|
||||
mapboxMap.getLatLngFromScreenCoords(mapView.width / 2f, mapView.height.toFloat()),
|
||||
mapboxMap.getLatLngFromScreenCoords(0f, mapView.height.toFloat()),
|
||||
mapboxMap.getLatLngFromScreenCoords(0f, mapView.height / 2f),
|
||||
mapboxMap.getLatLngFromScreenCoords(mapView.width / 2f, mapView.height / 2f)
|
||||
)
|
||||
|
||||
for (bearing in 45 until 360 step 45) {
|
||||
mapboxMap.moveCamera(CameraUpdateFactory.bearingTo(bearing.toDouble()))
|
||||
val visibleRegion = mapboxMap.projection.visibleRegion
|
||||
assertTrue(latLngs.all { visibleRegion.latLngBounds.contains(it) })
|
||||
}
|
||||
mapboxMap.setPadding(0, 0, mapView.width / 4, 0)
|
||||
|
||||
val visibleRegion = mapboxMap.projection.getVisibleRegion(false)
|
||||
val filtered = latLngs.filter { visibleRegion.latLngBounds.contains(it) }
|
||||
assertTrue(filtered.size == 6)
|
||||
assertFalse(filtered.contains(mapboxMap.getLatLngFromScreenCoords(mapView.width.toFloat(), mapView.height / 2f)))
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
fun visibleRotatedRegionOverDatelineTest() {
|
||||
validateTestSetup()
|
||||
invoke(mapboxMap) { _: UiController, mapboxMap: MapboxMap ->
|
||||
mapboxMap.moveCamera(CameraUpdateFactory.newLatLngZoom(LatLng(0.0, 180.0), 8.0))
|
||||
val d = Math.min(mapboxMap.width, mapboxMap.height) / 4
|
||||
val latLngs = listOf(
|
||||
mapboxMap.getLatLngFromScreenCoords(mapView.width / 2f, mapView.height / 2f),
|
||||
mapboxMap.getLatLngFromScreenCoords(mapView.width / 2f - d / 2f, mapView.height / 2f),
|
||||
mapboxMap.getLatLngFromScreenCoords(mapView.width / 2f + d / 2f, mapView.height / 2f)
|
||||
.also { it.longitude += 360 },
|
||||
mapboxMap.getLatLngFromScreenCoords(mapView.width / 2f, mapView.height / 2f - d / 2f),
|
||||
mapboxMap.getLatLngFromScreenCoords(mapView.width / 2f, mapView.height / 2f + d / 2f)
|
||||
)
|
||||
@Test
|
||||
fun paddedBottomVisibleRegionOverDatelineTest() {
|
||||
validateTestSetup()
|
||||
invoke(mapboxMap) { _: UiController, mapboxMap: MapboxMap ->
|
||||
mapboxMap.moveCamera(CameraUpdateFactory.newLatLngZoom(LatLng(0.0, 180.0), 8.0))
|
||||
val latLngs = listOf(
|
||||
mapboxMap.getLatLngFromScreenCoords(0f, 0f),
|
||||
mapboxMap.getLatLngFromScreenCoords(mapView.width / 2f, 0f),
|
||||
mapboxMap.getLatLngFromScreenCoords(mapView.width.toFloat(), 0f)
|
||||
.also { it.longitude += 360 },
|
||||
mapboxMap.getLatLngFromScreenCoords(mapView.width.toFloat(), mapView.height / 2f)
|
||||
.also { it.longitude += 360 },
|
||||
mapboxMap.getLatLngFromScreenCoords(mapView.width.toFloat(), mapView.height.toFloat())
|
||||
.also { it.longitude += 360 },
|
||||
mapboxMap.getLatLngFromScreenCoords(mapView.width / 2f, mapView.height.toFloat()),
|
||||
mapboxMap.getLatLngFromScreenCoords(0f, mapView.height.toFloat()),
|
||||
mapboxMap.getLatLngFromScreenCoords(0f, mapView.height / 2f),
|
||||
mapboxMap.getLatLngFromScreenCoords(mapView.width / 2f, mapView.height / 2f)
|
||||
)
|
||||
|
||||
for (bearing in 45 until 360 step 45) {
|
||||
mapboxMap.moveCamera(CameraUpdateFactory.bearingTo(bearing.toDouble()))
|
||||
val visibleRegion = mapboxMap.projection.visibleRegion
|
||||
assertTrue(latLngs.all { visibleRegion.latLngBounds.contains(it) })
|
||||
}
|
||||
mapboxMap.setPadding(0, 0, 0, mapView.height / 4)
|
||||
|
||||
val visibleRegion = mapboxMap.projection.getVisibleRegion(false)
|
||||
val filtered = latLngs.filter { visibleRegion.latLngBounds.contains(it) }
|
||||
assertTrue(filtered.size == 6)
|
||||
assertFalse(filtered.contains(mapboxMap.getLatLngFromScreenCoords(mapView.width / 2f, mapView.height.toFloat())))
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
fun visibleRegionWithBoundsEqualTest() {
|
||||
validateTestSetup()
|
||||
invoke(mapboxMap) { _: UiController, mapboxMap: MapboxMap ->
|
||||
mapboxMap.moveCamera(CameraUpdateFactory.newLatLngZoom(LatLng(0.0, 0.0), 8.0))
|
||||
val latLngs = listOf(
|
||||
mapboxMap.getLatLngFromScreenCoords(0f, 0f),
|
||||
mapboxMap.getLatLngFromScreenCoords(mapView.width / 2f, 0f),
|
||||
mapboxMap.getLatLngFromScreenCoords(mapView.width.toFloat(), 0f),
|
||||
mapboxMap.getLatLngFromScreenCoords(mapView.width.toFloat(), mapView.height / 2f),
|
||||
mapboxMap.getLatLngFromScreenCoords(mapView.width.toFloat(), mapView.height.toFloat()),
|
||||
mapboxMap.getLatLngFromScreenCoords(mapView.width / 2f, mapView.height.toFloat()),
|
||||
mapboxMap.getLatLngFromScreenCoords(0f, mapView.height.toFloat()),
|
||||
mapboxMap.getLatLngFromScreenCoords(0f, mapView.height / 2f),
|
||||
mapboxMap.getLatLngFromScreenCoords(mapView.width / 2f, mapView.height / 2f)
|
||||
)
|
||||
val bounds = doubleArrayOf(0.0, 0.0, 0.0, 0.0)
|
||||
mapboxMap.projection.getVisibleCoordinateBounds(bounds)
|
||||
val latLngBounds = LatLngBounds.from(bounds[0], bounds[1], bounds[2], bounds[3])
|
||||
val visibleRegion = mapboxMap.projection.visibleRegion
|
||||
assertTrue(latLngBounds == visibleRegion.latLngBounds)
|
||||
assertTrue(latLngs.all { latLngBounds.contains(it) })
|
||||
@Test
|
||||
fun visibleRotatedRegionTest() {
|
||||
validateTestSetup()
|
||||
invoke(mapboxMap) { _: UiController, mapboxMap: MapboxMap ->
|
||||
mapboxMap.moveCamera(CameraUpdateFactory.newLatLngZoom(LatLng(0.0, 0.0), 8.0))
|
||||
val d = Math.min(mapboxMap.width, mapboxMap.height) / 4
|
||||
val latLngs = listOf(
|
||||
mapboxMap.getLatLngFromScreenCoords(mapView.width / 2f, mapView.height / 2f),
|
||||
mapboxMap.getLatLngFromScreenCoords(mapView.width / 2f - d / 2f, mapView.height / 2f),
|
||||
mapboxMap.getLatLngFromScreenCoords(mapView.width / 2f + d / 2f, mapView.height / 2f),
|
||||
mapboxMap.getLatLngFromScreenCoords(mapView.width / 2f, mapView.height / 2f - d / 2f),
|
||||
mapboxMap.getLatLngFromScreenCoords(mapView.width / 2f, mapView.height / 2f + d / 2f)
|
||||
)
|
||||
|
||||
for (bearing in 45 until 360 step 45) {
|
||||
mapboxMap.moveCamera(CameraUpdateFactory.bearingTo(bearing.toDouble()))
|
||||
val visibleRegion = mapboxMap.projection.visibleRegion
|
||||
assertTrue(latLngs.all { visibleRegion.latLngBounds.contains(it) })
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
fun visibleRegionBoundsOverDatelineTest() {
|
||||
validateTestSetup()
|
||||
invoke(mapboxMap) { _: UiController, mapboxMap: MapboxMap ->
|
||||
mapboxMap.moveCamera(CameraUpdateFactory.newLatLngZoom(LatLng(0.0, 180.0), 8.0))
|
||||
val latLngs = listOf(
|
||||
mapboxMap.getLatLngFromScreenCoords(0f, 0f),
|
||||
mapboxMap.getLatLngFromScreenCoords(mapView.width / 2f, 0f),
|
||||
mapboxMap.getLatLngFromScreenCoords(mapView.width.toFloat(), 0f)
|
||||
.also { it.longitude += 360 },
|
||||
mapboxMap.getLatLngFromScreenCoords(mapView.width.toFloat(), mapView.height / 2f)
|
||||
.also { it.longitude += 360 },
|
||||
mapboxMap.getLatLngFromScreenCoords(mapView.width.toFloat(), mapView.height.toFloat())
|
||||
.also { it.longitude += 360 },
|
||||
mapboxMap.getLatLngFromScreenCoords(mapView.width / 2f, mapView.height.toFloat()),
|
||||
mapboxMap.getLatLngFromScreenCoords(0f, mapView.height.toFloat()),
|
||||
mapboxMap.getLatLngFromScreenCoords(0f, mapView.height / 2f),
|
||||
mapboxMap.getLatLngFromScreenCoords(mapView.width / 2f, mapView.height / 2f)
|
||||
)
|
||||
val bounds = doubleArrayOf(0.0, 0.0, 0.0, 0.0)
|
||||
mapboxMap.projection.getVisibleCoordinateBounds(bounds)
|
||||
val latLngBounds = LatLngBounds.from(bounds[0], bounds[1], bounds[2], bounds[3])
|
||||
assertTrue(latLngs.all { latLngBounds.contains(it) })
|
||||
@Test
|
||||
fun visibleRotatedRegionOverDatelineTest() {
|
||||
validateTestSetup()
|
||||
invoke(mapboxMap) { _: UiController, mapboxMap: MapboxMap ->
|
||||
mapboxMap.moveCamera(CameraUpdateFactory.newLatLngZoom(LatLng(0.0, 180.0), 8.0))
|
||||
val d = Math.min(mapboxMap.width, mapboxMap.height) / 4
|
||||
val latLngs = listOf(
|
||||
mapboxMap.getLatLngFromScreenCoords(mapView.width / 2f, mapView.height / 2f),
|
||||
mapboxMap.getLatLngFromScreenCoords(mapView.width / 2f - d / 2f, mapView.height / 2f),
|
||||
mapboxMap.getLatLngFromScreenCoords(mapView.width / 2f + d / 2f, mapView.height / 2f)
|
||||
.also { it.longitude += 360 },
|
||||
mapboxMap.getLatLngFromScreenCoords(mapView.width / 2f, mapView.height / 2f - d / 2f),
|
||||
mapboxMap.getLatLngFromScreenCoords(mapView.width / 2f, mapView.height / 2f + d / 2f)
|
||||
)
|
||||
|
||||
for (bearing in 45 until 360 step 45) {
|
||||
mapboxMap.moveCamera(CameraUpdateFactory.bearingTo(bearing.toDouble()))
|
||||
val visibleRegion = mapboxMap.projection.visibleRegion
|
||||
assertTrue(latLngs.all { visibleRegion.latLngBounds.contains(it) })
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
fun visibleRegionBoundsOverDatelineLatitudeZeroTest() {
|
||||
validateTestSetup()
|
||||
invoke(mapboxMap) { _: UiController, mapboxMap: MapboxMap ->
|
||||
mapboxMap.moveCamera(CameraUpdateFactory.newLatLngZoom(LatLng(0.0, 180.0), 8.0))
|
||||
val shift = mapboxMap.getLatLngFromScreenCoords(0f, 0f)
|
||||
mapboxMap.moveCamera(CameraUpdateFactory.newLatLng(LatLng(0.0, 180.0 - shift.longitude)))
|
||||
|
||||
val bounds = doubleArrayOf(0.0, 0.0, 0.0, 0.0)
|
||||
mapboxMap.projection.getVisibleCoordinateBounds(bounds)
|
||||
val latLngBounds = LatLngBounds.from(bounds[0], bounds[1], bounds[2], bounds[3])
|
||||
val visibleRegion = mapboxMap.projection.visibleRegion
|
||||
assertTrue(latLngBounds == visibleRegion.latLngBounds)
|
||||
@Test
|
||||
fun visibleRegionWithBoundsEqualTest() {
|
||||
validateTestSetup()
|
||||
invoke(mapboxMap) { _: UiController, mapboxMap: MapboxMap ->
|
||||
mapboxMap.moveCamera(CameraUpdateFactory.newLatLngZoom(LatLng(0.0, 0.0), 8.0))
|
||||
val latLngs = listOf(
|
||||
mapboxMap.getLatLngFromScreenCoords(0f, 0f),
|
||||
mapboxMap.getLatLngFromScreenCoords(mapView.width / 2f, 0f),
|
||||
mapboxMap.getLatLngFromScreenCoords(mapView.width.toFloat(), 0f),
|
||||
mapboxMap.getLatLngFromScreenCoords(mapView.width.toFloat(), mapView.height / 2f),
|
||||
mapboxMap.getLatLngFromScreenCoords(mapView.width.toFloat(), mapView.height.toFloat()),
|
||||
mapboxMap.getLatLngFromScreenCoords(mapView.width / 2f, mapView.height.toFloat()),
|
||||
mapboxMap.getLatLngFromScreenCoords(0f, mapView.height.toFloat()),
|
||||
mapboxMap.getLatLngFromScreenCoords(0f, mapView.height / 2f),
|
||||
mapboxMap.getLatLngFromScreenCoords(mapView.width / 2f, mapView.height / 2f)
|
||||
)
|
||||
val bounds = doubleArrayOf(0.0, 0.0, 0.0, 0.0)
|
||||
mapboxMap.projection.getVisibleCoordinateBounds(bounds)
|
||||
val latLngBounds = LatLngBounds.from(bounds[0], bounds[1], bounds[2], bounds[3])
|
||||
val visibleRegion = mapboxMap.projection.visibleRegion
|
||||
assertTrue(latLngBounds == visibleRegion.latLngBounds)
|
||||
assertTrue(latLngs.all { latLngBounds.contains(it) })
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
fun visibleRotatedRegionBoundEqualTest() {
|
||||
validateTestSetup()
|
||||
invoke(mapboxMap) { _: UiController, mapboxMap: MapboxMap ->
|
||||
mapboxMap.moveCamera(CameraUpdateFactory.newLatLngZoom(LatLng(0.0, 0.0), 8.0))
|
||||
val d = Math.min(mapboxMap.width, mapboxMap.height) / 4
|
||||
val latLngs = listOf(
|
||||
mapboxMap.getLatLngFromScreenCoords(mapView.width / 2f, mapView.height / 2f),
|
||||
mapboxMap.getLatLngFromScreenCoords(mapView.width / 2f - d / 2f, mapView.height / 2f),
|
||||
mapboxMap.getLatLngFromScreenCoords(mapView.width / 2f + d / 2f, mapView.height / 2f),
|
||||
mapboxMap.getLatLngFromScreenCoords(mapView.width / 2f, mapView.height / 2f - d / 2f),
|
||||
mapboxMap.getLatLngFromScreenCoords(mapView.width / 2f, mapView.height / 2f + d / 2f)
|
||||
)
|
||||
|
||||
for (bearing in 45 until 360 step 45) {
|
||||
mapboxMap.moveCamera(CameraUpdateFactory.bearingTo(bearing.toDouble()))
|
||||
val bounds = doubleArrayOf(0.0, 0.0, 0.0, 0.0)
|
||||
mapboxMap.projection.getVisibleCoordinateBounds(bounds)
|
||||
val latLngBounds = LatLngBounds.from(bounds[0], bounds[1], bounds[2], bounds[3])
|
||||
val visibleRegion = mapboxMap.projection.visibleRegion
|
||||
assertTrue(latLngBounds == visibleRegion.latLngBounds)
|
||||
assertTrue(latLngs.all { latLngBounds.contains(it) })
|
||||
}
|
||||
@Test
|
||||
fun visibleRegionBoundsOverDatelineTest() {
|
||||
validateTestSetup()
|
||||
invoke(mapboxMap) { _: UiController, mapboxMap: MapboxMap ->
|
||||
mapboxMap.moveCamera(CameraUpdateFactory.newLatLngZoom(LatLng(0.0, 180.0), 8.0))
|
||||
val latLngs = listOf(
|
||||
mapboxMap.getLatLngFromScreenCoords(0f, 0f),
|
||||
mapboxMap.getLatLngFromScreenCoords(mapView.width / 2f, 0f),
|
||||
mapboxMap.getLatLngFromScreenCoords(mapView.width.toFloat(), 0f)
|
||||
.also { it.longitude += 360 },
|
||||
mapboxMap.getLatLngFromScreenCoords(mapView.width.toFloat(), mapView.height / 2f)
|
||||
.also { it.longitude += 360 },
|
||||
mapboxMap.getLatLngFromScreenCoords(mapView.width.toFloat(), mapView.height.toFloat())
|
||||
.also { it.longitude += 360 },
|
||||
mapboxMap.getLatLngFromScreenCoords(mapView.width / 2f, mapView.height.toFloat()),
|
||||
mapboxMap.getLatLngFromScreenCoords(0f, mapView.height.toFloat()),
|
||||
mapboxMap.getLatLngFromScreenCoords(0f, mapView.height / 2f),
|
||||
mapboxMap.getLatLngFromScreenCoords(mapView.width / 2f, mapView.height / 2f)
|
||||
)
|
||||
val bounds = doubleArrayOf(0.0, 0.0, 0.0, 0.0)
|
||||
mapboxMap.projection.getVisibleCoordinateBounds(bounds)
|
||||
val latLngBounds = LatLngBounds.from(bounds[0], bounds[1], bounds[2], bounds[3])
|
||||
assertTrue(latLngs.all { latLngBounds.contains(it) })
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
fun visibleRotatedRegionBoundsOverDatelineTest() {
|
||||
validateTestSetup()
|
||||
invoke(mapboxMap) { _: UiController, mapboxMap: MapboxMap ->
|
||||
mapboxMap.moveCamera(CameraUpdateFactory.newLatLngZoom(LatLng(0.0, 179.0), 8.0))
|
||||
val d = Math.min(mapboxMap.width, mapboxMap.height) / 4
|
||||
val latLngs = listOf(
|
||||
mapboxMap.getLatLngFromScreenCoords(mapView.width / 2f, mapView.height / 2f),
|
||||
mapboxMap.getLatLngFromScreenCoords(mapView.width / 2f - d / 2f, mapView.height / 2f),
|
||||
mapboxMap.getLatLngFromScreenCoords(mapView.width / 2f + d / 2f, mapView.height / 2f),
|
||||
mapboxMap.getLatLngFromScreenCoords(mapView.width / 2f, mapView.height / 2f - d / 2f),
|
||||
mapboxMap.getLatLngFromScreenCoords(mapView.width / 2f, mapView.height / 2f + d / 2f)
|
||||
)
|
||||
@Test
|
||||
fun visibleRegionBoundsOverDatelineLatitudeZeroTest() {
|
||||
validateTestSetup()
|
||||
invoke(mapboxMap) { _: UiController, mapboxMap: MapboxMap ->
|
||||
mapboxMap.moveCamera(CameraUpdateFactory.newLatLngZoom(LatLng(0.0, 180.0), 8.0))
|
||||
val shift = mapboxMap.getLatLngFromScreenCoords(0f, 0f)
|
||||
mapboxMap.moveCamera(CameraUpdateFactory.newLatLng(LatLng(0.0, 180.0 - shift.longitude)))
|
||||
|
||||
for (bearing in 45 until 360 step 45) {
|
||||
mapboxMap.moveCamera(CameraUpdateFactory.bearingTo(bearing.toDouble()))
|
||||
val bounds = doubleArrayOf(0.0, 0.0, 0.0, 0.0)
|
||||
mapboxMap.projection.getVisibleCoordinateBounds(bounds)
|
||||
val latLngBounds = LatLngBounds.from(bounds[0], bounds[1], bounds[2], bounds[3])
|
||||
assertTrue(latLngs.all { latLngBounds.contains(it) })
|
||||
}
|
||||
val bounds = doubleArrayOf(0.0, 0.0, 0.0, 0.0)
|
||||
mapboxMap.projection.getVisibleCoordinateBounds(bounds)
|
||||
val latLngBounds = LatLngBounds.from(bounds[0], bounds[1], bounds[2], bounds[3])
|
||||
val visibleRegion = mapboxMap.projection.visibleRegion
|
||||
assertTrue(latLngBounds == visibleRegion.latLngBounds)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private fun MapboxMap.getLatLngFromScreenCoords(x: Float, y: Float): LatLng {
|
||||
return this.projection.fromScreenLocation(PointF(x, y))
|
||||
}
|
||||
}
|
||||
@Test
|
||||
fun visibleRotatedRegionBoundEqualTest() {
|
||||
validateTestSetup()
|
||||
invoke(mapboxMap) { _: UiController, mapboxMap: MapboxMap ->
|
||||
mapboxMap.moveCamera(CameraUpdateFactory.newLatLngZoom(LatLng(0.0, 0.0), 8.0))
|
||||
val d = Math.min(mapboxMap.width, mapboxMap.height) / 4
|
||||
val latLngs = listOf(
|
||||
mapboxMap.getLatLngFromScreenCoords(mapView.width / 2f, mapView.height / 2f),
|
||||
mapboxMap.getLatLngFromScreenCoords(mapView.width / 2f - d / 2f, mapView.height / 2f),
|
||||
mapboxMap.getLatLngFromScreenCoords(mapView.width / 2f + d / 2f, mapView.height / 2f),
|
||||
mapboxMap.getLatLngFromScreenCoords(mapView.width / 2f, mapView.height / 2f - d / 2f),
|
||||
mapboxMap.getLatLngFromScreenCoords(mapView.width / 2f, mapView.height / 2f + d / 2f)
|
||||
)
|
||||
|
||||
for (bearing in 45 until 360 step 45) {
|
||||
mapboxMap.moveCamera(CameraUpdateFactory.bearingTo(bearing.toDouble()))
|
||||
val bounds = doubleArrayOf(0.0, 0.0, 0.0, 0.0)
|
||||
mapboxMap.projection.getVisibleCoordinateBounds(bounds)
|
||||
val latLngBounds = LatLngBounds.from(bounds[0], bounds[1], bounds[2], bounds[3])
|
||||
val visibleRegion = mapboxMap.projection.visibleRegion
|
||||
assertTrue(latLngBounds == visibleRegion.latLngBounds)
|
||||
assertTrue(latLngs.all { latLngBounds.contains(it) })
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
fun visibleRotatedRegionBoundsOverDatelineTest() {
|
||||
validateTestSetup()
|
||||
invoke(mapboxMap) { _: UiController, mapboxMap: MapboxMap ->
|
||||
mapboxMap.moveCamera(CameraUpdateFactory.newLatLngZoom(LatLng(0.0, 179.0), 8.0))
|
||||
val d = Math.min(mapboxMap.width, mapboxMap.height) / 4
|
||||
val latLngs = listOf(
|
||||
mapboxMap.getLatLngFromScreenCoords(mapView.width / 2f, mapView.height / 2f),
|
||||
mapboxMap.getLatLngFromScreenCoords(mapView.width / 2f - d / 2f, mapView.height / 2f),
|
||||
mapboxMap.getLatLngFromScreenCoords(mapView.width / 2f + d / 2f, mapView.height / 2f),
|
||||
mapboxMap.getLatLngFromScreenCoords(mapView.width / 2f, mapView.height / 2f - d / 2f),
|
||||
mapboxMap.getLatLngFromScreenCoords(mapView.width / 2f, mapView.height / 2f + d / 2f)
|
||||
)
|
||||
|
||||
for (bearing in 45 until 360 step 45) {
|
||||
mapboxMap.moveCamera(CameraUpdateFactory.bearingTo(bearing.toDouble()))
|
||||
val bounds = doubleArrayOf(0.0, 0.0, 0.0, 0.0)
|
||||
mapboxMap.projection.getVisibleCoordinateBounds(bounds)
|
||||
val latLngBounds = LatLngBounds.from(bounds[0], bounds[1], bounds[2], bounds[3])
|
||||
assertTrue(latLngs.all { latLngBounds.contains(it) })
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private fun MapboxMap.getLatLngFromScreenCoords(x: Float, y: Float): LatLng {
|
||||
return this.projection.fromScreenLocation(PointF(x, y))
|
||||
}
|
||||
}
|
||||
|
||||
@@ -6,12 +6,12 @@ import com.mapbox.geojson.Point
|
||||
import com.mapbox.mapboxsdk.log.Logger
|
||||
import com.mapbox.mapboxsdk.maps.Style
|
||||
import com.mapbox.mapboxsdk.testapp.activity.FeatureOverviewActivity
|
||||
import java.util.concurrent.CountDownLatch
|
||||
import java.util.concurrent.TimeUnit
|
||||
import java.util.concurrent.TimeoutException
|
||||
import org.junit.Rule
|
||||
import org.junit.Test
|
||||
import org.junit.runner.RunWith
|
||||
import java.util.concurrent.CountDownLatch
|
||||
import java.util.concurrent.TimeUnit
|
||||
import java.util.concurrent.TimeoutException
|
||||
|
||||
/**
|
||||
* Integration test that validates downloading an offline region from a point geometry at zoomlevel 17
|
||||
@@ -19,67 +19,68 @@ import org.junit.runner.RunWith
|
||||
@RunWith(AndroidJUnit4::class)
|
||||
class OfflineDownloadTest : OfflineRegion.OfflineRegionObserver {
|
||||
|
||||
@Rule
|
||||
@JvmField
|
||||
var rule = ActivityTestRule(FeatureOverviewActivity::class.java)
|
||||
@Rule
|
||||
@JvmField
|
||||
var rule = ActivityTestRule(FeatureOverviewActivity::class.java)
|
||||
|
||||
private val countDownLatch = CountDownLatch(1)
|
||||
private lateinit var offlineRegion: OfflineRegion
|
||||
private val countDownLatch = CountDownLatch(1)
|
||||
private lateinit var offlineRegion: OfflineRegion
|
||||
|
||||
@Test(timeout = 60000)
|
||||
fun offlineDownload() {
|
||||
rule.runOnUiThreadActivity {
|
||||
OfflineManager.getInstance(rule.activity).createOfflineRegion(
|
||||
createTestRegionDefinition(),
|
||||
ByteArray(0),
|
||||
object : OfflineManager.CreateOfflineRegionCallback {
|
||||
override fun onCreate(region: OfflineRegion) {
|
||||
offlineRegion = region
|
||||
offlineRegion.setDownloadState(OfflineRegion.STATE_ACTIVE)
|
||||
offlineRegion.setObserver(this@OfflineDownloadTest)
|
||||
}
|
||||
@Test(timeout = 60000)
|
||||
fun offlineDownload() {
|
||||
rule.runOnUiThreadActivity {
|
||||
OfflineManager.getInstance(rule.activity).createOfflineRegion(
|
||||
createTestRegionDefinition(),
|
||||
ByteArray(0),
|
||||
object : OfflineManager.CreateOfflineRegionCallback {
|
||||
override fun onCreate(region: OfflineRegion) {
|
||||
offlineRegion = region
|
||||
offlineRegion.setDownloadState(OfflineRegion.STATE_ACTIVE)
|
||||
offlineRegion.setObserver(this@OfflineDownloadTest)
|
||||
}
|
||||
|
||||
override fun onError(error: String) {
|
||||
Logger.e(TAG, "Error while creating offline region: $error")
|
||||
}
|
||||
})
|
||||
override fun onError(error: String) {
|
||||
Logger.e(TAG, "Error while creating offline region: $error")
|
||||
}
|
||||
}
|
||||
)
|
||||
}
|
||||
|
||||
if (!countDownLatch.await(60, TimeUnit.SECONDS)) {
|
||||
throw TimeoutException()
|
||||
}
|
||||
}
|
||||
|
||||
if (!countDownLatch.await(60, TimeUnit.SECONDS)) {
|
||||
throw TimeoutException()
|
||||
override fun onStatusChanged(status: OfflineRegionStatus) {
|
||||
Logger.i(TAG, "Download percentage ${100.0 * status.completedResourceCount / status.requiredResourceCount}")
|
||||
if (status.isComplete) {
|
||||
offlineRegion.setDownloadState(OfflineRegion.STATE_INACTIVE)
|
||||
countDownLatch.countDown()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
override fun onStatusChanged(status: OfflineRegionStatus) {
|
||||
Logger.i(TAG, "Download percentage ${100.0 * status.completedResourceCount / status.requiredResourceCount}")
|
||||
if (status.isComplete) {
|
||||
offlineRegion.setDownloadState(OfflineRegion.STATE_INACTIVE)
|
||||
countDownLatch.countDown()
|
||||
override fun onError(error: OfflineRegionError) {
|
||||
Logger.e(TAG, "Error while downloading offline region: $error")
|
||||
}
|
||||
}
|
||||
|
||||
override fun onError(error: OfflineRegionError) {
|
||||
Logger.e(TAG, "Error while downloading offline region: $error")
|
||||
}
|
||||
override fun mapboxTileCountLimitExceeded(limit: Long) {
|
||||
Logger.e(TAG, "Tile count limited exceeded: $limit")
|
||||
}
|
||||
|
||||
override fun mapboxTileCountLimitExceeded(limit: Long) {
|
||||
Logger.e(TAG, "Tile count limited exceeded: $limit")
|
||||
}
|
||||
private fun createTestRegionDefinition(): OfflineRegionDefinition {
|
||||
return OfflineGeometryRegionDefinition(
|
||||
Style.MAPBOX_STREETS,
|
||||
Point.fromLngLat(50.847857, 4.360137),
|
||||
17.0,
|
||||
17.0,
|
||||
1.0f,
|
||||
false
|
||||
)
|
||||
}
|
||||
|
||||
private fun createTestRegionDefinition(): OfflineRegionDefinition {
|
||||
return OfflineGeometryRegionDefinition(
|
||||
Style.MAPBOX_STREETS,
|
||||
Point.fromLngLat(50.847857, 4.360137),
|
||||
17.0,
|
||||
17.0,
|
||||
1.0f,
|
||||
false
|
||||
)
|
||||
}
|
||||
|
||||
companion object {
|
||||
const val TAG = "OfflineDownloadTest"
|
||||
}
|
||||
companion object {
|
||||
const val TAG = "OfflineDownloadTest"
|
||||
}
|
||||
}
|
||||
|
||||
fun ActivityTestRule<*>.runOnUiThreadActivity(runnable: () -> Unit) = activity.runOnUiThread(runnable)
|
||||
fun ActivityTestRule<*>.runOnUiThreadActivity(runnable: () -> Unit) = activity.runOnUiThread(runnable)
|
||||
|
||||
@@ -8,14 +8,14 @@ import com.mapbox.mapboxsdk.maps.Style
|
||||
import com.mapbox.mapboxsdk.style.layers.BackgroundLayer
|
||||
import com.mapbox.mapboxsdk.style.layers.PropertyFactory
|
||||
import com.mapbox.mapboxsdk.testapp.activity.FeatureOverviewActivity
|
||||
import java.util.concurrent.CountDownLatch
|
||||
import java.util.concurrent.TimeUnit
|
||||
import java.util.concurrent.TimeoutException
|
||||
import junit.framework.Assert.assertNotNull
|
||||
import org.junit.Assert
|
||||
import org.junit.Rule
|
||||
import org.junit.Test
|
||||
import org.junit.runner.RunWith
|
||||
import java.util.concurrent.CountDownLatch
|
||||
import java.util.concurrent.TimeUnit
|
||||
import java.util.concurrent.TimeoutException
|
||||
|
||||
/**
|
||||
* Integration test that validates if a snapshotter creation
|
||||
@@ -23,39 +23,44 @@ import org.junit.runner.RunWith
|
||||
@RunWith(AndroidJUnit4::class)
|
||||
class MapSnapshotterTest {
|
||||
|
||||
@Rule
|
||||
@JvmField
|
||||
var rule = ActivityTestRule(FeatureOverviewActivity::class.java)
|
||||
@Rule
|
||||
@JvmField
|
||||
var rule = ActivityTestRule(FeatureOverviewActivity::class.java)
|
||||
|
||||
private val countDownLatch = CountDownLatch(1)
|
||||
private val countDownLatch = CountDownLatch(1)
|
||||
|
||||
@Test
|
||||
fun mapSnapshotter() {
|
||||
var mapSnapshotter: MapSnapshotter?
|
||||
rule.activity.runOnUiThread {
|
||||
val bg = BackgroundLayer("rand_tint")
|
||||
bg.setProperties(PropertyFactory.backgroundColor("rgba(255,128,0,0.7)"))
|
||||
val options = MapSnapshotter.Options(512, 512)
|
||||
.withPixelRatio(1.0f)
|
||||
.withStyleBuilder(Style.Builder().fromUri(Style.SATELLITE_STREETS)
|
||||
.withLayerAbove(bg, "country-label"))
|
||||
.withCameraPosition(
|
||||
CameraPosition.Builder()
|
||||
.zoom(12.0)
|
||||
.target(LatLng(51.145495, 5.742234))
|
||||
.build()
|
||||
)
|
||||
mapSnapshotter = MapSnapshotter(rule.activity, options)
|
||||
mapSnapshotter!!.start({
|
||||
assertNotNull(it)
|
||||
assertNotNull(it.bitmap)
|
||||
countDownLatch.countDown()
|
||||
}, {
|
||||
Assert.fail(it)
|
||||
})
|
||||
@Test
|
||||
fun mapSnapshotter() {
|
||||
var mapSnapshotter: MapSnapshotter?
|
||||
rule.activity.runOnUiThread {
|
||||
val bg = BackgroundLayer("rand_tint")
|
||||
bg.setProperties(PropertyFactory.backgroundColor("rgba(255,128,0,0.7)"))
|
||||
val options = MapSnapshotter.Options(512, 512)
|
||||
.withPixelRatio(1.0f)
|
||||
.withStyleBuilder(
|
||||
Style.Builder().fromUri(Style.SATELLITE_STREETS)
|
||||
.withLayerAbove(bg, "country-label")
|
||||
)
|
||||
.withCameraPosition(
|
||||
CameraPosition.Builder()
|
||||
.zoom(12.0)
|
||||
.target(LatLng(51.145495, 5.742234))
|
||||
.build()
|
||||
)
|
||||
mapSnapshotter = MapSnapshotter(rule.activity, options)
|
||||
mapSnapshotter!!.start(
|
||||
{
|
||||
assertNotNull(it)
|
||||
assertNotNull(it.bitmap)
|
||||
countDownLatch.countDown()
|
||||
},
|
||||
{
|
||||
Assert.fail(it)
|
||||
}
|
||||
)
|
||||
}
|
||||
if (!countDownLatch.await(30, TimeUnit.SECONDS)) {
|
||||
throw TimeoutException()
|
||||
}
|
||||
}
|
||||
if (!countDownLatch.await(30, TimeUnit.SECONDS)) {
|
||||
throw TimeoutException()
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -32,4 +32,4 @@ class MapDialogFragmentTest : AppCenter() {
|
||||
Thread.sleep(2500)
|
||||
Espresso.pressBack()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -7,66 +7,67 @@ import com.mapbox.mapboxsdk.maps.MapView
|
||||
import com.mapbox.mapboxsdk.maps.Style
|
||||
import com.mapbox.mapboxsdk.testapp.R
|
||||
import com.mapbox.mapboxsdk.testapp.activity.espresso.EspressoTestActivity
|
||||
import java.util.concurrent.CountDownLatch
|
||||
import java.util.concurrent.TimeUnit
|
||||
import java.util.concurrent.TimeoutException
|
||||
import junit.framework.Assert.assertEquals
|
||||
import org.junit.Before
|
||||
import org.junit.Rule
|
||||
import org.junit.Test
|
||||
import org.junit.runner.RunWith
|
||||
import java.util.concurrent.CountDownLatch
|
||||
import java.util.concurrent.TimeUnit
|
||||
import java.util.concurrent.TimeoutException
|
||||
|
||||
@RunWith(AndroidJUnit4::class)
|
||||
class ImageMissingTest : AppCenter() {
|
||||
|
||||
@Rule
|
||||
@JvmField
|
||||
var rule = ActivityTestRule(EspressoTestActivity::class.java)
|
||||
@Rule
|
||||
@JvmField
|
||||
var rule = ActivityTestRule(EspressoTestActivity::class.java)
|
||||
|
||||
private lateinit var mapView: MapView
|
||||
private lateinit var latch: CountDownLatch
|
||||
private lateinit var mapView: MapView
|
||||
private lateinit var latch: CountDownLatch
|
||||
|
||||
@Before
|
||||
fun setup() {
|
||||
latch = CountDownLatch(1)
|
||||
}
|
||||
|
||||
@Test
|
||||
fun testMissingImage() {
|
||||
rule.runOnUiThread {
|
||||
initMap(styleJson).addOnStyleImageMissingListener {
|
||||
assertEquals("missing-icon", it)
|
||||
latch.countDown()
|
||||
}
|
||||
@Before
|
||||
fun setup() {
|
||||
latch = CountDownLatch(1)
|
||||
}
|
||||
|
||||
if (!latch.await(10, TimeUnit.SECONDS)) {
|
||||
throw TimeoutException()
|
||||
}
|
||||
}
|
||||
@Test
|
||||
fun testMissingImage() {
|
||||
rule.runOnUiThread {
|
||||
initMap(styleJson).addOnStyleImageMissingListener {
|
||||
assertEquals("missing-icon", it)
|
||||
latch.countDown()
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
fun testMissingImage_invalidSprite() {
|
||||
rule.runOnUiThread {
|
||||
initMap(styleJsonInvalidSprite).addOnStyleImageMissingListener {
|
||||
assertEquals("missing-icon", it)
|
||||
latch.countDown()
|
||||
}
|
||||
if (!latch.await(10, TimeUnit.SECONDS)) {
|
||||
throw TimeoutException()
|
||||
}
|
||||
}
|
||||
|
||||
if (!latch.await(10, TimeUnit.SECONDS)) {
|
||||
throw TimeoutException()
|
||||
@Test
|
||||
fun testMissingImage_invalidSprite() {
|
||||
rule.runOnUiThread {
|
||||
initMap(styleJsonInvalidSprite).addOnStyleImageMissingListener {
|
||||
assertEquals("missing-icon", it)
|
||||
latch.countDown()
|
||||
}
|
||||
}
|
||||
|
||||
if (!latch.await(10, TimeUnit.SECONDS)) {
|
||||
throw TimeoutException()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private fun initMap(style: String): MapView {
|
||||
mapView = rule.activity.findViewById(R.id.mapView)
|
||||
mapView.getMapAsync { it.setStyle(Style.Builder().fromJson(style)) }
|
||||
return mapView
|
||||
}
|
||||
private fun initMap(style: String): MapView {
|
||||
mapView = rule.activity.findViewById(R.id.mapView)
|
||||
mapView.getMapAsync { it.setStyle(Style.Builder().fromJson(style)) }
|
||||
return mapView
|
||||
}
|
||||
|
||||
companion object {
|
||||
private const val styleJson = """
|
||||
companion object {
|
||||
private const val styleJson =
|
||||
"""
|
||||
{
|
||||
"version": 8,
|
||||
"name": "Mapbox Streets",
|
||||
@@ -109,7 +110,8 @@ class ImageMissingTest : AppCenter() {
|
||||
}
|
||||
"""
|
||||
|
||||
private const val styleJsonInvalidSprite = """
|
||||
private const val styleJsonInvalidSprite =
|
||||
"""
|
||||
{
|
||||
"version": 8,
|
||||
"name": "Mapbox Streets",
|
||||
@@ -151,5 +153,5 @@ class ImageMissingTest : AppCenter() {
|
||||
}]
|
||||
}
|
||||
"""
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -11,99 +11,100 @@ import com.mapbox.mapboxsdk.maps.MapboxMap
|
||||
import com.mapbox.mapboxsdk.maps.Style
|
||||
import com.mapbox.mapboxsdk.testapp.R
|
||||
import com.mapbox.mapboxsdk.testapp.activity.espresso.EspressoTestActivity
|
||||
import java.util.concurrent.CountDownLatch
|
||||
import java.util.concurrent.TimeUnit
|
||||
import java.util.concurrent.TimeoutException
|
||||
import org.junit.Assert.*
|
||||
import org.junit.Before
|
||||
import org.junit.Rule
|
||||
import org.junit.Test
|
||||
import org.junit.runner.RunWith
|
||||
import java.util.concurrent.CountDownLatch
|
||||
import java.util.concurrent.TimeUnit
|
||||
import java.util.concurrent.TimeoutException
|
||||
|
||||
@RunWith(AndroidJUnit4::class)
|
||||
class RemoveUnusedImagesTest : AppCenter() {
|
||||
|
||||
@Rule
|
||||
@JvmField
|
||||
var rule = ActivityTestRule(EspressoTestActivity::class.java)
|
||||
@Rule
|
||||
@JvmField
|
||||
var rule = ActivityTestRule(EspressoTestActivity::class.java)
|
||||
|
||||
private lateinit var mapView: MapView
|
||||
private lateinit var mapboxMap: MapboxMap
|
||||
private val latch = CountDownLatch(1)
|
||||
private lateinit var mapView: MapView
|
||||
private lateinit var mapboxMap: MapboxMap
|
||||
private val latch = CountDownLatch(1)
|
||||
|
||||
@Before
|
||||
fun setup() {
|
||||
rule.runOnUiThread {
|
||||
mapView = rule.activity.findViewById(R.id.mapView)
|
||||
mapView.getMapAsync {
|
||||
mapboxMap = it
|
||||
mapboxMap.setStyle(Style.Builder().fromJson(styleJson))
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
fun testRemoveUnusedImagesUserProvidedListener() {
|
||||
var callbackLatch = CountDownLatch(2)
|
||||
rule.runOnUiThread {
|
||||
mapView.addOnStyleImageMissingListener {
|
||||
mapboxMap.style!!.addImage(it, Bitmap.createBitmap(512, 512, Bitmap.Config.ARGB_8888))
|
||||
}
|
||||
|
||||
// Remove layer and source, so that rendered tiles are no longer used, therefore, map must
|
||||
// notify client about unused images.
|
||||
mapView.addOnDidBecomeIdleListener {
|
||||
mapboxMap.style!!.removeLayer("icon")
|
||||
mapboxMap.style!!.removeSource("geojson")
|
||||
}
|
||||
|
||||
mapView.addOnCanRemoveUnusedStyleImageListener {
|
||||
callbackLatch.countDown()
|
||||
mapboxMap.moveCamera(CameraUpdateFactory.newLatLngZoom(LatLng(0.0, 120.0), 8.0))
|
||||
mapView.addOnDidFinishRenderingFrameListener {
|
||||
assertNotNull(mapboxMap.style!!.getImage("small"))
|
||||
assertNotNull(mapboxMap.style!!.getImage("large"))
|
||||
latch.countDown()
|
||||
@Before
|
||||
fun setup() {
|
||||
rule.runOnUiThread {
|
||||
mapView = rule.activity.findViewById(R.id.mapView)
|
||||
mapView.getMapAsync {
|
||||
mapboxMap = it
|
||||
mapboxMap.setStyle(Style.Builder().fromJson(styleJson))
|
||||
}
|
||||
}
|
||||
return@addOnCanRemoveUnusedStyleImageListener false
|
||||
}
|
||||
}
|
||||
|
||||
if (!latch.await(5, TimeUnit.SECONDS) && !callbackLatch.await(5, TimeUnit.SECONDS)) {
|
||||
throw TimeoutException()
|
||||
}
|
||||
}
|
||||
@Test
|
||||
fun testRemoveUnusedImagesUserProvidedListener() {
|
||||
var callbackLatch = CountDownLatch(2)
|
||||
rule.runOnUiThread {
|
||||
mapView.addOnStyleImageMissingListener {
|
||||
mapboxMap.style!!.addImage(it, Bitmap.createBitmap(512, 512, Bitmap.Config.ARGB_8888))
|
||||
}
|
||||
|
||||
@Test
|
||||
fun testRemoveUnusedImagesDefaultListener() {
|
||||
rule.runOnUiThread {
|
||||
mapView.addOnStyleImageMissingListener {
|
||||
mapboxMap.style!!.addImage(it, Bitmap.createBitmap(512, 512, Bitmap.Config.ARGB_8888))
|
||||
}
|
||||
// Remove layer and source, so that rendered tiles are no longer used, therefore, map must
|
||||
// notify client about unused images.
|
||||
mapView.addOnDidBecomeIdleListener {
|
||||
mapboxMap.style!!.removeLayer("icon")
|
||||
mapboxMap.style!!.removeSource("geojson")
|
||||
}
|
||||
|
||||
// Remove layer and source, so that rendered tiles are no longer used, thus
|
||||
// map must request removal of unused images.
|
||||
mapView.addOnDidBecomeIdleListener {
|
||||
mapboxMap.style!!.removeLayer("icon")
|
||||
mapboxMap.style!!.removeSource("geojson")
|
||||
mapboxMap.moveCamera(CameraUpdateFactory.newLatLngZoom(LatLng(0.0, 120.0), 8.0))
|
||||
|
||||
// Wait for the next frame and check that images were removed from the style.
|
||||
mapView.addOnDidFinishRenderingFrameListener {
|
||||
if (mapboxMap.style!!.getImage("small") == null && mapboxMap.style!!.getImage("large") == null) {
|
||||
latch.countDown()
|
||||
}
|
||||
mapView.addOnCanRemoveUnusedStyleImageListener {
|
||||
callbackLatch.countDown()
|
||||
mapboxMap.moveCamera(CameraUpdateFactory.newLatLngZoom(LatLng(0.0, 120.0), 8.0))
|
||||
mapView.addOnDidFinishRenderingFrameListener {
|
||||
assertNotNull(mapboxMap.style!!.getImage("small"))
|
||||
assertNotNull(mapboxMap.style!!.getImage("large"))
|
||||
latch.countDown()
|
||||
}
|
||||
return@addOnCanRemoveUnusedStyleImageListener false
|
||||
}
|
||||
}
|
||||
|
||||
if (!latch.await(5, TimeUnit.SECONDS) && !callbackLatch.await(5, TimeUnit.SECONDS)) {
|
||||
throw TimeoutException()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (!latch.await(5, TimeUnit.SECONDS)) {
|
||||
throw TimeoutException()
|
||||
}
|
||||
}
|
||||
@Test
|
||||
fun testRemoveUnusedImagesDefaultListener() {
|
||||
rule.runOnUiThread {
|
||||
mapView.addOnStyleImageMissingListener {
|
||||
mapboxMap.style!!.addImage(it, Bitmap.createBitmap(512, 512, Bitmap.Config.ARGB_8888))
|
||||
}
|
||||
|
||||
companion object {
|
||||
private const val styleJson = """
|
||||
// Remove layer and source, so that rendered tiles are no longer used, thus
|
||||
// map must request removal of unused images.
|
||||
mapView.addOnDidBecomeIdleListener {
|
||||
mapboxMap.style!!.removeLayer("icon")
|
||||
mapboxMap.style!!.removeSource("geojson")
|
||||
mapboxMap.moveCamera(CameraUpdateFactory.newLatLngZoom(LatLng(0.0, 120.0), 8.0))
|
||||
|
||||
// Wait for the next frame and check that images were removed from the style.
|
||||
mapView.addOnDidFinishRenderingFrameListener {
|
||||
if (mapboxMap.style!!.getImage("small") == null && mapboxMap.style!!.getImage("large") == null) {
|
||||
latch.countDown()
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (!latch.await(5, TimeUnit.SECONDS)) {
|
||||
throw TimeoutException()
|
||||
}
|
||||
}
|
||||
|
||||
companion object {
|
||||
private const val styleJson =
|
||||
"""
|
||||
{
|
||||
"version": 8,
|
||||
"name": "Mapbox Streets",
|
||||
@@ -159,5 +160,5 @@ class RemoveUnusedImagesTest : AppCenter() {
|
||||
}]
|
||||
}
|
||||
"""
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -10,42 +10,43 @@ import com.mapbox.mapboxsdk.maps.MapView
|
||||
import com.mapbox.mapboxsdk.maps.MapboxMapOptions
|
||||
import com.mapbox.mapboxsdk.maps.renderer.glsurfaceview.MapboxGLSurfaceView
|
||||
import com.mapbox.mapboxsdk.testapp.activity.FeatureOverviewActivity
|
||||
import java.util.concurrent.CountDownLatch
|
||||
import junit.framework.Assert.assertNotNull
|
||||
import junit.framework.Assert.assertTrue
|
||||
import org.junit.Rule
|
||||
import org.junit.Test
|
||||
import org.junit.runner.RunWith
|
||||
import java.util.concurrent.CountDownLatch
|
||||
|
||||
@RunWith(AndroidJUnit4::class)
|
||||
class RenderViewGetterTest : AppCenter() {
|
||||
|
||||
@Rule
|
||||
@JvmField
|
||||
var rule = ActivityTestRule(FeatureOverviewActivity::class.java)
|
||||
@Rule
|
||||
@JvmField
|
||||
var rule = ActivityTestRule(FeatureOverviewActivity::class.java)
|
||||
|
||||
private lateinit var rootView: ViewGroup
|
||||
private lateinit var mapView: MapView
|
||||
private val latch: CountDownLatch = CountDownLatch(1)
|
||||
private lateinit var rootView: ViewGroup
|
||||
private lateinit var mapView: MapView
|
||||
private val latch: CountDownLatch = CountDownLatch(1)
|
||||
|
||||
@Test
|
||||
@UiThreadTest
|
||||
fun testGLSurfaceView() {
|
||||
rootView = rule.activity.findViewById(android.R.id.content)
|
||||
mapView = MapView(rule.activity)
|
||||
assertNotNull(mapView.renderView)
|
||||
assertTrue(mapView.renderView is MapboxGLSurfaceView)
|
||||
}
|
||||
@Test
|
||||
@UiThreadTest
|
||||
fun testGLSurfaceView() {
|
||||
rootView = rule.activity.findViewById(android.R.id.content)
|
||||
mapView = MapView(rule.activity)
|
||||
assertNotNull(mapView.renderView)
|
||||
assertTrue(mapView.renderView is MapboxGLSurfaceView)
|
||||
}
|
||||
|
||||
@Test
|
||||
@UiThreadTest
|
||||
fun testTextureView() {
|
||||
rootView = rule.activity.findViewById(android.R.id.content)
|
||||
mapView = MapView(rule.activity,
|
||||
MapboxMapOptions.createFromAttributes(rule.activity, null)
|
||||
.textureMode(true)
|
||||
)
|
||||
assertNotNull(mapView.renderView)
|
||||
assertTrue(mapView.renderView is TextureView)
|
||||
}
|
||||
}
|
||||
@Test
|
||||
@UiThreadTest
|
||||
fun testTextureView() {
|
||||
rootView = rule.activity.findViewById(android.R.id.content)
|
||||
mapView = MapView(
|
||||
rule.activity,
|
||||
MapboxMapOptions.createFromAttributes(rule.activity, null)
|
||||
.textureMode(true)
|
||||
)
|
||||
assertNotNull(mapView.renderView)
|
||||
assertTrue(mapView.renderView is TextureView)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -8,105 +8,121 @@ import com.mapbox.mapboxsdk.geometry.LatLng
|
||||
import com.mapbox.mapboxsdk.maps.MapView
|
||||
import com.mapbox.mapboxsdk.testapp.R
|
||||
import com.mapbox.mapboxsdk.testapp.activity.espresso.DeviceIndependentTestActivity
|
||||
import java.util.concurrent.CountDownLatch
|
||||
import java.util.concurrent.TimeUnit
|
||||
import org.junit.Assert.assertEquals
|
||||
import org.junit.Assert.assertTrue
|
||||
import org.junit.Before
|
||||
import org.junit.Rule
|
||||
import org.junit.Test
|
||||
import org.junit.runner.RunWith
|
||||
import java.util.concurrent.CountDownLatch
|
||||
import java.util.concurrent.TimeUnit
|
||||
|
||||
@RunWith(AndroidJUnit4::class)
|
||||
class ScreenCoordinateConversion : AppCenter() {
|
||||
|
||||
@Rule
|
||||
@JvmField
|
||||
var rule = ActivityTestRule(DeviceIndependentTestActivity::class.java)
|
||||
@Rule
|
||||
@JvmField
|
||||
var rule = ActivityTestRule(DeviceIndependentTestActivity::class.java)
|
||||
|
||||
private lateinit var mapView: MapView
|
||||
private lateinit var latch: CountDownLatch
|
||||
private lateinit var mapView: MapView
|
||||
private lateinit var latch: CountDownLatch
|
||||
|
||||
@Before
|
||||
fun setup() {
|
||||
latch = CountDownLatch(1)
|
||||
}
|
||||
|
||||
@Test
|
||||
fun testToScreenCoordinates() {
|
||||
rule.runOnUiThread {
|
||||
mapView = rule.activity.findViewById(R.id.mapView)
|
||||
val expected = doubleArrayOf(261.6888889445351, 253.15541110551123, 267.37777788907033, 247.4627648056528)
|
||||
val actual = doubleArrayOf(0.0, 0.0, 0.0, 0.0)
|
||||
mapView.getMapAsync {
|
||||
val projection = it.projection
|
||||
projection.toScreenLocations(doubleArrayOf(1.0, 2.0, 3.0, 4.0), actual)
|
||||
// check all values
|
||||
assertTrue(expected.contentEquals(actual))
|
||||
// check first coordinate value
|
||||
val pointFirst = PointF(expected[0].toFloat(), expected[1].toFloat())
|
||||
val convertedFirst = projection.toScreenLocation(LatLng(1.0, 2.0))
|
||||
assertEquals(
|
||||
pointFirst.x, convertedFirst.x, DELTA_FLOAT
|
||||
)
|
||||
assertEquals(
|
||||
pointFirst.y, convertedFirst.y, DELTA_FLOAT
|
||||
)
|
||||
|
||||
// check second latlng value
|
||||
val pointSecond = PointF(expected[2].toFloat(), expected[3].toFloat())
|
||||
val convertedSecond = projection.toScreenLocation(LatLng(3.0, 4.0))
|
||||
assertEquals(
|
||||
pointSecond.x, convertedSecond.x, DELTA_FLOAT
|
||||
)
|
||||
assertEquals(
|
||||
pointSecond.y, convertedSecond.y, DELTA_FLOAT
|
||||
)
|
||||
latch.countDown()
|
||||
}
|
||||
@Before
|
||||
fun setup() {
|
||||
latch = CountDownLatch(1)
|
||||
}
|
||||
latch.await(10, TimeUnit.SECONDS)
|
||||
}
|
||||
|
||||
@Test
|
||||
fun testFromScreenCoordinates() {
|
||||
rule.runOnUiThread {
|
||||
mapView = rule.activity.findViewById(R.id.mapView)
|
||||
val expected = doubleArrayOf(66.2314571265913, -89.64843662311537, 65.94647142295494, -88.94531162999371)
|
||||
val actual = doubleArrayOf(0.0, 0.0, 0.0, 0.0)
|
||||
mapView.getMapAsync {
|
||||
val projection = it.projection
|
||||
projection.fromScreenLocations(doubleArrayOf(1.0, 2.0, 3.0, 4.0), actual)
|
||||
// check all values at once
|
||||
assertTrue(expected.contentEquals(actual))
|
||||
@Test
|
||||
fun testToScreenCoordinates() {
|
||||
rule.runOnUiThread {
|
||||
mapView = rule.activity.findViewById(R.id.mapView)
|
||||
val expected = doubleArrayOf(261.6888889445351, 253.15541110551123, 267.37777788907033, 247.4627648056528)
|
||||
val actual = doubleArrayOf(0.0, 0.0, 0.0, 0.0)
|
||||
mapView.getMapAsync {
|
||||
val projection = it.projection
|
||||
projection.toScreenLocations(doubleArrayOf(1.0, 2.0, 3.0, 4.0), actual)
|
||||
// check all values
|
||||
assertTrue(expected.contentEquals(actual))
|
||||
// check first coordinate value
|
||||
val pointFirst = PointF(expected[0].toFloat(), expected[1].toFloat())
|
||||
val convertedFirst = projection.toScreenLocation(LatLng(1.0, 2.0))
|
||||
assertEquals(
|
||||
pointFirst.x,
|
||||
convertedFirst.x,
|
||||
DELTA_FLOAT
|
||||
)
|
||||
assertEquals(
|
||||
pointFirst.y,
|
||||
convertedFirst.y,
|
||||
DELTA_FLOAT
|
||||
)
|
||||
|
||||
// check first latlng value
|
||||
val latLngFirst = LatLng(expected[0], expected[1])
|
||||
val convertedFirst = projection.fromScreenLocation(PointF(1.0f, 2.0f))
|
||||
assertEquals(
|
||||
latLngFirst.latitude, convertedFirst.latitude, DELTA_DOUBLE
|
||||
)
|
||||
assertEquals(
|
||||
latLngFirst.longitude, convertedFirst.longitude, DELTA_DOUBLE
|
||||
)
|
||||
|
||||
// check second latlng value
|
||||
val latLngSecond = LatLng(expected[2], expected[3])
|
||||
val convertedSecond = projection.fromScreenLocation(PointF(3.0f, 4.0f))
|
||||
assertEquals(
|
||||
latLngSecond.latitude, convertedSecond.latitude, DELTA_DOUBLE
|
||||
)
|
||||
assertEquals(
|
||||
latLngSecond.longitude, convertedSecond.longitude, DELTA_DOUBLE
|
||||
)
|
||||
latch.countDown()
|
||||
}
|
||||
// check second latlng value
|
||||
val pointSecond = PointF(expected[2].toFloat(), expected[3].toFloat())
|
||||
val convertedSecond = projection.toScreenLocation(LatLng(3.0, 4.0))
|
||||
assertEquals(
|
||||
pointSecond.x,
|
||||
convertedSecond.x,
|
||||
DELTA_FLOAT
|
||||
)
|
||||
assertEquals(
|
||||
pointSecond.y,
|
||||
convertedSecond.y,
|
||||
DELTA_FLOAT
|
||||
)
|
||||
latch.countDown()
|
||||
}
|
||||
}
|
||||
latch.await(10, TimeUnit.SECONDS)
|
||||
}
|
||||
latch.await(10, TimeUnit.SECONDS)
|
||||
}
|
||||
|
||||
companion object {
|
||||
const val DELTA_DOUBLE = 0.000001
|
||||
const val DELTA_FLOAT = 0.000001f
|
||||
}
|
||||
}
|
||||
@Test
|
||||
fun testFromScreenCoordinates() {
|
||||
rule.runOnUiThread {
|
||||
mapView = rule.activity.findViewById(R.id.mapView)
|
||||
val expected = doubleArrayOf(66.2314571265913, -89.64843662311537, 65.94647142295494, -88.94531162999371)
|
||||
val actual = doubleArrayOf(0.0, 0.0, 0.0, 0.0)
|
||||
mapView.getMapAsync {
|
||||
val projection = it.projection
|
||||
projection.fromScreenLocations(doubleArrayOf(1.0, 2.0, 3.0, 4.0), actual)
|
||||
// check all values at once
|
||||
assertTrue(expected.contentEquals(actual))
|
||||
|
||||
// check first latlng value
|
||||
val latLngFirst = LatLng(expected[0], expected[1])
|
||||
val convertedFirst = projection.fromScreenLocation(PointF(1.0f, 2.0f))
|
||||
assertEquals(
|
||||
latLngFirst.latitude,
|
||||
convertedFirst.latitude,
|
||||
DELTA_DOUBLE
|
||||
)
|
||||
assertEquals(
|
||||
latLngFirst.longitude,
|
||||
convertedFirst.longitude,
|
||||
DELTA_DOUBLE
|
||||
)
|
||||
|
||||
// check second latlng value
|
||||
val latLngSecond = LatLng(expected[2], expected[3])
|
||||
val convertedSecond = projection.fromScreenLocation(PointF(3.0f, 4.0f))
|
||||
assertEquals(
|
||||
latLngSecond.latitude,
|
||||
convertedSecond.latitude,
|
||||
DELTA_DOUBLE
|
||||
)
|
||||
assertEquals(
|
||||
latLngSecond.longitude,
|
||||
convertedSecond.longitude,
|
||||
DELTA_DOUBLE
|
||||
)
|
||||
latch.countDown()
|
||||
}
|
||||
}
|
||||
latch.await(10, TimeUnit.SECONDS)
|
||||
}
|
||||
|
||||
companion object {
|
||||
const val DELTA_DOUBLE = 0.000001
|
||||
const val DELTA_FLOAT = 0.000001f
|
||||
}
|
||||
}
|
||||
|
||||
@@ -28,4 +28,4 @@ class StyleLoadTest : EspressoTest() {
|
||||
source.setGeoJson("{}")
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -5,100 +5,103 @@ import androidx.test.ext.junit.runners.AndroidJUnit4
|
||||
import androidx.test.rule.ActivityTestRule
|
||||
import com.mapbox.mapboxsdk.offline.OfflineManager
|
||||
import com.mapbox.mapboxsdk.testapp.activity.FeatureOverviewActivity
|
||||
import java.util.concurrent.CountDownLatch
|
||||
import org.junit.Assert
|
||||
import org.junit.Rule
|
||||
import org.junit.Test
|
||||
import org.junit.runner.RunWith
|
||||
import java.util.concurrent.CountDownLatch
|
||||
|
||||
@RunWith(AndroidJUnit4::class)
|
||||
class CacheTest {
|
||||
|
||||
@Rule
|
||||
@JvmField
|
||||
var rule = ActivityTestRule(FeatureOverviewActivity::class.java)
|
||||
@Rule
|
||||
@JvmField
|
||||
var rule = ActivityTestRule(FeatureOverviewActivity::class.java)
|
||||
|
||||
private val context: Context by lazy { rule.activity }
|
||||
private val context: Context by lazy { rule.activity }
|
||||
|
||||
private val countDownLatch = CountDownLatch(1)
|
||||
private val countDownLatch = CountDownLatch(1)
|
||||
|
||||
@Test
|
||||
fun testSetMaximumAmbientCacheSize() {
|
||||
rule.activity.runOnUiThread {
|
||||
OfflineManager.getInstance(context).setMaximumAmbientCacheSize(10000000, object : OfflineManager.FileSourceCallback {
|
||||
override fun onSuccess() {
|
||||
countDownLatch.countDown()
|
||||
@Test
|
||||
fun testSetMaximumAmbientCacheSize() {
|
||||
rule.activity.runOnUiThread {
|
||||
OfflineManager.getInstance(context).setMaximumAmbientCacheSize(
|
||||
10000000,
|
||||
object : OfflineManager.FileSourceCallback {
|
||||
override fun onSuccess() {
|
||||
countDownLatch.countDown()
|
||||
}
|
||||
|
||||
override fun onError(message: String) {
|
||||
Assert.assertNull("onError should not be called", message)
|
||||
}
|
||||
}
|
||||
)
|
||||
}
|
||||
|
||||
override fun onError(message: String) {
|
||||
Assert.assertNull("onError should not be called", message)
|
||||
}
|
||||
})
|
||||
countDownLatch.await()
|
||||
}
|
||||
countDownLatch.await()
|
||||
}
|
||||
|
||||
@Test
|
||||
fun testSetClearAmbientCache() {
|
||||
rule.activity.runOnUiThread {
|
||||
OfflineManager.getInstance(context).clearAmbientCache(object : OfflineManager.FileSourceCallback {
|
||||
override fun onSuccess() {
|
||||
countDownLatch.countDown()
|
||||
}
|
||||
@Test
|
||||
fun testSetClearAmbientCache() {
|
||||
rule.activity.runOnUiThread {
|
||||
OfflineManager.getInstance(context).clearAmbientCache(object : OfflineManager.FileSourceCallback {
|
||||
override fun onSuccess() {
|
||||
countDownLatch.countDown()
|
||||
}
|
||||
|
||||
override fun onError(message: String) {
|
||||
Assert.assertNull("onError should not be called", message)
|
||||
override fun onError(message: String) {
|
||||
Assert.assertNull("onError should not be called", message)
|
||||
}
|
||||
})
|
||||
}
|
||||
})
|
||||
countDownLatch.await()
|
||||
}
|
||||
countDownLatch.await()
|
||||
}
|
||||
|
||||
@Test
|
||||
fun testSetInvalidateAmbientCache() {
|
||||
rule.activity.runOnUiThread {
|
||||
OfflineManager.getInstance(context).invalidateAmbientCache(object : OfflineManager.FileSourceCallback {
|
||||
override fun onSuccess() {
|
||||
countDownLatch.countDown()
|
||||
}
|
||||
@Test
|
||||
fun testSetInvalidateAmbientCache() {
|
||||
rule.activity.runOnUiThread {
|
||||
OfflineManager.getInstance(context).invalidateAmbientCache(object : OfflineManager.FileSourceCallback {
|
||||
override fun onSuccess() {
|
||||
countDownLatch.countDown()
|
||||
}
|
||||
|
||||
override fun onError(message: String) {
|
||||
Assert.assertNull("onError should not be called", message)
|
||||
override fun onError(message: String) {
|
||||
Assert.assertNull("onError should not be called", message)
|
||||
}
|
||||
})
|
||||
}
|
||||
})
|
||||
countDownLatch.await()
|
||||
}
|
||||
countDownLatch.await()
|
||||
}
|
||||
|
||||
@Test
|
||||
fun testSetResetDatabase() {
|
||||
rule.activity.runOnUiThread {
|
||||
OfflineManager.getInstance(context).resetDatabase(object : OfflineManager.FileSourceCallback {
|
||||
override fun onSuccess() {
|
||||
countDownLatch.countDown()
|
||||
}
|
||||
@Test
|
||||
fun testSetResetDatabase() {
|
||||
rule.activity.runOnUiThread {
|
||||
OfflineManager.getInstance(context).resetDatabase(object : OfflineManager.FileSourceCallback {
|
||||
override fun onSuccess() {
|
||||
countDownLatch.countDown()
|
||||
}
|
||||
|
||||
override fun onError(message: String) {
|
||||
Assert.assertNull("onError should not be called", message)
|
||||
override fun onError(message: String) {
|
||||
Assert.assertNull("onError should not be called", message)
|
||||
}
|
||||
})
|
||||
}
|
||||
})
|
||||
countDownLatch.await()
|
||||
}
|
||||
countDownLatch.await()
|
||||
}
|
||||
|
||||
@Test
|
||||
fun testSetPackDatabase() {
|
||||
rule.activity.runOnUiThread {
|
||||
OfflineManager.getInstance(context).packDatabase(object : OfflineManager.FileSourceCallback {
|
||||
override fun onSuccess() {
|
||||
countDownLatch.countDown()
|
||||
}
|
||||
@Test
|
||||
fun testSetPackDatabase() {
|
||||
rule.activity.runOnUiThread {
|
||||
OfflineManager.getInstance(context).packDatabase(object : OfflineManager.FileSourceCallback {
|
||||
override fun onSuccess() {
|
||||
countDownLatch.countDown()
|
||||
}
|
||||
|
||||
override fun onError(message: String) {
|
||||
Assert.assertNull("onError should not be called", message)
|
||||
override fun onError(message: String) {
|
||||
Assert.assertNull("onError should not be called", message)
|
||||
}
|
||||
})
|
||||
}
|
||||
})
|
||||
countDownLatch.await()
|
||||
}
|
||||
countDownLatch.await()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -9,116 +9,120 @@ import com.mapbox.mapboxsdk.offline.OfflineRegion
|
||||
import com.mapbox.mapboxsdk.storage.FileSource
|
||||
import com.mapbox.mapboxsdk.testapp.activity.FeatureOverviewActivity
|
||||
import com.mapbox.mapboxsdk.testapp.utils.FileUtils
|
||||
import java.io.IOException
|
||||
import java.util.concurrent.CountDownLatch
|
||||
import org.junit.FixMethodOrder
|
||||
import org.junit.Rule
|
||||
import org.junit.Test
|
||||
import org.junit.runner.RunWith
|
||||
import org.junit.runners.MethodSorters
|
||||
import java.io.IOException
|
||||
import java.util.concurrent.CountDownLatch
|
||||
|
||||
@FixMethodOrder(MethodSorters.NAME_ASCENDING)
|
||||
@RunWith(AndroidJUnit4::class)
|
||||
class OfflineManagerTest : AppCenter() {
|
||||
|
||||
companion object {
|
||||
private const val TEST_DB_FILE_NAME = "offline_test.db"
|
||||
private lateinit var mergedRegion: OfflineRegion
|
||||
}
|
||||
|
||||
@Rule
|
||||
@JvmField
|
||||
var rule = ActivityTestRule(FeatureOverviewActivity::class.java)
|
||||
|
||||
private val context: Context by lazy { rule.activity }
|
||||
|
||||
@Test(timeout = 30_000)
|
||||
fun a_copyFileFromAssets() {
|
||||
val latch = CountDownLatch(1)
|
||||
rule.activity.runOnUiThread {
|
||||
FileUtils.CopyFileFromAssetsTask(rule.activity, object : FileUtils.OnFileCopiedFromAssetsListener {
|
||||
override fun onFileCopiedFromAssets() {
|
||||
latch.countDown()
|
||||
}
|
||||
|
||||
override fun onError() {
|
||||
throw IOException("Unable to copy DB file.")
|
||||
}
|
||||
}).execute(TEST_DB_FILE_NAME, FileSource.getResourcesCachePath(rule.activity))
|
||||
companion object {
|
||||
private const val TEST_DB_FILE_NAME = "offline_test.db"
|
||||
private lateinit var mergedRegion: OfflineRegion
|
||||
}
|
||||
latch.await()
|
||||
}
|
||||
|
||||
@Test(timeout = 30_000)
|
||||
fun b_mergeRegion() {
|
||||
val latch = CountDownLatch(1)
|
||||
rule.activity.runOnUiThread {
|
||||
OfflineManager.getInstance(context).mergeOfflineRegions(
|
||||
FileSource.getResourcesCachePath(rule.activity) + "/" + TEST_DB_FILE_NAME,
|
||||
object : OfflineManager.MergeOfflineRegionsCallback {
|
||||
override fun onMerge(offlineRegions: Array<out OfflineRegion>?) {
|
||||
assert(offlineRegions?.size == 1)
|
||||
latch.countDown()
|
||||
}
|
||||
@Rule
|
||||
@JvmField
|
||||
var rule = ActivityTestRule(FeatureOverviewActivity::class.java)
|
||||
|
||||
override fun onError(error: String?) {
|
||||
throw RuntimeException("Unable to merge external offline database. $error")
|
||||
}
|
||||
})
|
||||
private val context: Context by lazy { rule.activity }
|
||||
|
||||
@Test(timeout = 30_000)
|
||||
fun a_copyFileFromAssets() {
|
||||
val latch = CountDownLatch(1)
|
||||
rule.activity.runOnUiThread {
|
||||
FileUtils.CopyFileFromAssetsTask(
|
||||
rule.activity,
|
||||
object : FileUtils.OnFileCopiedFromAssetsListener {
|
||||
override fun onFileCopiedFromAssets() {
|
||||
latch.countDown()
|
||||
}
|
||||
|
||||
override fun onError() {
|
||||
throw IOException("Unable to copy DB file.")
|
||||
}
|
||||
}
|
||||
).execute(TEST_DB_FILE_NAME, FileSource.getResourcesCachePath(rule.activity))
|
||||
}
|
||||
latch.await()
|
||||
}
|
||||
latch.await()
|
||||
}
|
||||
|
||||
@Test(timeout = 30_000)
|
||||
fun c_listRegion() {
|
||||
val latch = CountDownLatch(1)
|
||||
rule.activity.runOnUiThread {
|
||||
OfflineManager.getInstance(context).listOfflineRegions(object : OfflineManager.ListOfflineRegionsCallback {
|
||||
override fun onList(offlineRegions: Array<out OfflineRegion>?) {
|
||||
assert(offlineRegions?.size == 1)
|
||||
mergedRegion = offlineRegions!![0]
|
||||
latch.countDown()
|
||||
}
|
||||
@Test(timeout = 30_000)
|
||||
fun b_mergeRegion() {
|
||||
val latch = CountDownLatch(1)
|
||||
rule.activity.runOnUiThread {
|
||||
OfflineManager.getInstance(context).mergeOfflineRegions(
|
||||
FileSource.getResourcesCachePath(rule.activity) + "/" + TEST_DB_FILE_NAME,
|
||||
object : OfflineManager.MergeOfflineRegionsCallback {
|
||||
override fun onMerge(offlineRegions: Array<out OfflineRegion>?) {
|
||||
assert(offlineRegions?.size == 1)
|
||||
latch.countDown()
|
||||
}
|
||||
|
||||
override fun onError(error: String?) {
|
||||
throw RuntimeException("Unable to merge external offline database. $error")
|
||||
override fun onError(error: String?) {
|
||||
throw RuntimeException("Unable to merge external offline database. $error")
|
||||
}
|
||||
}
|
||||
)
|
||||
}
|
||||
})
|
||||
latch.await()
|
||||
}
|
||||
latch.await()
|
||||
}
|
||||
|
||||
@Test(timeout = 30_000)
|
||||
fun d_invalidateRegion() {
|
||||
val latch = CountDownLatch(1)
|
||||
rule.activity.runOnUiThread {
|
||||
mergedRegion.invalidate(object : OfflineRegion.OfflineRegionInvalidateCallback {
|
||||
override fun onInvalidate() {
|
||||
latch.countDown()
|
||||
}
|
||||
@Test(timeout = 30_000)
|
||||
fun c_listRegion() {
|
||||
val latch = CountDownLatch(1)
|
||||
rule.activity.runOnUiThread {
|
||||
OfflineManager.getInstance(context).listOfflineRegions(object : OfflineManager.ListOfflineRegionsCallback {
|
||||
override fun onList(offlineRegions: Array<out OfflineRegion>?) {
|
||||
assert(offlineRegions?.size == 1)
|
||||
mergedRegion = offlineRegions!![0]
|
||||
latch.countDown()
|
||||
}
|
||||
|
||||
override fun onError(error: String?) {
|
||||
throw RuntimeException("Unable to delete region")
|
||||
override fun onError(error: String?) {
|
||||
throw RuntimeException("Unable to merge external offline database. $error")
|
||||
}
|
||||
})
|
||||
}
|
||||
})
|
||||
latch.await()
|
||||
}
|
||||
latch.await()
|
||||
}
|
||||
|
||||
@Test(timeout = 30_000)
|
||||
fun e_deleteRegion() {
|
||||
val latch = CountDownLatch(1)
|
||||
rule.activity.runOnUiThread {
|
||||
mergedRegion.delete(object : OfflineRegion.OfflineRegionDeleteCallback {
|
||||
override fun onDelete() {
|
||||
latch.countDown()
|
||||
}
|
||||
@Test(timeout = 30_000)
|
||||
fun d_invalidateRegion() {
|
||||
val latch = CountDownLatch(1)
|
||||
rule.activity.runOnUiThread {
|
||||
mergedRegion.invalidate(object : OfflineRegion.OfflineRegionInvalidateCallback {
|
||||
override fun onInvalidate() {
|
||||
latch.countDown()
|
||||
}
|
||||
|
||||
override fun onError(error: String?) {
|
||||
throw RuntimeException("Unable to delete region")
|
||||
override fun onError(error: String?) {
|
||||
throw RuntimeException("Unable to delete region")
|
||||
}
|
||||
})
|
||||
}
|
||||
})
|
||||
latch.await()
|
||||
}
|
||||
latch.await()
|
||||
}
|
||||
}
|
||||
|
||||
@Test(timeout = 30_000)
|
||||
fun e_deleteRegion() {
|
||||
val latch = CountDownLatch(1)
|
||||
rule.activity.runOnUiThread {
|
||||
mergedRegion.delete(object : OfflineRegion.OfflineRegionDeleteCallback {
|
||||
override fun onDelete() {
|
||||
latch.countDown()
|
||||
}
|
||||
|
||||
override fun onError(error: String?) {
|
||||
throw RuntimeException("Unable to delete region")
|
||||
}
|
||||
})
|
||||
}
|
||||
latch.await()
|
||||
}
|
||||
}
|
||||
|
||||
@@ -6,7 +6,6 @@ import androidx.test.rule.ActivityTestRule
|
||||
import com.mapbox.mapboxsdk.AppCenter
|
||||
import com.mapbox.mapboxsdk.storage.FileSource
|
||||
import com.mapbox.mapboxsdk.testapp.activity.espresso.EspressoTestActivity
|
||||
import java.util.concurrent.CountDownLatch
|
||||
import junit.framework.Assert
|
||||
import org.junit.After
|
||||
import org.junit.Before
|
||||
@@ -14,45 +13,49 @@ import org.junit.Rule
|
||||
import org.junit.Test
|
||||
import org.junit.rules.TestName
|
||||
import org.junit.runner.RunWith
|
||||
import java.util.concurrent.CountDownLatch
|
||||
|
||||
@RunWith(AndroidJUnit4::class)
|
||||
open class FileSourceMapTest : AppCenter() {
|
||||
|
||||
private lateinit var fileSourceTestUtils: FileSourceTestUtils
|
||||
private lateinit var fileSourceTestUtils: FileSourceTestUtils
|
||||
|
||||
@get:Rule
|
||||
val rule = ActivityTestRule(EspressoTestActivity::class.java)
|
||||
@get:Rule
|
||||
val rule = ActivityTestRule(EspressoTestActivity::class.java)
|
||||
|
||||
@get:Rule
|
||||
val testName = TestName()
|
||||
@get:Rule
|
||||
val testName = TestName()
|
||||
|
||||
@Before
|
||||
@UiThreadTest
|
||||
fun setup() {
|
||||
fileSourceTestUtils = FileSourceTestUtils(rule.activity)
|
||||
fileSourceTestUtils.setup()
|
||||
}
|
||||
|
||||
@Test
|
||||
fun changeResourcesPathWhileMapVisible() {
|
||||
val latch = CountDownLatch(1)
|
||||
rule.activity.runOnUiThread {
|
||||
FileSource.setResourcesCachePath(fileSourceTestUtils.testPath, object : FileSource.ResourcesCachePathChangeCallback {
|
||||
override fun onSuccess(path: String) {
|
||||
latch.countDown()
|
||||
Assert.assertEquals(fileSourceTestUtils.testPath, path)
|
||||
}
|
||||
|
||||
override fun onError(message: String) {
|
||||
Assert.fail("Resources path can be changed while the map is running")
|
||||
}
|
||||
})
|
||||
@Before
|
||||
@UiThreadTest
|
||||
fun setup() {
|
||||
fileSourceTestUtils = FileSourceTestUtils(rule.activity)
|
||||
fileSourceTestUtils.setup()
|
||||
}
|
||||
latch.await()
|
||||
}
|
||||
|
||||
@After
|
||||
fun cleanup() {
|
||||
fileSourceTestUtils.cleanup()
|
||||
}
|
||||
}
|
||||
@Test
|
||||
fun changeResourcesPathWhileMapVisible() {
|
||||
val latch = CountDownLatch(1)
|
||||
rule.activity.runOnUiThread {
|
||||
FileSource.setResourcesCachePath(
|
||||
fileSourceTestUtils.testPath,
|
||||
object : FileSource.ResourcesCachePathChangeCallback {
|
||||
override fun onSuccess(path: String) {
|
||||
latch.countDown()
|
||||
Assert.assertEquals(fileSourceTestUtils.testPath, path)
|
||||
}
|
||||
|
||||
override fun onError(message: String) {
|
||||
Assert.fail("Resources path can be changed while the map is running")
|
||||
}
|
||||
}
|
||||
)
|
||||
}
|
||||
latch.await()
|
||||
}
|
||||
|
||||
@After
|
||||
fun cleanup() {
|
||||
fileSourceTestUtils.cleanup()
|
||||
}
|
||||
}
|
||||
|
||||
@@ -6,105 +6,107 @@ import androidx.test.rule.ActivityTestRule
|
||||
import com.mapbox.mapboxsdk.AppCenter
|
||||
import com.mapbox.mapboxsdk.storage.FileSource
|
||||
import com.mapbox.mapboxsdk.testapp.activity.FeatureOverviewActivity
|
||||
import java.util.concurrent.CountDownLatch
|
||||
import java.util.concurrent.TimeUnit
|
||||
import org.junit.*
|
||||
import org.junit.rules.TestName
|
||||
import org.junit.runner.RunWith
|
||||
import java.util.concurrent.CountDownLatch
|
||||
import java.util.concurrent.TimeUnit
|
||||
|
||||
@RunWith(AndroidJUnit4::class)
|
||||
class FileSourceStandaloneTest : AppCenter() {
|
||||
|
||||
private lateinit var fileSourceTestUtils: FileSourceTestUtils
|
||||
private lateinit var fileSource: FileSource
|
||||
private lateinit var fileSourceTestUtils: FileSourceTestUtils
|
||||
private lateinit var fileSource: FileSource
|
||||
|
||||
@get:Rule
|
||||
val rule = ActivityTestRule(FeatureOverviewActivity::class.java)
|
||||
@get:Rule
|
||||
val rule = ActivityTestRule(FeatureOverviewActivity::class.java)
|
||||
|
||||
@get:Rule
|
||||
val testName = TestName()
|
||||
@get:Rule
|
||||
val testName = TestName()
|
||||
|
||||
@Before
|
||||
@UiThreadTest
|
||||
fun setup() {
|
||||
fileSource = FileSource.getInstance(rule.activity)
|
||||
fileSourceTestUtils = FileSourceTestUtils(rule.activity)
|
||||
fileSourceTestUtils.setup()
|
||||
}
|
||||
@Before
|
||||
@UiThreadTest
|
||||
fun setup() {
|
||||
fileSource = FileSource.getInstance(rule.activity)
|
||||
fileSourceTestUtils = FileSourceTestUtils(rule.activity)
|
||||
fileSourceTestUtils.setup()
|
||||
}
|
||||
|
||||
@Test
|
||||
@UiThreadTest
|
||||
fun testDefault() {
|
||||
Assert.assertTrue("FileSource should be active", fileSource.isActivated)
|
||||
}
|
||||
@Test
|
||||
@UiThreadTest
|
||||
fun testDefault() {
|
||||
Assert.assertTrue("FileSource should be active", fileSource.isActivated)
|
||||
}
|
||||
|
||||
@Test
|
||||
@UiThreadTest
|
||||
fun testActivateDeactivate() {
|
||||
Assert.assertTrue("1) FileSource should be active", fileSource.isActivated)
|
||||
fileSource.deactivate()
|
||||
Assert.assertFalse("2) FileSource should not be active", fileSource.isActivated)
|
||||
fileSource.activate()
|
||||
Assert.assertTrue("3) FileSource should be active", fileSource.isActivated)
|
||||
}
|
||||
@Test
|
||||
@UiThreadTest
|
||||
fun testActivateDeactivate() {
|
||||
Assert.assertTrue("1) FileSource should be active", fileSource.isActivated)
|
||||
fileSource.deactivate()
|
||||
Assert.assertFalse("2) FileSource should not be active", fileSource.isActivated)
|
||||
fileSource.activate()
|
||||
Assert.assertTrue("3) FileSource should be active", fileSource.isActivated)
|
||||
}
|
||||
|
||||
@Test
|
||||
fun pathChangeTest() {
|
||||
Assert.assertTrue("FileSource should be active", fileSource.isActivated)
|
||||
Assert.assertEquals(fileSourceTestUtils.originalPath, FileSource.getResourcesCachePath(rule.activity))
|
||||
@Test
|
||||
fun pathChangeTest() {
|
||||
Assert.assertTrue("FileSource should be active", fileSource.isActivated)
|
||||
Assert.assertEquals(fileSourceTestUtils.originalPath, FileSource.getResourcesCachePath(rule.activity))
|
||||
|
||||
fileSourceTestUtils.changePath(fileSourceTestUtils.testPath)
|
||||
Assert.assertEquals(fileSourceTestUtils.testPath, FileSource.getResourcesCachePath(rule.activity))
|
||||
Assert.assertTrue("FileSource should be active", fileSource.isActivated)
|
||||
fileSourceTestUtils.changePath(fileSourceTestUtils.testPath)
|
||||
Assert.assertEquals(fileSourceTestUtils.testPath, FileSource.getResourcesCachePath(rule.activity))
|
||||
Assert.assertTrue("FileSource should be active", fileSource.isActivated)
|
||||
|
||||
fileSourceTestUtils.changePath(fileSourceTestUtils.originalPath)
|
||||
Assert.assertEquals(fileSourceTestUtils.originalPath, FileSource.getResourcesCachePath(rule.activity))
|
||||
Assert.assertTrue("FileSource should be active", fileSource.isActivated)
|
||||
}
|
||||
fileSourceTestUtils.changePath(fileSourceTestUtils.originalPath)
|
||||
Assert.assertEquals(fileSourceTestUtils.originalPath, FileSource.getResourcesCachePath(rule.activity))
|
||||
Assert.assertTrue("FileSource should be active", fileSource.isActivated)
|
||||
}
|
||||
|
||||
@Test
|
||||
fun overridePathChangeCallTest() {
|
||||
val firstLatch = CountDownLatch(1)
|
||||
val secondLatch = CountDownLatch(1)
|
||||
rule.activity.runOnUiThread {
|
||||
FileSource.setResourcesCachePath(
|
||||
fileSourceTestUtils.testPath,
|
||||
object : FileSource.ResourcesCachePathChangeCallback {
|
||||
override fun onSuccess(path: String) {
|
||||
Assert.assertEquals(fileSourceTestUtils.testPath, path)
|
||||
firstLatch.countDown()
|
||||
}
|
||||
@Test
|
||||
fun overridePathChangeCallTest() {
|
||||
val firstLatch = CountDownLatch(1)
|
||||
val secondLatch = CountDownLatch(1)
|
||||
rule.activity.runOnUiThread {
|
||||
FileSource.setResourcesCachePath(
|
||||
fileSourceTestUtils.testPath,
|
||||
object : FileSource.ResourcesCachePathChangeCallback {
|
||||
override fun onSuccess(path: String) {
|
||||
Assert.assertEquals(fileSourceTestUtils.testPath, path)
|
||||
firstLatch.countDown()
|
||||
}
|
||||
|
||||
override fun onError(message: String) {
|
||||
override fun onError(message: String) {
|
||||
Assert.fail("First attempt should succeed.")
|
||||
}
|
||||
}
|
||||
)
|
||||
|
||||
FileSource.setResourcesCachePath(
|
||||
fileSourceTestUtils.testPath2,
|
||||
object : FileSource.ResourcesCachePathChangeCallback {
|
||||
override fun onSuccess(path: String) {
|
||||
Assert.fail("Second attempt should fail because first one is in progress.")
|
||||
}
|
||||
|
||||
override fun onError(message: String) {
|
||||
Assert.assertEquals("Another resources cache path change is in progress", message)
|
||||
secondLatch.countDown()
|
||||
}
|
||||
}
|
||||
)
|
||||
}
|
||||
|
||||
if (!secondLatch.await(5, TimeUnit.SECONDS)) {
|
||||
Assert.fail("Second attempt should fail.")
|
||||
}
|
||||
|
||||
if (!firstLatch.await(5, TimeUnit.SECONDS)) {
|
||||
Assert.fail("First attempt should succeed.")
|
||||
}
|
||||
})
|
||||
|
||||
FileSource.setResourcesCachePath(
|
||||
fileSourceTestUtils.testPath2,
|
||||
object : FileSource.ResourcesCachePathChangeCallback {
|
||||
override fun onSuccess(path: String) {
|
||||
Assert.fail("Second attempt should fail because first one is in progress.")
|
||||
}
|
||||
|
||||
override fun onError(message: String) {
|
||||
Assert.assertEquals("Another resources cache path change is in progress", message)
|
||||
secondLatch.countDown()
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
if (!secondLatch.await(5, TimeUnit.SECONDS)) {
|
||||
Assert.fail("Second attempt should fail.")
|
||||
@After
|
||||
fun cleanup() {
|
||||
fileSourceTestUtils.cleanup()
|
||||
}
|
||||
|
||||
if (!firstLatch.await(5, TimeUnit.SECONDS)) {
|
||||
Assert.fail("First attempt should succeed.")
|
||||
}
|
||||
}
|
||||
|
||||
@After
|
||||
fun cleanup() {
|
||||
fileSourceTestUtils.cleanup()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -4,56 +4,57 @@ import android.app.Activity
|
||||
import androidx.annotation.WorkerThread
|
||||
import com.mapbox.mapboxsdk.AppCenter
|
||||
import com.mapbox.mapboxsdk.storage.FileSource
|
||||
import junit.framework.Assert
|
||||
import java.io.File
|
||||
import java.util.concurrent.CountDownLatch
|
||||
import junit.framework.Assert
|
||||
|
||||
class FileSourceTestUtils(private val activity: Activity) : AppCenter() {
|
||||
val originalPath = FileSource.getResourcesCachePath(activity)
|
||||
val testPath = "$originalPath/test"
|
||||
val testPath2 = "$originalPath/test2"
|
||||
val originalPath = FileSource.getResourcesCachePath(activity)
|
||||
val testPath = "$originalPath/test"
|
||||
val testPath2 = "$originalPath/test2"
|
||||
|
||||
private val paths = listOf(testPath, testPath2)
|
||||
private val paths = listOf(testPath, testPath2)
|
||||
|
||||
fun setup() {
|
||||
for (path in paths) {
|
||||
val testFile = File(path)
|
||||
testFile.mkdirs()
|
||||
}
|
||||
}
|
||||
|
||||
@WorkerThread
|
||||
fun cleanup() {
|
||||
val currentPath = FileSource.getResourcesCachePath(activity)
|
||||
if (currentPath != originalPath) {
|
||||
changePath(originalPath)
|
||||
fun setup() {
|
||||
for (path in paths) {
|
||||
val testFile = File(path)
|
||||
testFile.mkdirs()
|
||||
}
|
||||
}
|
||||
|
||||
for (path in paths) {
|
||||
val testFile = File(path)
|
||||
if (testFile.exists()) {
|
||||
testFile.deleteRecursively()
|
||||
}
|
||||
}
|
||||
}
|
||||
@WorkerThread
|
||||
fun cleanup() {
|
||||
val currentPath = FileSource.getResourcesCachePath(activity)
|
||||
if (currentPath != originalPath) {
|
||||
changePath(originalPath)
|
||||
}
|
||||
|
||||
@WorkerThread
|
||||
fun changePath(requestedPath: String) {
|
||||
val latch = CountDownLatch(1)
|
||||
activity.runOnUiThread {
|
||||
FileSource.setResourcesCachePath(
|
||||
requestedPath,
|
||||
object : FileSource.ResourcesCachePathChangeCallback {
|
||||
override fun onSuccess(path: String) {
|
||||
Assert.assertEquals(requestedPath, path)
|
||||
latch.countDown()
|
||||
}
|
||||
|
||||
override fun onError(message: String) {
|
||||
Assert.fail("Resource path change failed - path: $requestedPath, message: $message")
|
||||
}
|
||||
})
|
||||
for (path in paths) {
|
||||
val testFile = File(path)
|
||||
if (testFile.exists()) {
|
||||
testFile.deleteRecursively()
|
||||
}
|
||||
}
|
||||
}
|
||||
latch.await()
|
||||
}
|
||||
}
|
||||
|
||||
@WorkerThread
|
||||
fun changePath(requestedPath: String) {
|
||||
val latch = CountDownLatch(1)
|
||||
activity.runOnUiThread {
|
||||
FileSource.setResourcesCachePath(
|
||||
requestedPath,
|
||||
object : FileSource.ResourcesCachePathChangeCallback {
|
||||
override fun onSuccess(path: String) {
|
||||
Assert.assertEquals(requestedPath, path)
|
||||
latch.countDown()
|
||||
}
|
||||
|
||||
override fun onError(message: String) {
|
||||
Assert.fail("Resource path change failed - path: $requestedPath, message: $message")
|
||||
}
|
||||
}
|
||||
)
|
||||
}
|
||||
latch.await()
|
||||
}
|
||||
}
|
||||
|
||||
@@ -19,92 +19,98 @@ import org.junit.Test
|
||||
|
||||
class CustomGeometrySourceTest : BaseTest() {
|
||||
|
||||
override fun getActivityClass(): Class<*> = GridSourceActivity::class.java
|
||||
override fun getActivityClass(): Class<*> = GridSourceActivity::class.java
|
||||
|
||||
@Test
|
||||
fun sourceNotLeakingThreadsTest() {
|
||||
validateTestSetup()
|
||||
WaitAction.invoke(4000)
|
||||
onView(isRoot()).perform(orientationLandscape())
|
||||
WaitAction.invoke(2000)
|
||||
onView(isRoot()).perform(orientationPortrait())
|
||||
WaitAction.invoke(2000)
|
||||
Assert.assertFalse("Threads should be shutdown when the source is destroyed.",
|
||||
Thread.getAllStackTraces().keys.filter {
|
||||
it.name.startsWith(THREAD_PREFIX)
|
||||
}.count() > THREAD_POOL_LIMIT)
|
||||
}
|
||||
|
||||
@Test
|
||||
fun threadsShutdownWhenSourceRemovedTest() {
|
||||
validateTestSetup()
|
||||
invoke(mapboxMap) { uiController, mapboxMap ->
|
||||
mapboxMap.style!!.removeLayer(ID_GRID_LAYER)
|
||||
TestingAsyncUtils.waitForLayer(uiController, mapView)
|
||||
mapboxMap.style!!.removeSource(ID_GRID_SOURCE)
|
||||
TestingAsyncUtils.waitForLayer(uiController, mapView)
|
||||
Assert.assertTrue("There should be no threads running when the source is removed.",
|
||||
Thread.getAllStackTraces().keys.filter {
|
||||
it.name.startsWith(THREAD_PREFIX)
|
||||
}.count() == 0)
|
||||
@Test
|
||||
fun sourceNotLeakingThreadsTest() {
|
||||
validateTestSetup()
|
||||
WaitAction.invoke(4000)
|
||||
onView(isRoot()).perform(orientationLandscape())
|
||||
WaitAction.invoke(2000)
|
||||
onView(isRoot()).perform(orientationPortrait())
|
||||
WaitAction.invoke(2000)
|
||||
Assert.assertFalse(
|
||||
"Threads should be shutdown when the source is destroyed.",
|
||||
Thread.getAllStackTraces().keys.filter {
|
||||
it.name.startsWith(THREAD_PREFIX)
|
||||
}.count() > THREAD_POOL_LIMIT
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
fun threadsRestartedWhenSourceReAddedTest() {
|
||||
validateTestSetup()
|
||||
invoke(mapboxMap) { uiController, mapboxMap ->
|
||||
mapboxMap.style!!.removeLayer((rule.activity as GridSourceActivity).layer)
|
||||
TestingAsyncUtils.waitForLayer(uiController, mapView)
|
||||
mapboxMap.style!!.removeSource(ID_GRID_SOURCE)
|
||||
TestingAsyncUtils.waitForLayer(uiController, mapView)
|
||||
mapboxMap.style!!.addSource((rule.activity as GridSourceActivity).source)
|
||||
mapboxMap.style!!.addLayer((rule.activity as GridSourceActivity).layer)
|
||||
TestingAsyncUtils.waitForLayer(uiController, mapView)
|
||||
Assert.assertTrue("Threads should be restarted when the source is re-added to the map.",
|
||||
Thread.getAllStackTraces().keys.filter {
|
||||
it.name.startsWith(THREAD_PREFIX)
|
||||
}.count() == THREAD_POOL_LIMIT)
|
||||
@Test
|
||||
fun threadsShutdownWhenSourceRemovedTest() {
|
||||
validateTestSetup()
|
||||
invoke(mapboxMap) { uiController, mapboxMap ->
|
||||
mapboxMap.style!!.removeLayer(ID_GRID_LAYER)
|
||||
TestingAsyncUtils.waitForLayer(uiController, mapView)
|
||||
mapboxMap.style!!.removeSource(ID_GRID_SOURCE)
|
||||
TestingAsyncUtils.waitForLayer(uiController, mapView)
|
||||
Assert.assertTrue(
|
||||
"There should be no threads running when the source is removed.",
|
||||
Thread.getAllStackTraces().keys.filter {
|
||||
it.name.startsWith(THREAD_PREFIX)
|
||||
}.count() == 0
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
fun sourceZoomDeltaTest() {
|
||||
validateTestSetup()
|
||||
invoke(mapboxMap) { uiController, mapboxMap ->
|
||||
mapboxMap.prefetchZoomDelta = 3
|
||||
mapboxMap.style!!.getSource(ID_GRID_SOURCE)!!.let {
|
||||
assertNull(it.prefetchZoomDelta)
|
||||
it.prefetchZoomDelta = 5
|
||||
assertNotNull(it.prefetchZoomDelta)
|
||||
assertEquals(5, it.prefetchZoomDelta!!)
|
||||
it.prefetchZoomDelta = null
|
||||
assertNull(it.prefetchZoomDelta)
|
||||
}
|
||||
@Test
|
||||
fun threadsRestartedWhenSourceReAddedTest() {
|
||||
validateTestSetup()
|
||||
invoke(mapboxMap) { uiController, mapboxMap ->
|
||||
mapboxMap.style!!.removeLayer((rule.activity as GridSourceActivity).layer)
|
||||
TestingAsyncUtils.waitForLayer(uiController, mapView)
|
||||
mapboxMap.style!!.removeSource(ID_GRID_SOURCE)
|
||||
TestingAsyncUtils.waitForLayer(uiController, mapView)
|
||||
mapboxMap.style!!.addSource((rule.activity as GridSourceActivity).source)
|
||||
mapboxMap.style!!.addLayer((rule.activity as GridSourceActivity).layer)
|
||||
TestingAsyncUtils.waitForLayer(uiController, mapView)
|
||||
Assert.assertTrue(
|
||||
"Threads should be restarted when the source is re-added to the map.",
|
||||
Thread.getAllStackTraces().keys.filter {
|
||||
it.name.startsWith(THREAD_PREFIX)
|
||||
}.count() == THREAD_POOL_LIMIT
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
fun isVolatileTest() {
|
||||
validateTestSetup()
|
||||
invoke(mapboxMap) { uiController, mapboxMap ->
|
||||
mapboxMap.style!!.getSource(ID_GRID_SOURCE)!!.let {
|
||||
assertFalse(it.isVolatile)
|
||||
it.isVolatile = true
|
||||
assertTrue(it.isVolatile)
|
||||
}
|
||||
@Test
|
||||
fun sourceZoomDeltaTest() {
|
||||
validateTestSetup()
|
||||
invoke(mapboxMap) { uiController, mapboxMap ->
|
||||
mapboxMap.prefetchZoomDelta = 3
|
||||
mapboxMap.style!!.getSource(ID_GRID_SOURCE)!!.let {
|
||||
assertNull(it.prefetchZoomDelta)
|
||||
it.prefetchZoomDelta = 5
|
||||
assertNotNull(it.prefetchZoomDelta)
|
||||
assertEquals(5, it.prefetchZoomDelta!!)
|
||||
it.prefetchZoomDelta = null
|
||||
assertNull(it.prefetchZoomDelta)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
fun minimumTileUpdateIntervalTest() {
|
||||
validateTestSetup()
|
||||
invoke(mapboxMap) { uiController, mapboxMap ->
|
||||
mapboxMap.style!!.getSource(ID_GRID_SOURCE)!!.let {
|
||||
assertEquals(0, it.minimumTileUpdateInterval)
|
||||
it.minimumTileUpdateInterval = 1000
|
||||
assertEquals(1000, it.minimumTileUpdateInterval)
|
||||
}
|
||||
@Test
|
||||
fun isVolatileTest() {
|
||||
validateTestSetup()
|
||||
invoke(mapboxMap) { uiController, mapboxMap ->
|
||||
mapboxMap.style!!.getSource(ID_GRID_SOURCE)!!.let {
|
||||
assertFalse(it.isVolatile)
|
||||
it.isVolatile = true
|
||||
assertTrue(it.isVolatile)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
fun minimumTileUpdateIntervalTest() {
|
||||
validateTestSetup()
|
||||
invoke(mapboxMap) { uiController, mapboxMap ->
|
||||
mapboxMap.style!!.getSource(ID_GRID_SOURCE)!!.let {
|
||||
assertEquals(0, it.minimumTileUpdateInterval)
|
||||
it.minimumTileUpdateInterval = 1000
|
||||
assertEquals(1000, it.minimumTileUpdateInterval)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -6,11 +6,11 @@ import androidx.test.ext.junit.runners.AndroidJUnit4
|
||||
import com.mapbox.mapboxsdk.testapp.R
|
||||
import com.mapbox.mapboxsdk.testapp.action.MapboxMapAction
|
||||
import com.mapbox.mapboxsdk.testapp.activity.EspressoTest
|
||||
import java.util.*
|
||||
import org.junit.Assert.assertNull
|
||||
import org.junit.Assert.assertTrue
|
||||
import org.junit.Test
|
||||
import org.junit.runner.RunWith
|
||||
import java.util.*
|
||||
|
||||
/**
|
||||
* CRUD tests around Image
|
||||
@@ -18,58 +18,58 @@ import org.junit.runner.RunWith
|
||||
@RunWith(AndroidJUnit4::class)
|
||||
class ImageTest : EspressoTest() {
|
||||
|
||||
companion object {
|
||||
private const val IMAGE_ID = "test.image"
|
||||
}
|
||||
|
||||
@Test
|
||||
fun testAddGetImage() {
|
||||
validateTestSetup()
|
||||
MapboxMapAction.invoke(mapboxMap) { uiController, mapboxMap ->
|
||||
val drawable = rule.activity.resources.getDrawable(R.drawable.ic_launcher_round)
|
||||
assertTrue(drawable is BitmapDrawable)
|
||||
|
||||
val bitmapSet = (drawable as BitmapDrawable).bitmap
|
||||
mapboxMap.style!!.addImage(IMAGE_ID, bitmapSet)
|
||||
|
||||
// adding an image requires converting the image with an asynctask
|
||||
uiController.loopMainThreadForAtLeast(200)
|
||||
|
||||
val bitmapGet = mapboxMap.style!!.getImage(IMAGE_ID)
|
||||
assertTrue(bitmapGet!!.similarTo(bitmapSet))
|
||||
|
||||
mapboxMap.style!!.removeImage(IMAGE_ID)
|
||||
assertNull(mapboxMap.style!!.getImage(IMAGE_ID))
|
||||
companion object {
|
||||
private const val IMAGE_ID = "test.image"
|
||||
}
|
||||
|
||||
@Test
|
||||
fun testAddGetImage() {
|
||||
validateTestSetup()
|
||||
MapboxMapAction.invoke(mapboxMap) { uiController, mapboxMap ->
|
||||
val drawable = rule.activity.resources.getDrawable(R.drawable.ic_launcher_round)
|
||||
assertTrue(drawable is BitmapDrawable)
|
||||
|
||||
val bitmapSet = (drawable as BitmapDrawable).bitmap
|
||||
mapboxMap.style!!.addImage(IMAGE_ID, bitmapSet)
|
||||
|
||||
// adding an image requires converting the image with an asynctask
|
||||
uiController.loopMainThreadForAtLeast(200)
|
||||
|
||||
val bitmapGet = mapboxMap.style!!.getImage(IMAGE_ID)
|
||||
assertTrue(bitmapGet!!.similarTo(bitmapSet))
|
||||
|
||||
mapboxMap.style!!.removeImage(IMAGE_ID)
|
||||
assertNull(mapboxMap.style!!.getImage(IMAGE_ID))
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Alternative implementation of Bitmap.sameAs #14060
|
||||
*/
|
||||
fun Bitmap.similarTo(other: Bitmap): Boolean {
|
||||
if (invalidConfig(other)) {
|
||||
return false
|
||||
}
|
||||
|
||||
// Allocate arrays
|
||||
val argb = IntArray(width * height)
|
||||
val argbOther = IntArray(other.width * other.height)
|
||||
getPixels(argb, 0, width, 0, 0, width, height)
|
||||
other.getPixels(argbOther, 0, width, 0, 0, width, height)
|
||||
|
||||
// Alpha channel special check
|
||||
if (config == Bitmap.Config.ALPHA_8) {
|
||||
// in this case we have to manually compare the alpha channel as the rest is garbage.
|
||||
val length = width * height
|
||||
for (i in 0 until length) {
|
||||
if (argb[i] and -0x1000000 != argbOther[i] and -0x1000000) {
|
||||
if (invalidConfig(other)) {
|
||||
return false
|
||||
}
|
||||
}
|
||||
return true
|
||||
}
|
||||
return Arrays.equals(argb, argbOther)
|
||||
|
||||
// Allocate arrays
|
||||
val argb = IntArray(width * height)
|
||||
val argbOther = IntArray(other.width * other.height)
|
||||
getPixels(argb, 0, width, 0, 0, width, height)
|
||||
other.getPixels(argbOther, 0, width, 0, 0, width, height)
|
||||
|
||||
// Alpha channel special check
|
||||
if (config == Bitmap.Config.ALPHA_8) {
|
||||
// in this case we have to manually compare the alpha channel as the rest is garbage.
|
||||
val length = width * height
|
||||
for (i in 0 until length) {
|
||||
if (argb[i] and -0x1000000 != argbOther[i] and -0x1000000) {
|
||||
return false
|
||||
}
|
||||
}
|
||||
return true
|
||||
}
|
||||
return Arrays.equals(argb, argbOther)
|
||||
}
|
||||
|
||||
fun Bitmap.invalidConfig(other: Bitmap): Boolean = this.config != other.config || this.width != other.width || this.height != other.height
|
||||
fun Bitmap.invalidConfig(other: Bitmap): Boolean = this.config != other.config || this.width != other.width || this.height != other.height
|
||||
|
||||
@@ -4,15 +4,15 @@ import androidx.test.espresso.UiController
|
||||
import com.mapbox.mapboxsdk.maps.MapView
|
||||
|
||||
object TestingAsyncUtils {
|
||||
private const val DEFAULT_TIMEOUT = 15_000L
|
||||
private const val DEFAULT_TIMEOUT = 15_000L
|
||||
|
||||
fun waitForLayer(uiController: UiController, mapView: MapView) {
|
||||
val start = System.nanoTime() / 1E6
|
||||
var isIdle = false
|
||||
mapView.addOnDidBecomeIdleListener { isIdle = true }
|
||||
fun waitForLayer(uiController: UiController, mapView: MapView) {
|
||||
val start = System.nanoTime() / 1E6
|
||||
var isIdle = false
|
||||
mapView.addOnDidBecomeIdleListener { isIdle = true }
|
||||
|
||||
while (!isIdle && System.nanoTime() / 1E6 - start < DEFAULT_TIMEOUT) {
|
||||
uiController.loopMainThreadForAtLeast(100)
|
||||
while (!isIdle && System.nanoTime() / 1E6 - start < DEFAULT_TIMEOUT) {
|
||||
uiController.loopMainThreadForAtLeast(100)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -19,147 +19,149 @@ import com.mapbox.mapboxsdk.style.sources.GeoJsonSource
|
||||
import com.mapbox.mapboxsdk.testapp.R
|
||||
import com.mapbox.mapboxsdk.testapp.utils.GeoParseUtil.loadStringFromAssets
|
||||
import com.mapbox.mapboxsdk.utils.BitmapUtils
|
||||
import java.net.URISyntaxException
|
||||
import kotlinx.android.synthetic.main.activity_latlngbounds.*
|
||||
import java.net.URISyntaxException
|
||||
|
||||
/**
|
||||
* Test activity showcasing using the LatLngBounds camera API.
|
||||
*/
|
||||
class LatLngBoundsActivity : AppCompatActivity() {
|
||||
|
||||
private lateinit var mapboxMap: MapboxMap
|
||||
private lateinit var bottomSheetBehavior: BottomSheetBehavior<*>
|
||||
private lateinit var bounds: LatLngBounds
|
||||
private lateinit var mapboxMap: MapboxMap
|
||||
private lateinit var bottomSheetBehavior: BottomSheetBehavior<*>
|
||||
private lateinit var bounds: LatLngBounds
|
||||
|
||||
private val peekHeight by lazy {
|
||||
375.toPx(this) // 375dp
|
||||
}
|
||||
|
||||
private val additionalPadding by lazy {
|
||||
32.toPx(this) // 32dp
|
||||
}
|
||||
|
||||
override fun onCreate(savedInstanceState: Bundle?) {
|
||||
super.onCreate(savedInstanceState)
|
||||
setContentView(R.layout.activity_latlngbounds)
|
||||
initMapView(savedInstanceState)
|
||||
}
|
||||
|
||||
private fun initMapView(savedInstanceState: Bundle?) {
|
||||
mapView.onCreate(savedInstanceState)
|
||||
mapView.getMapAsync { map ->
|
||||
mapboxMap = map
|
||||
|
||||
val featureCollection: FeatureCollection = fromJson(loadStringFromAssets(this, "points-sf.geojson"))
|
||||
bounds = createBounds(featureCollection)
|
||||
|
||||
map.getCameraForLatLngBounds(bounds, createPadding(peekHeight))?.let {
|
||||
map.cameraPosition = it
|
||||
}
|
||||
|
||||
try {
|
||||
loadStyle(featureCollection)
|
||||
} catch (e: URISyntaxException) {
|
||||
e.printStackTrace()
|
||||
}
|
||||
private val peekHeight by lazy {
|
||||
375.toPx(this) // 375dp
|
||||
}
|
||||
}
|
||||
|
||||
private fun loadStyle(featureCollection: FeatureCollection) {
|
||||
mapboxMap.setStyle(Style.Builder()
|
||||
.fromUri(Style.MAPBOX_STREETS)
|
||||
.withLayer(SymbolLayer("symbol", "symbol")
|
||||
.withProperties(
|
||||
iconAllowOverlap(true),
|
||||
iconIgnorePlacement(true),
|
||||
iconImage("icon"),
|
||||
iconAnchor(ICON_ANCHOR_CENTER)
|
||||
)
|
||||
)
|
||||
.withSource(GeoJsonSource("symbol", featureCollection))
|
||||
.withImage("icon", BitmapUtils.getDrawableFromRes(this@LatLngBoundsActivity, R.drawable.ic_android)!!)
|
||||
) {
|
||||
initBottomSheet()
|
||||
fab.setOnClickListener { bottomSheetBehavior.state = BottomSheetBehavior.STATE_EXPANDED }
|
||||
private val additionalPadding by lazy {
|
||||
32.toPx(this) // 32dp
|
||||
}
|
||||
}
|
||||
|
||||
private fun initBottomSheet() {
|
||||
bottomSheetBehavior = BottomSheetBehavior.from(bottomSheet)
|
||||
bottomSheetBehavior.setBottomSheetCallback(object : BottomSheetBehavior.BottomSheetCallback() {
|
||||
override fun onSlide(bottomSheet: View, slideOffset: Float) {
|
||||
val offset = convertSlideOffset(slideOffset)
|
||||
val bottomPadding = (peekHeight * offset).toInt()
|
||||
override fun onCreate(savedInstanceState: Bundle?) {
|
||||
super.onCreate(savedInstanceState)
|
||||
setContentView(R.layout.activity_latlngbounds)
|
||||
initMapView(savedInstanceState)
|
||||
}
|
||||
|
||||
mapboxMap.getCameraForLatLngBounds(bounds, createPadding(bottomPadding))?.let {
|
||||
mapboxMap.cameraPosition = it
|
||||
private fun initMapView(savedInstanceState: Bundle?) {
|
||||
mapView.onCreate(savedInstanceState)
|
||||
mapView.getMapAsync { map ->
|
||||
mapboxMap = map
|
||||
|
||||
val featureCollection: FeatureCollection = fromJson(loadStringFromAssets(this, "points-sf.geojson"))
|
||||
bounds = createBounds(featureCollection)
|
||||
|
||||
map.getCameraForLatLngBounds(bounds, createPadding(peekHeight))?.let {
|
||||
map.cameraPosition = it
|
||||
}
|
||||
|
||||
try {
|
||||
loadStyle(featureCollection)
|
||||
} catch (e: URISyntaxException) {
|
||||
e.printStackTrace()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
override fun onStateChanged(bottomSheet: View, newState: Int) {
|
||||
// no-op
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
// slideOffset ranges from NaN to -1.0, range from 1.0 to 0 instead
|
||||
fun convertSlideOffset(slideOffset: Float): Float {
|
||||
return if (slideOffset.equals(Float.NaN)) {
|
||||
1.0f
|
||||
} else {
|
||||
1 + slideOffset
|
||||
}
|
||||
}
|
||||
|
||||
fun createPadding(bottomPadding: Int): IntArray {
|
||||
return intArrayOf(additionalPadding, additionalPadding, additionalPadding, bottomPadding)
|
||||
}
|
||||
|
||||
private fun createBounds(featureCollection: FeatureCollection): LatLngBounds {
|
||||
val boundsBuilder = LatLngBounds.Builder()
|
||||
featureCollection.features()?.let {
|
||||
for (feature in it) {
|
||||
val point = feature.geometry() as Point
|
||||
boundsBuilder.include(LatLng(point.latitude(), point.longitude()))
|
||||
}
|
||||
private fun loadStyle(featureCollection: FeatureCollection) {
|
||||
mapboxMap.setStyle(
|
||||
Style.Builder()
|
||||
.fromUri(Style.MAPBOX_STREETS)
|
||||
.withLayer(
|
||||
SymbolLayer("symbol", "symbol")
|
||||
.withProperties(
|
||||
iconAllowOverlap(true),
|
||||
iconIgnorePlacement(true),
|
||||
iconImage("icon"),
|
||||
iconAnchor(ICON_ANCHOR_CENTER)
|
||||
)
|
||||
)
|
||||
.withSource(GeoJsonSource("symbol", featureCollection))
|
||||
.withImage("icon", BitmapUtils.getDrawableFromRes(this@LatLngBoundsActivity, R.drawable.ic_android)!!)
|
||||
) {
|
||||
initBottomSheet()
|
||||
fab.setOnClickListener { bottomSheetBehavior.state = BottomSheetBehavior.STATE_EXPANDED }
|
||||
}
|
||||
}
|
||||
return boundsBuilder.build()
|
||||
}
|
||||
|
||||
override fun onStart() {
|
||||
super.onStart()
|
||||
mapView.onStart()
|
||||
}
|
||||
private fun initBottomSheet() {
|
||||
bottomSheetBehavior = BottomSheetBehavior.from(bottomSheet)
|
||||
bottomSheetBehavior.setBottomSheetCallback(object : BottomSheetBehavior.BottomSheetCallback() {
|
||||
override fun onSlide(bottomSheet: View, slideOffset: Float) {
|
||||
val offset = convertSlideOffset(slideOffset)
|
||||
val bottomPadding = (peekHeight * offset).toInt()
|
||||
|
||||
override fun onResume() {
|
||||
super.onResume()
|
||||
mapView.onResume()
|
||||
}
|
||||
mapboxMap.getCameraForLatLngBounds(bounds, createPadding(bottomPadding))?.let {
|
||||
mapboxMap.cameraPosition = it
|
||||
}
|
||||
}
|
||||
|
||||
override fun onPause() {
|
||||
super.onPause()
|
||||
mapView.onPause()
|
||||
}
|
||||
override fun onStateChanged(bottomSheet: View, newState: Int) {
|
||||
// no-op
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
override fun onStop() {
|
||||
super.onStop()
|
||||
mapView.onStop()
|
||||
}
|
||||
// slideOffset ranges from NaN to -1.0, range from 1.0 to 0 instead
|
||||
fun convertSlideOffset(slideOffset: Float): Float {
|
||||
return if (slideOffset.equals(Float.NaN)) {
|
||||
1.0f
|
||||
} else {
|
||||
1 + slideOffset
|
||||
}
|
||||
}
|
||||
|
||||
override fun onLowMemory() {
|
||||
super.onLowMemory()
|
||||
mapView.onLowMemory()
|
||||
}
|
||||
fun createPadding(bottomPadding: Int): IntArray {
|
||||
return intArrayOf(additionalPadding, additionalPadding, additionalPadding, bottomPadding)
|
||||
}
|
||||
|
||||
override fun onDestroy() {
|
||||
super.onDestroy()
|
||||
mapView.onDestroy()
|
||||
}
|
||||
private fun createBounds(featureCollection: FeatureCollection): LatLngBounds {
|
||||
val boundsBuilder = LatLngBounds.Builder()
|
||||
featureCollection.features()?.let {
|
||||
for (feature in it) {
|
||||
val point = feature.geometry() as Point
|
||||
boundsBuilder.include(LatLng(point.latitude(), point.longitude()))
|
||||
}
|
||||
}
|
||||
return boundsBuilder.build()
|
||||
}
|
||||
|
||||
override fun onSaveInstanceState(outState: Bundle) {
|
||||
super.onSaveInstanceState(outState)
|
||||
mapView.onSaveInstanceState(outState)
|
||||
}
|
||||
override fun onStart() {
|
||||
super.onStart()
|
||||
mapView.onStart()
|
||||
}
|
||||
|
||||
override fun onResume() {
|
||||
super.onResume()
|
||||
mapView.onResume()
|
||||
}
|
||||
|
||||
override fun onPause() {
|
||||
super.onPause()
|
||||
mapView.onPause()
|
||||
}
|
||||
|
||||
override fun onStop() {
|
||||
super.onStop()
|
||||
mapView.onStop()
|
||||
}
|
||||
|
||||
override fun onLowMemory() {
|
||||
super.onLowMemory()
|
||||
mapView.onLowMemory()
|
||||
}
|
||||
|
||||
override fun onDestroy() {
|
||||
super.onDestroy()
|
||||
mapView.onDestroy()
|
||||
}
|
||||
|
||||
override fun onSaveInstanceState(outState: Bundle) {
|
||||
super.onSaveInstanceState(outState)
|
||||
mapView.onSaveInstanceState(outState)
|
||||
}
|
||||
}
|
||||
|
||||
fun Int.toPx(context: Context): Int = (this * context.resources.displayMetrics.density).toInt()
|
||||
fun Int.toPx(context: Context): Int = (this * context.resources.displayMetrics.density).toInt()
|
||||
|
||||
@@ -63,4 +63,4 @@ class PixelTestActivity : AppCompatActivity(), OnMapReadyCallback {
|
||||
super.onLowMemory()
|
||||
mapView.onLowMemory()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -14,54 +14,54 @@ import kotlinx.android.synthetic.main.activity_backstack_fragment.*
|
||||
*/
|
||||
class FragmentBackStackActivity : AppCompatActivity() {
|
||||
|
||||
companion object {
|
||||
private const val FRAGMENT_TAG = "map_fragment"
|
||||
}
|
||||
companion object {
|
||||
private const val FRAGMENT_TAG = "map_fragment"
|
||||
}
|
||||
|
||||
private lateinit var mapFragment: SupportMapFragment
|
||||
private lateinit var mapFragment: SupportMapFragment
|
||||
|
||||
override fun onCreate(savedInstanceState: Bundle?) {
|
||||
super.onCreate(savedInstanceState)
|
||||
setContentView(R.layout.activity_backstack_fragment)
|
||||
override fun onCreate(savedInstanceState: Bundle?) {
|
||||
super.onCreate(savedInstanceState)
|
||||
setContentView(R.layout.activity_backstack_fragment)
|
||||
|
||||
if (savedInstanceState == null) {
|
||||
mapFragment = SupportMapFragment.newInstance()
|
||||
mapFragment.getMapAsync { initMap(it) }
|
||||
if (savedInstanceState == null) {
|
||||
mapFragment = SupportMapFragment.newInstance()
|
||||
mapFragment.getMapAsync { initMap(it) }
|
||||
|
||||
supportFragmentManager.beginTransaction().apply {
|
||||
add(R.id.container, mapFragment, FRAGMENT_TAG)
|
||||
}.commit()
|
||||
} else {
|
||||
supportFragmentManager.findFragmentByTag(FRAGMENT_TAG)?.also { fragment ->
|
||||
if (fragment is SupportMapFragment) {
|
||||
fragment.getMapAsync { initMap(it) }
|
||||
supportFragmentManager.beginTransaction().apply {
|
||||
add(R.id.container, mapFragment, FRAGMENT_TAG)
|
||||
}.commit()
|
||||
} else {
|
||||
supportFragmentManager.findFragmentByTag(FRAGMENT_TAG)?.also { fragment ->
|
||||
if (fragment is SupportMapFragment) {
|
||||
fragment.getMapAsync { initMap(it) }
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
button.setOnClickListener { handleClick() }
|
||||
}
|
||||
|
||||
button.setOnClickListener { handleClick() }
|
||||
}
|
||||
|
||||
private fun initMap(mapboxMap: MapboxMap) {
|
||||
mapboxMap.setStyle(Style.SATELLITE) {
|
||||
mapboxMap.setPadding(300, 300, 300, 300)
|
||||
private fun initMap(mapboxMap: MapboxMap) {
|
||||
mapboxMap.setStyle(Style.SATELLITE) {
|
||||
mapboxMap.setPadding(300, 300, 300, 300)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private fun handleClick() {
|
||||
supportFragmentManager.beginTransaction().apply {
|
||||
replace(R.id.container, NestedViewPagerActivity.ItemAdapter.EmptyFragment())
|
||||
addToBackStack("map_empty_fragment")
|
||||
}.commit()
|
||||
}
|
||||
|
||||
override fun onBackPressed() {
|
||||
if (supportFragmentManager.backStackEntryCount == 0) {
|
||||
// activity uses singleInstance for testing purposes
|
||||
// code below provides a default navigation when using the app
|
||||
NavUtils.navigateHome(this)
|
||||
} else {
|
||||
super.onBackPressed()
|
||||
private fun handleClick() {
|
||||
supportFragmentManager.beginTransaction().apply {
|
||||
replace(R.id.container, NestedViewPagerActivity.ItemAdapter.EmptyFragment())
|
||||
addToBackStack("map_empty_fragment")
|
||||
}.commit()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
override fun onBackPressed() {
|
||||
if (supportFragmentManager.backStackEntryCount == 0) {
|
||||
// activity uses singleInstance for testing purposes
|
||||
// code below provides a default navigation when using the app
|
||||
NavUtils.navigateHome(this)
|
||||
} else {
|
||||
super.onBackPressed()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -41,9 +41,9 @@ class NestedViewPagerActivity : AppCompatActivity() {
|
||||
class ItemAdapter(private val context: Context, private val inflater: LayoutInflater, private val fragmentManager: androidx.fragment.app.FragmentManager) : androidx.recyclerview.widget.RecyclerView.Adapter<androidx.recyclerview.widget.RecyclerView.ViewHolder>() {
|
||||
|
||||
private val items = listOf(
|
||||
"one", "two", "three", ViewPagerItem(), "four", "five", "six", "seven", "eight", "nine", "ten",
|
||||
"eleven", "twelve", "thirteen", "fourteen", "fifteen", "sixteen", "seventeen", "eighteen",
|
||||
"nineteen", "twenty", "twenty-one"
|
||||
"one", "two", "three", ViewPagerItem(), "four", "five", "six", "seven", "eight", "nine", "ten",
|
||||
"eleven", "twelve", "thirteen", "fourteen", "fifteen", "sixteen", "seventeen", "eighteen",
|
||||
"nineteen", "twenty", "twenty-one"
|
||||
)
|
||||
|
||||
private var mapHolder: ViewPagerHolder? = null
|
||||
@@ -162,4 +162,4 @@ class NestedViewPagerActivity : AppCompatActivity() {
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -19,84 +19,85 @@ import kotlinx.android.synthetic.main.activity_viewpager.*
|
||||
*/
|
||||
class ViewPagerActivity : AppCompatActivity() {
|
||||
|
||||
override fun onCreate(savedInstanceState: Bundle?) {
|
||||
super.onCreate(savedInstanceState)
|
||||
setContentView(R.layout.activity_viewpager)
|
||||
viewPager.adapter = MapFragmentAdapter(this, supportFragmentManager)
|
||||
}
|
||||
|
||||
override fun onRestoreInstanceState(savedInstanceState: Bundle) {
|
||||
super.onRestoreInstanceState(savedInstanceState)
|
||||
val currentPosition = viewPager.currentItem
|
||||
val offscreenLimit = viewPager.offscreenPageLimit
|
||||
for (i in currentPosition - offscreenLimit..currentPosition + offscreenLimit) {
|
||||
if (i < 0 || i > viewPager.adapter?.count ?: 0) {
|
||||
continue
|
||||
}
|
||||
val mapFragment = viewPager.adapter?.instantiateItem(viewPager, i) as SupportMapFragment
|
||||
mapFragment.getMapAsync(i)
|
||||
}
|
||||
}
|
||||
|
||||
internal class MapFragmentAdapter(private val context: Context, fragmentManager: androidx.fragment.app.FragmentManager) : androidx.fragment.app.FragmentStatePagerAdapter(fragmentManager) {
|
||||
|
||||
override fun getCount(): Int {
|
||||
return NUM_ITEMS
|
||||
override fun onCreate(savedInstanceState: Bundle?) {
|
||||
super.onCreate(savedInstanceState)
|
||||
setContentView(R.layout.activity_viewpager)
|
||||
viewPager.adapter = MapFragmentAdapter(this, supportFragmentManager)
|
||||
}
|
||||
|
||||
override fun getItem(position: Int): androidx.fragment.app.Fragment? {
|
||||
val options = MapboxMapOptions.createFromAttributes(context)
|
||||
options.textureMode(true)
|
||||
options.camera(
|
||||
CameraPosition.Builder()
|
||||
.zoom(3.0)
|
||||
.target(
|
||||
when (position) {
|
||||
0 -> {
|
||||
LatLng(34.920526, 102.634774)
|
||||
}
|
||||
1 -> {
|
||||
LatLng(62.326440, 92.764913)
|
||||
}
|
||||
2 -> {
|
||||
LatLng(-25.007786, 133.623852)
|
||||
}
|
||||
3 -> {
|
||||
LatLng(62.326440, 92.764913)
|
||||
}
|
||||
else -> {
|
||||
LatLng(34.920526, 102.634774)
|
||||
}
|
||||
override fun onRestoreInstanceState(savedInstanceState: Bundle) {
|
||||
super.onRestoreInstanceState(savedInstanceState)
|
||||
val currentPosition = viewPager.currentItem
|
||||
val offscreenLimit = viewPager.offscreenPageLimit
|
||||
for (i in currentPosition - offscreenLimit..currentPosition + offscreenLimit) {
|
||||
if (i < 0 || i > viewPager.adapter?.count ?: 0) {
|
||||
continue
|
||||
}
|
||||
)
|
||||
.build())
|
||||
|
||||
val fragment = SupportMapFragment.newInstance(options)
|
||||
fragment.getMapAsync(position)
|
||||
return fragment
|
||||
val mapFragment = viewPager.adapter?.instantiateItem(viewPager, i) as SupportMapFragment
|
||||
mapFragment.getMapAsync(i)
|
||||
}
|
||||
}
|
||||
|
||||
override fun getPageTitle(position: Int): CharSequence? {
|
||||
return "Page $position"
|
||||
}
|
||||
internal class MapFragmentAdapter(private val context: Context, fragmentManager: androidx.fragment.app.FragmentManager) : androidx.fragment.app.FragmentStatePagerAdapter(fragmentManager) {
|
||||
|
||||
companion object {
|
||||
private const val NUM_ITEMS = 5
|
||||
override fun getCount(): Int {
|
||||
return NUM_ITEMS
|
||||
}
|
||||
|
||||
override fun getItem(position: Int): androidx.fragment.app.Fragment? {
|
||||
val options = MapboxMapOptions.createFromAttributes(context)
|
||||
options.textureMode(true)
|
||||
options.camera(
|
||||
CameraPosition.Builder()
|
||||
.zoom(3.0)
|
||||
.target(
|
||||
when (position) {
|
||||
0 -> {
|
||||
LatLng(34.920526, 102.634774)
|
||||
}
|
||||
1 -> {
|
||||
LatLng(62.326440, 92.764913)
|
||||
}
|
||||
2 -> {
|
||||
LatLng(-25.007786, 133.623852)
|
||||
}
|
||||
3 -> {
|
||||
LatLng(62.326440, 92.764913)
|
||||
}
|
||||
else -> {
|
||||
LatLng(34.920526, 102.634774)
|
||||
}
|
||||
}
|
||||
)
|
||||
.build()
|
||||
)
|
||||
|
||||
val fragment = SupportMapFragment.newInstance(options)
|
||||
fragment.getMapAsync(position)
|
||||
return fragment
|
||||
}
|
||||
|
||||
override fun getPageTitle(position: Int): CharSequence? {
|
||||
return "Page $position"
|
||||
}
|
||||
|
||||
companion object {
|
||||
private const val NUM_ITEMS = 5
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fun SupportMapFragment.getMapAsync(index: Int) {
|
||||
this.getMapAsync {
|
||||
it.setStyle(
|
||||
when (index) {
|
||||
0 -> Style.MAPBOX_STREETS
|
||||
1 -> Style.DARK
|
||||
2 -> Style.SATELLITE
|
||||
3 -> Style.LIGHT
|
||||
4 -> Style.TRAFFIC_NIGHT
|
||||
else -> Style.MAPBOX_STREETS
|
||||
}
|
||||
)
|
||||
}
|
||||
}
|
||||
this.getMapAsync {
|
||||
it.setStyle(
|
||||
when (index) {
|
||||
0 -> Style.MAPBOX_STREETS
|
||||
1 -> Style.DARK
|
||||
2 -> Style.SATELLITE
|
||||
3 -> Style.LIGHT
|
||||
4 -> Style.TRAFFIC_NIGHT
|
||||
else -> Style.MAPBOX_STREETS
|
||||
}
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -16,74 +16,74 @@ import timber.log.Timber
|
||||
*/
|
||||
class SnapshotActivity : AppCompatActivity(), OnMapReadyCallback {
|
||||
|
||||
private lateinit var mapboxMap: MapboxMap
|
||||
private lateinit var mapboxMap: MapboxMap
|
||||
|
||||
private val idleListener = object : MapView.OnDidFinishRenderingFrameListener {
|
||||
override fun onDidFinishRenderingFrame(fully: Boolean) {
|
||||
if (fully) {
|
||||
mapView.removeOnDidFinishRenderingFrameListener(this)
|
||||
Logger.v(TAG, LOG_MESSAGE)
|
||||
mapboxMap.snapshot { snapshot ->
|
||||
imageView.setImageBitmap(snapshot)
|
||||
mapView.addOnDidFinishRenderingFrameListener(this)
|
||||
private val idleListener = object : MapView.OnDidFinishRenderingFrameListener {
|
||||
override fun onDidFinishRenderingFrame(fully: Boolean) {
|
||||
if (fully) {
|
||||
mapView.removeOnDidFinishRenderingFrameListener(this)
|
||||
Logger.v(TAG, LOG_MESSAGE)
|
||||
mapboxMap.snapshot { snapshot ->
|
||||
imageView.setImageBitmap(snapshot)
|
||||
mapView.addOnDidFinishRenderingFrameListener(this)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public override fun onCreate(savedInstanceState: Bundle?) {
|
||||
super.onCreate(savedInstanceState)
|
||||
setContentView(R.layout.activity_snapshot)
|
||||
mapView.onCreate(savedInstanceState)
|
||||
mapView.getMapAsync(this)
|
||||
}
|
||||
|
||||
override fun onMapReady(map: MapboxMap) {
|
||||
mapboxMap = map
|
||||
mapboxMap.setStyle(Style.Builder().fromUri(Style.OUTDOORS)) { mapView.addOnDidFinishRenderingFrameListener(idleListener) }
|
||||
}
|
||||
|
||||
override fun onStart() {
|
||||
super.onStart()
|
||||
mapView.onStart()
|
||||
}
|
||||
|
||||
override fun onResume() {
|
||||
super.onResume()
|
||||
mapView.onResume()
|
||||
}
|
||||
|
||||
override fun onPause() {
|
||||
super.onPause()
|
||||
mapboxMap.snapshot {
|
||||
Timber.e("Regression test for https://github.com/mapbox/mapbox-gl-native/pull/11358")
|
||||
public override fun onCreate(savedInstanceState: Bundle?) {
|
||||
super.onCreate(savedInstanceState)
|
||||
setContentView(R.layout.activity_snapshot)
|
||||
mapView.onCreate(savedInstanceState)
|
||||
mapView.getMapAsync(this)
|
||||
}
|
||||
mapView.onPause()
|
||||
}
|
||||
|
||||
override fun onStop() {
|
||||
super.onStop()
|
||||
mapView.onStop()
|
||||
}
|
||||
override fun onMapReady(map: MapboxMap) {
|
||||
mapboxMap = map
|
||||
mapboxMap.setStyle(Style.Builder().fromUri(Style.OUTDOORS)) { mapView.addOnDidFinishRenderingFrameListener(idleListener) }
|
||||
}
|
||||
|
||||
public override fun onSaveInstanceState(outState: Bundle) {
|
||||
super.onSaveInstanceState(outState)
|
||||
mapView.onSaveInstanceState(outState)
|
||||
}
|
||||
override fun onStart() {
|
||||
super.onStart()
|
||||
mapView.onStart()
|
||||
}
|
||||
|
||||
override fun onLowMemory() {
|
||||
super.onLowMemory()
|
||||
mapView.onLowMemory()
|
||||
}
|
||||
override fun onResume() {
|
||||
super.onResume()
|
||||
mapView.onResume()
|
||||
}
|
||||
|
||||
public override fun onDestroy() {
|
||||
super.onDestroy()
|
||||
mapView.removeOnDidFinishRenderingFrameListener(idleListener)
|
||||
mapView.onDestroy()
|
||||
}
|
||||
override fun onPause() {
|
||||
super.onPause()
|
||||
mapboxMap.snapshot {
|
||||
Timber.e("Regression test for https://github.com/mapbox/mapbox-gl-native/pull/11358")
|
||||
}
|
||||
mapView.onPause()
|
||||
}
|
||||
|
||||
companion object {
|
||||
const val TAG = "Mbgl-SnapshotActivity"
|
||||
const val LOG_MESSAGE = "OnSnapshot"
|
||||
}
|
||||
}
|
||||
override fun onStop() {
|
||||
super.onStop()
|
||||
mapView.onStop()
|
||||
}
|
||||
|
||||
public override fun onSaveInstanceState(outState: Bundle) {
|
||||
super.onSaveInstanceState(outState)
|
||||
mapView.onSaveInstanceState(outState)
|
||||
}
|
||||
|
||||
override fun onLowMemory() {
|
||||
super.onLowMemory()
|
||||
mapView.onLowMemory()
|
||||
}
|
||||
|
||||
public override fun onDestroy() {
|
||||
super.onDestroy()
|
||||
mapView.removeOnDidFinishRenderingFrameListener(idleListener)
|
||||
mapView.onDestroy()
|
||||
}
|
||||
|
||||
companion object {
|
||||
const val TAG = "Mbgl-SnapshotActivity"
|
||||
const val LOG_MESSAGE = "OnSnapshot"
|
||||
}
|
||||
}
|
||||
|
||||
@@ -23,154 +23,159 @@ import com.mapbox.mapboxsdk.testapp.R
|
||||
import kotlinx.android.synthetic.main.activity_location_layer_fragment.*
|
||||
|
||||
class LocationFragmentActivity : AppCompatActivity() {
|
||||
private lateinit var permissionsManager: PermissionsManager
|
||||
private lateinit var permissionsManager: PermissionsManager
|
||||
|
||||
override fun onCreate(savedInstanceState: Bundle?) {
|
||||
super.onCreate(savedInstanceState)
|
||||
setContentView(R.layout.activity_location_layer_fragment)
|
||||
override fun onCreate(savedInstanceState: Bundle?) {
|
||||
super.onCreate(savedInstanceState)
|
||||
setContentView(R.layout.activity_location_layer_fragment)
|
||||
|
||||
fab.setOnClickListener {
|
||||
val fragment = supportFragmentManager.findFragmentByTag(EmptyFragment.TAG)
|
||||
if (fragment == null) {
|
||||
supportFragmentManager
|
||||
.beginTransaction()
|
||||
.replace(R.id.container, EmptyFragment.newInstance(), EmptyFragment.TAG)
|
||||
.addToBackStack("transaction2")
|
||||
.commit()
|
||||
} else {
|
||||
this.onBackPressed()
|
||||
}
|
||||
}
|
||||
supportActionBar?.setDisplayHomeAsUpEnabled(true)
|
||||
|
||||
if (PermissionsManager.areLocationPermissionsGranted(this)) {
|
||||
if (savedInstanceState == null) {
|
||||
supportFragmentManager
|
||||
.beginTransaction()
|
||||
.replace(R.id.container, LocationFragment.newInstance(), LocationFragment.TAG)
|
||||
.commit()
|
||||
}
|
||||
} else {
|
||||
permissionsManager = PermissionsManager(object : PermissionsListener {
|
||||
override fun onExplanationNeeded(permissionsToExplain: MutableList<String>?) {
|
||||
Toast.makeText(this@LocationFragmentActivity, "You need to accept location permissions.",
|
||||
Toast.LENGTH_SHORT).show()
|
||||
}
|
||||
|
||||
override fun onPermissionResult(granted: Boolean) {
|
||||
if (granted) {
|
||||
if (savedInstanceState == null) {
|
||||
supportFragmentManager
|
||||
.beginTransaction()
|
||||
.replace(R.id.container, LocationFragment.newInstance(), LocationFragment.TAG)
|
||||
.commit()
|
||||
fab.setOnClickListener {
|
||||
val fragment = supportFragmentManager.findFragmentByTag(EmptyFragment.TAG)
|
||||
if (fragment == null) {
|
||||
supportFragmentManager
|
||||
.beginTransaction()
|
||||
.replace(R.id.container, EmptyFragment.newInstance(), EmptyFragment.TAG)
|
||||
.addToBackStack("transaction2")
|
||||
.commit()
|
||||
} else {
|
||||
this.onBackPressed()
|
||||
}
|
||||
} else {
|
||||
finish()
|
||||
}
|
||||
}
|
||||
})
|
||||
permissionsManager.requestLocationPermissions(this)
|
||||
}
|
||||
}
|
||||
supportActionBar?.setDisplayHomeAsUpEnabled(true)
|
||||
|
||||
override fun onRequestPermissionsResult(requestCode: Int, permissions: Array<out String>, grantResults: IntArray) {
|
||||
super.onRequestPermissionsResult(requestCode, permissions, grantResults)
|
||||
permissionsManager.onRequestPermissionsResult(requestCode, permissions, grantResults)
|
||||
}
|
||||
if (PermissionsManager.areLocationPermissionsGranted(this)) {
|
||||
if (savedInstanceState == null) {
|
||||
supportFragmentManager
|
||||
.beginTransaction()
|
||||
.replace(R.id.container, LocationFragment.newInstance(), LocationFragment.TAG)
|
||||
.commit()
|
||||
}
|
||||
} else {
|
||||
permissionsManager = PermissionsManager(object : PermissionsListener {
|
||||
override fun onExplanationNeeded(permissionsToExplain: MutableList<String>?) {
|
||||
Toast.makeText(
|
||||
this@LocationFragmentActivity,
|
||||
"You need to accept location permissions.",
|
||||
Toast.LENGTH_SHORT
|
||||
).show()
|
||||
}
|
||||
|
||||
class LocationFragment : androidx.fragment.app.Fragment(), LocationEngineCallback<LocationEngineResult> {
|
||||
companion object {
|
||||
const val TAG = "LFragment"
|
||||
fun newInstance(): LocationFragment {
|
||||
return LocationFragment()
|
||||
}
|
||||
}
|
||||
|
||||
private lateinit var mapView: MapView
|
||||
private lateinit var mapboxMap: MapboxMap
|
||||
|
||||
override fun onCreateView(inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle?): View? {
|
||||
mapView = MapView(inflater.context)
|
||||
return mapView
|
||||
}
|
||||
|
||||
@SuppressLint("MissingPermission")
|
||||
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
|
||||
super.onViewCreated(view, savedInstanceState)
|
||||
mapView.onCreate(savedInstanceState)
|
||||
mapView.getMapAsync {
|
||||
mapboxMap = it
|
||||
it.setStyle(Style.MAPBOX_STREETS) { style ->
|
||||
val component = mapboxMap.locationComponent
|
||||
|
||||
component.activateLocationComponent(LocationComponentActivationOptions
|
||||
.builder(activity!!, style)
|
||||
.useDefaultLocationEngine(true)
|
||||
.build())
|
||||
|
||||
component.isLocationComponentEnabled = true
|
||||
component.locationEngine?.getLastLocation(this)
|
||||
override fun onPermissionResult(granted: Boolean) {
|
||||
if (granted) {
|
||||
if (savedInstanceState == null) {
|
||||
supportFragmentManager
|
||||
.beginTransaction()
|
||||
.replace(R.id.container, LocationFragment.newInstance(), LocationFragment.TAG)
|
||||
.commit()
|
||||
}
|
||||
} else {
|
||||
finish()
|
||||
}
|
||||
}
|
||||
})
|
||||
permissionsManager.requestLocationPermissions(this)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
override fun onSuccess(result: LocationEngineResult?) {
|
||||
if (!mapView.isDestroyed) mapboxMap.animateCamera(CameraUpdateFactory.newLatLngZoom(LatLng(result?.lastLocation), 12.0))
|
||||
override fun onRequestPermissionsResult(requestCode: Int, permissions: Array<out String>, grantResults: IntArray) {
|
||||
super.onRequestPermissionsResult(requestCode, permissions, grantResults)
|
||||
permissionsManager.onRequestPermissionsResult(requestCode, permissions, grantResults)
|
||||
}
|
||||
|
||||
override fun onFailure(exception: Exception) {
|
||||
// noop
|
||||
class LocationFragment : androidx.fragment.app.Fragment(), LocationEngineCallback<LocationEngineResult> {
|
||||
companion object {
|
||||
const val TAG = "LFragment"
|
||||
fun newInstance(): LocationFragment {
|
||||
return LocationFragment()
|
||||
}
|
||||
}
|
||||
|
||||
private lateinit var mapView: MapView
|
||||
private lateinit var mapboxMap: MapboxMap
|
||||
|
||||
override fun onCreateView(inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle?): View? {
|
||||
mapView = MapView(inflater.context)
|
||||
return mapView
|
||||
}
|
||||
|
||||
@SuppressLint("MissingPermission")
|
||||
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
|
||||
super.onViewCreated(view, savedInstanceState)
|
||||
mapView.onCreate(savedInstanceState)
|
||||
mapView.getMapAsync {
|
||||
mapboxMap = it
|
||||
it.setStyle(Style.MAPBOX_STREETS) { style ->
|
||||
val component = mapboxMap.locationComponent
|
||||
|
||||
component.activateLocationComponent(
|
||||
LocationComponentActivationOptions
|
||||
.builder(activity!!, style)
|
||||
.useDefaultLocationEngine(true)
|
||||
.build()
|
||||
)
|
||||
|
||||
component.isLocationComponentEnabled = true
|
||||
component.locationEngine?.getLastLocation(this)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
override fun onSuccess(result: LocationEngineResult?) {
|
||||
if (!mapView.isDestroyed) mapboxMap.animateCamera(CameraUpdateFactory.newLatLngZoom(LatLng(result?.lastLocation), 12.0))
|
||||
}
|
||||
|
||||
override fun onFailure(exception: Exception) {
|
||||
// noop
|
||||
}
|
||||
|
||||
override fun onStart() {
|
||||
super.onStart()
|
||||
mapView.onStart()
|
||||
}
|
||||
|
||||
override fun onResume() {
|
||||
super.onResume()
|
||||
mapView.onResume()
|
||||
}
|
||||
|
||||
override fun onPause() {
|
||||
super.onPause()
|
||||
mapView.onPause()
|
||||
}
|
||||
|
||||
override fun onSaveInstanceState(outState: Bundle) {
|
||||
super.onSaveInstanceState(outState)
|
||||
mapView.onSaveInstanceState(outState)
|
||||
}
|
||||
|
||||
override fun onStop() {
|
||||
super.onStop()
|
||||
mapView.onStop()
|
||||
}
|
||||
|
||||
override fun onLowMemory() {
|
||||
super.onLowMemory()
|
||||
mapView.onLowMemory()
|
||||
}
|
||||
|
||||
override fun onDestroyView() {
|
||||
super.onDestroyView()
|
||||
mapView.onDestroy()
|
||||
}
|
||||
}
|
||||
|
||||
override fun onStart() {
|
||||
super.onStart()
|
||||
mapView.onStart()
|
||||
}
|
||||
class EmptyFragment : androidx.fragment.app.Fragment() {
|
||||
companion object {
|
||||
const val TAG = "EmptyFragment"
|
||||
fun newInstance(): EmptyFragment {
|
||||
return EmptyFragment()
|
||||
}
|
||||
}
|
||||
|
||||
override fun onResume() {
|
||||
super.onResume()
|
||||
mapView.onResume()
|
||||
override fun onCreateView(inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle?): View? {
|
||||
val textView = TextView(inflater.context)
|
||||
textView.text = "This is an empty Fragment"
|
||||
return textView
|
||||
}
|
||||
}
|
||||
|
||||
override fun onPause() {
|
||||
super.onPause()
|
||||
mapView.onPause()
|
||||
}
|
||||
|
||||
override fun onSaveInstanceState(outState: Bundle) {
|
||||
super.onSaveInstanceState(outState)
|
||||
mapView.onSaveInstanceState(outState)
|
||||
}
|
||||
|
||||
override fun onStop() {
|
||||
super.onStop()
|
||||
mapView.onStop()
|
||||
}
|
||||
|
||||
override fun onLowMemory() {
|
||||
super.onLowMemory()
|
||||
mapView.onLowMemory()
|
||||
}
|
||||
|
||||
override fun onDestroyView() {
|
||||
super.onDestroyView()
|
||||
mapView.onDestroy()
|
||||
}
|
||||
}
|
||||
|
||||
class EmptyFragment : androidx.fragment.app.Fragment() {
|
||||
companion object {
|
||||
const val TAG = "EmptyFragment"
|
||||
fun newInstance(): EmptyFragment {
|
||||
return EmptyFragment()
|
||||
}
|
||||
}
|
||||
|
||||
override fun onCreateView(inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle?): View? {
|
||||
val textView = TextView(inflater.context)
|
||||
textView.text = "This is an empty Fragment"
|
||||
return textView
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -21,137 +21,137 @@ import kotlinx.android.synthetic.main.activity_recyclerview.*
|
||||
@SuppressLint("ClickableViewAccessibility")
|
||||
open class GLSurfaceRecyclerViewActivity : AppCompatActivity() {
|
||||
|
||||
override fun onCreate(savedInstanceState: Bundle?) {
|
||||
super.onCreate(savedInstanceState)
|
||||
setContentView(R.layout.activity_recyclerview)
|
||||
recyclerView.layoutManager = androidx.recyclerview.widget.LinearLayoutManager(this)
|
||||
recyclerView.adapter = ItemAdapter(this, LayoutInflater.from(this))
|
||||
}
|
||||
|
||||
override fun onLowMemory() {
|
||||
super.onLowMemory()
|
||||
// to release memory, we need to call MapView#onLowMemory
|
||||
(recyclerView.adapter as ItemAdapter).onLowMemory()
|
||||
}
|
||||
|
||||
override fun onDestroy() {
|
||||
super.onDestroy()
|
||||
// to perform cleanup, we need to call MapView#onDestroy
|
||||
(recyclerView.adapter as ItemAdapter).onDestroy()
|
||||
}
|
||||
|
||||
open fun getMapItemLayoutId(): Int {
|
||||
return R.layout.item_map_gl
|
||||
}
|
||||
|
||||
class ItemAdapter(private val activity: GLSurfaceRecyclerViewActivity, private val inflater: LayoutInflater) : androidx.recyclerview.widget.RecyclerView.Adapter<androidx.recyclerview.widget.RecyclerView.ViewHolder>() {
|
||||
|
||||
private val items = listOf(
|
||||
"one", "two", "three", MapItem(Style.MAPBOX_STREETS), "four", "five", MapItem(Style.DARK), "seven", "eight", "nine", "ten",
|
||||
"eleven", "twelve", "thirteen", "fourteen", "fifteen", "sixteen", "seventeen", "eighteen",
|
||||
"nineteen", "twenty", "twenty-one"
|
||||
)
|
||||
|
||||
private var mapHolders: MutableList<MapHolder> = mutableListOf()
|
||||
|
||||
companion object {
|
||||
const val TYPE_MAP = 0
|
||||
const val TYPE_TEXT = 1
|
||||
override fun onCreate(savedInstanceState: Bundle?) {
|
||||
super.onCreate(savedInstanceState)
|
||||
setContentView(R.layout.activity_recyclerview)
|
||||
recyclerView.layoutManager = androidx.recyclerview.widget.LinearLayoutManager(this)
|
||||
recyclerView.adapter = ItemAdapter(this, LayoutInflater.from(this))
|
||||
}
|
||||
|
||||
override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): androidx.recyclerview.widget.RecyclerView.ViewHolder {
|
||||
return if (viewType == TYPE_MAP) {
|
||||
val mapView = inflater.inflate(activity.getMapItemLayoutId(), parent, false) as MapView
|
||||
val mapHolder = MapHolder(mapView)
|
||||
mapHolders.add(mapHolder)
|
||||
return mapHolder
|
||||
} else {
|
||||
TextHolder(inflater.inflate(android.R.layout.simple_list_item_1, parent, false) as TextView)
|
||||
}
|
||||
override fun onLowMemory() {
|
||||
super.onLowMemory()
|
||||
// to release memory, we need to call MapView#onLowMemory
|
||||
(recyclerView.adapter as ItemAdapter).onLowMemory()
|
||||
}
|
||||
|
||||
override fun onViewAttachedToWindow(holder: androidx.recyclerview.widget.RecyclerView.ViewHolder) {
|
||||
super.onViewAttachedToWindow(holder)
|
||||
if (holder is MapHolder) {
|
||||
val mapView = holder.mapView
|
||||
mapView.isEnabled = false
|
||||
mapView.onStart()
|
||||
mapView.onResume()
|
||||
}
|
||||
override fun onDestroy() {
|
||||
super.onDestroy()
|
||||
// to perform cleanup, we need to call MapView#onDestroy
|
||||
(recyclerView.adapter as ItemAdapter).onDestroy()
|
||||
}
|
||||
|
||||
override fun onViewDetachedFromWindow(holder: androidx.recyclerview.widget.RecyclerView.ViewHolder) {
|
||||
super.onViewDetachedFromWindow(holder)
|
||||
if (holder is MapHolder) {
|
||||
val mapView = holder.mapView
|
||||
mapView.onPause()
|
||||
mapView.onStop()
|
||||
}
|
||||
open fun getMapItemLayoutId(): Int {
|
||||
return R.layout.item_map_gl
|
||||
}
|
||||
|
||||
override fun getItemCount(): Int {
|
||||
return items.count()
|
||||
}
|
||||
class ItemAdapter(private val activity: GLSurfaceRecyclerViewActivity, private val inflater: LayoutInflater) : androidx.recyclerview.widget.RecyclerView.Adapter<androidx.recyclerview.widget.RecyclerView.ViewHolder>() {
|
||||
|
||||
override fun onBindViewHolder(holder: androidx.recyclerview.widget.RecyclerView.ViewHolder, position: Int) {
|
||||
if (holder is TextHolder) {
|
||||
holder.bind(items[position] as String)
|
||||
} else if (holder is MapHolder) {
|
||||
holder.bind(items[position] as MapItem)
|
||||
}
|
||||
}
|
||||
private val items = listOf(
|
||||
"one", "two", "three", MapItem(Style.MAPBOX_STREETS), "four", "five", MapItem(Style.DARK), "seven", "eight", "nine", "ten",
|
||||
"eleven", "twelve", "thirteen", "fourteen", "fifteen", "sixteen", "seventeen", "eighteen",
|
||||
"nineteen", "twenty", "twenty-one"
|
||||
)
|
||||
|
||||
override fun getItemViewType(position: Int): Int {
|
||||
return if (items[position] is MapItem) {
|
||||
TYPE_MAP
|
||||
} else {
|
||||
TYPE_TEXT
|
||||
}
|
||||
}
|
||||
private var mapHolders: MutableList<MapHolder> = mutableListOf()
|
||||
|
||||
fun onLowMemory() {
|
||||
for (mapHolder in mapHolders) {
|
||||
mapHolder.mapView.onLowMemory()
|
||||
}
|
||||
}
|
||||
|
||||
fun onDestroy() {
|
||||
for (mapHolder in mapHolders) {
|
||||
mapHolder.mapView.let {
|
||||
it.onPause()
|
||||
it.onStop()
|
||||
it.onDestroy()
|
||||
companion object {
|
||||
const val TYPE_MAP = 0
|
||||
const val TYPE_TEXT = 1
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
data class MapItem(val style: String)
|
||||
class MapHolder(val mapView: MapView) : androidx.recyclerview.widget.RecyclerView.ViewHolder(mapView) {
|
||||
|
||||
init {
|
||||
// unfortunately, if there are multiple maps hosted in one activity, state saving is not possible
|
||||
mapView.onCreate(null)
|
||||
mapView.setOnTouchListener { view, motionEvent ->
|
||||
// Disallow the touch request for recyclerView scroll
|
||||
view.parent.requestDisallowInterceptTouchEvent(true)
|
||||
mapView.onTouchEvent(motionEvent)
|
||||
true
|
||||
override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): androidx.recyclerview.widget.RecyclerView.ViewHolder {
|
||||
return if (viewType == TYPE_MAP) {
|
||||
val mapView = inflater.inflate(activity.getMapItemLayoutId(), parent, false) as MapView
|
||||
val mapHolder = MapHolder(mapView)
|
||||
mapHolders.add(mapHolder)
|
||||
return mapHolder
|
||||
} else {
|
||||
TextHolder(inflater.inflate(android.R.layout.simple_list_item_1, parent, false) as TextView)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fun bind(mapItem: MapItem) {
|
||||
mapView.getMapAsync { mapboxMap ->
|
||||
mapboxMap.setStyle(mapItem.style) {
|
||||
mapboxMap.snapshot { }
|
||||
}
|
||||
override fun onViewAttachedToWindow(holder: androidx.recyclerview.widget.RecyclerView.ViewHolder) {
|
||||
super.onViewAttachedToWindow(holder)
|
||||
if (holder is MapHolder) {
|
||||
val mapView = holder.mapView
|
||||
mapView.isEnabled = false
|
||||
mapView.onStart()
|
||||
mapView.onResume()
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
class TextHolder(val textView: TextView) : androidx.recyclerview.widget.RecyclerView.ViewHolder(textView) {
|
||||
fun bind(item: String) {
|
||||
textView.text = item
|
||||
}
|
||||
override fun onViewDetachedFromWindow(holder: androidx.recyclerview.widget.RecyclerView.ViewHolder) {
|
||||
super.onViewDetachedFromWindow(holder)
|
||||
if (holder is MapHolder) {
|
||||
val mapView = holder.mapView
|
||||
mapView.onPause()
|
||||
mapView.onStop()
|
||||
}
|
||||
}
|
||||
|
||||
override fun getItemCount(): Int {
|
||||
return items.count()
|
||||
}
|
||||
|
||||
override fun onBindViewHolder(holder: androidx.recyclerview.widget.RecyclerView.ViewHolder, position: Int) {
|
||||
if (holder is TextHolder) {
|
||||
holder.bind(items[position] as String)
|
||||
} else if (holder is MapHolder) {
|
||||
holder.bind(items[position] as MapItem)
|
||||
}
|
||||
}
|
||||
|
||||
override fun getItemViewType(position: Int): Int {
|
||||
return if (items[position] is MapItem) {
|
||||
TYPE_MAP
|
||||
} else {
|
||||
TYPE_TEXT
|
||||
}
|
||||
}
|
||||
|
||||
fun onLowMemory() {
|
||||
for (mapHolder in mapHolders) {
|
||||
mapHolder.mapView.onLowMemory()
|
||||
}
|
||||
}
|
||||
|
||||
fun onDestroy() {
|
||||
for (mapHolder in mapHolders) {
|
||||
mapHolder.mapView.let {
|
||||
it.onPause()
|
||||
it.onStop()
|
||||
it.onDestroy()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
data class MapItem(val style: String)
|
||||
class MapHolder(val mapView: MapView) : androidx.recyclerview.widget.RecyclerView.ViewHolder(mapView) {
|
||||
|
||||
init {
|
||||
// unfortunately, if there are multiple maps hosted in one activity, state saving is not possible
|
||||
mapView.onCreate(null)
|
||||
mapView.setOnTouchListener { view, motionEvent ->
|
||||
// Disallow the touch request for recyclerView scroll
|
||||
view.parent.requestDisallowInterceptTouchEvent(true)
|
||||
mapView.onTouchEvent(motionEvent)
|
||||
true
|
||||
}
|
||||
}
|
||||
|
||||
fun bind(mapItem: MapItem) {
|
||||
mapView.getMapAsync { mapboxMap ->
|
||||
mapboxMap.setStyle(mapItem.style) {
|
||||
mapboxMap.snapshot { }
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
class TextHolder(val textView: TextView) : androidx.recyclerview.widget.RecyclerView.ViewHolder(textView) {
|
||||
fun bind(item: String) {
|
||||
textView.text = item
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -57,10 +57,10 @@ class OverlayMapActivity : AppCompatActivity() {
|
||||
}
|
||||
|
||||
override fun onSaveInstanceState(outState: Bundle?, outPersistentState: PersistableBundle?) {
|
||||
super.onSaveInstanceState(outState, outPersistentState)
|
||||
outState?.let {
|
||||
mapView.onSaveInstanceState(it)
|
||||
}
|
||||
super.onSaveInstanceState(outState, outPersistentState)
|
||||
outState?.let {
|
||||
mapView.onSaveInstanceState(it)
|
||||
}
|
||||
}
|
||||
|
||||
class OverlayView(context: Context) : View(context) {
|
||||
@@ -77,11 +77,17 @@ class OverlayMapActivity : AppCompatActivity() {
|
||||
paint.color = Color.BLACK
|
||||
paint.strokeWidth = 1.0f
|
||||
paint.style = Paint.Style.FILL_AND_STROKE
|
||||
paint.shader = RadialGradient(width / 2.0f, height / 2.0f,
|
||||
height / 3.0f, Color.TRANSPARENT, Color.BLACK, Shader.TileMode.CLAMP)
|
||||
paint.shader = RadialGradient(
|
||||
width / 2.0f,
|
||||
height / 2.0f,
|
||||
height / 3.0f,
|
||||
Color.TRANSPARENT,
|
||||
Color.BLACK,
|
||||
Shader.TileMode.CLAMP
|
||||
)
|
||||
}
|
||||
it.drawRect(0.0f, 0.0f, width.toFloat(), height.toFloat(), paint)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -9,7 +9,7 @@ import com.mapbox.mapboxsdk.testapp.R
|
||||
@SuppressLint("ClickableViewAccessibility")
|
||||
class TextureRecyclerViewActivity : GLSurfaceRecyclerViewActivity() {
|
||||
|
||||
override fun getMapItemLayoutId(): Int {
|
||||
return R.layout.item_map_texture
|
||||
}
|
||||
}
|
||||
override fun getMapItemLayoutId(): Int {
|
||||
return R.layout.item_map_texture
|
||||
}
|
||||
}
|
||||
|
||||
@@ -17,164 +17,165 @@ import com.mapbox.mapboxsdk.offline.OfflineManager
|
||||
import com.mapbox.mapboxsdk.offline.OfflineRegion
|
||||
import com.mapbox.mapboxsdk.storage.FileSource
|
||||
import com.mapbox.mapboxsdk.testapp.R
|
||||
import java.io.File
|
||||
import kotlinx.android.synthetic.main.activity_change_resources_cache_path.*
|
||||
import java.io.File
|
||||
|
||||
class ChangeResourcesCachePathActivity : AppCompatActivity(),
|
||||
AdapterView.OnItemClickListener,
|
||||
FileSource.ResourcesCachePathChangeCallback {
|
||||
class ChangeResourcesCachePathActivity :
|
||||
AppCompatActivity(),
|
||||
AdapterView.OnItemClickListener,
|
||||
FileSource.ResourcesCachePathChangeCallback {
|
||||
|
||||
companion object {
|
||||
private const val TAG = "Mbgl-ChangeResourcesCachePathActivity"
|
||||
}
|
||||
|
||||
private lateinit var adapter: PathAdapter
|
||||
|
||||
private lateinit var offlineManager: OfflineManager
|
||||
|
||||
private val callback = PathChangeCallback(this)
|
||||
|
||||
override fun onCreate(savedInstanceState: Bundle?) {
|
||||
super.onCreate(savedInstanceState)
|
||||
setContentView(R.layout.activity_change_resources_cache_path)
|
||||
|
||||
adapter = PathAdapter(this, obtainExternalFilesPaths())
|
||||
listView.adapter = adapter
|
||||
listView.emptyView = empty
|
||||
listView.onItemClickListener = this
|
||||
|
||||
offlineManager = OfflineManager.getInstance(this)
|
||||
}
|
||||
|
||||
override fun onStart() {
|
||||
super.onStart()
|
||||
val path: String? = FileSource.getResourcesCachePath(this)
|
||||
Toast.makeText(this, "Current path: $path", Toast.LENGTH_LONG).show()
|
||||
}
|
||||
|
||||
override fun onDestroy() {
|
||||
super.onDestroy()
|
||||
callback.onActivityDestroy()
|
||||
}
|
||||
|
||||
override fun onItemClick(parent: AdapterView<*>?, view: View?, position: Int, id: Long) {
|
||||
listView.onItemClickListener = null
|
||||
val path: String = adapter.getItem(position) as String
|
||||
FileSource.setResourcesCachePath(path, callback)
|
||||
}
|
||||
|
||||
override fun onError(message: String) {
|
||||
listView.onItemClickListener = this
|
||||
Toast.makeText(this, "Error: $message", Toast.LENGTH_LONG).show()
|
||||
}
|
||||
|
||||
override fun onSuccess(path: String) {
|
||||
listView.onItemClickListener = this
|
||||
Toast.makeText(this, "New path: $path", Toast.LENGTH_LONG).show()
|
||||
|
||||
offlineManager.listOfflineRegions(object : OfflineManager.ListOfflineRegionsCallback {
|
||||
override fun onList(offlineRegions: Array<out OfflineRegion>?) {
|
||||
Logger.i(TAG, "Number of saved offline regions in the new path: ${offlineRegions?.size}")
|
||||
}
|
||||
|
||||
override fun onError(error: String?) {
|
||||
Logger.e(TAG, error)
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
private fun Context.obtainExternalFilesPaths(): List<String> {
|
||||
val paths = ArrayList<String>()
|
||||
paths.add(this.filesDir.absolutePath)
|
||||
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT) {
|
||||
paths.addAll(obtainExternalFilesPathsKitKat())
|
||||
} else {
|
||||
paths.addAll(obtainExternalFilesPathsLegacy())
|
||||
companion object {
|
||||
private const val TAG = "Mbgl-ChangeResourcesCachePathActivity"
|
||||
}
|
||||
paths.add("${File.separator}invalid${File.separator}cache${File.separator}path")
|
||||
return paths
|
||||
}
|
||||
|
||||
private fun Context.obtainExternalFilesPathsLegacy(): List<String> {
|
||||
val postFix =
|
||||
"${File.separator}Android${File.separator}data${File.separator}${this.packageName}${File.separator}files"
|
||||
val paths = ArrayList<String>()
|
||||
val externalStorage = System.getenv("EXTERNAL_STORAGE")
|
||||
val secondaryStorage = System.getenv("SECONDARY_STORAGE")
|
||||
if (externalStorage != null) {
|
||||
paths.add(externalStorage + postFix)
|
||||
private lateinit var adapter: PathAdapter
|
||||
|
||||
private lateinit var offlineManager: OfflineManager
|
||||
|
||||
private val callback = PathChangeCallback(this)
|
||||
|
||||
override fun onCreate(savedInstanceState: Bundle?) {
|
||||
super.onCreate(savedInstanceState)
|
||||
setContentView(R.layout.activity_change_resources_cache_path)
|
||||
|
||||
adapter = PathAdapter(this, obtainExternalFilesPaths())
|
||||
listView.adapter = adapter
|
||||
listView.emptyView = empty
|
||||
listView.onItemClickListener = this
|
||||
|
||||
offlineManager = OfflineManager.getInstance(this)
|
||||
}
|
||||
if (secondaryStorage != null) {
|
||||
val secPaths = secondaryStorage.split(":".toRegex()).dropLastWhile { it.isEmpty() }.toTypedArray()
|
||||
for (path in secPaths) {
|
||||
paths.add(path + postFix)
|
||||
}
|
||||
|
||||
override fun onStart() {
|
||||
super.onStart()
|
||||
val path: String? = FileSource.getResourcesCachePath(this)
|
||||
Toast.makeText(this, "Current path: $path", Toast.LENGTH_LONG).show()
|
||||
}
|
||||
return paths
|
||||
}
|
||||
|
||||
@TargetApi(Build.VERSION_CODES.KITKAT)
|
||||
private fun Context.obtainExternalFilesPathsKitKat(): List<String> {
|
||||
val paths = ArrayList<String>()
|
||||
val extDirs = this.getExternalFilesDirs(null)
|
||||
for (dir in extDirs) {
|
||||
if (dir != null) {
|
||||
paths.add(dir.absolutePath)
|
||||
}
|
||||
override fun onDestroy() {
|
||||
super.onDestroy()
|
||||
callback.onActivityDestroy()
|
||||
}
|
||||
return paths
|
||||
}
|
||||
|
||||
private class PathChangeCallback(private var activity: ChangeResourcesCachePathActivity?) : FileSource.ResourcesCachePathChangeCallback {
|
||||
|
||||
override fun onSuccess(path: String) {
|
||||
activity?.onSuccess(path)
|
||||
override fun onItemClick(parent: AdapterView<*>?, view: View?, position: Int, id: Long) {
|
||||
listView.onItemClickListener = null
|
||||
val path: String = adapter.getItem(position) as String
|
||||
FileSource.setResourcesCachePath(path, callback)
|
||||
}
|
||||
|
||||
override fun onError(message: String) {
|
||||
activity?.onError(message)
|
||||
listView.onItemClickListener = this
|
||||
Toast.makeText(this, "Error: $message", Toast.LENGTH_LONG).show()
|
||||
}
|
||||
|
||||
fun onActivityDestroy() {
|
||||
activity = null
|
||||
}
|
||||
}
|
||||
override fun onSuccess(path: String) {
|
||||
listView.onItemClickListener = this
|
||||
Toast.makeText(this, "New path: $path", Toast.LENGTH_LONG).show()
|
||||
|
||||
class PathAdapter(private val context: Context, private val paths: List<String>) : BaseAdapter() {
|
||||
offlineManager.listOfflineRegions(object : OfflineManager.ListOfflineRegionsCallback {
|
||||
override fun onList(offlineRegions: Array<out OfflineRegion>?) {
|
||||
Logger.i(TAG, "Number of saved offline regions in the new path: ${offlineRegions?.size}")
|
||||
}
|
||||
|
||||
override fun getItem(position: Int): Any {
|
||||
return paths[position]
|
||||
override fun onError(error: String?) {
|
||||
Logger.e(TAG, error)
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
override fun getItemId(position: Int): Long {
|
||||
return position.toLong()
|
||||
private fun Context.obtainExternalFilesPaths(): List<String> {
|
||||
val paths = ArrayList<String>()
|
||||
paths.add(this.filesDir.absolutePath)
|
||||
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT) {
|
||||
paths.addAll(obtainExternalFilesPathsKitKat())
|
||||
} else {
|
||||
paths.addAll(obtainExternalFilesPathsLegacy())
|
||||
}
|
||||
paths.add("${File.separator}invalid${File.separator}cache${File.separator}path")
|
||||
return paths
|
||||
}
|
||||
|
||||
override fun getCount(): Int {
|
||||
return paths.size
|
||||
private fun Context.obtainExternalFilesPathsLegacy(): List<String> {
|
||||
val postFix =
|
||||
"${File.separator}Android${File.separator}data${File.separator}${this.packageName}${File.separator}files"
|
||||
val paths = ArrayList<String>()
|
||||
val externalStorage = System.getenv("EXTERNAL_STORAGE")
|
||||
val secondaryStorage = System.getenv("SECONDARY_STORAGE")
|
||||
if (externalStorage != null) {
|
||||
paths.add(externalStorage + postFix)
|
||||
}
|
||||
if (secondaryStorage != null) {
|
||||
val secPaths = secondaryStorage.split(":".toRegex()).dropLastWhile { it.isEmpty() }.toTypedArray()
|
||||
for (path in secPaths) {
|
||||
paths.add(path + postFix)
|
||||
}
|
||||
}
|
||||
return paths
|
||||
}
|
||||
|
||||
override fun getView(position: Int, convertView: View?, parent: ViewGroup?): View {
|
||||
val viewHolder: ViewHolder
|
||||
val view: View
|
||||
|
||||
if (convertView == null) {
|
||||
viewHolder = ViewHolder()
|
||||
view = LayoutInflater.from(context).inflate(android.R.layout.simple_list_item_1, parent, false)
|
||||
viewHolder.textView = view.findViewById(android.R.id.text1)
|
||||
view?.tag = viewHolder
|
||||
} else {
|
||||
view = convertView
|
||||
viewHolder = view.tag as ViewHolder
|
||||
}
|
||||
|
||||
viewHolder.textView?.text = paths[position]
|
||||
|
||||
return view
|
||||
@TargetApi(Build.VERSION_CODES.KITKAT)
|
||||
private fun Context.obtainExternalFilesPathsKitKat(): List<String> {
|
||||
val paths = ArrayList<String>()
|
||||
val extDirs = this.getExternalFilesDirs(null)
|
||||
for (dir in extDirs) {
|
||||
if (dir != null) {
|
||||
paths.add(dir.absolutePath)
|
||||
}
|
||||
}
|
||||
return paths
|
||||
}
|
||||
|
||||
class ViewHolder {
|
||||
var textView: TextView? = null
|
||||
private class PathChangeCallback(private var activity: ChangeResourcesCachePathActivity?) : FileSource.ResourcesCachePathChangeCallback {
|
||||
|
||||
override fun onSuccess(path: String) {
|
||||
activity?.onSuccess(path)
|
||||
}
|
||||
|
||||
override fun onError(message: String) {
|
||||
activity?.onError(message)
|
||||
}
|
||||
|
||||
fun onActivityDestroy() {
|
||||
activity = null
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
class PathAdapter(private val context: Context, private val paths: List<String>) : BaseAdapter() {
|
||||
|
||||
override fun getItem(position: Int): Any {
|
||||
return paths[position]
|
||||
}
|
||||
|
||||
override fun getItemId(position: Int): Long {
|
||||
return position.toLong()
|
||||
}
|
||||
|
||||
override fun getCount(): Int {
|
||||
return paths.size
|
||||
}
|
||||
|
||||
override fun getView(position: Int, convertView: View?, parent: ViewGroup?): View {
|
||||
val viewHolder: ViewHolder
|
||||
val view: View
|
||||
|
||||
if (convertView == null) {
|
||||
viewHolder = ViewHolder()
|
||||
view = LayoutInflater.from(context).inflate(android.R.layout.simple_list_item_1, parent, false)
|
||||
viewHolder.textView = view.findViewById(android.R.id.text1)
|
||||
view?.tag = viewHolder
|
||||
} else {
|
||||
view = convertView
|
||||
viewHolder = view.tag as ViewHolder
|
||||
}
|
||||
|
||||
viewHolder.textView?.text = paths[position]
|
||||
|
||||
return view
|
||||
}
|
||||
|
||||
class ViewHolder {
|
||||
var textView: TextView? = null
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -14,306 +14,313 @@ import com.mapbox.mapboxsdk.geometry.LatLngBounds
|
||||
import com.mapbox.mapboxsdk.maps.Style
|
||||
import com.mapbox.mapboxsdk.offline.*
|
||||
import com.mapbox.mapboxsdk.testapp.R
|
||||
import java.util.*
|
||||
import java.util.concurrent.TimeUnit
|
||||
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
|
||||
companion object {
|
||||
const val STATUS_UPDATE_TIMEOUT_MS = 10_000L
|
||||
}
|
||||
|
||||
// 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
|
||||
)
|
||||
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
|
||||
|
||||
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 onCreate(savedInstanceState: Bundle?) {
|
||||
super.onCreate(savedInstanceState)
|
||||
setContentView(R.layout.activity_region_download)
|
||||
|
||||
override fun onError(error: String) {
|
||||
logMessage("Failed to create offline region: $error")
|
||||
}
|
||||
})
|
||||
}
|
||||
offlineManager = OfflineManager.getInstance(this)
|
||||
offlineManager.setOfflineMapboxTileCountLimit(Long.MAX_VALUE)
|
||||
initUi()
|
||||
|
||||
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)
|
||||
deleteOldOfflineRegions {
|
||||
container.visibility = View.VISIBLE
|
||||
fab.visibility = View.VISIBLE
|
||||
}
|
||||
}
|
||||
}, 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) {
|
||||
"Completed".let {
|
||||
logMessage("SUCCESS! $it")
|
||||
download_status.text = it
|
||||
}
|
||||
fab.setImageResource(R.drawable.ic_play_arrow_black_24dp)
|
||||
handler.removeCallbacksAndMessages(null)
|
||||
offlineRegion?.setObserver(null)
|
||||
offlineRegion?.setDownloadState(OfflineRegion.STATE_INACTIVE)
|
||||
} else {
|
||||
val statusText = "Downloaded ${status.completedResourceCount}/${status.requiredResourceCount}"
|
||||
statusText.let {
|
||||
logMessage(it)
|
||||
download_status.text = it
|
||||
}
|
||||
|
||||
if (status.completedResourceCount > status.requiredResourceCount &&
|
||||
previousCompletedResourceCount <= status.requiredResourceCount
|
||||
) {
|
||||
logMessage("FAILURE! Completed > required")
|
||||
}
|
||||
}
|
||||
|
||||
previousCompletedResourceCount = status.completedResourceCount
|
||||
previousUpdateTimestamp = System.currentTimeMillis()
|
||||
}
|
||||
override fun onDestroy() {
|
||||
handler.removeCallbacksAndMessages(null)
|
||||
offlineRegion?.setObserver(null)
|
||||
super.onDestroy()
|
||||
}
|
||||
|
||||
override fun onError(error: OfflineRegionError) {
|
||||
logMessage("Error: $error")
|
||||
}
|
||||
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()
|
||||
|
||||
override fun mapboxTileCountLimitExceeded(limit: Long) {
|
||||
logMessage("Error: tile count limit exceeded")
|
||||
}
|
||||
if (!validCoordinates(latitudeNorth, longitudeEast, latitudeSouth, longitudeWest)) {
|
||||
Toast.makeText(this, "coordinates need to be in valid range", Toast.LENGTH_LONG).show()
|
||||
return
|
||||
}
|
||||
|
||||
protected fun logMessage(message: String) {
|
||||
Timber.d(message)
|
||||
logView.append(message)
|
||||
logView.append("\n")
|
||||
}
|
||||
// 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
|
||||
)
|
||||
|
||||
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()
|
||||
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) {
|
||||
"Completed".let {
|
||||
logMessage("SUCCESS! $it")
|
||||
download_status.text = it
|
||||
}
|
||||
fab.setImageResource(R.drawable.ic_play_arrow_black_24dp)
|
||||
handler.removeCallbacksAndMessages(null)
|
||||
offlineRegion?.setObserver(null)
|
||||
offlineRegion?.setDownloadState(OfflineRegion.STATE_INACTIVE)
|
||||
} else {
|
||||
onCompleted()
|
||||
val statusText = "Downloaded ${status.completedResourceCount}/${status.requiredResourceCount}"
|
||||
statusText.let {
|
||||
logMessage(it)
|
||||
download_status.text = it
|
||||
}
|
||||
|
||||
if (status.completedResourceCount > status.requiredResourceCount &&
|
||||
previousCompletedResourceCount <= status.requiredResourceCount
|
||||
) {
|
||||
logMessage("FAILURE! Completed > required")
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
override fun onError(error: String) {
|
||||
logMessage("Failed to list offline regions: $error")
|
||||
onCompleted()
|
||||
}
|
||||
})
|
||||
}
|
||||
previousCompletedResourceCount = status.completedResourceCount
|
||||
previousUpdateTimestamp = System.currentTimeMillis()
|
||||
}
|
||||
|
||||
// ui
|
||||
override fun onError(error: OfflineRegionError) {
|
||||
logMessage("Error: $error")
|
||||
}
|
||||
|
||||
private val logView: TextView by lazy {
|
||||
findViewById<TextView>(R.id.log_text)
|
||||
}
|
||||
override fun mapboxTileCountLimitExceeded(limit: Long) {
|
||||
logMessage("Error: tile count limit exceeded")
|
||||
}
|
||||
|
||||
private fun initUi() {
|
||||
initEditTexts()
|
||||
initSeekbars()
|
||||
initSpinner()
|
||||
initZoomLevelTextviews()
|
||||
initSeekbarListeners()
|
||||
initFab()
|
||||
}
|
||||
protected fun logMessage(message: String) {
|
||||
Timber.d(message)
|
||||
logView.append(message)
|
||||
logView.append("\n")
|
||||
}
|
||||
|
||||
private fun initEditTexts() {
|
||||
editTextLatNorth.setText("62.0")
|
||||
editTextLonEast.setText("24.0")
|
||||
editTextLatSouth.setText("60.0")
|
||||
editTextLonWest.setText("22.5")
|
||||
}
|
||||
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()
|
||||
}
|
||||
|
||||
private fun initSeekbars() {
|
||||
val maxZoom = MapboxConstants.MAXIMUM_ZOOM.toInt()
|
||||
seekbarMinZoom.max = maxZoom
|
||||
seekbarMinZoom.progress = 1
|
||||
seekbarMaxZoom.max = maxZoom
|
||||
seekbarMaxZoom.progress = 15
|
||||
}
|
||||
override fun onError(error: String) {
|
||||
Timber.e("Failed to delete region: $error")
|
||||
onProcessed()
|
||||
}
|
||||
|
||||
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 onProcessed() {
|
||||
remainingCount--
|
||||
if (remainingCount == 0) {
|
||||
logMessage("Done deleting")
|
||||
onCompleted()
|
||||
}
|
||||
}
|
||||
})
|
||||
}
|
||||
} else {
|
||||
onCompleted()
|
||||
}
|
||||
}
|
||||
|
||||
private fun initZoomLevelTextviews() {
|
||||
textViewMaxText.text = String.format("Max zoom: %s", seekbarMaxZoom.progress)
|
||||
textViewMinText.text = String.format("Min zoom: %s", seekbarMinZoom.progress)
|
||||
}
|
||||
override fun onError(error: String) {
|
||||
logMessage("Failed to list offline regions: $error")
|
||||
onCompleted()
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
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)
|
||||
}
|
||||
// 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)
|
||||
}
|
||||
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 onStartTrackingTouch(seekBar: SeekBar) {
|
||||
}
|
||||
|
||||
override fun onStopTrackingTouch(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)
|
||||
}
|
||||
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 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
|
||||
override fun onStopTrackingTouch(seekBar: SeekBar) {
|
||||
}
|
||||
})
|
||||
}
|
||||
return true
|
||||
}
|
||||
}
|
||||
|
||||
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
|
||||
}
|
||||
}
|
||||
|
||||
@@ -14,134 +14,139 @@ import com.mapbox.mapboxsdk.testapp.utils.FileUtils
|
||||
import kotlinx.android.synthetic.main.activity_merge_offline_regions.*
|
||||
|
||||
class MergeOfflineRegionsActivity : AppCompatActivity() {
|
||||
companion object {
|
||||
private const val LOG_TAG = "Mbgl-MergeOfflineRegionsActivity"
|
||||
private const val TEST_DB_FILE_NAME = "offline_test.db"
|
||||
private const val TEST_STYLE = Style.SATELLITE
|
||||
}
|
||||
|
||||
private val onFileCopiedListener = object : FileUtils.OnFileCopiedFromAssetsListener {
|
||||
override fun onFileCopiedFromAssets() {
|
||||
Toast.makeText(
|
||||
this@MergeOfflineRegionsActivity,
|
||||
String.format("OnFileCopied."),
|
||||
Toast.LENGTH_LONG).show()
|
||||
mergeDb()
|
||||
companion object {
|
||||
private const val LOG_TAG = "Mbgl-MergeOfflineRegionsActivity"
|
||||
private const val TEST_DB_FILE_NAME = "offline_test.db"
|
||||
private const val TEST_STYLE = Style.SATELLITE
|
||||
}
|
||||
|
||||
override fun onError() {
|
||||
Toast.makeText(
|
||||
this@MergeOfflineRegionsActivity,
|
||||
String.format("Error copying DB file."),
|
||||
Toast.LENGTH_LONG).show()
|
||||
}
|
||||
}
|
||||
private val onFileCopiedListener = object : FileUtils.OnFileCopiedFromAssetsListener {
|
||||
override fun onFileCopiedFromAssets() {
|
||||
Toast.makeText(
|
||||
this@MergeOfflineRegionsActivity,
|
||||
String.format("OnFileCopied."),
|
||||
Toast.LENGTH_LONG
|
||||
).show()
|
||||
mergeDb()
|
||||
}
|
||||
|
||||
private val onRegionMergedListener = object : OfflineManager.MergeOfflineRegionsCallback {
|
||||
override fun onMerge(offlineRegions: Array<OfflineRegion>) {
|
||||
mapView.getMapAsync {
|
||||
it.setStyle(Style.Builder().fromUri(TEST_STYLE))
|
||||
}
|
||||
Toast.makeText(
|
||||
this@MergeOfflineRegionsActivity,
|
||||
String.format("Merged %d regions.", offlineRegions.size),
|
||||
Toast.LENGTH_LONG).show()
|
||||
override fun onError() {
|
||||
Toast.makeText(
|
||||
this@MergeOfflineRegionsActivity,
|
||||
String.format("Error copying DB file."),
|
||||
Toast.LENGTH_LONG
|
||||
).show()
|
||||
}
|
||||
}
|
||||
|
||||
override fun onError(error: String) {
|
||||
Toast.makeText(
|
||||
this@MergeOfflineRegionsActivity,
|
||||
String.format("Offline DB merge error."),
|
||||
Toast.LENGTH_LONG).show()
|
||||
Logger.e(LOG_TAG, error)
|
||||
}
|
||||
}
|
||||
private val onRegionMergedListener = object : OfflineManager.MergeOfflineRegionsCallback {
|
||||
override fun onMerge(offlineRegions: Array<OfflineRegion>) {
|
||||
mapView.getMapAsync {
|
||||
it.setStyle(Style.Builder().fromUri(TEST_STYLE))
|
||||
}
|
||||
Toast.makeText(
|
||||
this@MergeOfflineRegionsActivity,
|
||||
String.format("Merged %d regions.", offlineRegions.size),
|
||||
Toast.LENGTH_LONG
|
||||
).show()
|
||||
}
|
||||
|
||||
/**
|
||||
* Since we expect from the results of the offline merge callback to interact with the hosting activity,
|
||||
* we need to ensure that we are not interacting with a destroyed activity.
|
||||
*/
|
||||
private class MergeCallback(private var activityCallback: OfflineManager.MergeOfflineRegionsCallback?) : OfflineManager.MergeOfflineRegionsCallback {
|
||||
|
||||
override fun onMerge(offlineRegions: Array<out OfflineRegion>?) {
|
||||
activityCallback?.onMerge(offlineRegions)
|
||||
override fun onError(error: String) {
|
||||
Toast.makeText(
|
||||
this@MergeOfflineRegionsActivity,
|
||||
String.format("Offline DB merge error."),
|
||||
Toast.LENGTH_LONG
|
||||
).show()
|
||||
Logger.e(LOG_TAG, error)
|
||||
}
|
||||
}
|
||||
|
||||
override fun onError(error: String?) {
|
||||
activityCallback?.onError(error)
|
||||
/**
|
||||
* Since we expect from the results of the offline merge callback to interact with the hosting activity,
|
||||
* we need to ensure that we are not interacting with a destroyed activity.
|
||||
*/
|
||||
private class MergeCallback(private var activityCallback: OfflineManager.MergeOfflineRegionsCallback?) : OfflineManager.MergeOfflineRegionsCallback {
|
||||
|
||||
override fun onMerge(offlineRegions: Array<out OfflineRegion>?) {
|
||||
activityCallback?.onMerge(offlineRegions)
|
||||
}
|
||||
|
||||
override fun onError(error: String?) {
|
||||
activityCallback?.onError(error)
|
||||
}
|
||||
|
||||
fun onActivityDestroy() {
|
||||
activityCallback = null
|
||||
}
|
||||
}
|
||||
|
||||
fun onActivityDestroy() {
|
||||
activityCallback = null
|
||||
private val mergeCallback = MergeCallback(onRegionMergedListener)
|
||||
|
||||
override fun onCreate(savedInstanceState: Bundle?) {
|
||||
super.onCreate(savedInstanceState)
|
||||
setContentView(R.layout.activity_merge_offline_regions)
|
||||
|
||||
// forcing offline state
|
||||
Mapbox.setConnected(false)
|
||||
|
||||
mapView.onCreate(savedInstanceState)
|
||||
load_region_btn.setOnClickListener {
|
||||
copyAsset()
|
||||
}
|
||||
mapView.getMapAsync {
|
||||
it.isDebugActive = true
|
||||
it.setStyle(Style.Builder().fromUri(TEST_STYLE))
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private val mergeCallback = MergeCallback(onRegionMergedListener)
|
||||
|
||||
override fun onCreate(savedInstanceState: Bundle?) {
|
||||
super.onCreate(savedInstanceState)
|
||||
setContentView(R.layout.activity_merge_offline_regions)
|
||||
|
||||
// forcing offline state
|
||||
Mapbox.setConnected(false)
|
||||
|
||||
mapView.onCreate(savedInstanceState)
|
||||
load_region_btn.setOnClickListener {
|
||||
copyAsset()
|
||||
private fun copyAsset() {
|
||||
// copy db asset to internal memory
|
||||
FileUtils.CopyFileFromAssetsTask(this, onFileCopiedListener).execute(TEST_DB_FILE_NAME, FileSource.getResourcesCachePath(this))
|
||||
}
|
||||
mapView.getMapAsync {
|
||||
it.isDebugActive = true
|
||||
it.setStyle(Style.Builder().fromUri(TEST_STYLE))
|
||||
|
||||
private fun mergeDb() {
|
||||
OfflineManager.getInstance(this).mergeOfflineRegions(
|
||||
FileSource.getResourcesCachePath(this) + "/" + TEST_DB_FILE_NAME,
|
||||
mergeCallback
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
private fun copyAsset() {
|
||||
// copy db asset to internal memory
|
||||
FileUtils.CopyFileFromAssetsTask(this, onFileCopiedListener).execute(TEST_DB_FILE_NAME, FileSource.getResourcesCachePath(this))
|
||||
}
|
||||
override fun onStart() {
|
||||
super.onStart()
|
||||
mapView.onStart()
|
||||
}
|
||||
|
||||
private fun mergeDb() {
|
||||
OfflineManager.getInstance(this).mergeOfflineRegions(
|
||||
FileSource.getResourcesCachePath(this) + "/" + TEST_DB_FILE_NAME, mergeCallback
|
||||
)
|
||||
}
|
||||
override fun onResume() {
|
||||
super.onResume()
|
||||
mapView.onResume()
|
||||
}
|
||||
|
||||
override fun onStart() {
|
||||
super.onStart()
|
||||
mapView.onStart()
|
||||
}
|
||||
override fun onPause() {
|
||||
super.onPause()
|
||||
mapView.onPause()
|
||||
}
|
||||
|
||||
override fun onResume() {
|
||||
super.onResume()
|
||||
mapView.onResume()
|
||||
}
|
||||
override fun onStop() {
|
||||
super.onStop()
|
||||
mapView.onStop()
|
||||
}
|
||||
|
||||
override fun onPause() {
|
||||
super.onPause()
|
||||
mapView.onPause()
|
||||
}
|
||||
override fun onLowMemory() {
|
||||
super.onLowMemory()
|
||||
mapView.onLowMemory()
|
||||
}
|
||||
|
||||
override fun onStop() {
|
||||
super.onStop()
|
||||
mapView.onStop()
|
||||
}
|
||||
override fun onDestroy() {
|
||||
super.onDestroy()
|
||||
mergeCallback.onActivityDestroy()
|
||||
mapView.onDestroy()
|
||||
|
||||
override fun onLowMemory() {
|
||||
super.onLowMemory()
|
||||
mapView.onLowMemory()
|
||||
}
|
||||
// restoring connectivity state
|
||||
Mapbox.setConnected(null)
|
||||
}
|
||||
|
||||
override fun onDestroy() {
|
||||
super.onDestroy()
|
||||
mergeCallback.onActivityDestroy()
|
||||
mapView.onDestroy()
|
||||
|
||||
// restoring connectivity state
|
||||
Mapbox.setConnected(null)
|
||||
}
|
||||
|
||||
override fun onSaveInstanceState(outState: Bundle) {
|
||||
super.onSaveInstanceState(outState)
|
||||
mapView.onSaveInstanceState(outState)
|
||||
}
|
||||
}
|
||||
override fun onSaveInstanceState(outState: Bundle) {
|
||||
super.onSaveInstanceState(outState)
|
||||
mapView.onSaveInstanceState(outState)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -13,65 +13,68 @@ import kotlinx.android.synthetic.main.activity_cache_management.*
|
||||
*/
|
||||
class CacheManagementActivity : AppCompatActivity() {
|
||||
|
||||
override fun onCreate(savedInstanceState: Bundle?) {
|
||||
super.onCreate(savedInstanceState)
|
||||
setContentView(R.layout.activity_cache_management)
|
||||
override fun onCreate(savedInstanceState: Bundle?) {
|
||||
super.onCreate(savedInstanceState)
|
||||
setContentView(R.layout.activity_cache_management)
|
||||
|
||||
val fileSource = OfflineManager.getInstance(this)
|
||||
resetDatabaseButton.setOnClickListener {
|
||||
fileSource.resetDatabase(object : OfflineManager.FileSourceCallback {
|
||||
override fun onSuccess() {
|
||||
showSnackbar("Reset database success")
|
||||
val fileSource = OfflineManager.getInstance(this)
|
||||
resetDatabaseButton.setOnClickListener {
|
||||
fileSource.resetDatabase(object : OfflineManager.FileSourceCallback {
|
||||
override fun onSuccess() {
|
||||
showSnackbar("Reset database success")
|
||||
}
|
||||
|
||||
override fun onError(message: String) {
|
||||
showSnackbar("Reset database fail: $message")
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
override fun onError(message: String) {
|
||||
showSnackbar("Reset database fail: $message")
|
||||
invalidateAmbientCacheButton.setOnClickListener {
|
||||
fileSource.invalidateAmbientCache(object : OfflineManager.FileSourceCallback {
|
||||
override fun onSuccess() {
|
||||
showSnackbar("Invalidate ambient cache success")
|
||||
}
|
||||
|
||||
override fun onError(message: String) {
|
||||
showSnackbar("Invalidate ambient cache fail: $message")
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
clearAmbientCacheButton.setOnClickListener {
|
||||
fileSource.clearAmbientCache(object : OfflineManager.FileSourceCallback {
|
||||
override fun onSuccess() {
|
||||
showSnackbar("Clear ambient cache success")
|
||||
}
|
||||
|
||||
override fun onError(message: String) {
|
||||
showSnackbar("Clear ambient cache fail: $message")
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
setMaximumAmbientCacheSizeButton.setOnClickListener {
|
||||
fileSource.setMaximumAmbientCacheSize(
|
||||
5000000,
|
||||
object : OfflineManager.FileSourceCallback {
|
||||
override fun onSuccess() {
|
||||
showSnackbar("Set maximum ambient cache size success")
|
||||
}
|
||||
|
||||
override fun onError(message: String) {
|
||||
showSnackbar("Set maximum ambient cache size fail: $message")
|
||||
}
|
||||
}
|
||||
)
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
invalidateAmbientCacheButton.setOnClickListener {
|
||||
fileSource.invalidateAmbientCache(object : OfflineManager.FileSourceCallback {
|
||||
override fun onSuccess() {
|
||||
showSnackbar("Invalidate ambient cache success")
|
||||
}
|
||||
fun showSnackbar(message: String) {
|
||||
// validate that all callbacks occur on main thread
|
||||
assert(Looper.myLooper() == Looper.getMainLooper())
|
||||
|
||||
override fun onError(message: String) {
|
||||
showSnackbar("Invalidate ambient cache fail: $message")
|
||||
}
|
||||
})
|
||||
// show snackbar
|
||||
Snackbar.make(container, message, Snackbar.LENGTH_SHORT).show()
|
||||
}
|
||||
|
||||
clearAmbientCacheButton.setOnClickListener {
|
||||
fileSource.clearAmbientCache(object : OfflineManager.FileSourceCallback {
|
||||
override fun onSuccess() {
|
||||
showSnackbar("Clear ambient cache success")
|
||||
}
|
||||
|
||||
override fun onError(message: String) {
|
||||
showSnackbar("Clear ambient cache fail: $message")
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
setMaximumAmbientCacheSizeButton.setOnClickListener {
|
||||
fileSource.setMaximumAmbientCacheSize(5000000, object : OfflineManager.FileSourceCallback {
|
||||
override fun onSuccess() {
|
||||
showSnackbar("Set maximum ambient cache size success")
|
||||
}
|
||||
|
||||
override fun onError(message: String) {
|
||||
showSnackbar("Set maximum ambient cache size fail: $message")
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
fun showSnackbar(message: String) {
|
||||
// validate that all callbacks occur on main thread
|
||||
assert(Looper.myLooper() == Looper.getMainLooper())
|
||||
|
||||
// show snackbar
|
||||
Snackbar.make(container, message, Snackbar.LENGTH_SHORT).show()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -18,118 +18,119 @@ import com.mapbox.mapboxsdk.style.layers.LineLayer
|
||||
import com.mapbox.mapboxsdk.style.layers.PropertyFactory
|
||||
import com.mapbox.mapboxsdk.style.sources.GeoJsonSource
|
||||
import com.mapbox.mapboxsdk.testapp.R
|
||||
import java.util.*
|
||||
import kotlinx.android.synthetic.main.activity_collection_update_on_style_change.*
|
||||
import java.util.*
|
||||
|
||||
/**
|
||||
* Test activity that verifies whether the GeoJsonSource transition over style changes can be smooth.
|
||||
*/
|
||||
class CollectionUpdateOnStyleChange : AppCompatActivity(), OnMapReadyCallback, Style.OnStyleLoaded {
|
||||
|
||||
private lateinit var mapboxMap: MapboxMap
|
||||
private var currentStyleIndex: Int = 0
|
||||
private lateinit var mapboxMap: MapboxMap
|
||||
private var currentStyleIndex: Int = 0
|
||||
|
||||
override fun onCreate(savedInstanceState: Bundle?) {
|
||||
super.onCreate(savedInstanceState)
|
||||
setContentView(R.layout.activity_collection_update_on_style_change)
|
||||
mapView.onCreate(savedInstanceState)
|
||||
mapView.getMapAsync(this)
|
||||
setupStyleChangeView()
|
||||
Toast.makeText(
|
||||
this,
|
||||
"Make sure that the collection doesn't blink on style change",
|
||||
Toast.LENGTH_LONG)
|
||||
.show()
|
||||
}
|
||||
|
||||
override fun onMapReady(map: MapboxMap) {
|
||||
mapboxMap = map
|
||||
mapboxMap.setStyle(Style.Builder().fromUri(STYLES[currentStyleIndex]), this)
|
||||
}
|
||||
|
||||
override fun onStyleLoaded(style: Style) {
|
||||
setupLayer(style)
|
||||
}
|
||||
|
||||
private fun setupLayer(style: Style) {
|
||||
val source = GeoJsonSource("source", featureCollection)
|
||||
val lineLayer = LineLayer("layer", "source")
|
||||
.withProperties(
|
||||
PropertyFactory.lineColor(Color.RED),
|
||||
PropertyFactory.lineWidth(10f)
|
||||
)
|
||||
|
||||
style.addSource(source)
|
||||
style.addLayer(lineLayer)
|
||||
}
|
||||
|
||||
private fun setupStyleChangeView() {
|
||||
val fabStyles = findViewById<FloatingActionButton>(R.id.fabStyles)
|
||||
fabStyles.setOnClickListener {
|
||||
currentStyleIndex++
|
||||
if (currentStyleIndex == STYLES.size) {
|
||||
currentStyleIndex = 0
|
||||
}
|
||||
mapboxMap.setStyle(Style.Builder().fromUri(STYLES[currentStyleIndex]), this)
|
||||
}
|
||||
}
|
||||
|
||||
override fun onStart() {
|
||||
super.onStart()
|
||||
mapView.onStart()
|
||||
}
|
||||
|
||||
override fun onResume() {
|
||||
super.onResume()
|
||||
mapView.onResume()
|
||||
}
|
||||
|
||||
override fun onPause() {
|
||||
super.onPause()
|
||||
mapView.onPause()
|
||||
}
|
||||
|
||||
override fun onStop() {
|
||||
super.onStop()
|
||||
mapView.onStop()
|
||||
}
|
||||
|
||||
override fun onSaveInstanceState(outState: Bundle) {
|
||||
super.onSaveInstanceState(outState)
|
||||
mapView.onSaveInstanceState(outState)
|
||||
}
|
||||
|
||||
override fun onDestroy() {
|
||||
super.onDestroy()
|
||||
mapView.onDestroy()
|
||||
}
|
||||
|
||||
override fun onLowMemory() {
|
||||
super.onLowMemory()
|
||||
mapView.onLowMemory()
|
||||
}
|
||||
|
||||
companion object {
|
||||
|
||||
private val STYLES = arrayOf(Style.MAPBOX_STREETS, Style.OUTDOORS, Style.LIGHT, Style.DARK, Style.SATELLITE, Style.SATELLITE_STREETS, Style.TRAFFIC_DAY, Style.TRAFFIC_NIGHT)
|
||||
|
||||
private val featureCollection: FeatureCollection
|
||||
|
||||
init {
|
||||
val bounds = LatLngBounds.from(60.0, 100.0, -60.0, -100.0)
|
||||
val points = ArrayList<Point>()
|
||||
for (i in 0 until 1000) {
|
||||
val latLng = getLatLngInBounds(bounds)
|
||||
points.add(Point.fromLngLat(latLng.longitude, latLng.latitude))
|
||||
}
|
||||
featureCollection = FeatureCollection.fromFeature(Feature.fromGeometry(LineString.fromLngLats(points)))
|
||||
override fun onCreate(savedInstanceState: Bundle?) {
|
||||
super.onCreate(savedInstanceState)
|
||||
setContentView(R.layout.activity_collection_update_on_style_change)
|
||||
mapView.onCreate(savedInstanceState)
|
||||
mapView.getMapAsync(this)
|
||||
setupStyleChangeView()
|
||||
Toast.makeText(
|
||||
this,
|
||||
"Make sure that the collection doesn't blink on style change",
|
||||
Toast.LENGTH_LONG
|
||||
)
|
||||
.show()
|
||||
}
|
||||
|
||||
private fun getLatLngInBounds(bounds: LatLngBounds): LatLng {
|
||||
val generator = Random()
|
||||
val randomLat = bounds.latSouth + generator.nextDouble() * (bounds.latNorth - bounds.latSouth)
|
||||
val randomLon = bounds.lonWest + generator.nextDouble() * (bounds.lonEast - bounds.lonWest)
|
||||
return LatLng(randomLat, randomLon)
|
||||
override fun onMapReady(map: MapboxMap) {
|
||||
mapboxMap = map
|
||||
mapboxMap.setStyle(Style.Builder().fromUri(STYLES[currentStyleIndex]), this)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
override fun onStyleLoaded(style: Style) {
|
||||
setupLayer(style)
|
||||
}
|
||||
|
||||
private fun setupLayer(style: Style) {
|
||||
val source = GeoJsonSource("source", featureCollection)
|
||||
val lineLayer = LineLayer("layer", "source")
|
||||
.withProperties(
|
||||
PropertyFactory.lineColor(Color.RED),
|
||||
PropertyFactory.lineWidth(10f)
|
||||
)
|
||||
|
||||
style.addSource(source)
|
||||
style.addLayer(lineLayer)
|
||||
}
|
||||
|
||||
private fun setupStyleChangeView() {
|
||||
val fabStyles = findViewById<FloatingActionButton>(R.id.fabStyles)
|
||||
fabStyles.setOnClickListener {
|
||||
currentStyleIndex++
|
||||
if (currentStyleIndex == STYLES.size) {
|
||||
currentStyleIndex = 0
|
||||
}
|
||||
mapboxMap.setStyle(Style.Builder().fromUri(STYLES[currentStyleIndex]), this)
|
||||
}
|
||||
}
|
||||
|
||||
override fun onStart() {
|
||||
super.onStart()
|
||||
mapView.onStart()
|
||||
}
|
||||
|
||||
override fun onResume() {
|
||||
super.onResume()
|
||||
mapView.onResume()
|
||||
}
|
||||
|
||||
override fun onPause() {
|
||||
super.onPause()
|
||||
mapView.onPause()
|
||||
}
|
||||
|
||||
override fun onStop() {
|
||||
super.onStop()
|
||||
mapView.onStop()
|
||||
}
|
||||
|
||||
override fun onSaveInstanceState(outState: Bundle) {
|
||||
super.onSaveInstanceState(outState)
|
||||
mapView.onSaveInstanceState(outState)
|
||||
}
|
||||
|
||||
override fun onDestroy() {
|
||||
super.onDestroy()
|
||||
mapView.onDestroy()
|
||||
}
|
||||
|
||||
override fun onLowMemory() {
|
||||
super.onLowMemory()
|
||||
mapView.onLowMemory()
|
||||
}
|
||||
|
||||
companion object {
|
||||
|
||||
private val STYLES = arrayOf(Style.MAPBOX_STREETS, Style.OUTDOORS, Style.LIGHT, Style.DARK, Style.SATELLITE, Style.SATELLITE_STREETS, Style.TRAFFIC_DAY, Style.TRAFFIC_NIGHT)
|
||||
|
||||
private val featureCollection: FeatureCollection
|
||||
|
||||
init {
|
||||
val bounds = LatLngBounds.from(60.0, 100.0, -60.0, -100.0)
|
||||
val points = ArrayList<Point>()
|
||||
for (i in 0 until 1000) {
|
||||
val latLng = getLatLngInBounds(bounds)
|
||||
points.add(Point.fromLngLat(latLng.longitude, latLng.latitude))
|
||||
}
|
||||
featureCollection = FeatureCollection.fromFeature(Feature.fromGeometry(LineString.fromLngLats(points)))
|
||||
}
|
||||
|
||||
private fun getLatLngInBounds(bounds: LatLngBounds): LatLng {
|
||||
val generator = Random()
|
||||
val randomLat = bounds.latSouth + generator.nextDouble() * (bounds.latNorth - bounds.latSouth)
|
||||
val randomLon = bounds.lonWest + generator.nextDouble() * (bounds.lonEast - bounds.lonWest)
|
||||
return LatLng(randomLat, randomLon)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -26,104 +26,109 @@ import kotlinx.android.synthetic.main.activity_physical_circle.*
|
||||
*/
|
||||
class DistanceExpressionActivity : AppCompatActivity() {
|
||||
|
||||
private lateinit var mapboxMap: MapboxMap
|
||||
private lateinit var mapboxMap: MapboxMap
|
||||
|
||||
private val lat = 37.78794572301525
|
||||
private val lon = -122.40752220153807
|
||||
private val lat = 37.78794572301525
|
||||
private val lon = -122.40752220153807
|
||||
|
||||
override fun onCreate(savedInstanceState: Bundle?) {
|
||||
super.onCreate(savedInstanceState)
|
||||
setContentView(R.layout.activity_within_expression)
|
||||
override fun onCreate(savedInstanceState: Bundle?) {
|
||||
super.onCreate(savedInstanceState)
|
||||
setContentView(R.layout.activity_within_expression)
|
||||
|
||||
mapView.onCreate(savedInstanceState)
|
||||
mapView.getMapAsync { map ->
|
||||
mapboxMap = map
|
||||
mapView.onCreate(savedInstanceState)
|
||||
mapView.getMapAsync { map ->
|
||||
mapboxMap = map
|
||||
|
||||
// Setup camera position above Georgetown
|
||||
mapboxMap.cameraPosition = CameraPosition.Builder()
|
||||
.target(LatLng(lat, lon))
|
||||
.zoom(16.0)
|
||||
.build()
|
||||
setupStyle()
|
||||
// Setup camera position above Georgetown
|
||||
mapboxMap.cameraPosition = CameraPosition.Builder()
|
||||
.target(LatLng(lat, lon))
|
||||
.zoom(16.0)
|
||||
.build()
|
||||
setupStyle()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private fun setupStyle() {
|
||||
val center = Point.fromLngLat(lon, lat)
|
||||
val circle = TurfTransformation.circle(center, 150.0, TurfConstants.UNIT_METRES)
|
||||
// Setup style with additional layers,
|
||||
// using Style.MAPBOX_STREETS as a base style
|
||||
mapboxMap.setStyle(
|
||||
Style.Builder()
|
||||
.fromUri(Style.MAPBOX_STREETS)
|
||||
.withSources(
|
||||
GeoJsonSource(
|
||||
POINT_ID, Point.fromLngLat(lon, lat)
|
||||
),
|
||||
GeoJsonSource(CIRCLE_ID, circle)
|
||||
)
|
||||
.withLayerBelow(
|
||||
FillLayer(CIRCLE_ID, CIRCLE_ID)
|
||||
.withProperties(
|
||||
fillOpacity(0.5f),
|
||||
fillColor(Color.parseColor("#3bb2d0"))
|
||||
), "poi-label"
|
||||
)
|
||||
) { style ->
|
||||
// Show only POI labels inside circle radius using distance expression
|
||||
val symbolLayer = style.getLayer("poi-label") as SymbolLayer
|
||||
symbolLayer.setFilter(lt(
|
||||
distance(
|
||||
Point.fromLngLat(lon, lat)
|
||||
), 150)
|
||||
)
|
||||
private fun setupStyle() {
|
||||
val center = Point.fromLngLat(lon, lat)
|
||||
val circle = TurfTransformation.circle(center, 150.0, TurfConstants.UNIT_METRES)
|
||||
// Setup style with additional layers,
|
||||
// using Style.MAPBOX_STREETS as a base style
|
||||
mapboxMap.setStyle(
|
||||
Style.Builder()
|
||||
.fromUri(Style.MAPBOX_STREETS)
|
||||
.withSources(
|
||||
GeoJsonSource(
|
||||
POINT_ID,
|
||||
Point.fromLngLat(lon, lat)
|
||||
),
|
||||
GeoJsonSource(CIRCLE_ID, circle)
|
||||
)
|
||||
.withLayerBelow(
|
||||
FillLayer(CIRCLE_ID, CIRCLE_ID)
|
||||
.withProperties(
|
||||
fillOpacity(0.5f),
|
||||
fillColor(Color.parseColor("#3bb2d0"))
|
||||
),
|
||||
"poi-label"
|
||||
)
|
||||
) { style ->
|
||||
// Show only POI labels inside circle radius using distance expression
|
||||
val symbolLayer = style.getLayer("poi-label") as SymbolLayer
|
||||
symbolLayer.setFilter(
|
||||
lt(
|
||||
distance(
|
||||
Point.fromLngLat(lon, lat)
|
||||
),
|
||||
150
|
||||
)
|
||||
)
|
||||
|
||||
// Hide other types of labels to highlight POI labels
|
||||
(style.getLayer("road-label") as SymbolLayer).setProperties(visibility(NONE))
|
||||
(style.getLayer("transit-label") as SymbolLayer).setProperties(visibility(NONE))
|
||||
(style.getLayer("road-number-shield") as SymbolLayer).setProperties(visibility(NONE))
|
||||
// Hide other types of labels to highlight POI labels
|
||||
(style.getLayer("road-label") as SymbolLayer).setProperties(visibility(NONE))
|
||||
(style.getLayer("transit-label") as SymbolLayer).setProperties(visibility(NONE))
|
||||
(style.getLayer("road-number-shield") as SymbolLayer).setProperties(visibility(NONE))
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
override fun onStart() {
|
||||
super.onStart()
|
||||
mapView.onStart()
|
||||
}
|
||||
|
||||
override fun onResume() {
|
||||
super.onResume()
|
||||
mapView.onResume()
|
||||
}
|
||||
|
||||
override fun onPause() {
|
||||
super.onPause()
|
||||
mapView.onPause()
|
||||
}
|
||||
|
||||
override fun onStop() {
|
||||
super.onStop()
|
||||
mapView.onStop()
|
||||
}
|
||||
|
||||
override fun onLowMemory() {
|
||||
super.onLowMemory()
|
||||
mapView.onLowMemory()
|
||||
}
|
||||
|
||||
override fun onDestroy() {
|
||||
super.onDestroy()
|
||||
mapView.onDestroy()
|
||||
}
|
||||
|
||||
override fun onSaveInstanceState(outState: Bundle?, outPersistentState: PersistableBundle?) {
|
||||
super.onSaveInstanceState(outState, outPersistentState)
|
||||
outState?.let {
|
||||
mapView.onSaveInstanceState(it)
|
||||
override fun onStart() {
|
||||
super.onStart()
|
||||
mapView.onStart()
|
||||
}
|
||||
}
|
||||
|
||||
companion object {
|
||||
const val POINT_ID = "point"
|
||||
const val CIRCLE_ID = "circle"
|
||||
}
|
||||
}
|
||||
override fun onResume() {
|
||||
super.onResume()
|
||||
mapView.onResume()
|
||||
}
|
||||
|
||||
override fun onPause() {
|
||||
super.onPause()
|
||||
mapView.onPause()
|
||||
}
|
||||
|
||||
override fun onStop() {
|
||||
super.onStop()
|
||||
mapView.onStop()
|
||||
}
|
||||
|
||||
override fun onLowMemory() {
|
||||
super.onLowMemory()
|
||||
mapView.onLowMemory()
|
||||
}
|
||||
|
||||
override fun onDestroy() {
|
||||
super.onDestroy()
|
||||
mapView.onDestroy()
|
||||
}
|
||||
|
||||
override fun onSaveInstanceState(outState: Bundle?, outPersistentState: PersistableBundle?) {
|
||||
super.onSaveInstanceState(outState, outPersistentState)
|
||||
outState?.let {
|
||||
mapView.onSaveInstanceState(it)
|
||||
}
|
||||
}
|
||||
|
||||
companion object {
|
||||
const val POINT_ID = "point"
|
||||
const val CIRCLE_ID = "circle"
|
||||
}
|
||||
}
|
||||
|
||||
@@ -28,305 +28,320 @@ import kotlinx.android.synthetic.main.activity_draggable_marker.*
|
||||
* An Activity that showcases how to make symbols draggable.
|
||||
*/
|
||||
class DraggableMarkerActivity : AppCompatActivity() {
|
||||
companion object {
|
||||
private const val sourceId = "source_draggable"
|
||||
private const val layerId = "layer_draggable"
|
||||
private const val markerImageId = "marker_icon_draggable"
|
||||
companion object {
|
||||
private const val sourceId = "source_draggable"
|
||||
private const val layerId = "layer_draggable"
|
||||
private const val markerImageId = "marker_icon_draggable"
|
||||
|
||||
private var latestId: Long = 0
|
||||
fun generateMarkerId(): String {
|
||||
if (latestId == Long.MAX_VALUE) {
|
||||
throw RuntimeException("You've added too many markers.")
|
||||
}
|
||||
return latestId++.toString()
|
||||
}
|
||||
}
|
||||
|
||||
private val actionBarHeight: Int by lazy {
|
||||
supportActionBar?.height ?: 0
|
||||
}
|
||||
|
||||
// View property is required for activity sanity tests
|
||||
// we perform reflection on this requires using findViewById
|
||||
private lateinit var mapView: MapView
|
||||
private lateinit var mapboxMap: MapboxMap
|
||||
private val featureCollection = FeatureCollection.fromFeatures(mutableListOf())
|
||||
private val source = GeoJsonSource(sourceId, featureCollection)
|
||||
private val layer = SymbolLayer(layerId, sourceId)
|
||||
.withProperties(
|
||||
iconImage(markerImageId),
|
||||
iconAllowOverlap(true),
|
||||
iconIgnorePlacement(true))
|
||||
|
||||
private var draggableSymbolsManager: DraggableSymbolsManager? = null
|
||||
|
||||
override fun onCreate(savedInstanceState: Bundle?) {
|
||||
super.onCreate(savedInstanceState)
|
||||
setContentView(R.layout.activity_draggable_marker)
|
||||
|
||||
mapView = findViewById(R.id.mapView)
|
||||
mapView.onCreate(savedInstanceState)
|
||||
mapView.getMapAsync { mapboxMap ->
|
||||
this.mapboxMap = mapboxMap
|
||||
|
||||
mapboxMap.setStyle(
|
||||
Style.Builder()
|
||||
.fromUri(Style.MAPBOX_STREETS)
|
||||
.withImage(markerImageId, IconFactory.getInstance(this).defaultMarker().bitmap)
|
||||
.withSource(source)
|
||||
.withLayer(layer)
|
||||
)
|
||||
|
||||
// Add initial markers
|
||||
addMarker(LatLng(52.407210, 16.924324))
|
||||
addMarker(LatLng(41.382679, 2.181555))
|
||||
addMarker(LatLng(51.514886, -0.112589))
|
||||
|
||||
// Initial camera position
|
||||
mapboxMap.moveCamera(CameraUpdateFactory.newLatLngZoom(
|
||||
LatLng(45.0, 8.0), 3.0
|
||||
))
|
||||
|
||||
mapboxMap.addOnMapClickListener {
|
||||
// Adding a marker on map click
|
||||
val features = mapboxMap.queryRenderedSymbols(it, layerId)
|
||||
if (features.isEmpty()) {
|
||||
addMarker(it)
|
||||
} else {
|
||||
// Displaying marker info on marker click
|
||||
Snackbar.make(
|
||||
mapView,
|
||||
"Marker's position: %.4f, %.4f".format(it.latitude, it.longitude),
|
||||
Snackbar.LENGTH_LONG)
|
||||
.show()
|
||||
}
|
||||
|
||||
false
|
||||
}
|
||||
|
||||
draggableSymbolsManager = DraggableSymbolsManager(
|
||||
mapView, mapboxMap, featureCollection, source, layerId, actionBarHeight, 0)
|
||||
|
||||
// Adding symbol drag listeners
|
||||
draggableSymbolsManager?.addOnSymbolDragListener(object : DraggableSymbolsManager.OnSymbolDragListener {
|
||||
override fun onSymbolDragStarted(id: String) {
|
||||
draggedMarkerPositionTv.visibility = View.VISIBLE
|
||||
Snackbar.make(
|
||||
mapView,
|
||||
"Marker drag started (%s)".format(id),
|
||||
Snackbar.LENGTH_SHORT)
|
||||
.show()
|
||||
}
|
||||
|
||||
override fun onSymbolDrag(id: String) {
|
||||
val point = featureCollection.features()?.find {
|
||||
it.id() == id
|
||||
}?.geometry() as Point
|
||||
draggedMarkerPositionTv.text = "Dragged marker's position: %.4f, %.4f".format(point.latitude(), point.longitude())
|
||||
}
|
||||
|
||||
override fun onSymbolDragFinished(id: String) {
|
||||
draggedMarkerPositionTv.visibility = View.GONE
|
||||
Snackbar.make(
|
||||
mapView,
|
||||
"Marker drag finished (%s)".format(id),
|
||||
Snackbar.LENGTH_SHORT)
|
||||
.show()
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
private fun addMarker(latLng: LatLng) {
|
||||
featureCollection.features()?.add(
|
||||
Feature.fromGeometry(Point.fromLngLat(latLng.longitude, latLng.latitude), null, generateMarkerId()))
|
||||
source.setGeoJson(featureCollection)
|
||||
}
|
||||
|
||||
override fun dispatchTouchEvent(ev: MotionEvent?): Boolean {
|
||||
// Dispatching parent's touch events to the manager
|
||||
draggableSymbolsManager?.onParentTouchEvent(ev)
|
||||
return super.dispatchTouchEvent(ev)
|
||||
}
|
||||
|
||||
/**
|
||||
* A manager, that allows dragging symbols after they are long clicked.
|
||||
* Since this manager lives outside of the Maps SDK, we need to intercept parent's motion events
|
||||
* and pass them with [DraggableSymbolsManager.onParentTouchEvent].
|
||||
* If we were to try and overwrite [AppCompatActivity.onTouchEvent], those events would've been
|
||||
* consumed by the map.
|
||||
*
|
||||
* We also need to setup a [DraggableSymbolsManager.androidGesturesManager],
|
||||
* because after disabling map's gestures and starting the drag process
|
||||
* we still need to listen for move gesture events which map won't be able to provide anymore.
|
||||
*
|
||||
* @param mapView the mapView
|
||||
* @param mapboxMap the mapboxMap
|
||||
* @param symbolsCollection the collection that contains all the symbols that we want to be draggable
|
||||
* @param symbolsSource the source that contains the [symbolsCollection]
|
||||
* @param symbolsLayerId the ID of the layer that the symbols are displayed on
|
||||
* @param touchAreaShiftX X-axis padding that is applied to the parent's window motion event,
|
||||
* as that window can be bigger than the [mapView].
|
||||
* @param touchAreaShiftY Y-axis padding that is applied to the parent's window motion event,
|
||||
* as that window can be bigger than the [mapView].
|
||||
* @param touchAreaMaxX maximum value of X-axis motion event
|
||||
* @param touchAreaMaxY maximum value of Y-axis motion event
|
||||
*/
|
||||
class DraggableSymbolsManager(
|
||||
mapView: MapView,
|
||||
private val mapboxMap: MapboxMap,
|
||||
private val symbolsCollection: FeatureCollection,
|
||||
private val symbolsSource: GeoJsonSource,
|
||||
private val symbolsLayerId: String,
|
||||
private val touchAreaShiftY: Int = 0,
|
||||
private val touchAreaShiftX: Int = 0,
|
||||
private val touchAreaMaxX: Int = mapView.width,
|
||||
private val touchAreaMaxY: Int = mapView.height
|
||||
) {
|
||||
|
||||
private val androidGesturesManager: AndroidGesturesManager = AndroidGesturesManager(mapView.context, false)
|
||||
private var draggedSymbolId: String? = null
|
||||
private val onSymbolDragListeners: MutableList<OnSymbolDragListener> = mutableListOf<OnSymbolDragListener>()
|
||||
|
||||
init {
|
||||
mapboxMap.addOnMapLongClickListener {
|
||||
// Starting the drag process on long click
|
||||
draggedSymbolId = mapboxMap.queryRenderedSymbols(it, symbolsLayerId).firstOrNull()?.id()?.also { id ->
|
||||
mapboxMap.uiSettings.setAllGesturesEnabled(false)
|
||||
mapboxMap.gesturesManager.moveGestureDetector.interrupt()
|
||||
notifyOnSymbolDragListeners {
|
||||
onSymbolDragStarted(id)
|
||||
}
|
||||
}
|
||||
false
|
||||
}
|
||||
|
||||
androidGesturesManager.setMoveGestureListener(MyMoveGestureListener())
|
||||
}
|
||||
|
||||
inner class MyMoveGestureListener : MoveGestureDetector.OnMoveGestureListener {
|
||||
override fun onMoveBegin(detector: MoveGestureDetector): Boolean {
|
||||
return true
|
||||
}
|
||||
|
||||
override fun onMove(detector: MoveGestureDetector, distanceX: Float, distanceY: Float): Boolean {
|
||||
if (detector.pointersCount > 1) {
|
||||
// Stopping the drag when we don't work with a simple, on-pointer move anymore
|
||||
stopDragging()
|
||||
return true
|
||||
}
|
||||
|
||||
// Updating symbol's position
|
||||
draggedSymbolId?.also { draggedSymbolId ->
|
||||
val moveObject = detector.getMoveObject(0)
|
||||
val point = PointF(moveObject.currentX - touchAreaShiftX, moveObject.currentY - touchAreaShiftY)
|
||||
|
||||
if (point.x < 0 || point.y < 0 || point.x > touchAreaMaxX || point.y > touchAreaMaxY) {
|
||||
stopDragging()
|
||||
}
|
||||
|
||||
val latLng = mapboxMap.projection.fromScreenLocation(point)
|
||||
|
||||
symbolsCollection.features()?.indexOfFirst {
|
||||
it.id() == draggedSymbolId
|
||||
}?.also { index ->
|
||||
symbolsCollection.features()?.get(index)?.also { oldFeature ->
|
||||
val properties = oldFeature.properties()
|
||||
val newFeature = Feature.fromGeometry(
|
||||
Point.fromLngLat(latLng.longitude, latLng.latitude),
|
||||
properties,
|
||||
draggedSymbolId
|
||||
)
|
||||
symbolsCollection.features()?.set(index, newFeature)
|
||||
symbolsSource.setGeoJson(symbolsCollection)
|
||||
notifyOnSymbolDragListeners {
|
||||
onSymbolDrag(draggedSymbolId)
|
||||
}
|
||||
return true
|
||||
private var latestId: Long = 0
|
||||
fun generateMarkerId(): String {
|
||||
if (latestId == Long.MAX_VALUE) {
|
||||
throw RuntimeException("You've added too many markers.")
|
||||
}
|
||||
}
|
||||
return latestId++.toString()
|
||||
}
|
||||
}
|
||||
|
||||
private val actionBarHeight: Int by lazy {
|
||||
supportActionBar?.height ?: 0
|
||||
}
|
||||
|
||||
// View property is required for activity sanity tests
|
||||
// we perform reflection on this requires using findViewById
|
||||
private lateinit var mapView: MapView
|
||||
private lateinit var mapboxMap: MapboxMap
|
||||
private val featureCollection = FeatureCollection.fromFeatures(mutableListOf())
|
||||
private val source = GeoJsonSource(sourceId, featureCollection)
|
||||
private val layer = SymbolLayer(layerId, sourceId)
|
||||
.withProperties(
|
||||
iconImage(markerImageId),
|
||||
iconAllowOverlap(true),
|
||||
iconIgnorePlacement(true)
|
||||
)
|
||||
|
||||
private var draggableSymbolsManager: DraggableSymbolsManager? = null
|
||||
|
||||
override fun onCreate(savedInstanceState: Bundle?) {
|
||||
super.onCreate(savedInstanceState)
|
||||
setContentView(R.layout.activity_draggable_marker)
|
||||
|
||||
mapView = findViewById(R.id.mapView)
|
||||
mapView.onCreate(savedInstanceState)
|
||||
mapView.getMapAsync { mapboxMap ->
|
||||
this.mapboxMap = mapboxMap
|
||||
|
||||
mapboxMap.setStyle(
|
||||
Style.Builder()
|
||||
.fromUri(Style.MAPBOX_STREETS)
|
||||
.withImage(markerImageId, IconFactory.getInstance(this).defaultMarker().bitmap)
|
||||
.withSource(source)
|
||||
.withLayer(layer)
|
||||
)
|
||||
|
||||
// Add initial markers
|
||||
addMarker(LatLng(52.407210, 16.924324))
|
||||
addMarker(LatLng(41.382679, 2.181555))
|
||||
addMarker(LatLng(51.514886, -0.112589))
|
||||
|
||||
// Initial camera position
|
||||
mapboxMap.moveCamera(
|
||||
CameraUpdateFactory.newLatLngZoom(
|
||||
LatLng(45.0, 8.0),
|
||||
3.0
|
||||
)
|
||||
)
|
||||
|
||||
mapboxMap.addOnMapClickListener {
|
||||
// Adding a marker on map click
|
||||
val features = mapboxMap.queryRenderedSymbols(it, layerId)
|
||||
if (features.isEmpty()) {
|
||||
addMarker(it)
|
||||
} else {
|
||||
// Displaying marker info on marker click
|
||||
Snackbar.make(
|
||||
mapView,
|
||||
"Marker's position: %.4f, %.4f".format(it.latitude, it.longitude),
|
||||
Snackbar.LENGTH_LONG
|
||||
)
|
||||
.show()
|
||||
}
|
||||
|
||||
false
|
||||
}
|
||||
|
||||
draggableSymbolsManager = DraggableSymbolsManager(
|
||||
mapView,
|
||||
mapboxMap,
|
||||
featureCollection,
|
||||
source,
|
||||
layerId,
|
||||
actionBarHeight,
|
||||
0
|
||||
)
|
||||
|
||||
// Adding symbol drag listeners
|
||||
draggableSymbolsManager?.addOnSymbolDragListener(object : DraggableSymbolsManager.OnSymbolDragListener {
|
||||
override fun onSymbolDragStarted(id: String) {
|
||||
draggedMarkerPositionTv.visibility = View.VISIBLE
|
||||
Snackbar.make(
|
||||
mapView,
|
||||
"Marker drag started (%s)".format(id),
|
||||
Snackbar.LENGTH_SHORT
|
||||
)
|
||||
.show()
|
||||
}
|
||||
|
||||
override fun onSymbolDrag(id: String) {
|
||||
val point = featureCollection.features()?.find {
|
||||
it.id() == id
|
||||
}?.geometry() as Point
|
||||
draggedMarkerPositionTv.text = "Dragged marker's position: %.4f, %.4f".format(point.latitude(), point.longitude())
|
||||
}
|
||||
|
||||
override fun onSymbolDragFinished(id: String) {
|
||||
draggedMarkerPositionTv.visibility = View.GONE
|
||||
Snackbar.make(
|
||||
mapView,
|
||||
"Marker drag finished (%s)".format(id),
|
||||
Snackbar.LENGTH_SHORT
|
||||
)
|
||||
.show()
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
private fun addMarker(latLng: LatLng) {
|
||||
featureCollection.features()?.add(
|
||||
Feature.fromGeometry(Point.fromLngLat(latLng.longitude, latLng.latitude), null, generateMarkerId())
|
||||
)
|
||||
source.setGeoJson(featureCollection)
|
||||
}
|
||||
|
||||
override fun dispatchTouchEvent(ev: MotionEvent?): Boolean {
|
||||
// Dispatching parent's touch events to the manager
|
||||
draggableSymbolsManager?.onParentTouchEvent(ev)
|
||||
return super.dispatchTouchEvent(ev)
|
||||
}
|
||||
|
||||
/**
|
||||
* A manager, that allows dragging symbols after they are long clicked.
|
||||
* Since this manager lives outside of the Maps SDK, we need to intercept parent's motion events
|
||||
* and pass them with [DraggableSymbolsManager.onParentTouchEvent].
|
||||
* If we were to try and overwrite [AppCompatActivity.onTouchEvent], those events would've been
|
||||
* consumed by the map.
|
||||
*
|
||||
* We also need to setup a [DraggableSymbolsManager.androidGesturesManager],
|
||||
* because after disabling map's gestures and starting the drag process
|
||||
* we still need to listen for move gesture events which map won't be able to provide anymore.
|
||||
*
|
||||
* @param mapView the mapView
|
||||
* @param mapboxMap the mapboxMap
|
||||
* @param symbolsCollection the collection that contains all the symbols that we want to be draggable
|
||||
* @param symbolsSource the source that contains the [symbolsCollection]
|
||||
* @param symbolsLayerId the ID of the layer that the symbols are displayed on
|
||||
* @param touchAreaShiftX X-axis padding that is applied to the parent's window motion event,
|
||||
* as that window can be bigger than the [mapView].
|
||||
* @param touchAreaShiftY Y-axis padding that is applied to the parent's window motion event,
|
||||
* as that window can be bigger than the [mapView].
|
||||
* @param touchAreaMaxX maximum value of X-axis motion event
|
||||
* @param touchAreaMaxY maximum value of Y-axis motion event
|
||||
*/
|
||||
class DraggableSymbolsManager(
|
||||
mapView: MapView,
|
||||
private val mapboxMap: MapboxMap,
|
||||
private val symbolsCollection: FeatureCollection,
|
||||
private val symbolsSource: GeoJsonSource,
|
||||
private val symbolsLayerId: String,
|
||||
private val touchAreaShiftY: Int = 0,
|
||||
private val touchAreaShiftX: Int = 0,
|
||||
private val touchAreaMaxX: Int = mapView.width,
|
||||
private val touchAreaMaxY: Int = mapView.height
|
||||
) {
|
||||
|
||||
private val androidGesturesManager: AndroidGesturesManager = AndroidGesturesManager(mapView.context, false)
|
||||
private var draggedSymbolId: String? = null
|
||||
private val onSymbolDragListeners: MutableList<OnSymbolDragListener> = mutableListOf<OnSymbolDragListener>()
|
||||
|
||||
init {
|
||||
mapboxMap.addOnMapLongClickListener {
|
||||
// Starting the drag process on long click
|
||||
draggedSymbolId = mapboxMap.queryRenderedSymbols(it, symbolsLayerId).firstOrNull()?.id()?.also { id ->
|
||||
mapboxMap.uiSettings.setAllGesturesEnabled(false)
|
||||
mapboxMap.gesturesManager.moveGestureDetector.interrupt()
|
||||
notifyOnSymbolDragListeners {
|
||||
onSymbolDragStarted(id)
|
||||
}
|
||||
}
|
||||
false
|
||||
}
|
||||
|
||||
androidGesturesManager.setMoveGestureListener(MyMoveGestureListener())
|
||||
}
|
||||
|
||||
return false
|
||||
}
|
||||
inner class MyMoveGestureListener : MoveGestureDetector.OnMoveGestureListener {
|
||||
override fun onMoveBegin(detector: MoveGestureDetector): Boolean {
|
||||
return true
|
||||
}
|
||||
|
||||
override fun onMoveEnd(detector: MoveGestureDetector, velocityX: Float, velocityY: Float) {
|
||||
// Stopping the drag when move ends
|
||||
stopDragging()
|
||||
}
|
||||
}
|
||||
override fun onMove(detector: MoveGestureDetector, distanceX: Float, distanceY: Float): Boolean {
|
||||
if (detector.pointersCount > 1) {
|
||||
// Stopping the drag when we don't work with a simple, on-pointer move anymore
|
||||
stopDragging()
|
||||
return true
|
||||
}
|
||||
|
||||
private fun stopDragging() {
|
||||
mapboxMap.uiSettings.setAllGesturesEnabled(true)
|
||||
draggedSymbolId?.let {
|
||||
notifyOnSymbolDragListeners {
|
||||
onSymbolDragFinished(it)
|
||||
// Updating symbol's position
|
||||
draggedSymbolId?.also { draggedSymbolId ->
|
||||
val moveObject = detector.getMoveObject(0)
|
||||
val point = PointF(moveObject.currentX - touchAreaShiftX, moveObject.currentY - touchAreaShiftY)
|
||||
|
||||
if (point.x < 0 || point.y < 0 || point.x > touchAreaMaxX || point.y > touchAreaMaxY) {
|
||||
stopDragging()
|
||||
}
|
||||
|
||||
val latLng = mapboxMap.projection.fromScreenLocation(point)
|
||||
|
||||
symbolsCollection.features()?.indexOfFirst {
|
||||
it.id() == draggedSymbolId
|
||||
}?.also { index ->
|
||||
symbolsCollection.features()?.get(index)?.also { oldFeature ->
|
||||
val properties = oldFeature.properties()
|
||||
val newFeature = Feature.fromGeometry(
|
||||
Point.fromLngLat(latLng.longitude, latLng.latitude),
|
||||
properties,
|
||||
draggedSymbolId
|
||||
)
|
||||
symbolsCollection.features()?.set(index, newFeature)
|
||||
symbolsSource.setGeoJson(symbolsCollection)
|
||||
notifyOnSymbolDragListeners {
|
||||
onSymbolDrag(draggedSymbolId)
|
||||
}
|
||||
return true
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return false
|
||||
}
|
||||
|
||||
override fun onMoveEnd(detector: MoveGestureDetector, velocityX: Float, velocityY: Float) {
|
||||
// Stopping the drag when move ends
|
||||
stopDragging()
|
||||
}
|
||||
}
|
||||
|
||||
private fun stopDragging() {
|
||||
mapboxMap.uiSettings.setAllGesturesEnabled(true)
|
||||
draggedSymbolId?.let {
|
||||
notifyOnSymbolDragListeners {
|
||||
onSymbolDragFinished(it)
|
||||
}
|
||||
}
|
||||
draggedSymbolId = null
|
||||
}
|
||||
|
||||
fun onParentTouchEvent(ev: MotionEvent?) {
|
||||
androidGesturesManager.onTouchEvent(ev)
|
||||
}
|
||||
|
||||
private fun notifyOnSymbolDragListeners(action: OnSymbolDragListener.() -> Unit) {
|
||||
onSymbolDragListeners.forEach(action)
|
||||
}
|
||||
|
||||
fun addOnSymbolDragListener(listener: OnSymbolDragListener) {
|
||||
onSymbolDragListeners.add(listener)
|
||||
}
|
||||
|
||||
fun removeOnSymbolDragListener(listener: OnSymbolDragListener) {
|
||||
onSymbolDragListeners.remove(listener)
|
||||
}
|
||||
|
||||
interface OnSymbolDragListener {
|
||||
fun onSymbolDragStarted(id: String)
|
||||
fun onSymbolDrag(id: String)
|
||||
fun onSymbolDragFinished(id: String)
|
||||
}
|
||||
}
|
||||
draggedSymbolId = null
|
||||
}
|
||||
|
||||
fun onParentTouchEvent(ev: MotionEvent?) {
|
||||
androidGesturesManager.onTouchEvent(ev)
|
||||
override fun onStart() {
|
||||
super.onStart()
|
||||
mapView.onStart()
|
||||
}
|
||||
|
||||
private fun notifyOnSymbolDragListeners(action: OnSymbolDragListener.() -> Unit) {
|
||||
onSymbolDragListeners.forEach(action)
|
||||
override fun onResume() {
|
||||
super.onResume()
|
||||
mapView.onResume()
|
||||
}
|
||||
|
||||
fun addOnSymbolDragListener(listener: OnSymbolDragListener) {
|
||||
onSymbolDragListeners.add(listener)
|
||||
override fun onPause() {
|
||||
super.onPause()
|
||||
mapView.onPause()
|
||||
}
|
||||
|
||||
fun removeOnSymbolDragListener(listener: OnSymbolDragListener) {
|
||||
onSymbolDragListeners.remove(listener)
|
||||
override fun onStop() {
|
||||
super.onStop()
|
||||
mapView.onStop()
|
||||
}
|
||||
|
||||
interface OnSymbolDragListener {
|
||||
fun onSymbolDragStarted(id: String)
|
||||
fun onSymbolDrag(id: String)
|
||||
fun onSymbolDragFinished(id: String)
|
||||
override fun onLowMemory() {
|
||||
super.onLowMemory()
|
||||
mapView.onLowMemory()
|
||||
}
|
||||
}
|
||||
|
||||
override fun onStart() {
|
||||
super.onStart()
|
||||
mapView.onStart()
|
||||
}
|
||||
|
||||
override fun onResume() {
|
||||
super.onResume()
|
||||
mapView.onResume()
|
||||
}
|
||||
|
||||
override fun onPause() {
|
||||
super.onPause()
|
||||
mapView.onPause()
|
||||
}
|
||||
|
||||
override fun onStop() {
|
||||
super.onStop()
|
||||
mapView.onStop()
|
||||
}
|
||||
|
||||
override fun onLowMemory() {
|
||||
super.onLowMemory()
|
||||
mapView.onLowMemory()
|
||||
}
|
||||
|
||||
override fun onDestroy() {
|
||||
super.onDestroy()
|
||||
mapView.onDestroy()
|
||||
}
|
||||
|
||||
override fun onSaveInstanceState(outState: Bundle?, outPersistentState: PersistableBundle?) {
|
||||
super.onSaveInstanceState(outState, outPersistentState)
|
||||
outState?.let {
|
||||
mapView.onSaveInstanceState(it)
|
||||
override fun onDestroy() {
|
||||
super.onDestroy()
|
||||
mapView.onDestroy()
|
||||
}
|
||||
|
||||
override fun onSaveInstanceState(outState: Bundle?, outPersistentState: PersistableBundle?) {
|
||||
super.onSaveInstanceState(outState, outPersistentState)
|
||||
outState?.let {
|
||||
mapView.onSaveInstanceState(it)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private fun MapboxMap.queryRenderedSymbols(latLng: LatLng, layerId: String): List<Feature> {
|
||||
return this.queryRenderedFeatures(this.projection.toScreenLocation(latLng), layerId)
|
||||
}
|
||||
return this.queryRenderedFeatures(this.projection.toScreenLocation(latLng), layerId)
|
||||
}
|
||||
|
||||
@@ -12,74 +12,74 @@ import com.mapbox.mapboxsdk.style.layers.PropertyFactory.*
|
||||
import com.mapbox.mapboxsdk.style.layers.SymbolLayer
|
||||
import com.mapbox.mapboxsdk.style.sources.GeoJsonSource
|
||||
import com.mapbox.mapboxsdk.testapp.R
|
||||
import java.net.URI
|
||||
import kotlinx.android.synthetic.main.activity_map_simple.*
|
||||
import java.net.URI
|
||||
|
||||
/**
|
||||
* Activity showcasing how to load symbols on a map without a Style URI or Style JSON.
|
||||
*/
|
||||
class NoStyleActivity : AppCompatActivity() {
|
||||
|
||||
private val imageIcon: Drawable by lazy {
|
||||
ResourcesCompat.getDrawable(resources, R.drawable.ic_add_white, theme)!!
|
||||
}
|
||||
|
||||
override fun onCreate(savedInstanceState: Bundle?) {
|
||||
super.onCreate(savedInstanceState)
|
||||
setContentView(R.layout.activity_map_simple)
|
||||
mapView.getMapAsync { map ->
|
||||
map.moveCamera(CameraUpdateFactory.newLatLngZoom(cameraTarget, cameraZoom))
|
||||
map.setStyle(
|
||||
Style.Builder()
|
||||
.withImage(imageId, imageIcon)
|
||||
.withSource(GeoJsonSource(sourceId, URI("asset://points-sf.geojson")))
|
||||
.withLayer(SymbolLayer(layerId, sourceId).withProperties(iconImage(imageId)))
|
||||
)
|
||||
private val imageIcon: Drawable by lazy {
|
||||
ResourcesCompat.getDrawable(resources, R.drawable.ic_add_white, theme)!!
|
||||
}
|
||||
}
|
||||
|
||||
override fun onStart() {
|
||||
super.onStart()
|
||||
mapView.onStart()
|
||||
}
|
||||
|
||||
override fun onResume() {
|
||||
super.onResume()
|
||||
mapView.onResume()
|
||||
}
|
||||
|
||||
override fun onPause() {
|
||||
super.onPause()
|
||||
mapView.onPause()
|
||||
}
|
||||
|
||||
override fun onStop() {
|
||||
super.onStop()
|
||||
mapView.onStop()
|
||||
}
|
||||
|
||||
override fun onLowMemory() {
|
||||
super.onLowMemory()
|
||||
mapView.onLowMemory()
|
||||
}
|
||||
|
||||
override fun onDestroy() {
|
||||
super.onDestroy()
|
||||
mapView.onDestroy()
|
||||
}
|
||||
|
||||
override fun onSaveInstanceState(outState: Bundle?, outPersistentState: PersistableBundle?) {
|
||||
super.onSaveInstanceState(outState, outPersistentState)
|
||||
outState?.let {
|
||||
mapView.onSaveInstanceState(it)
|
||||
override fun onCreate(savedInstanceState: Bundle?) {
|
||||
super.onCreate(savedInstanceState)
|
||||
setContentView(R.layout.activity_map_simple)
|
||||
mapView.getMapAsync { map ->
|
||||
map.moveCamera(CameraUpdateFactory.newLatLngZoom(cameraTarget, cameraZoom))
|
||||
map.setStyle(
|
||||
Style.Builder()
|
||||
.withImage(imageId, imageIcon)
|
||||
.withSource(GeoJsonSource(sourceId, URI("asset://points-sf.geojson")))
|
||||
.withLayer(SymbolLayer(layerId, sourceId).withProperties(iconImage(imageId)))
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
companion object {
|
||||
const val layerId = "custom-layer-id"
|
||||
const val sourceId = "custom-source-id"
|
||||
const val imageId = "image-id"
|
||||
const val cameraZoom = 10.0
|
||||
val cameraTarget = LatLng(37.758912, -122.442578)
|
||||
}
|
||||
}
|
||||
override fun onStart() {
|
||||
super.onStart()
|
||||
mapView.onStart()
|
||||
}
|
||||
|
||||
override fun onResume() {
|
||||
super.onResume()
|
||||
mapView.onResume()
|
||||
}
|
||||
|
||||
override fun onPause() {
|
||||
super.onPause()
|
||||
mapView.onPause()
|
||||
}
|
||||
|
||||
override fun onStop() {
|
||||
super.onStop()
|
||||
mapView.onStop()
|
||||
}
|
||||
|
||||
override fun onLowMemory() {
|
||||
super.onLowMemory()
|
||||
mapView.onLowMemory()
|
||||
}
|
||||
|
||||
override fun onDestroy() {
|
||||
super.onDestroy()
|
||||
mapView.onDestroy()
|
||||
}
|
||||
|
||||
override fun onSaveInstanceState(outState: Bundle?, outPersistentState: PersistableBundle?) {
|
||||
super.onSaveInstanceState(outState, outPersistentState)
|
||||
outState?.let {
|
||||
mapView.onSaveInstanceState(it)
|
||||
}
|
||||
}
|
||||
|
||||
companion object {
|
||||
const val layerId = "custom-layer-id"
|
||||
const val sourceId = "custom-source-id"
|
||||
const val imageId = "image-id"
|
||||
const val cameraZoom = 10.0
|
||||
val cameraTarget = LatLng(37.758912, -122.442578)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -30,248 +30,254 @@ import kotlinx.android.synthetic.main.activity_snapshot.*
|
||||
*/
|
||||
class MapSnapshotterWithinExpression : AppCompatActivity() {
|
||||
|
||||
private lateinit var mapboxMap: MapboxMap
|
||||
private lateinit var snapshotter: MapSnapshotter
|
||||
private var snapshotInProgress = false
|
||||
private lateinit var mapboxMap: MapboxMap
|
||||
private lateinit var snapshotter: MapSnapshotter
|
||||
private var snapshotInProgress = false
|
||||
|
||||
private val cameraListener = object : MapView.OnCameraDidChangeListener {
|
||||
override fun onCameraDidChange(animated: Boolean) {
|
||||
if (!snapshotInProgress) {
|
||||
snapshotInProgress = true
|
||||
snapshotter.setCameraPosition(mapboxMap.cameraPosition)
|
||||
snapshotter.start {
|
||||
imageView.setImageBitmap(it.bitmap)
|
||||
snapshotInProgress = false
|
||||
private val cameraListener = object : MapView.OnCameraDidChangeListener {
|
||||
override fun onCameraDidChange(animated: Boolean) {
|
||||
if (!snapshotInProgress) {
|
||||
snapshotInProgress = true
|
||||
snapshotter.setCameraPosition(mapboxMap.cameraPosition)
|
||||
snapshotter.start {
|
||||
imageView.setImageBitmap(it.bitmap)
|
||||
snapshotInProgress = false
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private val snapshotterObserver = object : MapSnapshotter.Observer {
|
||||
override fun onStyleImageMissing(imageName: String?) {
|
||||
}
|
||||
|
||||
override fun onDidFinishLoadingStyle() {
|
||||
// Show only POI labels inside geometry using within expression
|
||||
(snapshotter.getLayer("poi-label") as SymbolLayer).setFilter(
|
||||
within(
|
||||
bufferLineStringGeometry()
|
||||
)
|
||||
)
|
||||
// Hide other types of labels to highlight POI labels
|
||||
(snapshotter.getLayer("road-label") as SymbolLayer).setProperties(visibility(NONE))
|
||||
(snapshotter.getLayer("transit-label") as SymbolLayer).setProperties(visibility(NONE))
|
||||
(snapshotter.getLayer("road-number-shield") as SymbolLayer).setProperties(visibility(NONE))
|
||||
private val snapshotterObserver = object : MapSnapshotter.Observer {
|
||||
override fun onStyleImageMissing(imageName: String?) {
|
||||
}
|
||||
|
||||
override fun onDidFinishLoadingStyle() {
|
||||
// Show only POI labels inside geometry using within expression
|
||||
(snapshotter.getLayer("poi-label") as SymbolLayer).setFilter(
|
||||
within(
|
||||
bufferLineStringGeometry()
|
||||
)
|
||||
)
|
||||
// Hide other types of labels to highlight POI labels
|
||||
(snapshotter.getLayer("road-label") as SymbolLayer).setProperties(visibility(NONE))
|
||||
(snapshotter.getLayer("transit-label") as SymbolLayer).setProperties(visibility(NONE))
|
||||
(snapshotter.getLayer("road-number-shield") as SymbolLayer).setProperties(visibility(NONE))
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
override fun onCreate(savedInstanceState: Bundle?) {
|
||||
super.onCreate(savedInstanceState)
|
||||
setContentView(R.layout.activity_mapsnapshotter_within_expression)
|
||||
override fun onCreate(savedInstanceState: Bundle?) {
|
||||
super.onCreate(savedInstanceState)
|
||||
setContentView(R.layout.activity_mapsnapshotter_within_expression)
|
||||
|
||||
mapView.onCreate(savedInstanceState)
|
||||
mapView.getMapAsync { map ->
|
||||
mapboxMap = map
|
||||
mapView.onCreate(savedInstanceState)
|
||||
mapView.getMapAsync { map ->
|
||||
mapboxMap = map
|
||||
|
||||
// Setup camera position above Georgetown
|
||||
mapboxMap.cameraPosition = CameraPosition.Builder()
|
||||
.target(LatLng(38.90628988399711, -77.06574689337494))
|
||||
.zoom(15.5)
|
||||
.build()
|
||||
|
||||
// Wait for the map to become idle before manipulating the style and camera of the map
|
||||
mapView.addOnDidBecomeIdleListener(object : MapView.OnDidBecomeIdleListener {
|
||||
override fun onDidBecomeIdle() {
|
||||
mapboxMap.easeCamera(
|
||||
CameraUpdateFactory.newCameraPosition(
|
||||
CameraPosition.Builder()
|
||||
.zoom(16.0)
|
||||
.target(LatLng(38.905156245642814, -77.06535338052844))
|
||||
.bearing(80.68015859462369)
|
||||
.tilt(55.0)
|
||||
// Setup camera position above Georgetown
|
||||
mapboxMap.cameraPosition = CameraPosition.Builder()
|
||||
.target(LatLng(38.90628988399711, -77.06574689337494))
|
||||
.zoom(15.5)
|
||||
.build()
|
||||
), 1000
|
||||
)
|
||||
mapView.removeOnDidBecomeIdleListener(this)
|
||||
|
||||
// Wait for the map to become idle before manipulating the style and camera of the map
|
||||
mapView.addOnDidBecomeIdleListener(object : MapView.OnDidBecomeIdleListener {
|
||||
override fun onDidBecomeIdle() {
|
||||
mapboxMap.easeCamera(
|
||||
CameraUpdateFactory.newCameraPosition(
|
||||
CameraPosition.Builder()
|
||||
.zoom(16.0)
|
||||
.target(LatLng(38.905156245642814, -77.06535338052844))
|
||||
.bearing(80.68015859462369)
|
||||
.tilt(55.0)
|
||||
.build()
|
||||
),
|
||||
1000
|
||||
)
|
||||
mapView.removeOnDidBecomeIdleListener(this)
|
||||
}
|
||||
})
|
||||
// Load mapbox streets and add lines and circles
|
||||
setupStyle()
|
||||
}
|
||||
})
|
||||
// Load mapbox streets and add lines and circles
|
||||
setupStyle()
|
||||
}
|
||||
}
|
||||
|
||||
private fun setupStyle() {
|
||||
// Assume the route is represented by an array of coordinates.
|
||||
val coordinates = listOf<Point>(
|
||||
Point.fromLngLat(
|
||||
-77.06866264343262,
|
||||
38.90506061276737
|
||||
),
|
||||
Point.fromLngLat(
|
||||
-77.06283688545227,
|
||||
38.905194197410545
|
||||
),
|
||||
Point.fromLngLat(
|
||||
-77.06285834312439,
|
||||
38.906429843444094
|
||||
),
|
||||
Point.fromLngLat(
|
||||
-77.0630407333374,
|
||||
38.90680554236621
|
||||
)
|
||||
)
|
||||
|
||||
// Setup style with additional layers,
|
||||
// using Style.MAPBOX_STREETS as a base style
|
||||
mapboxMap.setStyle(
|
||||
Style.Builder()
|
||||
.fromUri(Style.MAPBOX_STREETS)
|
||||
) {
|
||||
mapView.addOnCameraDidChangeListener(cameraListener)
|
||||
}
|
||||
|
||||
val options = MapSnapshotter.Options(imageView.measuredWidth / 2, imageView.measuredHeight / 2)
|
||||
.withCameraPosition(mapboxMap.cameraPosition)
|
||||
.withPixelRatio(2.0f)
|
||||
.withStyleBuilder(Style.Builder()
|
||||
.fromUri(Style.MAPBOX_STREETS)
|
||||
.withSources(
|
||||
GeoJsonSource(
|
||||
POINT_ID, LineString.fromLngLats(coordinates)
|
||||
),
|
||||
GeoJsonSource(
|
||||
FILL_ID,
|
||||
FeatureCollection.fromFeature(Feature.fromGeometry(bufferLineStringGeometry())),
|
||||
GeoJsonOptions().withBuffer(0).withTolerance(0.0f)
|
||||
)
|
||||
private fun setupStyle() {
|
||||
// Assume the route is represented by an array of coordinates.
|
||||
val coordinates = listOf<Point>(
|
||||
Point.fromLngLat(
|
||||
-77.06866264343262,
|
||||
38.90506061276737
|
||||
),
|
||||
Point.fromLngLat(
|
||||
-77.06283688545227,
|
||||
38.905194197410545
|
||||
),
|
||||
Point.fromLngLat(
|
||||
-77.06285834312439,
|
||||
38.906429843444094
|
||||
),
|
||||
Point.fromLngLat(
|
||||
-77.0630407333374,
|
||||
38.90680554236621
|
||||
)
|
||||
)
|
||||
.withLayerBelow(
|
||||
LineLayer(LINE_ID, POINT_ID)
|
||||
.withProperties(lineWidth(7.5f), lineColor(Color.LTGRAY)),
|
||||
"poi-label"
|
||||
)
|
||||
.withLayerBelow(
|
||||
CircleLayer(POINT_ID, POINT_ID)
|
||||
.withProperties(
|
||||
circleRadius(7.5f),
|
||||
circleColor(Color.DKGRAY),
|
||||
circleOpacity(0.75f)
|
||||
), "poi-label"
|
||||
).withLayerBelow(
|
||||
FillLayer(FILL_ID, FILL_ID)
|
||||
.withProperties(
|
||||
fillOpacity(0.12f),
|
||||
fillColor(Color.YELLOW)
|
||||
), LINE_ID
|
||||
))
|
||||
snapshotter = MapSnapshotter(this, options)
|
||||
snapshotter.setObserver(snapshotterObserver)
|
||||
}
|
||||
|
||||
override fun onStart() {
|
||||
super.onStart()
|
||||
mapView.onStart()
|
||||
}
|
||||
// Setup style with additional layers,
|
||||
// using Style.MAPBOX_STREETS as a base style
|
||||
mapboxMap.setStyle(
|
||||
Style.Builder()
|
||||
.fromUri(Style.MAPBOX_STREETS)
|
||||
) {
|
||||
mapView.addOnCameraDidChangeListener(cameraListener)
|
||||
}
|
||||
|
||||
override fun onResume() {
|
||||
super.onResume()
|
||||
mapView.onResume()
|
||||
}
|
||||
|
||||
override fun onPause() {
|
||||
super.onPause()
|
||||
mapView.onPause()
|
||||
}
|
||||
|
||||
override fun onStop() {
|
||||
super.onStop()
|
||||
mapView.onStop()
|
||||
}
|
||||
|
||||
override fun onLowMemory() {
|
||||
super.onLowMemory()
|
||||
mapView.onLowMemory()
|
||||
}
|
||||
|
||||
override fun onDestroy() {
|
||||
super.onDestroy()
|
||||
mapView.onDestroy()
|
||||
}
|
||||
|
||||
override fun onSaveInstanceState(outState: Bundle?, outPersistentState: PersistableBundle?) {
|
||||
super.onSaveInstanceState(outState, outPersistentState)
|
||||
outState?.let {
|
||||
mapView.onSaveInstanceState(it)
|
||||
val options = MapSnapshotter.Options(imageView.measuredWidth / 2, imageView.measuredHeight / 2)
|
||||
.withCameraPosition(mapboxMap.cameraPosition)
|
||||
.withPixelRatio(2.0f)
|
||||
.withStyleBuilder(
|
||||
Style.Builder()
|
||||
.fromUri(Style.MAPBOX_STREETS)
|
||||
.withSources(
|
||||
GeoJsonSource(
|
||||
POINT_ID,
|
||||
LineString.fromLngLats(coordinates)
|
||||
),
|
||||
GeoJsonSource(
|
||||
FILL_ID,
|
||||
FeatureCollection.fromFeature(Feature.fromGeometry(bufferLineStringGeometry())),
|
||||
GeoJsonOptions().withBuffer(0).withTolerance(0.0f)
|
||||
)
|
||||
)
|
||||
.withLayerBelow(
|
||||
LineLayer(LINE_ID, POINT_ID)
|
||||
.withProperties(lineWidth(7.5f), lineColor(Color.LTGRAY)),
|
||||
"poi-label"
|
||||
)
|
||||
.withLayerBelow(
|
||||
CircleLayer(POINT_ID, POINT_ID)
|
||||
.withProperties(
|
||||
circleRadius(7.5f),
|
||||
circleColor(Color.DKGRAY),
|
||||
circleOpacity(0.75f)
|
||||
),
|
||||
"poi-label"
|
||||
).withLayerBelow(
|
||||
FillLayer(FILL_ID, FILL_ID)
|
||||
.withProperties(
|
||||
fillOpacity(0.12f),
|
||||
fillColor(Color.YELLOW)
|
||||
),
|
||||
LINE_ID
|
||||
)
|
||||
)
|
||||
snapshotter = MapSnapshotter(this, options)
|
||||
snapshotter.setObserver(snapshotterObserver)
|
||||
}
|
||||
}
|
||||
|
||||
private fun bufferLineStringGeometry(): Polygon {
|
||||
// TODO replace static data by Turf#Buffer: mapbox-java/issues/987
|
||||
return FeatureCollection.fromJson(
|
||||
"""
|
||||
{
|
||||
"type": "FeatureCollection",
|
||||
"features": [
|
||||
{
|
||||
"type": "Feature",
|
||||
"properties": {},
|
||||
"geometry": {
|
||||
"type": "Polygon",
|
||||
"coordinates": [
|
||||
[
|
||||
[
|
||||
-77.06867337226866,
|
||||
38.90467655551809
|
||||
],
|
||||
[
|
||||
-77.06233263015747,
|
||||
38.90479344272695
|
||||
],
|
||||
[
|
||||
-77.06234335899353,
|
||||
38.906463238984344
|
||||
],
|
||||
[
|
||||
-77.06290125846863,
|
||||
38.907206285691615
|
||||
],
|
||||
[
|
||||
-77.06364154815674,
|
||||
38.90684728656818
|
||||
],
|
||||
[
|
||||
-77.06326603889465,
|
||||
38.90637140121084
|
||||
],
|
||||
[
|
||||
-77.06321239471436,
|
||||
38.905561553883246
|
||||
],
|
||||
[
|
||||
-77.0691454410553,
|
||||
38.905436318935635
|
||||
],
|
||||
[
|
||||
-77.06912398338318,
|
||||
38.90466820642439
|
||||
],
|
||||
[
|
||||
-77.06867337226866,
|
||||
38.90467655551809
|
||||
]
|
||||
override fun onStart() {
|
||||
super.onStart()
|
||||
mapView.onStart()
|
||||
}
|
||||
|
||||
override fun onResume() {
|
||||
super.onResume()
|
||||
mapView.onResume()
|
||||
}
|
||||
|
||||
override fun onPause() {
|
||||
super.onPause()
|
||||
mapView.onPause()
|
||||
}
|
||||
|
||||
override fun onStop() {
|
||||
super.onStop()
|
||||
mapView.onStop()
|
||||
}
|
||||
|
||||
override fun onLowMemory() {
|
||||
super.onLowMemory()
|
||||
mapView.onLowMemory()
|
||||
}
|
||||
|
||||
override fun onDestroy() {
|
||||
super.onDestroy()
|
||||
mapView.onDestroy()
|
||||
}
|
||||
|
||||
override fun onSaveInstanceState(outState: Bundle?, outPersistentState: PersistableBundle?) {
|
||||
super.onSaveInstanceState(outState, outPersistentState)
|
||||
outState?.let {
|
||||
mapView.onSaveInstanceState(it)
|
||||
}
|
||||
}
|
||||
|
||||
private fun bufferLineStringGeometry(): Polygon {
|
||||
// TODO replace static data by Turf#Buffer: mapbox-java/issues/987
|
||||
return FeatureCollection.fromJson(
|
||||
"""
|
||||
{
|
||||
"type": "FeatureCollection",
|
||||
"features": [
|
||||
{
|
||||
"type": "Feature",
|
||||
"properties": {},
|
||||
"geometry": {
|
||||
"type": "Polygon",
|
||||
"coordinates": [
|
||||
[
|
||||
[
|
||||
-77.06867337226866,
|
||||
38.90467655551809
|
||||
],
|
||||
[
|
||||
-77.06233263015747,
|
||||
38.90479344272695
|
||||
],
|
||||
[
|
||||
-77.06234335899353,
|
||||
38.906463238984344
|
||||
],
|
||||
[
|
||||
-77.06290125846863,
|
||||
38.907206285691615
|
||||
],
|
||||
[
|
||||
-77.06364154815674,
|
||||
38.90684728656818
|
||||
],
|
||||
[
|
||||
-77.06326603889465,
|
||||
38.90637140121084
|
||||
],
|
||||
[
|
||||
-77.06321239471436,
|
||||
38.905561553883246
|
||||
],
|
||||
[
|
||||
-77.0691454410553,
|
||||
38.905436318935635
|
||||
],
|
||||
[
|
||||
-77.06912398338318,
|
||||
38.90466820642439
|
||||
],
|
||||
[
|
||||
-77.06867337226866,
|
||||
38.90467655551809
|
||||
]
|
||||
]
|
||||
]
|
||||
}
|
||||
}
|
||||
]
|
||||
]
|
||||
}
|
||||
}
|
||||
]
|
||||
}
|
||||
""".trimIndent()
|
||||
).features()!![0].geometry() as Polygon
|
||||
}
|
||||
""".trimIndent()
|
||||
).features()!![0].geometry() as Polygon
|
||||
}
|
||||
|
||||
companion object {
|
||||
const val POINT_ID = "point"
|
||||
const val FILL_ID = "fill"
|
||||
const val LINE_ID = "line"
|
||||
}
|
||||
}
|
||||
companion object {
|
||||
const val POINT_ID = "point"
|
||||
const val FILL_ID = "fill"
|
||||
const val LINE_ID = "line"
|
||||
}
|
||||
}
|
||||
|
||||
@@ -22,105 +22,124 @@ import kotlinx.android.synthetic.main.activity_physical_circle.*
|
||||
*/
|
||||
class PhysicalUnitCircleActivity : AppCompatActivity(), SeekBar.OnSeekBarChangeListener {
|
||||
|
||||
companion object {
|
||||
const val LAYER_ID = "circle-id"
|
||||
const val SOURCE_ID = "circle-id"
|
||||
const val LATITUDE = 22.928207
|
||||
const val LONGITUDE = 15.0155543
|
||||
const val ZOOM = 10.0
|
||||
}
|
||||
|
||||
private lateinit var source: GeoJsonSource
|
||||
private var steps: Int = 10
|
||||
private var radius: Double = 9000.0
|
||||
|
||||
override fun onCreate(savedInstanceState: Bundle?) {
|
||||
super.onCreate(savedInstanceState)
|
||||
setContentView(R.layout.activity_physical_circle)
|
||||
mapView.onCreate(savedInstanceState)
|
||||
mapView.getMapAsync { mapboxMap ->
|
||||
|
||||
mapboxMap.cameraPosition = CameraPosition.Builder()
|
||||
.target(LatLng(LATITUDE, LONGITUDE))
|
||||
.zoom(ZOOM)
|
||||
.build()
|
||||
|
||||
source = GeoJsonSource(SOURCE_ID, TurfTransformation.circle(
|
||||
Point.fromLngLat(LONGITUDE, LATITUDE), 9000.0, 10, "meters")
|
||||
)
|
||||
|
||||
stepsBar.setOnSeekBarChangeListener(this)
|
||||
radiusBar.setOnSeekBarChangeListener(this)
|
||||
|
||||
mapboxMap.setStyle(Style.Builder()
|
||||
.fromUri(Style.SATELLITE_STREETS)
|
||||
.withLayer(FillLayer(LAYER_ID, SOURCE_ID).withProperties(fillColor(interpolate(
|
||||
exponential(0.5f), zoom(),
|
||||
stop(8, color(Color.RED)),
|
||||
stop(12, color(Color.BLUE)),
|
||||
stop(16, color(Color.GREEN))
|
||||
))))
|
||||
.withSource(source)
|
||||
)
|
||||
companion object {
|
||||
const val LAYER_ID = "circle-id"
|
||||
const val SOURCE_ID = "circle-id"
|
||||
const val LATITUDE = 22.928207
|
||||
const val LONGITUDE = 15.0155543
|
||||
const val ZOOM = 10.0
|
||||
}
|
||||
}
|
||||
|
||||
override fun onProgressChanged(seekBar: SeekBar?, progress: Int, fromUser: Boolean) {
|
||||
seekBar?.let {
|
||||
if (it.id == stepsBar.id) {
|
||||
steps = progress
|
||||
} else {
|
||||
radius = progress.toDouble()
|
||||
}
|
||||
private lateinit var source: GeoJsonSource
|
||||
private var steps: Int = 10
|
||||
private var radius: Double = 9000.0
|
||||
|
||||
source.setGeoJson(TurfTransformation.circle(
|
||||
Point.fromLngLat(LONGITUDE, LATITUDE), radius, steps, "meters")
|
||||
)
|
||||
override fun onCreate(savedInstanceState: Bundle?) {
|
||||
super.onCreate(savedInstanceState)
|
||||
setContentView(R.layout.activity_physical_circle)
|
||||
mapView.onCreate(savedInstanceState)
|
||||
mapView.getMapAsync { mapboxMap ->
|
||||
|
||||
mapboxMap.cameraPosition = CameraPosition.Builder()
|
||||
.target(LatLng(LATITUDE, LONGITUDE))
|
||||
.zoom(ZOOM)
|
||||
.build()
|
||||
|
||||
source = GeoJsonSource(
|
||||
SOURCE_ID,
|
||||
TurfTransformation.circle(
|
||||
Point.fromLngLat(LONGITUDE, LATITUDE),
|
||||
9000.0,
|
||||
10,
|
||||
"meters"
|
||||
)
|
||||
)
|
||||
|
||||
stepsBar.setOnSeekBarChangeListener(this)
|
||||
radiusBar.setOnSeekBarChangeListener(this)
|
||||
|
||||
mapboxMap.setStyle(
|
||||
Style.Builder()
|
||||
.fromUri(Style.SATELLITE_STREETS)
|
||||
.withLayer(
|
||||
FillLayer(LAYER_ID, SOURCE_ID).withProperties(
|
||||
fillColor(
|
||||
interpolate(
|
||||
exponential(0.5f),
|
||||
zoom(),
|
||||
stop(8, color(Color.RED)),
|
||||
stop(12, color(Color.BLUE)),
|
||||
stop(16, color(Color.GREEN))
|
||||
)
|
||||
)
|
||||
)
|
||||
)
|
||||
.withSource(source)
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
override fun onStartTrackingTouch(seekBar: SeekBar?) {
|
||||
// no-op
|
||||
}
|
||||
override fun onProgressChanged(seekBar: SeekBar?, progress: Int, fromUser: Boolean) {
|
||||
seekBar?.let {
|
||||
if (it.id == stepsBar.id) {
|
||||
steps = progress
|
||||
} else {
|
||||
radius = progress.toDouble()
|
||||
}
|
||||
|
||||
override fun onStopTrackingTouch(seekBar: SeekBar?) {
|
||||
// no-op
|
||||
}
|
||||
|
||||
override fun onStart() {
|
||||
super.onStart()
|
||||
mapView.onStart()
|
||||
}
|
||||
|
||||
override fun onResume() {
|
||||
super.onResume()
|
||||
mapView.onResume()
|
||||
}
|
||||
|
||||
override fun onPause() {
|
||||
super.onPause()
|
||||
mapView.onPause()
|
||||
}
|
||||
|
||||
override fun onStop() {
|
||||
super.onStop()
|
||||
mapView.onStop()
|
||||
}
|
||||
|
||||
override fun onLowMemory() {
|
||||
super.onLowMemory()
|
||||
mapView.onLowMemory()
|
||||
}
|
||||
|
||||
override fun onDestroy() {
|
||||
super.onDestroy()
|
||||
mapView.onDestroy()
|
||||
}
|
||||
|
||||
override fun onSaveInstanceState(outState: Bundle?, outPersistentState: PersistableBundle?) {
|
||||
super.onSaveInstanceState(outState, outPersistentState)
|
||||
outState?.let {
|
||||
mapView.onSaveInstanceState(it)
|
||||
source.setGeoJson(
|
||||
TurfTransformation.circle(
|
||||
Point.fromLngLat(LONGITUDE, LATITUDE),
|
||||
radius,
|
||||
steps,
|
||||
"meters"
|
||||
)
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
override fun onStartTrackingTouch(seekBar: SeekBar?) {
|
||||
// no-op
|
||||
}
|
||||
|
||||
override fun onStopTrackingTouch(seekBar: SeekBar?) {
|
||||
// no-op
|
||||
}
|
||||
|
||||
override fun onStart() {
|
||||
super.onStart()
|
||||
mapView.onStart()
|
||||
}
|
||||
|
||||
override fun onResume() {
|
||||
super.onResume()
|
||||
mapView.onResume()
|
||||
}
|
||||
|
||||
override fun onPause() {
|
||||
super.onPause()
|
||||
mapView.onPause()
|
||||
}
|
||||
|
||||
override fun onStop() {
|
||||
super.onStop()
|
||||
mapView.onStop()
|
||||
}
|
||||
|
||||
override fun onLowMemory() {
|
||||
super.onLowMemory()
|
||||
mapView.onLowMemory()
|
||||
}
|
||||
|
||||
override fun onDestroy() {
|
||||
super.onDestroy()
|
||||
mapView.onDestroy()
|
||||
}
|
||||
|
||||
override fun onSaveInstanceState(outState: Bundle?, outPersistentState: PersistableBundle?) {
|
||||
super.onSaveInstanceState(outState, outPersistentState)
|
||||
outState?.let {
|
||||
mapView.onSaveInstanceState(it)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -29,240 +29,244 @@ import kotlinx.android.synthetic.main.activity_physical_circle.*
|
||||
*/
|
||||
class WithinExpressionActivity : AppCompatActivity() {
|
||||
|
||||
private lateinit var mapboxMap: MapboxMap
|
||||
private val handler: Handler = Handler()
|
||||
private val runnable: Runnable = Runnable {
|
||||
optimizeStyle()
|
||||
}
|
||||
private lateinit var mapboxMap: MapboxMap
|
||||
private val handler: Handler = Handler()
|
||||
private val runnable: Runnable = Runnable {
|
||||
optimizeStyle()
|
||||
}
|
||||
|
||||
override fun onCreate(savedInstanceState: Bundle?) {
|
||||
super.onCreate(savedInstanceState)
|
||||
setContentView(R.layout.activity_within_expression)
|
||||
override fun onCreate(savedInstanceState: Bundle?) {
|
||||
super.onCreate(savedInstanceState)
|
||||
setContentView(R.layout.activity_within_expression)
|
||||
|
||||
mapView.onCreate(savedInstanceState)
|
||||
mapView.getMapAsync { map ->
|
||||
mapboxMap = map
|
||||
mapView.onCreate(savedInstanceState)
|
||||
mapView.getMapAsync { map ->
|
||||
mapboxMap = map
|
||||
|
||||
// Setup camera position above Georgetown
|
||||
mapboxMap.cameraPosition = CameraPosition.Builder()
|
||||
.target(LatLng(38.90628988399711, -77.06574689337494))
|
||||
.zoom(15.5)
|
||||
.build()
|
||||
// Setup camera position above Georgetown
|
||||
mapboxMap.cameraPosition = CameraPosition.Builder()
|
||||
.target(LatLng(38.90628988399711, -77.06574689337494))
|
||||
.zoom(15.5)
|
||||
.build()
|
||||
|
||||
// Wait for the map to become idle before manipulating the style and camera of the map
|
||||
mapView.addOnDidBecomeIdleListener(object : MapView.OnDidBecomeIdleListener {
|
||||
override fun onDidBecomeIdle() {
|
||||
handler.postDelayed(runnable, 2500)
|
||||
mapView.removeOnDidBecomeIdleListener(this)
|
||||
// Wait for the map to become idle before manipulating the style and camera of the map
|
||||
mapView.addOnDidBecomeIdleListener(object : MapView.OnDidBecomeIdleListener {
|
||||
override fun onDidBecomeIdle() {
|
||||
handler.postDelayed(runnable, 2500)
|
||||
mapView.removeOnDidBecomeIdleListener(this)
|
||||
}
|
||||
})
|
||||
|
||||
// Load mapbox streets and add lines and circles
|
||||
setupStyle()
|
||||
}
|
||||
})
|
||||
|
||||
// Load mapbox streets and add lines and circles
|
||||
setupStyle()
|
||||
}
|
||||
}
|
||||
|
||||
private fun setupStyle() {
|
||||
// Assume the route is represented by an array of coordinates.
|
||||
val coordinates = listOf<Point>(
|
||||
Point.fromLngLat(
|
||||
-77.06866264343262,
|
||||
38.90506061276737
|
||||
),
|
||||
Point.fromLngLat(
|
||||
-77.06283688545227,
|
||||
38.905194197410545
|
||||
),
|
||||
Point.fromLngLat(
|
||||
-77.06285834312439,
|
||||
38.906429843444094
|
||||
),
|
||||
Point.fromLngLat(
|
||||
-77.0630407333374,
|
||||
38.90680554236621
|
||||
)
|
||||
)
|
||||
|
||||
// Convert to a LineString
|
||||
val routeLineString = LineString.fromLngLats(coordinates)
|
||||
|
||||
// Create buffer around linestring
|
||||
val bufferedRouteGeometry = bufferLineStringGeometry(routeLineString)
|
||||
|
||||
// Setup style with additional layers,
|
||||
// using Style.MAPBOX_STREETS as a base style
|
||||
mapboxMap.setStyle(
|
||||
Style.Builder()
|
||||
.fromUri(Style.MAPBOX_STREETS)
|
||||
.withSources(
|
||||
GeoJsonSource(
|
||||
POINT_ID, LineString.fromLngLats(coordinates)
|
||||
),
|
||||
GeoJsonSource(
|
||||
FILL_ID,
|
||||
FeatureCollection.fromFeature(Feature.fromGeometry(bufferedRouteGeometry)),
|
||||
GeoJsonOptions().withBuffer(0).withTolerance(0.0f)
|
||||
)
|
||||
private fun setupStyle() {
|
||||
// Assume the route is represented by an array of coordinates.
|
||||
val coordinates = listOf<Point>(
|
||||
Point.fromLngLat(
|
||||
-77.06866264343262,
|
||||
38.90506061276737
|
||||
),
|
||||
Point.fromLngLat(
|
||||
-77.06283688545227,
|
||||
38.905194197410545
|
||||
),
|
||||
Point.fromLngLat(
|
||||
-77.06285834312439,
|
||||
38.906429843444094
|
||||
),
|
||||
Point.fromLngLat(
|
||||
-77.0630407333374,
|
||||
38.90680554236621
|
||||
)
|
||||
)
|
||||
.withLayerBelow(
|
||||
LineLayer(LINE_ID, POINT_ID)
|
||||
.withProperties(lineWidth(7.5f), lineColor(Color.LTGRAY)),
|
||||
"poi-label"
|
||||
|
||||
// Convert to a LineString
|
||||
val routeLineString = LineString.fromLngLats(coordinates)
|
||||
|
||||
// Create buffer around linestring
|
||||
val bufferedRouteGeometry = bufferLineStringGeometry(routeLineString)
|
||||
|
||||
// Setup style with additional layers,
|
||||
// using Style.MAPBOX_STREETS as a base style
|
||||
mapboxMap.setStyle(
|
||||
Style.Builder()
|
||||
.fromUri(Style.MAPBOX_STREETS)
|
||||
.withSources(
|
||||
GeoJsonSource(
|
||||
POINT_ID,
|
||||
LineString.fromLngLats(coordinates)
|
||||
),
|
||||
GeoJsonSource(
|
||||
FILL_ID,
|
||||
FeatureCollection.fromFeature(Feature.fromGeometry(bufferedRouteGeometry)),
|
||||
GeoJsonOptions().withBuffer(0).withTolerance(0.0f)
|
||||
)
|
||||
)
|
||||
.withLayerBelow(
|
||||
LineLayer(LINE_ID, POINT_ID)
|
||||
.withProperties(lineWidth(7.5f), lineColor(Color.LTGRAY)),
|
||||
"poi-label"
|
||||
)
|
||||
.withLayerBelow(
|
||||
CircleLayer(POINT_ID, POINT_ID)
|
||||
.withProperties(
|
||||
circleRadius(7.5f),
|
||||
circleColor(Color.DKGRAY),
|
||||
circleOpacity(0.75f)
|
||||
),
|
||||
"poi-label"
|
||||
)
|
||||
)
|
||||
.withLayerBelow(
|
||||
CircleLayer(POINT_ID, POINT_ID)
|
||||
.withProperties(
|
||||
circleRadius(7.5f),
|
||||
circleColor(Color.DKGRAY),
|
||||
circleOpacity(0.75f)
|
||||
), "poi-label"
|
||||
)
|
||||
)
|
||||
}
|
||||
|
||||
private fun optimizeStyle() {
|
||||
val style = mapboxMap.style!!
|
||||
|
||||
// Add fill layer to represent buffered LineString
|
||||
mapboxMap.style!!.addLayerBelow(
|
||||
FillLayer(FILL_ID, FILL_ID)
|
||||
.withProperties(
|
||||
fillOpacity(0.12f),
|
||||
fillColor(Color.YELLOW)
|
||||
), LINE_ID
|
||||
)
|
||||
|
||||
// Move to a new camera position
|
||||
mapboxMap.easeCamera(
|
||||
CameraUpdateFactory.newCameraPosition(
|
||||
CameraPosition.Builder()
|
||||
.zoom(16.0)
|
||||
.target(LatLng(38.905156245642814, -77.06535338052844))
|
||||
.bearing(80.68015859462369)
|
||||
.tilt(55.0)
|
||||
.build()
|
||||
), 1750
|
||||
)
|
||||
|
||||
// Show only POI labels inside geometry using within expression
|
||||
val symbolLayer = style.getLayer("poi-label") as SymbolLayer
|
||||
symbolLayer.setFilter(
|
||||
within(
|
||||
bufferLineStringGeometry()
|
||||
)
|
||||
)
|
||||
|
||||
// Hide other types of labels to highlight POI labels
|
||||
(style.getLayer("road-label") as SymbolLayer).setProperties(visibility(NONE))
|
||||
(style.getLayer("transit-label") as SymbolLayer).setProperties(visibility(NONE))
|
||||
(style.getLayer("road-number-shield") as SymbolLayer).setProperties(visibility(NONE))
|
||||
}
|
||||
|
||||
override fun onStart() {
|
||||
super.onStart()
|
||||
mapView.onStart()
|
||||
}
|
||||
|
||||
override fun onResume() {
|
||||
super.onResume()
|
||||
mapView.onResume()
|
||||
}
|
||||
|
||||
override fun onPause() {
|
||||
super.onPause()
|
||||
mapView.onPause()
|
||||
}
|
||||
|
||||
override fun onStop() {
|
||||
super.onStop()
|
||||
mapView.onStop()
|
||||
}
|
||||
|
||||
override fun onLowMemory() {
|
||||
super.onLowMemory()
|
||||
mapView.onLowMemory()
|
||||
}
|
||||
|
||||
override fun onDestroy() {
|
||||
super.onDestroy()
|
||||
handler.removeCallbacks(runnable)
|
||||
mapView.onDestroy()
|
||||
}
|
||||
|
||||
override fun onSaveInstanceState(outState: Bundle?, outPersistentState: PersistableBundle?) {
|
||||
super.onSaveInstanceState(outState, outPersistentState)
|
||||
outState?.let {
|
||||
mapView.onSaveInstanceState(it)
|
||||
}
|
||||
}
|
||||
|
||||
private fun bufferLineStringGeometry(lineString: LineString? = null): Polygon {
|
||||
// TODO replace static data by Turf#Buffer: mapbox-java/issues/987
|
||||
return FeatureCollection.fromJson(
|
||||
"""
|
||||
{
|
||||
"type": "FeatureCollection",
|
||||
"features": [
|
||||
{
|
||||
"type": "Feature",
|
||||
"properties": {},
|
||||
"geometry": {
|
||||
"type": "Polygon",
|
||||
"coordinates": [
|
||||
[
|
||||
[
|
||||
-77.06867337226866,
|
||||
38.90467655551809
|
||||
],
|
||||
[
|
||||
-77.06233263015747,
|
||||
38.90479344272695
|
||||
],
|
||||
[
|
||||
-77.06234335899353,
|
||||
38.906463238984344
|
||||
],
|
||||
[
|
||||
-77.06290125846863,
|
||||
38.907206285691615
|
||||
],
|
||||
[
|
||||
-77.06364154815674,
|
||||
38.90684728656818
|
||||
],
|
||||
[
|
||||
-77.06326603889465,
|
||||
38.90637140121084
|
||||
],
|
||||
[
|
||||
-77.06321239471436,
|
||||
38.905561553883246
|
||||
],
|
||||
[
|
||||
-77.0691454410553,
|
||||
38.905436318935635
|
||||
],
|
||||
[
|
||||
-77.06912398338318,
|
||||
38.90466820642439
|
||||
],
|
||||
[
|
||||
-77.06867337226866,
|
||||
38.90467655551809
|
||||
]
|
||||
private fun optimizeStyle() {
|
||||
val style = mapboxMap.style!!
|
||||
|
||||
// Add fill layer to represent buffered LineString
|
||||
mapboxMap.style!!.addLayerBelow(
|
||||
FillLayer(FILL_ID, FILL_ID)
|
||||
.withProperties(
|
||||
fillOpacity(0.12f),
|
||||
fillColor(Color.YELLOW)
|
||||
),
|
||||
LINE_ID
|
||||
)
|
||||
|
||||
// Move to a new camera position
|
||||
mapboxMap.easeCamera(
|
||||
CameraUpdateFactory.newCameraPosition(
|
||||
CameraPosition.Builder()
|
||||
.zoom(16.0)
|
||||
.target(LatLng(38.905156245642814, -77.06535338052844))
|
||||
.bearing(80.68015859462369)
|
||||
.tilt(55.0)
|
||||
.build()
|
||||
),
|
||||
1750
|
||||
)
|
||||
|
||||
// Show only POI labels inside geometry using within expression
|
||||
val symbolLayer = style.getLayer("poi-label") as SymbolLayer
|
||||
symbolLayer.setFilter(
|
||||
within(
|
||||
bufferLineStringGeometry()
|
||||
)
|
||||
)
|
||||
|
||||
// Hide other types of labels to highlight POI labels
|
||||
(style.getLayer("road-label") as SymbolLayer).setProperties(visibility(NONE))
|
||||
(style.getLayer("transit-label") as SymbolLayer).setProperties(visibility(NONE))
|
||||
(style.getLayer("road-number-shield") as SymbolLayer).setProperties(visibility(NONE))
|
||||
}
|
||||
|
||||
override fun onStart() {
|
||||
super.onStart()
|
||||
mapView.onStart()
|
||||
}
|
||||
|
||||
override fun onResume() {
|
||||
super.onResume()
|
||||
mapView.onResume()
|
||||
}
|
||||
|
||||
override fun onPause() {
|
||||
super.onPause()
|
||||
mapView.onPause()
|
||||
}
|
||||
|
||||
override fun onStop() {
|
||||
super.onStop()
|
||||
mapView.onStop()
|
||||
}
|
||||
|
||||
override fun onLowMemory() {
|
||||
super.onLowMemory()
|
||||
mapView.onLowMemory()
|
||||
}
|
||||
|
||||
override fun onDestroy() {
|
||||
super.onDestroy()
|
||||
handler.removeCallbacks(runnable)
|
||||
mapView.onDestroy()
|
||||
}
|
||||
|
||||
override fun onSaveInstanceState(outState: Bundle?, outPersistentState: PersistableBundle?) {
|
||||
super.onSaveInstanceState(outState, outPersistentState)
|
||||
outState?.let {
|
||||
mapView.onSaveInstanceState(it)
|
||||
}
|
||||
}
|
||||
|
||||
private fun bufferLineStringGeometry(lineString: LineString? = null): Polygon {
|
||||
// TODO replace static data by Turf#Buffer: mapbox-java/issues/987
|
||||
return FeatureCollection.fromJson(
|
||||
"""
|
||||
{
|
||||
"type": "FeatureCollection",
|
||||
"features": [
|
||||
{
|
||||
"type": "Feature",
|
||||
"properties": {},
|
||||
"geometry": {
|
||||
"type": "Polygon",
|
||||
"coordinates": [
|
||||
[
|
||||
[
|
||||
-77.06867337226866,
|
||||
38.90467655551809
|
||||
],
|
||||
[
|
||||
-77.06233263015747,
|
||||
38.90479344272695
|
||||
],
|
||||
[
|
||||
-77.06234335899353,
|
||||
38.906463238984344
|
||||
],
|
||||
[
|
||||
-77.06290125846863,
|
||||
38.907206285691615
|
||||
],
|
||||
[
|
||||
-77.06364154815674,
|
||||
38.90684728656818
|
||||
],
|
||||
[
|
||||
-77.06326603889465,
|
||||
38.90637140121084
|
||||
],
|
||||
[
|
||||
-77.06321239471436,
|
||||
38.905561553883246
|
||||
],
|
||||
[
|
||||
-77.0691454410553,
|
||||
38.905436318935635
|
||||
],
|
||||
[
|
||||
-77.06912398338318,
|
||||
38.90466820642439
|
||||
],
|
||||
[
|
||||
-77.06867337226866,
|
||||
38.90467655551809
|
||||
]
|
||||
]
|
||||
]
|
||||
}
|
||||
}
|
||||
]
|
||||
]
|
||||
}
|
||||
}
|
||||
]
|
||||
}
|
||||
""".trimIndent()
|
||||
).features()!![0].geometry() as Polygon
|
||||
}
|
||||
""".trimIndent()
|
||||
).features()!![0].geometry() as Polygon
|
||||
}
|
||||
|
||||
companion object {
|
||||
const val POINT_ID = "point"
|
||||
const val FILL_ID = "fill"
|
||||
const val LINE_ID = "line"
|
||||
}
|
||||
}
|
||||
companion object {
|
||||
const val POINT_ID = "point"
|
||||
const val FILL_ID = "fill"
|
||||
const val LINE_ID = "line"
|
||||
}
|
||||
}
|
||||
|
||||
@@ -8,57 +8,57 @@ import java.lang.ref.WeakReference
|
||||
|
||||
class FileUtils {
|
||||
|
||||
/**
|
||||
* Task that copies a file from the assets directory to a provided directory.
|
||||
* The asset's name is going to be kept in the new directory.
|
||||
*/
|
||||
class CopyFileFromAssetsTask(context: Context, listener: OnFileCopiedFromAssetsListener) : AsyncTask<String, Void, Boolean>() {
|
||||
private val contextWeakReference: WeakReference<Context> = WeakReference(context)
|
||||
private val listenerWeakReference: WeakReference<OnFileCopiedFromAssetsListener> = WeakReference(listener)
|
||||
/**
|
||||
* Task that copies a file from the assets directory to a provided directory.
|
||||
* The asset's name is going to be kept in the new directory.
|
||||
*/
|
||||
class CopyFileFromAssetsTask(context: Context, listener: OnFileCopiedFromAssetsListener) : AsyncTask<String, Void, Boolean>() {
|
||||
private val contextWeakReference: WeakReference<Context> = WeakReference(context)
|
||||
private val listenerWeakReference: WeakReference<OnFileCopiedFromAssetsListener> = WeakReference(listener)
|
||||
|
||||
override fun doInBackground(vararg strings: String): Boolean? {
|
||||
val assetName = strings[0]
|
||||
val destinationPath = strings[1]
|
||||
contextWeakReference.get()?.let {
|
||||
try {
|
||||
copyAsset(it, assetName, destinationPath)
|
||||
} catch (ex: Exception) {
|
||||
return false
|
||||
override fun doInBackground(vararg strings: String): Boolean? {
|
||||
val assetName = strings[0]
|
||||
val destinationPath = strings[1]
|
||||
contextWeakReference.get()?.let {
|
||||
try {
|
||||
copyAsset(it, assetName, destinationPath)
|
||||
} catch (ex: Exception) {
|
||||
return false
|
||||
}
|
||||
}
|
||||
|
||||
return true
|
||||
}
|
||||
}
|
||||
|
||||
return true
|
||||
override fun onCancelled() {
|
||||
listenerWeakReference.get()?.onError()
|
||||
}
|
||||
|
||||
override fun onPostExecute(result: Boolean) {
|
||||
if (result) {
|
||||
listenerWeakReference.get()?.onFileCopiedFromAssets()
|
||||
} else {
|
||||
listenerWeakReference.get()?.onError()
|
||||
}
|
||||
}
|
||||
|
||||
private fun copyAsset(context: Context, assetName: String, destinationPath: String) {
|
||||
val bufferSize = 1024
|
||||
val assetManager = context.assets
|
||||
val inputStream = assetManager.open(assetName)
|
||||
val outputStream = FileOutputStream(File(destinationPath, assetName))
|
||||
try {
|
||||
inputStream.copyTo(outputStream, bufferSize)
|
||||
} finally {
|
||||
inputStream.close()
|
||||
outputStream.flush()
|
||||
outputStream.close()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
override fun onCancelled() {
|
||||
listenerWeakReference.get()?.onError()
|
||||
interface OnFileCopiedFromAssetsListener {
|
||||
fun onFileCopiedFromAssets()
|
||||
fun onError()
|
||||
}
|
||||
|
||||
override fun onPostExecute(result: Boolean) {
|
||||
if (result) {
|
||||
listenerWeakReference.get()?.onFileCopiedFromAssets()
|
||||
} else {
|
||||
listenerWeakReference.get()?.onError()
|
||||
}
|
||||
}
|
||||
|
||||
private fun copyAsset(context: Context, assetName: String, destinationPath: String) {
|
||||
val bufferSize = 1024
|
||||
val assetManager = context.assets
|
||||
val inputStream = assetManager.open(assetName)
|
||||
val outputStream = FileOutputStream(File(destinationPath, assetName))
|
||||
try {
|
||||
inputStream.copyTo(outputStream, bufferSize)
|
||||
} finally {
|
||||
inputStream.close()
|
||||
outputStream.flush()
|
||||
outputStream.close()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
interface OnFileCopiedFromAssetsListener {
|
||||
fun onFileCopiedFromAssets()
|
||||
fun onError()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -37,7 +37,7 @@ ext {
|
||||
gms : '16.0.0',
|
||||
jacoco : '0.8.5',
|
||||
appcenter : '1.4',
|
||||
ktlint : '0.34.0',
|
||||
ktlint : '0.40.0',
|
||||
commonsIO : '2.6',
|
||||
mapboxSdkVersions: '1.0.1'
|
||||
]
|
||||
|
||||
@@ -16,7 +16,7 @@ task ktlint(type: JavaExec, group: "verification") {
|
||||
description = "Check Kotlin code style."
|
||||
classpath = configurations.ktlint
|
||||
main = "com.pinterest.ktlint.Main"
|
||||
args "src/**/*.kt"
|
||||
args "--disabled_rules=no-wildcard-imports", "src/**/*.kt"
|
||||
}
|
||||
|
||||
task ktlintFormat(type: JavaExec, group: "formatting") {
|
||||
|
||||
Reference in New Issue
Block a user