Я пытаюсь отследить местоположение устройства и отобразить его на карте MapBox
. Я должен использовать фрагмент, чтобы отобразить карту, и он реализован, как показано ниже.
Макет
<?xml version="1.0" encoding="utf-8"?>
<layout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
xmlns:mapbox="http://schemas.android.com/apk/res-auto">
<androidx.constraintlayout.widget.ConstraintLayout
android:id="@+id/explore_container"
android:layout_width="match_parent"
android:layout_height="match_parent"
tools:context=".presentation.main.explore.ExploreFragment">
<com.mapbox.mapboxsdk.maps.MapView
android:id="@+id/map_view"
mapbox:layout_constraintBottom_toBottomOf="parent"
mapbox:layout_constraintEnd_toEndOf="parent"
mapbox:layout_constraintStart_toStartOf="parent"
mapbox:layout_constraintTop_toTopOf="parent"
android:layout_width="match_parent"
android:layout_height="match_parent" />
</androidx.constraintlayout.widget.ConstraintLayout>
</layout>
Фрагмент
class MapFragment : Fragment(), OnMapReadyCallback, PermissionsListener {
private lateinit var binding: FragmentMapBinding
private lateinit var map: MapboxMap
private lateinit var permissionsManager: PermissionsManager
private var locationEngine: LocationEngine? = null
private val locationCallback = LocationCallback(this)
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
Mapbox.getInstance(requireContext().applicationContext, getString(R.string.mapbox_token))
}
override fun onCreateView(
inflater: LayoutInflater,
container: ViewGroup?,
savedInstanceState: Bundle?
) {
binding = DataBindingUtil.inflate(
inflater,
R.layout.fragment_explore,
container,
false
)
binding.lifecycleOwner = this
return binding.root
}
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
super.onViewCreated(view, savedInstanceState)
binding.mapView.onCreate(savedInstanceState)
binding.mapView.getMapAsync(this)
}
override fun onMapReady(mapboxMap: MapboxMap) {
map = mapboxMap
mapboxMap.setStyle(Style.MAPBOX_STREETS) { loadedStyle ->
enableLocation(loadedStyle)
}
}
private fun enableLocation(loadedMapStyle: Style) {
if (PermissionsManager.areLocationPermissionsGranted(requireActivity())) {
initLocationComponent(loadedMapStyle)
initLocationEngine()
} else {
permissionsManager = PermissionsManager(this)
permissionsManager.requestLocationPermissions(requireActivity())
}
}
private fun initLocationComponent(loadedMapStyle: Style) {
val locationComponent: LocationComponent = map.locationComponent
val locationComponentActivationOptions = LocationComponentActivationOptions.builder(
requireActivity(),
loadedMapStyle
)
.useDefaultLocationEngine(false)
.build()
locationComponent.activateLocationComponent(locationComponentActivationOptions)
locationComponent.isLocationComponentEnabled = true
locationComponent.cameraMode = CameraMode.TRACKING
locationComponent.renderMode = RenderMode.COMPASS
}
private fun initLocationEngine() {
locationEngine = LocationEngineProvider.getBestLocationEngine(requireActivity())
val request = LocationEngineRequest.Builder(1000L)
.setPriority(LocationEngineRequest.PRIORITY_HIGH_ACCURACY)
.setMaxWaitTime(5000L).build()
locationEngine!!.requestLocationUpdates(request, locationCallback, getMainLooper())
locationEngine!!.getLastLocation(locationCallback)
}
override fun onRequestPermissionsResult(
requestCode: Int,
permissions: Array<out String>,
grantResults: IntArray
) {
permissionsManager.onRequestPermissionsResult(requestCode, permissions, grantResults)
}
override fun onExplanationNeeded(permissionsToExplain: MutableList<String>?) {
Toast.makeText(requireActivity(), "GRANT NEEDED", Toast.LENGTH_LONG).show()
}
override fun onPermissionResult(granted: Boolean) {
if (granted) {
map.getStyle { loadedStyle ->
enableLocation(loadedStyle)
}
} else {
Toast.makeText(requireActivity(), "NOT GRANTED", Toast.LENGTH_LONG).show()
}
}
private class LocationCallback(
fragment: ExploreFragment
) : LocationEngineCallback<LocationEngineResult> {
private val fragmentWeakReference: WeakReference<ExploreFragment> = WeakReference(fragment)
override fun onSuccess(result: LocationEngineResult?) {
if (fragmentWeakReference.get() == null || result == null || result.lastLocation == null) return
Log.d("TEST", "LAT: ${result.lastLocation?.latitude}")
Log.d("TEST", "LONG: ${result.lastLocation?.longitude}")
}
override fun onFailure(exception: Exception) {
if (fragmentWeakReference.get() == null) return
Log.d("TEST", "ERROR: ${exception.localizedMessage}")
}
}
override fun onResume() {
super.onResume()
if (::binding.isInitialized) binding.mapView.onResume()
}
override fun onPause() {
super.onPause()
if (::binding.isInitialized) binding.mapView.onPause()
}
override fun onSaveInstanceState(outState: Bundle) {
super.onSaveInstanceState(outState)
if (::binding.isInitialized) binding.mapView.onSaveInstanceState(outState)
}
override fun onLowMemory() {
super.onLowMemory()
if (::binding.isInitialized) binding.mapView.onLowMemory()
}
override fun onDestroyView() {
super.onDestroyView()
if (locationEngine != null) locationEngine!!.removeLocationUpdates(locationCallback)
if (::binding.isInitialized) binding.mapView.onDestroy()
}
}
Я пытался следовать примеру из документ и применить его к Fragment
. Проблема заключается в том, что когда прослушивание местоположения включено и пользователь пытается выйти из MapFragment
, приложение вылетает с ошибкой: java.lang.IllegalStateException: Calling getSourceAs when a newer style is loading/has loaded.
Если я удаляю строку if (:: binding.isInitialized) привязки. mapView.onDestroy () из onDestroyView приложение не создает sh, но я знаю, что удалять эту строку не очень хорошая идея.
Как MapBox newb ie, я понятия не имею, в чем причина , Любая помощь будет оценена.