mirror of
https://github.com/meshtastic/Meshtastic-Android.git
synced 2026-04-20 22:23:37 +00:00
Migrating to Mapbox API V10
This commit is contained in:
parent
88a4825b28
commit
ed98232263
5 changed files with 116 additions and 128 deletions
|
|
@ -127,6 +127,9 @@ dependencies {
|
|||
implementation 'androidx.appcompat:appcompat:1.4.1'
|
||||
implementation 'androidx.core:core-ktx:1.7.0'
|
||||
implementation 'androidx.fragment:fragment-ktx:1.4.0'
|
||||
implementation('com.mapbox.maps:android:10.2.0') {
|
||||
exclude group: 'com.mapbox.mapboxsdk', module: 'mapbox-android-telemetry'
|
||||
}
|
||||
implementation 'androidx.cardview:cardview:1.0.0'
|
||||
implementation 'androidx.recyclerview:recyclerview:1.2.1'
|
||||
implementation 'androidx.constraintlayout:constraintlayout:2.1.3'
|
||||
|
|
@ -158,11 +161,11 @@ 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'
|
||||
|
|
|
|||
|
|
@ -6,6 +6,7 @@ import android.view.LayoutInflater
|
|||
import android.view.View
|
||||
import android.view.ViewGroup
|
||||
import androidx.core.content.ContextCompat
|
||||
import androidx.core.view.isVisible
|
||||
import androidx.fragment.app.activityViewModels
|
||||
import androidx.lifecycle.Observer
|
||||
import com.geeksville.android.GeeksvilleApplication
|
||||
|
|
@ -17,20 +18,17 @@ 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.mapboxsdk.style.layers.PropertyFactory.textAllowOverlap
|
||||
import com.mapbox.maps.MapView
|
||||
import com.mapbox.maps.CameraOptions
|
||||
import com.mapbox.maps.MapboxMap
|
||||
import com.mapbox.maps.Style
|
||||
import com.mapbox.maps.extension.style.expressions.generated.Expression
|
||||
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.generated.GeoJsonSource
|
||||
|
||||
|
||||
class MapFragment : ScreenFragment("Map"), Logging {
|
||||
|
|
@ -42,22 +40,19 @@ class MapFragment : ScreenFragment("Map"), Logging {
|
|||
private val labelLayerId = "label-layer"
|
||||
private val markerImageId = "my-marker-image"
|
||||
|
||||
private val nodePositions = GeoJsonSource(nodeSourceId)
|
||||
private val 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)
|
||||
|
||||
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()
|
||||
.textColor(Color.RED)
|
||||
.textVariableAnchor(arrayListOf(TextAnchor.TOP.toString()))
|
||||
.textJustify(TextJustify.AUTO)
|
||||
.textAllowOverlap(true)
|
||||
|
||||
|
||||
private fun onNodesChanged(map: MapboxMap, nodes: Collection<NodeInfo>) {
|
||||
|
|
@ -89,33 +84,34 @@ class MapFragment : ScreenFragment("Map"), Logging {
|
|||
}
|
||||
|
||||
|
||||
|
||||
nodePositions.setGeoJson(getCurrentNodes()) // Update node positions
|
||||
// nodePositions.setGeoJson(getCurrentNodes()) // Update node positions
|
||||
}
|
||||
|
||||
fun zoomToNodes(map: MapboxMap) {
|
||||
val nodesWithPosition =
|
||||
model.nodeDB.nodes.value?.values?.filter { it.validPosition != null }
|
||||
if (nodesWithPosition != null && nodesWithPosition.isNotEmpty()) {
|
||||
val update = 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)
|
||||
} 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)
|
||||
}
|
||||
map.animateCamera(update, 1000)
|
||||
// val update = 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)
|
||||
// } 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)
|
||||
// }
|
||||
// map.animateCamera(update, 1000)
|
||||
// }
|
||||
// }
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -141,7 +137,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,50 +147,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 = BitmapFactory.decodeResource(context.resources, R.drawable.ic_twotone_person_pin_24)
|
||||
val markerIcon =
|
||||
ContextCompat.getDrawable(
|
||||
requireActivity(),
|
||||
R.drawable.ic_twotone_person_pin_24
|
||||
)!!
|
||||
|
||||
map.setStyle(Style.OUTDOORS) { style ->
|
||||
style.addSource(nodePositions)
|
||||
style.addImage(markerImageId, markerIcon)
|
||||
style.addLayer(nodeLayer)
|
||||
style.addLayer(labelLayer)
|
||||
}
|
||||
map.loadStyleUri(Style.OUTDOORS)
|
||||
// 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.uiSettings.isRotateGesturesEnabled = 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)
|
||||
}
|
||||
|
||||
// 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()
|
||||
|
|
@ -205,11 +195,6 @@ class MapFragment : ScreenFragment("Map"), Logging {
|
|||
super.onStop()
|
||||
}
|
||||
|
||||
override fun onResume() {
|
||||
super.onResume()
|
||||
mapView?.onResume()
|
||||
}
|
||||
|
||||
override fun onDestroyView() {
|
||||
super.onDestroyView()
|
||||
mapView?.onDestroy()
|
||||
|
|
@ -217,18 +202,18 @@ class MapFragment : ScreenFragment("Map"), Logging {
|
|||
|
||||
override fun onSaveInstanceState(outState: Bundle) {
|
||||
mapView?.let {
|
||||
if (!it.isDestroyed)
|
||||
it.onSaveInstanceState(outState)
|
||||
super.onSaveInstanceState(outState)
|
||||
}
|
||||
super.onSaveInstanceState(outState)
|
||||
}
|
||||
|
||||
override fun onLowMemory() {
|
||||
mapView?.let {
|
||||
if (!it.isDestroyed)
|
||||
it.onLowMemory()
|
||||
}
|
||||
super.onLowMemory()
|
||||
mapView?.onLowMemory()
|
||||
}
|
||||
|
||||
override fun onDestroy() {
|
||||
super.onDestroy()
|
||||
mapView?.onDestroy()
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -2,16 +2,17 @@
|
|||
|
||||
<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
xmlns:mapbox="http://schemas.android.com/apk/res-auto"
|
||||
android:id="@+id/mapFrame"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent"
|
||||
android:id="@+id/mapFrame"> <!-- tab layout requires a unique ID -->
|
||||
android:layout_height="match_parent"> <!-- tab layout requires a unique ID -->
|
||||
|
||||
<com.mapbox.mapboxsdk.maps.MapView
|
||||
<com.mapbox.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>
|
||||
android:clickable="true"
|
||||
android:focusable="true"
|
||||
mapbox:mapbox_uiScrollGestures="true"
|
||||
mapbox:mapbox_uiZoomGestures="true"></com.mapbox.maps.MapView>
|
||||
|
||||
</FrameLayout>
|
||||
25
build.gradle
25
build.gradle
|
|
@ -6,7 +6,6 @@ buildscript {
|
|||
|
||||
repositories {
|
||||
google()
|
||||
// jcenter()
|
||||
mavenCentral()
|
||||
}
|
||||
dependencies {
|
||||
|
|
@ -34,30 +33,6 @@ buildscript {
|
|||
}
|
||||
}
|
||||
|
||||
allprojects {
|
||||
repositories {
|
||||
maven {
|
||||
// Per https://docs.mapbox.com/android/maps/guides/install/ we now need to signin to download mapbox lib
|
||||
url 'https://api.mapbox.com/downloads/v2/releases/maven'
|
||||
authentication {
|
||||
basic(BasicAuthentication)
|
||||
}
|
||||
credentials {
|
||||
// Do not change the username below.
|
||||
// This should always be `mapbox` (not your username).
|
||||
username = 'mapbox'
|
||||
// Use the secret token you stored in gradle.properties as the password
|
||||
password = project.properties['MAPBOX_DOWNLOADS_TOKEN'] ?: ""
|
||||
}
|
||||
}
|
||||
google()
|
||||
mavenCentral()
|
||||
// jcenter()
|
||||
maven { url 'https://jitpack.io' }
|
||||
//maven { url "https://plugins.gradle.org/m2/" }
|
||||
}
|
||||
}
|
||||
|
||||
task clean(type: Delete) {
|
||||
delete rootProject.buildDir
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,5 +1,29 @@
|
|||
include ':app'
|
||||
rootProject.name='Mesh Util'
|
||||
rootProject.name = 'Mesh Util'
|
||||
|
||||
include ':geeksville-androidlib'
|
||||
project(':geeksville-androidlib').projectDir = new File('geeksville-androidlib')
|
||||
|
||||
|
||||
dependencyResolutionManagement {
|
||||
repositoriesMode.set(RepositoriesMode.PREFER_SETTINGS)
|
||||
repositories {
|
||||
google()
|
||||
mavenCentral()
|
||||
// jcenter() // Warning: this repository is going to shut down soon
|
||||
maven {
|
||||
url 'https://api.mapbox.com/downloads/v2/releases/maven'
|
||||
authentication {
|
||||
basic(BasicAuthentication)
|
||||
}
|
||||
credentials {
|
||||
// Do not change the username below.
|
||||
// This should always be `mapbox` (not your username).
|
||||
username = "mapbox"
|
||||
// Use the secret token you stored in gradle.properties as the password
|
||||
password = System.properties["MAPBOX_DOWNLOADS_TOKEN"]
|
||||
}
|
||||
}
|
||||
maven { url 'https://jitpack.io' }
|
||||
}
|
||||
}
|
||||
Loading…
Add table
Add a link
Reference in a new issue