Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
@@ -0,0 +1,88 @@
package com.mapbox.maps.mapbox_maps

import com.mapbox.bindgen.DataRef
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think this import can be removed

import com.mapbox.maps.MapboxExperimental
import com.mapbox.maps.MapboxMap
import com.mapbox.maps.MapboxMapRecorder
import com.mapbox.maps.mapbox_maps.pigeons.MapPlayerOptions
import com.mapbox.maps.mapbox_maps.pigeons.MapRecorderOptions
import com.mapbox.maps.mapbox_maps.pigeons._MapRecorderMessenger
import java.nio.ByteBuffer

/**
* Controller for MapRecorder functionality.
*
* Provides functions to record and replay API calls of a MapboxMap instance.
* These recordings can be used to debug issues which require multiple steps to reproduce.
* Additionally, playbacks can be used for performance testing custom scenarios.
*/
@OptIn(MapboxExperimental::class)
class MapRecorderController(
private val mapboxMap: MapboxMap
) : _MapRecorderMessenger {

private var recorder: MapboxMapRecorder? = null
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This should be cleaned up to avoid memory leaks. Please add a dispose() and call it from MapboxMapController.dispose()

fun dispose() {
  recorder = null
}

And then in MapboxMapController.kt:

override fun dispose() {
  if (mapView == null) {
    return
  }
  lifecycleHelper?.dispose()
  lifecycleHelper = null
  mapView?.setViewTreeLifecycleOwner(null)
  mapView = null
  mapboxMap = null
  methodChannel.setMethodCallHandler(null)

  StyleManager.setUp(messenger, null, channelSuffix)
  _CameraManager.setUp(messenger, null, channelSuffix)
  Projection.setUp(messenger, null, channelSuffix)
  _MapInterface.setUp(messenger, null, channelSuffix)
  _AnimationManager.setUp(messenger, null, channelSuffix)
  annotationController.dispose()
  _LocationComponentSettingsInterface.setUp(messenger, null, channelSuffix)
  LogoSettingsInterface.setUp(messenger, null, channelSuffix)
  GesturesSettingsInterface.setUp(messenger, null, channelSuffix)
  CompassSettingsInterface.setUp(messenger, null, channelSuffix)
  ScaleBarSettingsInterface.setUp(messenger, null, channelSuffix)
  AttributionSettingsInterface.setUp(messenger, null, channelSuffix)
  _ViewportMessenger.setUp(messenger, null, channelSuffix)
  _PerformanceStatisticsApi.setUp(messenger, null, channelSuffix)
  _MapRecorderMessenger.setUp(messenger, null, channelSuffix)  // ← ADD THIS
  mapRecorderController.dispose() // ← ADD THIS
}


/**
* Get or create the recorder instance.
*/
private fun getRecorder(): MapboxMapRecorder {
if (recorder == null) {
recorder = mapboxMap.createRecorder()
}
return recorder!!
}

override fun startRecording(options: MapRecorderOptions) {
val nativeOptions = com.mapbox.maps.MapRecorderOptions.Builder()
.apply {
options.timeWindow?.let { timeWindow(it.toLong()) }
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think this toLong() conversion is redundant - timeWindow is already Long? from the pigeon definition.

loggingEnabled(options.loggingEnabled)
compressed(options.compressed)
}
.build()

getRecorder().startRecording(nativeOptions)
}

override fun stopRecording(callback: (Result<ByteArray>) -> Unit) {
try {
val data = getRecorder().stopRecording()
val bytes = ByteArray(data.remaining())
data.get(bytes)
data.rewind()
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I don't think that this data.rewind() is necessary as the data has already been copied to the byte array. Is there another purpose I'm missing?

callback(Result.success(bytes))
} catch (e: Exception) {
callback(Result.failure(e))
}
}

override fun replay(
recordedSequence: ByteArray,
options: MapPlayerOptions,
callback: (Result<Unit>) -> Unit
) {
try {
val nativeOptions = com.mapbox.maps.MapPlayerOptions.Builder()
.playbackCount(options.playbackCount.toInt())
.playbackSpeedMultiplier(options.playbackSpeedMultiplier)
.avoidPlaybackPauses(options.avoidPlaybackPauses)
.build()

val buffer = ByteBuffer.wrap(recordedSequence)
getRecorder().replay(buffer, nativeOptions) {
callback(Result.success(Unit))
}
} catch (e: Exception) {
callback(Result.failure(e))
}
}

override fun togglePauseReplay() {
getRecorder().togglePauseReplay()
}

override fun getPlaybackState(): String {
return getRecorder().getPlaybackState()
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,7 @@ import com.mapbox.maps.mapbox_maps.pigeons._LocationComponentSettingsInterface
import com.mapbox.maps.mapbox_maps.pigeons._MapInterface
import com.mapbox.maps.mapbox_maps.pigeons._PerformanceStatisticsApi
import com.mapbox.maps.mapbox_maps.pigeons._ViewportMessenger
import com.mapbox.maps.mapbox_maps.pigeons._MapRecorderMessenger
import com.mapbox.maps.plugin.animation.camera
import com.mapbox.maps.plugin.viewport.viewport
import io.flutter.embedding.android.FlutterActivity
Expand Down Expand Up @@ -122,6 +123,7 @@ class MapboxMapController(
private val compassController: CompassController
private val viewportController: ViewportController
private val performanceStatisticsController: PerformanceStatisticsController
private val mapRecorderController: MapRecorderController

private val eventHandler: MapboxEventHandler

Expand Down Expand Up @@ -206,6 +208,7 @@ class MapboxMapController(
compassController = CompassController(mapView)
viewportController = ViewportController(mapView.viewport, mapView.camera, context, mapboxMap)
performanceStatisticsController = PerformanceStatisticsController(mapboxMap, this.messenger, this.channelSuffix)
mapRecorderController = MapRecorderController(mapboxMap)
changeUserAgent(pluginVersion)

StyleManager.setUp(messenger, styleController, this.channelSuffix)
Expand All @@ -222,6 +225,7 @@ class MapboxMapController(
CompassSettingsInterface.setUp(messenger, compassController, this.channelSuffix)
_ViewportMessenger.setUp(messenger, viewportController, this.channelSuffix)
_PerformanceStatisticsApi.setUp(messenger, performanceStatisticsController, this.channelSuffix)
_MapRecorderMessenger.setUp(messenger, mapRecorderController, this.channelSuffix)

methodChannel = MethodChannel(messenger, "plugins.flutter.io.$channelSuffix")
methodChannel.setMethodCallHandler(this)
Expand Down
Loading