Merge pull request #368 from ScriptTactics/feature/mapbox-v10-migration

Migrating to Mapbox API V10
pull/360/head
Andre Kirchhoff 2022-02-06 00:57:52 -03:00 zatwierdzone przez GitHub
commit 1f177dc63e
Nie znaleziono w bazie danych klucza dla tego podpisu
ID klucza GPG: 4AEE18F83AFDEB23
5 zmienionych plików z 84 dodań i 135 usunięć

Wyświetl plik

@ -158,14 +158,14 @@ dependencies {
implementation "org.jetbrains.kotlinx:kotlinx-coroutines-android:$coroutines_version"
// For now I'm not using javalite, because I want JSON printing
implementation ('com.google.protobuf:protobuf-java:3.15.8')
implementation('com.google.protobuf:protobuf-java:3.15.8')
// For UART access
// implementation 'com.google.android.things:androidthings:1.0'
implementation 'com.github.mik3y:usb-serial-for-android:v3.0.0'
implementation 'com.github.mik3y:usb-serial-for-android:3.4.3'
// mapbox
implementation 'com.mapbox.mapboxsdk:mapbox-android-sdk:9.7.1'
implementation('com.mapbox.maps:android:10.2.0')
// mapbox specifies a really old version of okhttp3 which causes lots of API warnings. trying a newer version
implementation 'com.squareup.okhttp3:okhttp:4.9.0'

Wyświetl plik

@ -7,8 +7,6 @@ import com.geeksville.android.GeeksvilleApplication
import com.geeksville.android.Logging
import com.geeksville.util.Exceptions
import com.google.firebase.crashlytics.FirebaseCrashlytics
import com.mapbox.mapboxsdk.Mapbox
class MeshUtilApplication : GeeksvilleApplication() {
@ -50,7 +48,5 @@ class MeshUtilApplication : GeeksvilleApplication() {
sendCrashReports() // Send the new report
}
}
Mapbox.getInstance(this, getString(R.string.mapbox_access_token))
}
}

Wyświetl plik

@ -6,6 +6,8 @@ import android.view.LayoutInflater
import android.view.View
import android.view.ViewGroup
import androidx.core.content.ContextCompat
import androidx.core.graphics.drawable.toBitmap
import androidx.core.view.isVisible
import androidx.fragment.app.activityViewModels
import androidx.lifecycle.Observer
import com.geeksville.android.GeeksvilleApplication
@ -17,20 +19,19 @@ import com.geeksville.util.formatAgo
import com.mapbox.geojson.Feature
import com.mapbox.geojson.FeatureCollection
import com.mapbox.geojson.Point
import com.mapbox.mapboxsdk.camera.CameraPosition
import com.mapbox.mapboxsdk.camera.CameraUpdateFactory
import com.mapbox.mapboxsdk.geometry.LatLng
import com.mapbox.mapboxsdk.geometry.LatLngBounds
import com.mapbox.mapboxsdk.maps.MapView
import com.mapbox.mapboxsdk.maps.MapboxMap
import com.mapbox.mapboxsdk.maps.Style
import com.mapbox.mapboxsdk.style.expressions.Expression
import com.mapbox.mapboxsdk.style.layers.Property
import com.mapbox.mapboxsdk.style.layers.Property.TEXT_ANCHOR_TOP
import com.mapbox.mapboxsdk.style.layers.Property.TEXT_JUSTIFY_AUTO
import com.mapbox.mapboxsdk.style.layers.PropertyFactory.*
import com.mapbox.mapboxsdk.style.layers.SymbolLayer
import com.mapbox.mapboxsdk.style.sources.GeoJsonSource
import com.mapbox.maps.*
import com.mapbox.maps.dsl.cameraOptions
import com.mapbox.maps.extension.style.expressions.generated.Expression
import com.mapbox.maps.extension.style.layers.addLayer
import com.mapbox.maps.extension.style.layers.generated.SymbolLayer
import com.mapbox.maps.extension.style.layers.properties.generated.IconAnchor
import com.mapbox.maps.extension.style.layers.properties.generated.TextAnchor
import com.mapbox.maps.extension.style.layers.properties.generated.TextJustify
import com.mapbox.maps.extension.style.sources.addSource
import com.mapbox.maps.extension.style.sources.generated.GeoJsonSource
import com.mapbox.maps.plugin.animation.MapAnimationOptions
import com.mapbox.maps.plugin.animation.flyTo
import com.mapbox.maps.plugin.gestures.gestures
class MapFragment : ScreenFragment("Map"), Logging {
@ -42,22 +43,21 @@ class MapFragment : ScreenFragment("Map"), Logging {
private val labelLayerId = "label-layer"
private val markerImageId = "my-marker-image"
private val nodePositions = GeoJsonSource(nodeSourceId)
private var nodePositions = GeoJsonSource(GeoJsonSource.Builder(nodeSourceId))
private val nodeLayer = SymbolLayer(nodeLayerId, nodeSourceId).withProperties(
iconImage(markerImageId),
iconAnchor(Property.ICON_ANCHOR_BOTTOM),
iconAllowOverlap(true)
)
private val nodeLayer = SymbolLayer(nodeLayerId, nodeSourceId)
.iconImage(markerImageId)
.iconAnchor(IconAnchor.BOTTOM)
.iconAllowOverlap(true)
private val labelLayer = SymbolLayer(labelLayerId, nodeSourceId).withProperties(
textField(Expression.get("name")),
textSize(12f),
textColor(Color.RED),
textVariableAnchor(arrayOf(TEXT_ANCHOR_TOP)),
textJustify(TEXT_JUSTIFY_AUTO),
textAllowOverlap(true)
)
private val labelLayer = SymbolLayer(labelLayerId, nodeSourceId)
.textField(Expression.get("name"))
.textSize(12.0)
.textColor(Color.RED)
.textAnchor(TextAnchor.TOP)
//.textVariableAnchor(TextAnchor.TOP) //TODO investigate need for variable anchor vs normal anchor
.textJustify(TextJustify.AUTO)
.textAllowOverlap(true)
private fun onNodesChanged(map: MapboxMap, nodes: Collection<NodeInfo>) {
@ -87,35 +87,39 @@ class MapFragment : ScreenFragment("Map"), Logging {
return FeatureCollection.fromFeatures(locations)
}
nodePositions.setGeoJson(getCurrentNodes()) // Update node positions
nodePositions.featureCollection(getCurrentNodes())
}
fun zoomToNodes(map: MapboxMap) {
private fun zoomToNodes(map: MapboxMap) {
val points: MutableList<Point> = mutableListOf()
val nodesWithPosition =
model.nodeDB.nodes.value?.values?.filter { it.validPosition != null }
if (nodesWithPosition != null && nodesWithPosition.isNotEmpty()) {
val update = if (nodesWithPosition.size >= 2) {
val unit = if (nodesWithPosition.size >= 2) {
// Multiple nodes, make them all fit on the map view
val bounds = LatLngBounds.Builder()
// Add all positions
bounds.includes(nodesWithPosition.map { it.position!! }
.map { LatLng(it.latitude, it.longitude) })
CameraUpdateFactory.newLatLngBounds(bounds.build(), 150)
nodesWithPosition.forEach {
points.add(
Point.fromLngLat(
it.position!!.longitude,
it.position!!.latitude
)
)
}
map.cameraForCoordinates(points)
} else {
// Only one node, just zoom in on it
val it = nodesWithPosition[0].position!!
val cameraPos = CameraPosition.Builder().target(
LatLng(it.latitude, it.longitude)
).zoom(9.0).build()
CameraUpdateFactory.newCameraPosition(cameraPos)
points.add(Point.fromLngLat(it.longitude, it.latitude))
map.cameraForCoordinates(points)
cameraOptions {
this.zoom(9.0)
this.center(points[0])
}
}
map.animateCamera(update, 1000)
map.flyTo(
unit,
MapAnimationOptions.mapAnimationOptions { duration(1000) })
}
}
@ -141,7 +145,7 @@ class MapFragment : ScreenFragment("Map"), Logging {
* Mapbox native code can crash painfully if you ever call a mapbox view function while the view is not actively being show
*/
private val isViewVisible: Boolean
get() = !(mapView?.isDestroyed ?: true)
get() = mapView?.isVisible == true
override fun onViewCreated(viewIn: View, savedInstanceState: Bundle?) {
super.onViewCreated(viewIn, savedInstanceState)
@ -151,85 +155,44 @@ class MapFragment : ScreenFragment("Map"), Logging {
val vIn = viewIn.findViewById<MapView>(R.id.mapView)
mapView = vIn
mapView?.let { v ->
v.onCreate(savedInstanceState)
// Each time the pane is shown start fetching new map info (we do this here instead of
// onCreate because getMapAsync can die in native code if the view goes away)
v.getMapAsync { map ->
if (view != null) { // it might have gone away by now
// val markerIcon = BitmapFactory.decodeResource(context.resources, R.drawable.ic_twotone_person_pin_24)
val markerIcon =
ContextCompat.getDrawable(
requireActivity(),
R.drawable.ic_twotone_person_pin_24
)!!
val map = v.getMapboxMap()
if (view != null) { // it might have gone away by now
val markerIcon =
ContextCompat.getDrawable(
requireActivity(),
R.drawable.ic_twotone_person_pin_24
)!!.toBitmap()
map.setStyle(Style.OUTDOORS) { style ->
style.addSource(nodePositions)
style.addImage(markerImageId, markerIcon)
style.addLayer(nodeLayer)
style.addLayer(labelLayer)
}
map.uiSettings.isRotateGesturesEnabled = false
// Provide initial positions
model.nodeDB.nodes.value?.let { nodes ->
onNodesChanged(map, nodes.values)
map.loadStyleUri(Style.OUTDOORS) {
if (it.isStyleLoaded) {
it.addSource(nodePositions)
it.addImage(markerImageId, markerIcon)
it.addLayer(nodeLayer)
it.addLayer(labelLayer)
}
}
// Any times nodes change update our map
model.nodeDB.nodes.observe(viewLifecycleOwner, Observer { nodes ->
if (isViewVisible)
onNodesChanged(map, nodes.values)
})
zoomToNodes(map)
v.gestures.rotateEnabled = false
// Provide initial positions
model.nodeDB.nodes.value?.let { nodes ->
onNodesChanged(map, nodes.values)
}
}
// Any times nodes change update our map
model.nodeDB.nodes.observe(viewLifecycleOwner, Observer { nodes ->
if (isViewVisible)
onNodesChanged(map, nodes.values)
})
zoomToNodes(map)
}
}
}
override fun onPause() {
mapView?.onPause()
super.onPause()
}
override fun onStart() {
super.onStart()
mapView?.onStart()
}
override fun onStop() {
mapView?.onStop()
super.onStop()
}
override fun onResume() {
super.onResume()
mapView?.onResume()
}
override fun onDestroyView() {
super.onDestroyView()
mapView?.onDestroy()
}
override fun onSaveInstanceState(outState: Bundle) {
mapView?.let {
if (!it.isDestroyed)
it.onSaveInstanceState(outState)
}
super.onSaveInstanceState(outState)
}
override fun onLowMemory() {
mapView?.let {
if (!it.isDestroyed)
it.onLowMemory()
}
super.onLowMemory()
}
}

Wyświetl plik

@ -1,17 +1,8 @@
<?xml version="1.0" encoding="utf-8"?>
<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
<com.mapbox.maps.MapView xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:mapbox="http://schemas.android.com/apk/res-auto"
android:id="@+id/mapView"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:id="@+id/mapFrame"> <!-- tab layout requires a unique ID -->
<com.mapbox.mapboxsdk.maps.MapView
android:id="@+id/mapView"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:clickable="true" android:focusable="true"
mapbox:mapbox_uiZoomGestures="true"
mapbox:mapbox_uiScrollGestures="true"></com.mapbox.mapboxsdk.maps.MapView>
</FrameLayout>
mapbox:mapbox_cameraZoom="0" />

Wyświetl plik

@ -6,7 +6,6 @@ buildscript {
repositories {
google()
// jcenter()
mavenCentral()
}
dependencies {