From 017095d171f1d85ff05cd32d8280d6340651d5a0 Mon Sep 17 00:00:00 2001 From: PWRxPSYCHO Date: Tue, 23 Aug 2022 20:05:19 -0400 Subject: [PATCH 01/20] Working on migrating to OSMdroid from Mapbox --- app/build.gradle | 8 +- .../com/geeksville/mesh/ui/MapFragment.kt | 745 +++--------------- app/src/main/res/layout/map_not_allowed.xml | 19 - app/src/main/res/layout/map_view.xml | 89 +-- app/src/main/res/values/arrays.xml | 16 +- app/src/main/res/values/strings.xml | 2 +- 6 files changed, 144 insertions(+), 735 deletions(-) delete mode 100644 app/src/main/res/layout/map_not_allowed.xml diff --git a/app/build.gradle b/app/build.gradle index b10034946..a26fcdf1a 100644 --- a/app/build.gradle +++ b/app/build.gradle @@ -88,7 +88,7 @@ android { kotlinOptions { jvmTarget = "1.8" - freeCompilerArgs += [ '-opt-in=kotlin.RequiresOptIn' ] + freeCompilerArgs += ['-opt-in=kotlin.RequiresOptIn'] } lint { abortOnError false @@ -140,6 +140,9 @@ dependencies { kapt "androidx.room:room-compiler:$room_version" kapt "com.google.dagger:hilt-compiler:$hilt_version" + //OSMAND + implementation 'org.osmdroid:osmdroid-android:6.1.14' + // optional - Kotlin Extensions and Coroutines support for Room implementation "androidx.room:room-ktx:$room_version" @@ -166,9 +169,6 @@ dependencies { // implementation 'com.google.android.things:androidthings:1.0' implementation 'com.github.mik3y:usb-serial-for-android:3.4.6' - // mapbox - implementation 'com.mapbox.maps:android:10.2.0' - // location services implementation 'com.google.android.gms:play-services-location:19.0.1' // For Google Sign-In (owner name accesss) diff --git a/app/src/main/java/com/geeksville/mesh/ui/MapFragment.kt b/app/src/main/java/com/geeksville/mesh/ui/MapFragment.kt index 220554801..1042bc7dc 100644 --- a/app/src/main/java/com/geeksville/mesh/ui/MapFragment.kt +++ b/app/src/main/java/com/geeksville/mesh/ui/MapFragment.kt @@ -1,680 +1,189 @@ package com.geeksville.mesh.ui -import android.app.AlertDialog + import android.content.Context -import android.content.SharedPreferences -import android.graphics.Color import android.os.Bundle import android.view.LayoutInflater import android.view.View import android.view.ViewGroup -import android.widget.EditText -import android.widget.Toast 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 import com.geeksville.android.Logging +import com.geeksville.mesh.BuildConfig import com.geeksville.mesh.NodeInfo import com.geeksville.mesh.R -import com.geeksville.mesh.databinding.MapNotAllowedBinding -import com.geeksville.mesh.databinding.MapViewBinding import com.geeksville.mesh.model.UIViewModel import com.geeksville.util.formatAgo -import com.mapbox.bindgen.Value -import com.mapbox.common.* -import com.mapbox.geojson.* -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.addPersistentLayer -import com.mapbox.maps.extension.style.layers.generated.LineLayer -import com.mapbox.maps.extension.style.layers.generated.SymbolLayer -import com.mapbox.maps.extension.style.layers.generated.lineLayer -import com.mapbox.maps.extension.style.layers.properties.generated.* -import com.mapbox.maps.extension.style.sources.addSource -import com.mapbox.maps.extension.style.sources.generated.GeoJsonSource -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.OnMapLongClickListener -import com.mapbox.maps.plugin.gestures.gestures import dagger.hilt.android.AndroidEntryPoint -import kotlin.math.cos -import kotlin.math.sin +import org.osmdroid.api.IMapController +import org.osmdroid.config.Configuration +import org.osmdroid.tileprovider.tilesource.OnlineTileSourceBase +import org.osmdroid.tileprovider.tilesource.TileSourceFactory +import org.osmdroid.util.GeoPoint +import org.osmdroid.views.CustomZoomButtonsController +import org.osmdroid.views.MapView +import org.osmdroid.views.overlay.CopyrightOverlay +import org.osmdroid.views.overlay.OverlayItem @AndroidEntryPoint class MapFragment : ScreenFragment("Map"), Logging { - - private val tileStore: TileStore by lazy { - TileStore.create().also { - // Set default access token for the created tile store instance - it.setOption( - TileStoreOptions.MAPBOX_ACCESS_TOKEN, - TileDataDomain.MAPS, - Value(getString(R.string.mapbox_access_token)) - ) - } - } - - /** - * DEVELOPER OPTION TO ENABLE OFFLINE MAPS - * Set this variable to true to enable offline maps - */ - //___________________________________________________ - private val offlineEnabled = false - //___________________________________________________ - - - private val resourceOptions: ResourceOptions by lazy { - ResourceOptions.Builder().applyDefaultParams(requireContext()).tileStore(tileStore).build() - } - private val offlineManager: OfflineManager by lazy { - OfflineManager(resourceOptions) - } - - private lateinit var binding: MapViewBinding - private lateinit var mapNotAllowedBinding: MapNotAllowedBinding - private var userStyleURI: String? = null - - private lateinit var geoJsonSource: GeoJsonSource - private lateinit var lineLayer: LineLayer - - private var point: Point? = null - + private lateinit var map: MapView + private lateinit var mapController: IMapController + private lateinit var nodePositions: List private val model: UIViewModel by activityViewModels() - private val nodeSourceId = "node-positions" - private val nodeLayerId = "node-layer" - private val labelLayerId = "label-layer" - private val markerImageId = "my-marker-image" - private val userPointImageId = "user-image" - private val boundingBoxId = "bounding-box-id" - private val lineLayerId = "line-layer-id" - private var stylePackCancelable: Cancelable? = null - private var tilePackCancelable: Cancelable? = null + private val defaultLat = 38.8976763 + private val defaultLong = -77.0365298 + private val defaultZoomLevel = 6.0 + private val defaultZoomSpeed = 3000L + private val defaultMinZoom = 3.0 - private lateinit var squareRegion: Geometry - - private val userTouchPositionId = "user-touch-position" - private val userTouchLayerId = "user-touch-layer" - private var nodePositions = GeoJsonSource(GeoJsonSource.Builder(nodeSourceId)) - - private var tileRegionDownloadSuccess = false - private var stylePackDownloadSuccess = false - private val userTouchPosition = GeoJsonSource(GeoJsonSource.Builder(userTouchPositionId)) - - - private val nodeLayer = SymbolLayer(nodeLayerId, nodeSourceId) - .iconImage(markerImageId) - .iconAnchor(IconAnchor.BOTTOM) - .iconAllowOverlap(true) - - private val userTouchLayer = SymbolLayer(userTouchLayerId, userTouchPositionId) - .iconImage(userPointImageId) - .iconAnchor(IconAnchor.BOTTOM) - - 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(nodes: Collection) { - val nodesWithPosition = nodes.filter { it.validPosition != null } - - /** - * Using the latest nodedb, generate geojson features - */ - fun getCurrentNodes(): FeatureCollection { - // Find all nodes with valid locations - - val locations = nodesWithPosition.map { node -> - val p = node.position!! - debug("Showing on map: $node") - - val f = Feature.fromGeometry( - Point.fromLngLat( - p.longitude, - p.latitude - ) - ) - node.user?.let { - f.addStringProperty("name", it.longName + " " + formatAgo(p.time)) - } - f - } - - return FeatureCollection.fromFeatures(locations) - } - nodePositions.featureCollection(getCurrentNodes()) - } - - private fun zoomToNodes(map: MapboxMap) { - val points: MutableList = mutableListOf() - val nodesWithPosition = - model.nodeDB.nodes.value?.values?.filter { it.validPosition != null } - if (nodesWithPosition != null && nodesWithPosition.isNotEmpty()) { - val unit = if (nodesWithPosition.size >= 2) { - - // Multiple nodes, make them all fit on the map view - 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!! - points.add(Point.fromLngLat(it.longitude, it.latitude)) - map.cameraForCoordinates(points) - cameraOptions { - this.zoom(9.0) - this.center(points[0]) - } - } - map.flyTo( - unit, - MapAnimationOptions.mapAnimationOptions { duration(1000) }) - } - } override fun onCreateView( inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle? ): View { - // We can't allow mapbox if user doesn't want analytics - return if ((requireContext().applicationContext as GeeksvilleApplication).isAnalyticsAllowed) { - // Mapbox Access token - binding = MapViewBinding.inflate(inflater, container, false) - binding.root - } else { - mapNotAllowedBinding = MapNotAllowedBinding.inflate(inflater, container, false) - mapNotAllowedBinding.root - } + return inflater.inflate(R.layout.map_view, container, false) } - var mapView: MapView? = null + private fun onNodesChanged(nodes: Collection) { + val nodesWithPosition = nodes.filter { it.validPosition != null } + /** + * Using the latest nodedb, generate GeoPoint + */ + // Find all nodes with valid locations - private fun removeOfflineRegions() { - // Remove the tile region with the tile region ID. - // Note this will not remove the downloaded tile packs, instead, it will just mark the tileset - // not a part of a tile region. The tiles still exists as a predictive cache in TileStore. - tileStore.removeTileRegion(TILE_REGION_ID) + val locations = nodesWithPosition.map { node -> + val p = node.position!! + debug("Showing on map: $node") + val f = GeoPoint(p.latitude, p.longitude) - // Set the disk quota to zero, so that tile regions are fully evicted - // when removed. The TileStore is also used when `ResourceOptions.isLoadTilePacksFromNetwork` - // is `true`, and also by the Navigation SDK. - // This removes the tiles that do not belong to any tile regions. - tileStore.setOption(TileStoreOptions.DISK_QUOTA, Value(0)) - - // Remove the style pack with the style url. - // Note this will not remove the downloaded style pack, instead, it will just mark the resources - // not a part of the existing style pack. The resources still exists as disk cache. - - if (userStyleURI != null) { - offlineManager.removeStylePack(userStyleURI!!) - mapView?.getMapboxMap()?.loadStyleUri(loadMapStyleFromPref()) - } else { - offlineManager.removeStylePack(mapView?.getMapboxMap()?.getStyle()?.styleURI.toString()) - mapView?.getMapboxMap()?.loadStyleUri(loadMapStyleFromPref()) - } - MapboxMap.clearData(resourceOptions) { - it.error?.let { error -> - debug(error) + node.user?.let { + OverlayItem("name", it.longName + " " + formatAgo(p.time), f) } + f } - updateStylePackDownloadProgress(0, 0) - updateTileRegionDownloadProgress(0, 0) + nodePositions = locations } - /** - * 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?.isVisible == true - override fun onViewCreated(viewIn: View, savedInstanceState: Bundle?) { super.onViewCreated(viewIn, savedInstanceState) + Configuration.getInstance().userAgentValue = + BuildConfig.APPLICATION_ID // Required to get online tiles - // We might not have a real mapview if running with analytics - if ((requireContext().applicationContext as GeeksvilleApplication).isAnalyticsAllowed) { -// binding.fabStyleToggle.setOnClickListener { -// //TODO: Setup Style menu for satellite view, street view, & outdoor view -// } - binding.downloadRegion.setOnClickListener { - // Display menu for download region - this.downloadRegionDialogFragment() + map = viewIn.findViewById(R.id.map) as MapView + + /** + * Copyright layer required + */ + //////////////////////////////////////////////////////////// + val copyrightNotice: String = + map.tileProvider.tileSource.copyrightNotice + val copyrightOverlay = CopyrightOverlay(context) + copyrightOverlay.setCopyrightNotice(copyrightNotice) + map.overlays.add(copyrightOverlay) + /////////////////////////////////////////////////////////// + + setupMapProperties() + if (view != null) { + val markerIcon = + ContextCompat.getDrawable( + requireActivity(), + R.drawable.ic_twotone_person_pin_24 + )!!.toBitmap() + + + // Provide initial positions + model.nodeDB.nodes.value?.let { nodes -> + onNodesChanged(nodes.values) } - val vIn = viewIn.findViewById(R.id.mapView) - mapView = vIn - mapView?.let { v -> - - // 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) - - 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.loadStyleUri(loadMapStyleFromPref()) { - if (it.isStyleLoaded) { - it.addSource(nodePositions) - it.addImage(markerImageId, markerIcon) - it.addPersistentLayer(nodeLayer) - it.addPersistentLayer(labelLayer) - } - } - - v.gestures.rotateEnabled = false - if (offlineEnabled) { - v.gestures.addOnMapLongClickListener(this.longClick) - } - - // Provide initial positions - model.nodeDB.nodes.value?.let { nodes -> - onNodesChanged(nodes.values) - } - } - // Any times nodes change update our map - model.nodeDB.nodes.observe(viewLifecycleOwner, Observer { nodes -> - if (isViewVisible) - onNodesChanged(nodes.values) - }) - //viewAnnotationManager = v.viewAnnotationManager - zoomToNodes(map) + zoomToNodes(mapController) + // Any times nodes change update our map + model.nodeDB.nodes.observe(viewLifecycleOwner) { nodes -> + onNodesChanged(nodes.values) } + + } + + + } + + private fun setupMapProperties() { + if (this::map.isInitialized) { + map.setTileSource(loadOnlineTileSourceBase()) + map.minZoomLevel = defaultMinZoom + map.setMultiTouchControls(true) // Sets gesture controls to true + map.zoomController.setVisibility(CustomZoomButtonsController.Visibility.NEVER) // Disables default +/- button for zooming + mapController = map.controller + val point = GeoPoint(defaultLat, defaultLong) //White House Coordinates, Washington DC + mapController.animateTo(point, defaultZoomLevel, defaultZoomSpeed) } } - private fun downloadOfflineRegion(styleURI: String = "") { - - val style = styleURI.ifEmpty { - mapView?.getMapboxMap() - ?.getStyle()?.styleURI.toString() - } - - if (OfflineSwitch.getInstance().isMapboxStackConnected) { - - // By default, users may download up to 250MB of data for offline use without incurring - // additional charges. This limit is subject to change during the beta. - - // - - - - - - - - - - // 1. Create style package with loadStylePack() call. - - // A style pack (a Style offline package) contains the loaded style and its resources: loaded - // sources, fonts, sprites. Style packs are identified with their style URI. - - // Style packs are stored in the disk cache database, but their resources are not subject to - // the data eviction algorithm and are not considered when calculating the disk cache size. - - binding.stylePackDownloadProgress.visibility = View.VISIBLE - binding.stylePackText.visibility = View.VISIBLE - stylePackCancelable = offlineManager.loadStylePack( - style, - // Build Style pack load options - StylePackLoadOptions.Builder() - .glyphsRasterizationMode(GlyphsRasterizationMode.IDEOGRAPHS_RASTERIZED_LOCALLY) - .metadata(Value(STYLE_PACK_METADATA)) - .build(), - { progress -> - updateStylePackDownloadProgress( - progress.completedResourceCount, - progress.requiredResourceCount, - ) - }, - { expected -> - if (expected.isValue) { - expected.value?.let { stylePack -> - // Style pack download finishes successfully - debug("StylePack downloaded: $stylePack") - if (binding.stylePackDownloadProgress.progress == binding.stylePackDownloadProgress.max) { - debug("Style pack download complete") - binding.stylePackText.visibility = View.INVISIBLE - binding.stylePackDownloadProgress.visibility = View.INVISIBLE - stylePackDownloadSuccess = true - } else { - debug("Waiting for tile region download to be finished.") - } - } - } - expected.error?.let { - stylePackDownloadSuccess = false - // Handle error occurred during the style pack download. - binding.stylePackText.visibility = View.INVISIBLE - binding.stylePackDownloadProgress.visibility = View.INVISIBLE - debug("StylePackError: $it") - } - } - ) - - // - - - - - - - - - - // 2. Create a tile region with tiles for the outdoors style - - // A Tile Region represents an identifiable geographic tile region with metadata, consisting of - // a set of tiles packs that cover a given area (a polygon). Tile Regions allow caching tiles - // packs in an explicit way: By creating a Tile Region, developers can ensure that all tiles in - // that region will be downloaded and remain cached until explicitly deleted. - - // Creating a Tile Region requires supplying a description of the area geometry, the tilesets - // and zoom ranges of the tiles within the region. - - // The tileset descriptor encapsulates the tile-specific data, such as which tilesets, zoom ranges, - // pixel ratio etc. the cached tile packs should have. It is passed to the Tile Store along with - // the region area geometry to load a new Tile Region. - - // The OfflineManager is responsible for creating tileset descriptors for the given style and zoom range. - - val tilesetDescriptor = offlineManager.createTilesetDescriptor( - TilesetDescriptorOptions.Builder() - .styleURI(style) - .minZoom(0) - .maxZoom(10) - .build() - ) - // Use the the default TileStore to load this region. You can create custom TileStores are are - // unique for a particular file path, i.e. there is only ever one TileStore per unique path. - - // Note that the TileStore path must be the same with the TileStore used when initialise the MapView. - binding.tilePackText.visibility = View.VISIBLE - binding.tilePackDownloadProgress.visibility = View.VISIBLE - tilePackCancelable = tileStore.loadTileRegion( - TILE_REGION_ID, // Make this dynamic - TileRegionLoadOptions.Builder() - .geometry(squareRegion) - .descriptors(listOf(tilesetDescriptor)) - .metadata(Value(TILE_REGION_METADATA)) - .acceptExpired(true) - .networkRestriction(NetworkRestriction.NONE) - .build(), - { progress -> - updateTileRegionDownloadProgress( - progress.completedResourceCount, - progress.requiredResourceCount, + private fun zoomToNodes(controller: IMapController) { + val points: MutableList = mutableListOf() + val nodesWithPosition = + model.nodeDB.nodes.value?.values?.filter { it.validPosition != null } + if ((nodesWithPosition != null) && nodesWithPosition.isNotEmpty()) { + val unit = if (nodesWithPosition.size >= 2) { + // Multiple nodes, make them all fit on the map view + nodesWithPosition.forEach { + points.add( + GeoPoint( + it.position!!.longitude, + it.position!!.latitude + ) ) } - ) { expected -> - if (expected.isValue) { - // Tile pack download finishes successfully - expected.value?.let { region -> - debug("TileRegion downloaded: $region") - if (binding.tilePackDownloadProgress.progress == binding.tilePackDownloadProgress.max) { - debug("Finished tilepack download") - binding.tilePackDownloadProgress.visibility = View.INVISIBLE - binding.tilePackText.visibility = View.INVISIBLE - tileRegionDownloadSuccess = true - - } else { - debug("Waiting for style pack download to be finished.") - } - } - } - expected.error?.let { - tileRegionDownloadSuccess = false - // Handle error occurred during the tile region download. - binding.tilePackDownloadProgress.visibility = View.INVISIBLE - binding.tilePackText.visibility = View.INVISIBLE - debug("TileRegionError: $it") - } - } - } else { - Toast.makeText( - requireContext(), - R.string.download_region_connection_alert, - Toast.LENGTH_LONG - ).show() - } - } - - /** - * OnLongClick of the map set a position marker. - * If a user long-clicks again, the position of the first marker will be updated - */ - private val longClick = OnMapLongClickListener { - val userDefinedPointImg = - ContextCompat.getDrawable( - requireActivity(), - R.drawable.baseline_location_on_white_24dp - )!! - .toBitmap() - point = Point.fromLngLat(it.longitude(), it.latitude()) - - - /* - Calculate region from user specified position. - 5 miles NE,NW,SE,SW from user center point. - 25 Sq Mile Region - */ - //____________________________________________________________________________________________ - val topRight = calculateCoordinate(45.0, point?.latitude()!!, point?.longitude()!!) - val topLeft = calculateCoordinate(135.0, point?.latitude()!!, point?.longitude()!!) - val bottomLeft = calculateCoordinate(225.0, point?.latitude()!!, point?.longitude()!!) - val bottomRight = calculateCoordinate(315.0, point?.latitude()!!, point?.longitude()!!) - //____________________________________________________________________________________________ - - val pointList = listOf(topRight, topLeft, bottomLeft, bottomRight, topRight) - - squareRegion = LineString.fromLngLats(pointList) - - geoJsonSource = geoJsonSource(boundingBoxId) { - geometry(squareRegion) - } - lineLayer = lineLayer(lineLayerId, boundingBoxId) { - lineCap(LineCap.ROUND) - lineJoin(LineJoin.MITER) - lineOpacity(0.7) - lineWidth(1.5) - lineColor("#888") - } - - if (point != null) { - binding.downloadRegion.visibility = View.VISIBLE - } - - mapView?.getMapboxMap()?.getStyle()?.let { style -> - userTouchPosition.geometry(point!!) - if (!style.styleLayerExists(userTouchLayerId)) { - style.addImage(userPointImageId, userDefinedPointImg) - style.addSource(userTouchPosition) - style.addSource(geoJsonSource) - style.addPersistentLayer(lineLayer) - style.addLayer(userTouchLayer) + // TODO: zoom to the middle of all points + controller.animateTo(points[0]) } else { - style.removeStyleLayer(lineLayerId) - style.removeStyleSource(boundingBoxId) - style.addSource(geoJsonSource) - style.addLayer(lineLayer) - } - } - mapView?.getMapboxMap().also { mapboxMap -> - mapboxMap?.flyTo( - CameraOptions.Builder() - .zoom(ZOOM) - .center(point) - .build(), MapAnimationOptions.mapAnimationOptions { duration(1000) }) - } - return@OnMapLongClickListener true - } - - /** - * Find's coordinates (Lat,Lon) a specified distance from given (lat,lon) using degrees to determine direction - * @param degrees degree of desired position from current position. (center point is 0,0 and desired point, top right corner, is 45 degrees from 0,0) - * @param lat latitude position (current position lat) - * @param lon longitude position (current position lon) - * @return Point - */ - private fun calculateCoordinate(degrees: Double, lat: Double, lon: Double): Point { - val deg = Math.toRadians(degrees) - val distancesInMeters = - 1609.344 * 2.5 // 1609.344 is 1 mile in meters -> multiplier will be user specified up to a max of 10 - val radiusOfEarthInMeters = 6378137 - val x = - lon + (180 / Math.PI) * (distancesInMeters / radiusOfEarthInMeters) * cos( - deg - ) - val y = - lat + (180 / Math.PI) * (distancesInMeters / radiusOfEarthInMeters) * sin(deg) - return Point.fromLngLat(x, y) - } - - private fun updateStylePackDownloadProgress( - progress: Long, - max: Long, - ) { - binding.stylePackDownloadProgress.max = max.toInt() - binding.stylePackDownloadProgress.progress = progress.toInt() - } - - private fun updateTileRegionDownloadProgress( - progress: Long, - max: Long, - ) { - binding.tilePackDownloadProgress.max = max.toInt() - binding.tilePackDownloadProgress.progress = progress.toInt() - } - - companion object { - private const val ZOOM = 12.5 - private const val TILE_REGION_ID = "tile-region" - private const val STYLE_PACK_METADATA = "outdoor-style-pack" - private const val TILE_REGION_METADATA = "outdoor-tile-region" - } - - private fun downloadRegionDialogFragment() { - val mapDownloadView = layoutInflater.inflate(R.layout.dialog_map_download, null) - val uri = mapDownloadView.findViewById(R.id.uri) - val downloadRegionDialogFragment = AlertDialog.Builder(context) - - - downloadRegionDialogFragment.setView(mapDownloadView) - .setTitle(R.string.download_region_dialog_title) - .setMultiChoiceItems( - R.array.MapMenuCheckbox, - null, - ) { _, _, isChecked -> - if (isChecked) { - if (!uri.isVisible) { - uri.visibility = - View.VISIBLE - } - } else { - if (uri.isVisible) { - uri.visibility = - View.GONE - } - } - } - .setPositiveButton( - R.string.save_btn, null - ) - .setNeutralButton(R.string.view_region_btn) { _, _ -> - if (tileRegionDownloadSuccess && stylePackDownloadSuccess) { - mapView?.getMapboxMap().also { - it?.flyTo( - CameraOptions.Builder() - .zoom(ZOOM) - .center(point) - .build(), - MapAnimationOptions.mapAnimationOptions { duration(1000) }) - if (userStyleURI != null) { - it?.loadStyleUri(userStyleURI.toString()) - } else { - it?.getStyle().also { style -> - style?.removeStyleImage(userPointImageId) - } - } - } - } else { - Toast.makeText( - requireContext(), - R.string.no_download_region_alert, - Toast.LENGTH_SHORT - ).show() - } - } - .setNegativeButton( - R.string.cancel - ) { dialog, _ -> - mapView?.getMapboxMap()?.getStyle { style -> - point = null - userStyleURI = null - style.removeStyleLayer(lineLayerId) - style.removeStyleSource(boundingBoxId) - style.removeStyleLayer(userTouchLayerId) - style.removeStyleSource(userTouchPositionId) - style.removeStyleImage(userPointImageId) - } - binding.downloadRegion.visibility = View.INVISIBLE - - removeOfflineRegions() //TODO: Add to offline manager window - dialog.cancel() - } - - val dialog = downloadRegionDialogFragment.create() - dialog.show() - dialog.getButton(AlertDialog.BUTTON_POSITIVE).setOnClickListener { - if (uri.isVisible) { - if (uri.text.isNotEmpty()) { - // Save URI - userStyleURI = uri.text.toString() - uri.setText("") // clear text - - downloadOfflineRegion(userStyleURI!!) - dialog.dismiss() - } else { - Toast.makeText( - requireContext(), - R.string.style_uri_empty_alert, - Toast.LENGTH_SHORT - ).show() - } - } else { - downloadOfflineRegion() - dialog.dismiss() + // Only one node, just zoom in on it + val it = nodesWithPosition[0].position!! + points.add(GeoPoint(it.longitude, it.latitude)) + controller.animateTo(points[0], defaultZoomLevel, defaultZoomSpeed) } } } - private fun loadMapStyleFromPref():String { + private fun loadOnlineTileSourceBase(): OnlineTileSourceBase { val prefs = context?.getSharedPreferences("ui-prefs", Context.MODE_PRIVATE) - val mapStyleId = prefs?.getInt("map_style_id", 1) - debug("mapStyleId from prefs: $mapStyleId") - val mapStyle = when (mapStyleId) { - 0 -> Style.MAPBOX_STREETS - 1 -> Style.OUTDOORS - 2 -> Style.LIGHT - 3 -> Style.DARK - 4 -> Style.SATELLITE - 5 -> Style.SATELLITE_STREETS - 6 -> Style.TRAFFIC_DAY - 7 -> Style.TRAFFIC_NIGHT - else -> Style.OUTDOORS + val mapSourceId = prefs?.getInt("map_style_id", 1) + debug("mapStyleId from prefs: $mapSourceId") + val mapSource = when (mapSourceId) { + 0 -> TileSourceFactory.MAPNIK + 1 -> TileSourceFactory.USGS_TOPO + 2 -> TileSourceFactory.USGS_SAT + 3 -> TileSourceFactory.OpenTopo + 4 -> TileSourceFactory.ROADS_OVERLAY_NL + 5 -> TileSourceFactory.CLOUDMADESMALLTILES + 6 -> TileSourceFactory.ChartbundleENRH + 7 -> TileSourceFactory.ChartbundleWAC + else -> TileSourceFactory.MAPNIK } - return mapStyle + return mapSource } + override fun onPause() { + map.onPause() + super.onPause() + } + + override fun onResume() { + super.onResume() + map.onResume() + } + + override fun onDestroy() { + super.onDestroy() + map.onDetach() + } } diff --git a/app/src/main/res/layout/map_not_allowed.xml b/app/src/main/res/layout/map_not_allowed.xml deleted file mode 100644 index b90ab1204..000000000 --- a/app/src/main/res/layout/map_not_allowed.xml +++ /dev/null @@ -1,19 +0,0 @@ - - - - - \ No newline at end of file diff --git a/app/src/main/res/layout/map_view.xml b/app/src/main/res/layout/map_view.xml index 7b1c190c3..a1a6e1265 100644 --- a/app/src/main/res/layout/map_view.xml +++ b/app/src/main/res/layout/map_view.xml @@ -5,93 +5,12 @@ android:layout_width="match_parent" android:layout_height="match_parent"> - - - - - - - - - - - - - - - - - - - - - - - - - - - + tools:layout_editor_absoluteX="110dp" + tools:layout_editor_absoluteY="16dp" /> \ No newline at end of file diff --git a/app/src/main/res/values/arrays.xml b/app/src/main/res/values/arrays.xml index 38e18b013..357dc973a 100644 --- a/app/src/main/res/values/arrays.xml +++ b/app/src/main/res/values/arrays.xml @@ -63,13 +63,13 @@ tr - Streets - Outdoors - Light - Dark - Satellite - Satellite Streets - Navigation Day - Navigation Night + OpenStreetMap + USGS TOPO + USGS Satellite + OpenTopo + Roads Overlay NL + Cloud Made Small Tiles + Chartbundle ENRH + Chartbundle WAC \ No newline at end of file diff --git a/app/src/main/res/values/strings.xml b/app/src/main/res/values/strings.xml index 58a385dee..74edf5905 100644 --- a/app/src/main/res/values/strings.xml +++ b/app/src/main/res/values/strings.xml @@ -140,7 +140,7 @@ Unable to download style pack Language (restart needed) System default - Map style + Map Source Resend Shutdown Reboot From 269a6df35316f673de86cb9df19fa0f3636f6ec4 Mon Sep 17 00:00:00 2001 From: PWRxPSYCHO Date: Tue, 23 Aug 2022 20:27:14 -0400 Subject: [PATCH 02/20] Added zoom for multiple GeoPoints --- app/src/main/java/com/geeksville/mesh/ui/MapFragment.kt | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/app/src/main/java/com/geeksville/mesh/ui/MapFragment.kt b/app/src/main/java/com/geeksville/mesh/ui/MapFragment.kt index 1042bc7dc..415b9cddd 100644 --- a/app/src/main/java/com/geeksville/mesh/ui/MapFragment.kt +++ b/app/src/main/java/com/geeksville/mesh/ui/MapFragment.kt @@ -20,6 +20,7 @@ import org.osmdroid.api.IMapController import org.osmdroid.config.Configuration import org.osmdroid.tileprovider.tilesource.OnlineTileSourceBase import org.osmdroid.tileprovider.tilesource.TileSourceFactory +import org.osmdroid.util.BoundingBox import org.osmdroid.util.GeoPoint import org.osmdroid.views.CustomZoomButtonsController import org.osmdroid.views.MapView @@ -141,8 +142,7 @@ class MapFragment : ScreenFragment("Map"), Logging { ) ) } - // TODO: zoom to the middle of all points - controller.animateTo(points[0]) + map.zoomToBoundingBox(BoundingBox.fromGeoPoints(points), true) } else { // Only one node, just zoom in on it val it = nodesWithPosition[0].position!! From a84eb7e4b60235f530a761c88e2a681c45e1d3dc Mon Sep 17 00:00:00 2001 From: PWRxPSYCHO Date: Tue, 23 Aug 2022 22:32:32 -0400 Subject: [PATCH 03/20] Setting up markers for map, Looking into options of showing text --- .../com/geeksville/mesh/ui/MapFragment.kt | 27 +++++++++---------- 1 file changed, 12 insertions(+), 15 deletions(-) diff --git a/app/src/main/java/com/geeksville/mesh/ui/MapFragment.kt b/app/src/main/java/com/geeksville/mesh/ui/MapFragment.kt index 415b9cddd..753c4f1b0 100644 --- a/app/src/main/java/com/geeksville/mesh/ui/MapFragment.kt +++ b/app/src/main/java/com/geeksville/mesh/ui/MapFragment.kt @@ -7,7 +7,6 @@ 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.fragment.app.activityViewModels import com.geeksville.android.Logging import com.geeksville.mesh.BuildConfig @@ -25,7 +24,7 @@ import org.osmdroid.util.GeoPoint import org.osmdroid.views.CustomZoomButtonsController import org.osmdroid.views.MapView import org.osmdroid.views.overlay.CopyrightOverlay -import org.osmdroid.views.overlay.OverlayItem +import org.osmdroid.views.overlay.Marker @AndroidEntryPoint @@ -33,7 +32,6 @@ class MapFragment : ScreenFragment("Map"), Logging { private lateinit var map: MapView private lateinit var mapController: IMapController - private lateinit var nodePositions: List private val model: UIViewModel by activityViewModels() @@ -59,17 +57,25 @@ class MapFragment : ScreenFragment("Map"), Logging { */ // Find all nodes with valid locations - val locations = nodesWithPosition.map { node -> + nodesWithPosition.map { node -> val p = node.position!! debug("Showing on map: $node") val f = GeoPoint(p.latitude, p.longitude) node.user?.let { - OverlayItem("name", it.longName + " " + formatAgo(p.time), f) + val marker = Marker(map) + marker.title = it.longName + " " + formatAgo(p.time) + marker.setAnchor(Marker.ANCHOR_BOTTOM, Marker.ANCHOR_CENTER) + marker.position = f + marker.icon = ContextCompat.getDrawable( + requireActivity(), + R.drawable.ic_twotone_person_pin_24 + ) + map.overlays.add(marker) + map.invalidate() } f } - nodePositions = locations } override fun onViewCreated(viewIn: View, savedInstanceState: Bundle?) { @@ -92,14 +98,6 @@ class MapFragment : ScreenFragment("Map"), Logging { setupMapProperties() if (view != null) { - val markerIcon = - ContextCompat.getDrawable( - requireActivity(), - R.drawable.ic_twotone_person_pin_24 - )!!.toBitmap() - - - // Provide initial positions model.nodeDB.nodes.value?.let { nodes -> onNodesChanged(nodes.values) } @@ -117,7 +115,6 @@ class MapFragment : ScreenFragment("Map"), Logging { private fun setupMapProperties() { if (this::map.isInitialized) { - map.setTileSource(loadOnlineTileSourceBase()) map.minZoomLevel = defaultMinZoom map.setMultiTouchControls(true) // Sets gesture controls to true map.zoomController.setVisibility(CustomZoomButtonsController.Visibility.NEVER) // Disables default +/- button for zooming From b8ef088d8e5042a8d83994618fb87b1fbe4f389d Mon Sep 17 00:00:00 2001 From: PWRxPSYCHO Date: Tue, 23 Aug 2022 22:49:46 -0400 Subject: [PATCH 04/20] Remove all references to MapBox, MapBox tokens, and credentials --- .github/workflows/android.yml | 10 ----- .github/workflows/release.yml | 2 - README.md | 45 +++++++++++----------- app/build.gradle | 1 - app/proguard-rules.pro | 3 -- app/src/main/res/values-cs/strings.xml | 3 -- app/src/main/res/values-el/strings.xml | 3 -- app/src/main/res/values-fr/strings.xml | 3 -- app/src/main/res/values-ga/strings.xml | 4 -- app/src/main/res/values-ht/strings.xml | 1 - app/src/main/res/values-hu/strings.xml | 3 -- app/src/main/res/values-it/strings.xml | 4 -- app/src/main/res/values-ja/strings.xml | 3 -- app/src/main/res/values-ko-rKR/strings.xml | 1 - app/src/main/res/values-nl/strings.xml | 3 -- app/src/main/res/values-no/strings.xml | 3 -- app/src/main/res/values-pl/strings.xml | 3 -- app/src/main/res/values-pt-rBR/strings.xml | 3 -- app/src/main/res/values-pt/strings.xml | 3 -- app/src/main/res/values-ro/strings.xml | 3 -- app/src/main/res/values-ru/strings.xml | 3 -- app/src/main/res/values-sk/strings.xml | 3 -- app/src/main/res/values-sl/strings.xml | 1 - app/src/main/res/values-tr/strings.xml | 3 -- app/src/main/res/values-zh/strings.xml | 3 -- app/src/main/res/values/strings.xml | 3 -- build.gradle | 14 ------- 27 files changed, 22 insertions(+), 112 deletions(-) diff --git a/.github/workflows/android.yml b/.github/workflows/android.yml index 70fe2759d..cf79f7891 100644 --- a/.github/workflows/android.yml +++ b/.github/workflows/android.yml @@ -16,16 +16,6 @@ jobs: with: submodules: 'recursive' - - name: Load secrets - run: | - rm ./app/src/main/res/values/mapbox-token.xml - echo -e "\n $MAPBOX_ACCESS_TOKEN\n" > ./app/src/main/res/values/mapbox-token.xml - mkdir -p ~/.gradle - echo "MAPBOX_DOWNLOADS_TOKEN=$MAPBOX_DOWNLOADS_TOKEN" >>~/.gradle/gradle.properties - env: - MAPBOX_ACCESS_TOKEN: ${{ secrets.MAPBOX_ACCESS_TOKEN }} - MAPBOX_DOWNLOADS_TOKEN: ${{ secrets.MAPBOX_DOWNLOADS_TOKEN }} - - name: Mock files for CI run: | rm ./app/google-services.json diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml index 9f8787afb..babebda34 100644 --- a/.github/workflows/release.yml +++ b/.github/workflows/release.yml @@ -29,8 +29,6 @@ jobs: echo "$KEYSTORE_PROPERTIES" > ./keystore.properties env: GSERVICES: ${{ secrets.GSERVICES }} - MAPBOX_ACCESS_TOKEN: ${{ secrets.MAPBOX_ACCESS_TOKEN }} - MAPBOX_DOWNLOADS_TOKEN: ${{ secrets.MAPBOX_DOWNLOADS_TOKEN }} KEYSTORE: ${{ secrets.KEYSTORE }} KEYSTORE_FILENAME: ${{ secrets.KEYSTORE_FILENAME }} KEYSTORE_PROPERTIES: ${{ secrets.KEYSTORE_PROPERTIES }} diff --git a/README.md b/README.md index 87f94d701..19927744c 100644 --- a/README.md +++ b/README.md @@ -6,51 +6,50 @@ [![Fiscal Contributors](https://opencollective.com/meshtastic/tiers/badge.svg?label=Fiscal%20Contributors&color=deeppink)](https://opencollective.com/meshtastic/) [![Vercel](https://img.shields.io/static/v1?label=Powered%20by&message=Vercel&style=flat&logo=vercel&color=000000)](https://vercel.com?utm_source=meshtastic&utm_campaign=oss) -This is a tool for using Android with open-source mesh radios. For more information see our webpage: [meshtastic.org](https://www.meshtastic.org). If you are looking for the the device side code, see [here](https://github.com/meshtastic/Meshtastic-esp32). +This is a tool for using Android with open-source mesh radios. For more information see our +webpage: [meshtastic.org](https://www.meshtastic.org). If you are looking for the the device side +code, see [here](https://github.com/meshtastic/Meshtastic-esp32). -This project is currently beta testing, if you have questions or feedback please [Join our discussion forum](https://meshtastic.discourse.group/). We would love to hear from you! +This project is currently beta testing, if you have questions or feedback +please [Join our discussion forum](https://meshtastic.discourse.group/). We would love to hear from +you! The production version of our application is here: [![Download at https://play.google.com/store/apps/details?id=com.geeksville.mesh](https://play.google.com/intl/en_us/badges/static/images/badges/en_badge_web_generic.png)](https://play.google.com/store/apps/details?id=com.geeksville.mesh&referrer=utm_source%3Dgithub-android-readme) -To join the beta program for the app go to this [URL](https://play.google.com/apps/testing/com.geeksville.mesh) to opt-in to the alpha/beta test. -If you encounter any problems or have questions, [post in the forum](https://meshtastic.discourse.group/) and we'll help. +To join the beta program for the app go to +this [URL](https://play.google.com/apps/testing/com.geeksville.mesh) to opt-in to the alpha/beta +test. If you encounter any problems or have +questions, [post in the forum](https://meshtastic.discourse.group/) and we'll help. -The app is also distributed via F-Droid repo: [https://mesh.tastic.app/fdroid/repo](https://mesh.tastic.app/fdroid/repo) +The app is also distributed via F-Droid +repo: [https://mesh.tastic.app/fdroid/repo](https://mesh.tastic.app/fdroid/repo) -However, if you must use 'raw' APKs you can get them from our [github releases](https://github.com/meshtastic/Meshtastic-Android/releases). This is not recommended because if you manually install an APK it will not automatically update. +However, if you must use 'raw' APKs you can get them from +our [github releases](https://github.com/meshtastic/Meshtastic-Android/releases). This is not +recommended because if you manually install an APK it will not automatically update. ## Build instructions -If you would like to develop this application we'd love your help! These build instructions are brief -and should be improved, please send a PR if you can. +If you would like to develop this application we'd love your help! These build instructions are +brief and should be improved, please send a PR if you can. - Use Android Studio to build/debug - Use "git submodule update --init --recursive" to pull in the various submodules we depend on -- There are a few config files which you'll need to copy from templates included in the project. - Run the following commands to do so: +- There are a few config files which you'll need to copy from templates included in the project. Run + the following commands to do so: ```bash rm ./app/google-services.json cp ./app/google-services-example.json ./app/google-services.json -rm ./app/src/main/res/values/mapbox-token.xml -cp ./app/special/mapbox-token.xml ./app/src/main/res/values/ rm ./app/src/main/res/values/curfirmwareversion.xml cp ./app/special/curfirmwareversion.xml ./app/src/main/res/values/ ``` -- (unfortunately) you need to get a (free) mapbox developer token [here](https://docs.mapbox.com/android/maps/guides/install/) and put that token in your user gradle.properties. - -```bash -cat ~/.gradle/gradle.properties -MAPBOX_DOWNLOADS_TOKEN=sk.yourtokenherexxx -``` -- (optional) to run CI tests on your fork: 1) allow GitHub Actions; 2) add your token at: Settings > Secrets > Actions > New repository secret: Name: MAPBOXTOKEN Value: sk.yourtokenherexxx - -- Now you should be able to select "Run / Run" in the IDE and it will happily start running on your phone - or the emulator. Note: The emulators don't support bluetooth, so some features can not be used in - that environment. +- Now you should be able to select "Run / Run" in the IDE and it will happily start running on your + phone or the emulator. Note: The emulators don't support bluetooth, so some features can not be + used in that environment. ## Analytics setup diff --git a/app/build.gradle b/app/build.gradle index a26fcdf1a..c56338557 100644 --- a/app/build.gradle +++ b/app/build.gradle @@ -69,7 +69,6 @@ android { // doesn't like and we need to strip them (gr) resConfigs "cs", "de", "el", "en", "es", "fi", "fr", "ga", "ht", "it", "ja", "ko-rKR", "nl", "no", "pl", "pt", "pt-rBR", "ro", "ru", "sk", "sl", "sq", "sv", "tr", "zh" - // Needed to make mapbox work inside the firebase testlab - FIXME, alas, still doesn't work ndk { // abiFilters "armeabi-v7a", "arm64-v8a", "x86", "x86_64" } diff --git a/app/proguard-rules.pro b/app/proguard-rules.pro index 41240d9b4..45e42cc0e 100644 --- a/app/proguard-rules.pro +++ b/app/proguard-rules.pro @@ -30,9 +30,6 @@ -keep class com.geeksville.mesh.**{*;} -keepclassmembers class * extends com.google.protobuf.GeneratedMessageLite { ; } -# Recommended by mapbox to prevent native crashes --dontwarn com.mapbox.** --keep class com.mapbox.** { *; } # for kotlinx.serialization -keepattributes *Annotation*, InnerClasses diff --git a/app/src/main/res/values-cs/strings.xml b/app/src/main/res/values-cs/strings.xml index d5e126be7..4199217b0 100644 --- a/app/src/main/res/values-cs/strings.xml +++ b/app/src/main/res/values-cs/strings.xml @@ -28,9 +28,6 @@ Jste si jistý, že chcete změnit kanál? Veškerá komunikace s ostatními vysílači přestane fungovat až do momentu distribuce stejného nastavení na ostatní vysílače. Nová URL kanálu přijata. Chcete se připojit ke kanálu \'%s\' ? - You have analytics disabled. Unfortunately our map provider (mapbox) requires analytics to be allowed for their \'free\' plan. So we have turned off the map view.\n\n - If you would like to see the map, you\'ll need to turn on analytics in the Settings pane (also, for the time being you might need to force restart the application).\n\n - If you are interested in us paying for mapbox (or switching to a different map provider), please post in meshtastic.discourse.group Chybí požadovaná oprávnění, Meshtastic nebude fungovat správně. Prosím změntě oprávnění pro aplikaci. Vysílač je uspaný, nepodařilo se změnit kanál. Nahlášení chyby diff --git a/app/src/main/res/values-el/strings.xml b/app/src/main/res/values-el/strings.xml index a29066008..0d2ac198f 100644 --- a/app/src/main/res/values-el/strings.xml +++ b/app/src/main/res/values-el/strings.xml @@ -28,9 +28,6 @@ Είστε βέβαιοι ότι θέλετε να αλλάξετε κανάλι? Η επικοινωνία με άλλες συσκευές θα σταματήσεις μέχρι να μοιραστείτε τις ρυθμίσεις του νέου καναλιού. Λήψη URL νέου καναλιού Θέλετε να αλλάξετε ‘%s’ κανάλι? - Έχετε απενεργοποιήσει την ανάλυση δεδομένων. Δυστυχώς ο πάροχος χαρτών μας (mapbox) απαιτεί η ανάλυση δεδομένων να επιτρέπεται στο ‘δωρεάν’ πακέτο. Επομένως έχουμε απενεργοποιήσει το χάρτη.\n\n - Αν επιθυμείτε να δείτε το χάρτη, θα πρέπει να ενεργοποιήσετε την ανάλυση δεδομένων στις Ρυθμίσεις (επίσης - προσωρινά - θα πρέπει να επανεκκινήσετε την εφαρμογή).\n\n - Αν θεωρείτε ότι πρέπει να πληρώνουμε το mapbox (η να αλλάξουμε πάροχο χαρτών), παρακαλώ δημοσιεύστε στο meshtastic.discourse.group Λείπει μια απαιτούμενη άδεια, Meshtastic δεν θα λειτοργεί σωστά. Ενεργοποιήστε τις ρυθμίσεις εφαρμογής Android. Radio σε κατάσταση ύπνου, δεν γίνεται αλλαγή καναλιού Αναφορά Bug diff --git a/app/src/main/res/values-fr/strings.xml b/app/src/main/res/values-fr/strings.xml index 82595b286..c3c32f312 100644 --- a/app/src/main/res/values-fr/strings.xml +++ b/app/src/main/res/values-fr/strings.xml @@ -28,9 +28,6 @@ Vous êtes sur de vouloir changer de canal? Toute communication aux autres nœuds va s\'arrêter jusqu\'à ce que vous partagez les nouveaux réglages. Nouveau URL canal reçu Voulez-vous changer vers canal \'%s\' ? - Vous avez désactivé les analytiques. Malheureusement notre fournisseur de carte (mapbox) a besoin d\'analytiques activés pour le plan \'gratuit\'. Désormais nous avons désactivé l\'apercu carte.\n\n - Si vous désirez voir la carte, vous avez besoin d\'activer les analytiques dans les Réglages (également, provisoirement, il peut être nécessaire de redémarrer l\'application).\n\n - Si vous trouvez que nous devons payer pour mapbox (ou changer de fournisseur de carte), veuillez poster dans meshtastic.discourse.group Une permission indispensable manque, Meshtastic ne peut pas fonctionner. Veuillez modifier dans Réglages. Radio en veille, change de Canal impossible Rapporter Bogue diff --git a/app/src/main/res/values-ga/strings.xml b/app/src/main/res/values-ga/strings.xml index 1b14b2349..f61bc3c85 100644 --- a/app/src/main/res/values-ga/strings.xml +++ b/app/src/main/res/values-ga/strings.xml @@ -28,10 +28,6 @@ An bhfuil tú cinnte gur mhaith leat an cainéal a athrú? Stopfaidh gach cumarsáid le nóid eile go dtí go roinnfidh tú na socruithe nua cainéil. URL Cainéal nua faighte Ar mhaith leat aistriú go dtí an cainéal \'%s\'? - Tá anailísíocht díchumasaithe agat. Ar an drochuair, éilíonn ár soláthraí léarscáileanna (bosca léarscáileanna) go gceadófar anailísíocht dá phlean \'saor in aisce\'. - Mar sin, táimid tar éis an radharc léarscáile a mhúchadh. Más mian leat an léarscáil a fheiceáil, beidh ort anailísíocht a chur ar siúl sa phána Socruithe (freisin, faoi - láthair, b’fhéidir go mbeidh ort iallach a chur ar an bhfeidhmchlár atosú). Má tá suim agat muid a íoc as bosca léarscáileanna (nó aistriú chuig soláthraí léarscáileanna eile), - abair é le do thoil i meshtastic.discourse.group. Tá cead riachtanach ar iarraidh, ní bheidh Meshtastic in ann oibriú i gceart. Cumasaigh i socruithe feidhmchláir le do thoil. Bhí an raidió ina chodladh, ní raibh sé in ann an cainéal a athrú Tuairiscigh fabht diff --git a/app/src/main/res/values-ht/strings.xml b/app/src/main/res/values-ht/strings.xml index 5fb52deec..beb4ef769 100644 --- a/app/src/main/res/values-ht/strings.xml +++ b/app/src/main/res/values-ht/strings.xml @@ -28,7 +28,6 @@ Èske ou sèten ke ou vle chanje chènn nan? Tout kominikasyon ak lòt ne elektwonik yo ap kanpe jiskaske ou pataje nouvo paramèt chènn yo. Te resevwa nouvo Chènn URL Eke ou vle chanje a chènn \'%s\'? - Ou gen analitik ki enfim. Malerezman founisè kat jeyografik nou an (mapbox) mande pou analitik yo pèmèt plan gratis. Se konsa, nou te etènn kat la. Si ou ta renmen wè kat jeyografik la ou pral bezwen ouvri analytics nan Paramèt (si ou enterese pou nou peye pou mapbox (oswa pou nou chanje founisè kat jeyografik la) tanpri poste nan meshtastic.discourse.group Manke pèmisyon obligatwa, Meshtastic pap ka fonksyone byen. Tanpri ale bay pèmisyon an nan paramèt aplikasyon android. Radyo t\'ap dòmi, pat ka chanje chènn Report Bug diff --git a/app/src/main/res/values-hu/strings.xml b/app/src/main/res/values-hu/strings.xml index a63c87642..efe79a501 100644 --- a/app/src/main/res/values-hu/strings.xml +++ b/app/src/main/res/values-hu/strings.xml @@ -27,9 +27,6 @@ Biztosan csatornát akar váltani? Minden kommunikáció a többi állomással megszakad amíg nem osztja meg velük az új csatorna beállításokat. Új csatorna URL érkezett Átkapcsol a(z) \'%s\' csatornára? - Az analitikák küldése ki van kapcsolva. Sajnos a térkép szolgáltatónk (mapbox) megköveteli az analitikák küldését számukra az \'ingyenes\' előfizetéshez. Ezért a térkép nézetet ki kellett kapcsolnunk.\n\n - Ha szeretné látni a térképet, ahhoz be kell kapcsolja az analitikák küldését a program beállítások oldalán (és lehet, hogy az alkalmazást is újra kell indítani hozzá).\n\n - Ha érdeklődne az általunk történő fizetéses megoldás iránt a mapbox felé (vagy egy másik térkép szolgáltatóra váltásról), kérem írjon bejegyzést a meshtastic.discourse.group fórumba. Egy szükséges engedély hiányzik, ezért a Meshtastic nem fog tudni rendesen működni. Kérem engedélyezze az Android alkalmazások beállításai között. A rádió alvó üzemmódban volt, ezért nem lehetett csatornát váltani. Hiba jelentése diff --git a/app/src/main/res/values-it/strings.xml b/app/src/main/res/values-it/strings.xml index 74cd6d8d3..8c328c9e5 100644 --- a/app/src/main/res/values-it/strings.xml +++ b/app/src/main/res/values-it/strings.xml @@ -28,10 +28,6 @@ Sei sicuro di voler cambiare canale ? Tutte le comunicazioni con gli altri nodi termineranno fino a quando non condividi le impostazioni del nuovo canale. Nuovo Canale URL ricevuto Vuoi passare al canale \'%s\' ? - YL\'analisi è disabilitata. Sfortunatamente il nostro fornitore di mappe (mapbox) richiede che le analisi siano consentite per il loro piano \'gratuito \'. - Quindi abbiamo disattivato la visualizzazione della mappa. \n\n - Se desideri visualizzare la mappa, dovrai attivare l\'analisi nel riquadro Impostazioni (inoltre, per il momento potresti dover forzare il riavvio dell\'applicazione). \n\n - Se sei interessato a pagare per mapbox (o passare ad un altro fornitore di mappe), scrivi in meshtastic.discourse.group Manca un\'autorizzazione richiesta, Meshtastic non sarà in grado di funzionare correttamente. Si prega di abilitarlo nelle impostazioni dell\'applicazione. La radio dormiva, non poteva cambiare canale. Segnala bug diff --git a/app/src/main/res/values-ja/strings.xml b/app/src/main/res/values-ja/strings.xml index 786052953..ac3d65f79 100644 --- a/app/src/main/res/values-ja/strings.xml +++ b/app/src/main/res/values-ja/strings.xml @@ -28,9 +28,6 @@ チャンネルを変更しますか?新しいチャンネル設定をシェアするまで他のノードとの通信はすべて停止します。 新しいチャンネルURLを受信しました \'%s\チャンネルに変更しますか? - 解析が無効になっています。残念ながら地図プロバイダ(mapbox)は無料プランの場合、解析を有効にする必要があります。マップビューをオフにしました。\n\n -マップを表示したい場合は設定パネルで匿名の診断情報と不具合報告にチェックする必要があります(また当分の間アプリを強制停止して再起動する必要があります)。\n\n -mapboxの有償プラン(または代替地図プロバイダ)を検討される方は meshtastic.discourse.group に書き込んでください。 必要なアクセス権限が拒否されているため、アプリが正常に動作しません。設定により権限を許可してください。 Meshtasticデバイスはスリープ状態です。チャンネルを変更できませんでした。 バグ報告 diff --git a/app/src/main/res/values-ko-rKR/strings.xml b/app/src/main/res/values-ko-rKR/strings.xml index 91c9047e0..72c833ae3 100644 --- a/app/src/main/res/values-ko-rKR/strings.xml +++ b/app/src/main/res/values-ko-rKR/strings.xml @@ -28,7 +28,6 @@ 채널 변경을 원하세요? 채널 설정이 공유되기 전까지 다른 노드와의 통신은 중단됩니다. 새로운 채널 URL 수신 \'%s\' 채널로 변경할 까요? - 분석이 비활성화 되었습니다. 현재 앱에서 사용하는 지도 제공자(mapbox)의 \'무료\' 계정을 사용하기 위해서는 분석을 활성화 해야합니다. 따라서 기본적으로 지도를 비활성화 시켰습니다. 만약 지도를 보길 원한다면 설정 창에서 분석 설정을 켜야합니다(또한, 앱을 강제 재부팅해야 할 수도 있습니다). 만약 mapbox 사용에 대해서 도움주길 원하거나 다른 지도 제공자로 바꾸길 원한다면 포럼에 글을 게시해주세요. 필요로 하는 권한을 얻지 못했습니다. Meshtastic는 정상적으로 작동하지 않을 수도 있습니다. 스마트폰 설정에서 권한을 설정해주세요. 메쉬태스틱기기가 절전모드 중 이므로 채널을 변경할 수 없습니다. 버그 보고 diff --git a/app/src/main/res/values-nl/strings.xml b/app/src/main/res/values-nl/strings.xml index b8f70c89e..0938a9391 100644 --- a/app/src/main/res/values-nl/strings.xml +++ b/app/src/main/res/values-nl/strings.xml @@ -28,9 +28,6 @@ Ben je zeker van kanaal te willen veranderen? Alle communicatie met andere nodes wordt gestopt tot je de nieuwe instellingen deelt. Nieuw kanaal URL ontvangen Wil je veranderen naar kanaal \'%s\' ? - Je hebt analytics uitgeschakeld. Spijtig want onze kaartprovider (mapbox) vereist ingeschakelde analytics voor het \'gratis\' plan. Daarom hebben we de kaartmodus uitgeschakeld.\n\n - Indien je de kaart wil zien, is het nodig analytics aan te zetten in de Instellingen (ook is het mogelijk, voorlopig, dat een herstart van de applicatie nodig is).\n\n - Indien je het nodig acht dat we betalen voor mapbox (of veranderen naar een andere kaartprovider), post dan een berichtje in de meshtastic.discourse.group Een vereiste toelating ontbreekt, Meshtastic kan niet goed werken. Graag aanzetten in Instellingen. Radio was in slaapmodus, kon het kanaal niet veranderen Rapporteer Bug diff --git a/app/src/main/res/values-no/strings.xml b/app/src/main/res/values-no/strings.xml index ab30033c3..f206a8c60 100644 --- a/app/src/main/res/values-no/strings.xml +++ b/app/src/main/res/values-no/strings.xml @@ -28,9 +28,6 @@ Er du sikker på at du vil endre kanalen? All kommunikasjon med andre noder vil stanse, intill du deler de nye kanalinstillingene. Ny kanal URL mottatt Vil du bytte til \'%s\' kanal? - Du har slått av analytics. Desverre krever kartleverandøren vår (mapbox) at analytics er slått på for deres \'grtis\' plan. Så vi har slått av kartvisning.\n\n - Hvis du vil se kartet, må du slå på analytics i instillingspanelet (også, for øyeblikket, må du kanskje tvangsstoppe og restarte applikasjonen).\n\n - Hvis du er interessert i at vi betaler for mapbox(eller bytter kartleveradøt), vennligst post i meshtastic.discourse.group En påkrevet tilgang mangler, Meshtastic vil ikke fungere korrekt. Vennligst slå på i Android appliksjonsinstillinger. Radio sov.kunne ikke endre kanal Rapporter Feil diff --git a/app/src/main/res/values-pl/strings.xml b/app/src/main/res/values-pl/strings.xml index bf12b3bd7..c499cbf59 100644 --- a/app/src/main/res/values-pl/strings.xml +++ b/app/src/main/res/values-pl/strings.xml @@ -28,9 +28,6 @@ Are you sure you want to change the channel? All communication with other nodes will stop until you share the new channel settings. Odebrano nowy URL kanału Chcesz przełączyć na \'%s\' kanał? - Masz wyłączone analizy. Niestety nasz dostawca map (mapbox) wymaga, aby analizy były dozwolone w ich planie \'free\'Dlatego wyłączyliśmy widok mapy.\n\n -Jeśli chcesz zobaczyć mapę, musisz włączyć analitykę w panelu Ustawienia (również na razie może być konieczne wymuszenie ponownego uruchomienia aplikacji).\n\n -Jeśli jesteś zainteresowany opłaceniem przez nas mapboxa (lub przejściem do innego dostawcy map), napisz na meshtastic.discourse.group Meshtastic potrzebuje %s zezwolenie i lokalizacja muszą być włączone, aby można było znaleźć nowe urządzenia przez Bluetooth. Możesz go później wyłączyć. Radio było w trybie uśpienia, nie mogło zmienić kanału Zgłoś bug diff --git a/app/src/main/res/values-pt-rBR/strings.xml b/app/src/main/res/values-pt-rBR/strings.xml index 8f91e4f93..6261501ac 100644 --- a/app/src/main/res/values-pt-rBR/strings.xml +++ b/app/src/main/res/values-pt-rBR/strings.xml @@ -28,9 +28,6 @@ Tem certeza que deseja mudar de canal? Toda comunicação com os outros dispositivos será interrompida até serem compartilhadas as novas configurações do canal. Novo link de canal recebido Deseja mudar para o canal \'%s\'? - O Google Analytics está desativado. Infelizmente a plataforma de mapas utilizada (Mapbox) requer este recurso ativado para uso do plano \’gratuito\’ . Tivemos que desativar a visualização do mapa.\n\n - Para poder visualizar o mapa será necessário ativar o Google Analytics na configuração do Android (pode ser necessário forçar o reinício do aplicativo).\n\n - Se tiver interesse em que o Meshtastic use um plano pago do Mapbox (ou mude para uma plataforma de mapas diferente), por favor envie uma mensagem em meshtastic.discourse.group Meshtastic precisa da permissão de %s e da localização ativada para encontrar novos dispositivos via bluetooth. Você pode desativar novamente depois. Rádio estava em suspensão (sleep), não foi possível mudar de canal Informar Bug diff --git a/app/src/main/res/values-pt/strings.xml b/app/src/main/res/values-pt/strings.xml index 880878e99..0f46fff81 100644 --- a/app/src/main/res/values-pt/strings.xml +++ b/app/src/main/res/values-pt/strings.xml @@ -27,9 +27,6 @@ Tem certeza que deseja mudar de canal? Todas as comunicações com outros nós serão interrompidas até que partilhe as novas configurações do canal. Novo Link Recebido do Canal Pretende mudar para o canal \'%s\' ? - Tem os dados analícos desativados. Infelizmente o fornecedor do mapa (mapbox) requer dos dados analíticos estejam activados para o seu plano \'gratuito\' . Por isso a visualização do mapa esta desativado.\n\n - Se pretender visualizar o mapa, vai necessitar de ativar os dados anaíticos no painel Configurações (também pode ser necessário forçar o reinício do aplicativo). \n\n - Se estiver interessado em pagarmos pelo mapbox (ou mudar para um provedor de mapas diferente), contacte através de meshtastic.discourse.group Meshtastic precisa da permissão de %s e da localização ativada para encontrar novos dispositivos via bluetooth. Você pode desativar novamente depois. O rádio estava a dormir, não conseguia mudar de canal Reportar Bug diff --git a/app/src/main/res/values-ro/strings.xml b/app/src/main/res/values-ro/strings.xml index 9906c35bd..8c8424a03 100644 --- a/app/src/main/res/values-ro/strings.xml +++ b/app/src/main/res/values-ro/strings.xml @@ -28,9 +28,6 @@ Ești sigur că vrei să schimbi canalul? Toate comunicațiile cu alte noduri vor fi oprite până când setezi aceleași detalii pe alte noduri. Am primit un nou URL de canal Vrei să faci schimbul \'%s\' canalului? - Ai analiticele dezactivate. Din nefericire providerul hărților (mapbox) necesită analitice în planul \'gratuit\'. Așadar am dezactivat harta.\n\n - Dacă vrei să vezi harta, trebuie să pornești analiticele în panoul de setări (s-ar putea să fii nevoit să restartezi aplicația).\n\n - Dacă sugerezi să plătim pentru mapbox (sau să schimbăm providerul hărții), te rog, postează în meshtastic.discourse.group O permisiune necesară lipsește, Meshtastic nu o să funcționeze corespunzător. Te rugăm activează-o în setările Android. Nu am putut să schimb canalul deoarece dispozitivul era în sleep mode Raportează Bug diff --git a/app/src/main/res/values-ru/strings.xml b/app/src/main/res/values-ru/strings.xml index 87ef9a607..2cbcdb3a9 100644 --- a/app/src/main/res/values-ru/strings.xml +++ b/app/src/main/res/values-ru/strings.xml @@ -28,9 +28,6 @@ Вы уверены, что хотите изменить канал? Связь с другими устройствами будет прервана, пока вы не поделитесь новыми настройками канала. URL нового канала получен Вы хотите переключиться на \'%s\' канал? - У вас отключена аналитика. К сожалению, наш поставщик карт (mapbox) требует, чтобы аналитика была разрешена для «бесплатного» использования. Мы вынуждены отключить карту.\n\n - Если вы хотите использовать карту, вам нужно включить аналитику на панели настроек (также, на данный момент вам может потребоваться принудительный перезапуск приложения).\n\n - Если вы заинтересованы в том, чтобы мы платили за карту (или переходили на другого поставщика карт), отправьте сообщение по адресу meshtastic.discourse.group. Требуемое разрешение отсутствует, Meshtastic не сможет работать должным образом. Пожалуйста, включите в настройках приложения. Радиомодуль в режиме сна, смена канала невозможна Сообщить об ошибке diff --git a/app/src/main/res/values-sk/strings.xml b/app/src/main/res/values-sk/strings.xml index 41ee01ff4..6da0d9549 100644 --- a/app/src/main/res/values-sk/strings.xml +++ b/app/src/main/res/values-sk/strings.xml @@ -28,9 +28,6 @@ Ste si istý, že chcete zmeniť kanál? Všetka komunikácia s ostatnými vysielačmi prestane fungovať až do momentu distribúcie rovnakého nastavenia na ostatné vysielače. Obdržaná nová URL kanálu. Chcete sa prpnúť na kanál \'%s\' ? - You have analytics disabled. Unfortunately our map provider (mapbox) requires analytics to be allowed for their \'free\' plan. So we have turned off the map view.\n\n - If you would like to see the map, you\'ll need to turn on analytics in the Settings pane (also, for the time being you might need to force restart the application).\n\n - If you are interested in us paying for mapbox (or switching to a different map provider), please post in meshtastic.discourse.group Aplikácia Meshtastic nemá pridelené požadované oprávnenie a pravdepodobne nebude fungovať správne. Prosím povoľte tieto oprávnenia v nastaveniach aplikácie. Vysielač je uspatý, nepodarilo sa zmeniť kanál Nahlásenie chyby diff --git a/app/src/main/res/values-sl/strings.xml b/app/src/main/res/values-sl/strings.xml index 96340e38d..4fa0e9f46 100644 --- a/app/src/main/res/values-sl/strings.xml +++ b/app/src/main/res/values-sl/strings.xml @@ -28,7 +28,6 @@ Ali ste prepričani, da želite spremeniti kanal? Vsa komunikacija z drugimi vozlišči se ustavi, dokler ne delite novih nastavitev kanala. Prejet je bil novi URL kanala Ali želite preklopiti na kanal \'%s\' ? - Vaša analitika je onemogočena. Na žalost naš ponudnik zemljevidov (mapbox) zahteva analitiko, ki je dovoljena za njihov "brezplačen" načrt. Torej smo izključili prikaz zemljevida. \n\nČe želite videti zemljevid, boste morali v podoknu z nastavitvami vklopiti analitiko (morda boste morali znova zagnati aplikacijo). \n\nČe vas zanima, kako plačujemo za karto (ali preklopiti na drugega ponudnika zemljevidov), pošljite sporočilo v meshtastic.discourse.group Manjka zahtevano dovoljenje: Meshtastic ne bo mogel pravilno delovati. Omogočite v nastavitvah aplikacije za Android. Radio je "spal", sprememba kanala ni bila izvedena. Prijavi napako diff --git a/app/src/main/res/values-tr/strings.xml b/app/src/main/res/values-tr/strings.xml index 33d304a9f..9d7d3178a 100644 --- a/app/src/main/res/values-tr/strings.xml +++ b/app/src/main/res/values-tr/strings.xml @@ -28,9 +28,6 @@ Kanalı değiştirmek istediğinize emin misiniz? Yeni kanal ayarlarını paylaşana dek tüm node\'lar ile iletişim sonlanacak. Yeni Kanal Adresi alındı \'%s\' kanalına geçmek istiyor musunuz? - Analitik raporları kapattınız. Harita sağlayıcımız (mapbox) ücretsiz kullanım paketi için analitik raporları gerektiriyor maalesef. Bu yüzden harita görünümü pasif hale getirdik.\n\n - Haritayı görmek istiyorsanız, Ayarlar bölümünden analitik raporları aktif hale getirmeniz gerekiyor. (ayrıca, şu an bunun için uygulamayı tümüyle kapatıp yeniden açmanız gerekebilir).\n\n - Eğer mapbox için ödeme yapmamız (ya da başka bir harita sağlayıcıya geçme) konusunda ilgiliyseniz, lütfen meshtastic.discourse.group sayfasında paylaşınız. Gerekli bir izin eksik, Meshtastic düzgün çalışamayacak. Lütfen Android ayarlarından izni aktif hale getiriniz. Telsiz uyku durumundaydı, kanal değiştirilemedi Hata Bildir diff --git a/app/src/main/res/values-zh/strings.xml b/app/src/main/res/values-zh/strings.xml index ef65f5359..1816ec780 100644 --- a/app/src/main/res/values-zh/strings.xml +++ b/app/src/main/res/values-zh/strings.xml @@ -28,9 +28,6 @@ 您确定要修改通信频道吗?这将会使你与其他节点断开通信. 收到新的频道URL 您是否要切换到\'%s\'频道? - 您已禁用分析。 不幸的是,我们的地图提供商 (mapbox) 要求允许分析 \“免费”\计划。 所以我们关闭了地图视图.\n\n - 如果您想查看地图,您将需要在“设置”窗格中打开分析(此外,您可能暂时需要强制重新启动应用程序).\n\n - 如果您对我们为 mapbox付费或切换到不同的地图提供商感兴趣,请在 meshtastic.discourse.group 中发帖 缺少所需的权限,Mesh网络将无法正常工作.请在应用程序设置中启用. 设备正在休眠,无法更改频道 报告BUG diff --git a/app/src/main/res/values/strings.xml b/app/src/main/res/values/strings.xml index 74edf5905..c2caba121 100644 --- a/app/src/main/res/values/strings.xml +++ b/app/src/main/res/values/strings.xml @@ -32,9 +32,6 @@ Are you sure you want to change the channel? All communication with other nodes will stop until you share the new channel settings. New Channel URL received Do you want to switch to the \'%s\' channel? - You have analytics disabled. Unfortunately our map provider (mapbox) requires analytics to be allowed for their \'free\' plan. So we have turned off the map view.\n\n - If you would like to see the map, you\'ll need to turn on analytics in the Settings pane (also, for the time being you might need to force restart the application).\n\n - If you are interested in us paying for mapbox (or switching to a different map provider), please post in meshtastic.discourse.group Meshtastic needs %s permission and location must be turned on to find new devices via bluetooth. You can turn it off again afterwards. Radio was sleeping, could not change channel Report Bug diff --git a/build.gradle b/build.gradle index fd0857482..57b5b6936 100644 --- a/build.gradle +++ b/build.gradle @@ -40,20 +40,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() From bd2951c845522d53f72d1cc99e47487ec35ffa5d Mon Sep 17 00:00:00 2001 From: PWRxPSYCHO Date: Wed, 24 Aug 2022 11:08:39 -0400 Subject: [PATCH 05/20] Setup switching of map source --- .../com/geeksville/mesh/ui/MapFragment.kt | 97 ++++++++++++------- 1 file changed, 61 insertions(+), 36 deletions(-) diff --git a/app/src/main/java/com/geeksville/mesh/ui/MapFragment.kt b/app/src/main/java/com/geeksville/mesh/ui/MapFragment.kt index 753c4f1b0..9e650c2f2 100644 --- a/app/src/main/java/com/geeksville/mesh/ui/MapFragment.kt +++ b/app/src/main/java/com/geeksville/mesh/ui/MapFragment.kt @@ -2,6 +2,7 @@ package com.geeksville.mesh.ui import android.content.Context +import android.content.SharedPreferences import android.os.Bundle import android.view.LayoutInflater import android.view.View @@ -32,6 +33,7 @@ class MapFragment : ScreenFragment("Map"), Logging { private lateinit var map: MapView private lateinit var mapController: IMapController + private lateinit var mPrefs: SharedPreferences private val model: UIViewModel by activityViewModels() @@ -40,13 +42,46 @@ class MapFragment : ScreenFragment("Map"), Logging { private val defaultZoomLevel = 6.0 private val defaultZoomSpeed = 3000L private val defaultMinZoom = 3.0 + private val prefsName = "org.andnav.osm.prefs" + private val prefsZoomLevelDouble = "prefsZoomLevelDouble" + private val prefsTileSource = "prefsTileSource" override fun onCreateView( inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle? ): View { - return inflater.inflate(R.layout.map_view, container, false) + map = MapView(inflater.context) + map.setDestroyMode(false) + map.tag = "mapView" + return map + } + + override fun onViewCreated(viewIn: View, savedInstanceState: Bundle?) { + super.onViewCreated(viewIn, savedInstanceState) + Configuration.getInstance().userAgentValue = + BuildConfig.APPLICATION_ID // Required to get online tiles + + mPrefs = context!!.getSharedPreferences(prefsName, Context.MODE_PRIVATE) + + addCopyright() // Copyright is required for certain map sources + setupMapProperties() + loadOnlineTileSourceBase() + mapController = map.controller + val point = GeoPoint(defaultLat, defaultLong) //White House Coordinates, Washington DC + mapController.animateTo(point, defaultZoomLevel, defaultZoomSpeed) + if (view != null) { + model.nodeDB.nodes.value?.let { nodes -> + onNodesChanged(nodes.values) + } + + zoomToNodes(mapController) + // Any times nodes change update our map + model.nodeDB.nodes.observe(viewLifecycleOwner) { nodes -> + onNodesChanged(nodes.values) + } + + } } private fun onNodesChanged(nodes: Collection) { @@ -71,56 +106,32 @@ class MapFragment : ScreenFragment("Map"), Logging { requireActivity(), R.drawable.ic_twotone_person_pin_24 ) - map.overlays.add(marker) map.invalidate() + map.overlays.add(marker) } f } } - override fun onViewCreated(viewIn: View, savedInstanceState: Bundle?) { - super.onViewCreated(viewIn, savedInstanceState) - Configuration.getInstance().userAgentValue = - BuildConfig.APPLICATION_ID // Required to get online tiles - - map = viewIn.findViewById(R.id.map) as MapView - - /** - * Copyright layer required - */ - //////////////////////////////////////////////////////////// + /** + * Adds copyright to map depending on what source is showing + */ + private fun addCopyright() { val copyrightNotice: String = map.tileProvider.tileSource.copyrightNotice val copyrightOverlay = CopyrightOverlay(context) copyrightOverlay.setCopyrightNotice(copyrightNotice) map.overlays.add(copyrightOverlay) - /////////////////////////////////////////////////////////// - - setupMapProperties() - if (view != null) { - model.nodeDB.nodes.value?.let { nodes -> - onNodesChanged(nodes.values) - } - - zoomToNodes(mapController) - // Any times nodes change update our map - model.nodeDB.nodes.observe(viewLifecycleOwner) { nodes -> - onNodesChanged(nodes.values) - } - - } - - } private fun setupMapProperties() { if (this::map.isInitialized) { - map.minZoomLevel = defaultMinZoom + map.isTilesScaledToDpi = + true // scales the map tiles to the display density of the + map.minZoomLevel = + defaultMinZoom // sets the minimum zoom level (the furthest out you can zoom) map.setMultiTouchControls(true) // Sets gesture controls to true map.zoomController.setVisibility(CustomZoomButtonsController.Visibility.NEVER) // Disables default +/- button for zooming - mapController = map.controller - val point = GeoPoint(defaultLat, defaultLong) //White House Coordinates, Washington DC - mapController.animateTo(point, defaultZoomLevel, defaultZoomSpeed) } } @@ -168,17 +179,31 @@ class MapFragment : ScreenFragment("Map"), Logging { } override fun onPause() { + val edit = mPrefs.edit() + edit.putString(prefsTileSource, loadOnlineTileSourceBase().name()) + edit.putFloat(prefsZoomLevelDouble, map.zoomLevelDouble.toFloat()) + edit.commit() + map.onPause() super.onPause() } override fun onResume() { super.onResume() - map.onResume() + val tileSourceName = mPrefs.getString( + prefsTileSource, + TileSourceFactory.DEFAULT_TILE_SOURCE.name() + ) + try { + val tileSource = TileSourceFactory.getTileSource(tileSourceName) + map.setTileSource(tileSource) + } catch (e: IllegalArgumentException) { + map.setTileSource(TileSourceFactory.DEFAULT_TILE_SOURCE) + } } override fun onDestroy() { - super.onDestroy() + super.onDestroyView() map.onDetach() } } From 43e59d21cc650dc6db0fd0021ccef4cc58284145 Mon Sep 17 00:00:00 2001 From: PWRxPSYCHO Date: Wed, 24 Aug 2022 11:30:42 -0400 Subject: [PATCH 06/20] creating constants for all hardcoded strings --- .../main/java/com/geeksville/mesh/ui/MapFragment.kt | 11 +++++++---- 1 file changed, 7 insertions(+), 4 deletions(-) diff --git a/app/src/main/java/com/geeksville/mesh/ui/MapFragment.kt b/app/src/main/java/com/geeksville/mesh/ui/MapFragment.kt index 9e650c2f2..bcda93187 100644 --- a/app/src/main/java/com/geeksville/mesh/ui/MapFragment.kt +++ b/app/src/main/java/com/geeksville/mesh/ui/MapFragment.kt @@ -39,12 +39,15 @@ class MapFragment : ScreenFragment("Map"), Logging { private val defaultLat = 38.8976763 private val defaultLong = -77.0365298 + private val defaultMinZoom = 3.0 private val defaultZoomLevel = 6.0 private val defaultZoomSpeed = 3000L - private val defaultMinZoom = 3.0 private val prefsName = "org.andnav.osm.prefs" private val prefsZoomLevelDouble = "prefsZoomLevelDouble" private val prefsTileSource = "prefsTileSource" + private val mapStyleId = "map_style_id" + private val mapTag = "mapView" + private val uiPrefs = "ui-prefs" override fun onCreateView( @@ -53,7 +56,7 @@ class MapFragment : ScreenFragment("Map"), Logging { ): View { map = MapView(inflater.context) map.setDestroyMode(false) - map.tag = "mapView" + map.tag = mapTag return map } @@ -161,8 +164,8 @@ class MapFragment : ScreenFragment("Map"), Logging { } private fun loadOnlineTileSourceBase(): OnlineTileSourceBase { - val prefs = context?.getSharedPreferences("ui-prefs", Context.MODE_PRIVATE) - val mapSourceId = prefs?.getInt("map_style_id", 1) + val prefs = context?.getSharedPreferences(uiPrefs, Context.MODE_PRIVATE) + val mapSourceId = prefs?.getInt(mapStyleId, 1) debug("mapStyleId from prefs: $mapSourceId") val mapSource = when (mapSourceId) { 0 -> TileSourceFactory.MAPNIK From 0648ccad4be9a3001a26b0047898c65024ce4d0a Mon Sep 17 00:00:00 2001 From: PWRxPSYCHO Date: Wed, 24 Aug 2022 12:16:57 -0400 Subject: [PATCH 07/20] Moved Map Source menu to MapFragment --- .../java/com/geeksville/mesh/MainActivity.kt | 45 ++++++------------- .../com/geeksville/mesh/ui/MapFragment.kt | 33 +++++++++++++- app/src/main/res/layout/map_view.xml | 18 ++++++-- app/src/main/res/menu/menu_main.xml | 4 -- 4 files changed, 59 insertions(+), 41 deletions(-) diff --git a/app/src/main/java/com/geeksville/mesh/MainActivity.kt b/app/src/main/java/com/geeksville/mesh/MainActivity.kt index e38b7d5d7..d02041216 100644 --- a/app/src/main/java/com/geeksville/mesh/MainActivity.kt +++ b/app/src/main/java/com/geeksville/mesh/MainActivity.kt @@ -126,6 +126,7 @@ class MainActivity : BaseActivity(), Logging, // const val REQUEST_ENABLE_BT = 10 const val DID_REQUEST_PERM = 11 const val RC_SIGN_IN = 12 // google signin completed + // const val SELECT_DEVICE_REQUEST_CODE = 13 const val CREATE_CSV_FILE = 14 } @@ -331,7 +332,7 @@ class MainActivity : BaseActivity(), Logging, DID_REQUEST_PERM -> { // If request is cancelled, the result arrays are empty. if ((grantResults.isNotEmpty() && - grantResults[0] == PackageManager.PERMISSION_GRANTED) + grantResults[0] == PackageManager.PERMISSION_GRANTED) ) { // Permission is granted. Continue the action or workflow // in your app. @@ -665,7 +666,13 @@ class MainActivity : BaseActivity(), Logging, // model.setLocalConfig(LocalOnlyProtos.LocalConfig.parseFrom(service.deviceConfig)) - model.setChannels(ChannelSet(AppOnlyProtos.ChannelSet.parseFrom(service.channels))) + model.setChannels( + ChannelSet( + AppOnlyProtos.ChannelSet.parseFrom( + service.channels + ) + ) + ) model.updateNodesFromDevice() @@ -1073,14 +1080,10 @@ class MainActivity : BaseActivity(), Logging, chooseLangDialog() return true } - R.id.preferences_map_style -> { - chooseMapStyle() - return true - } R.id.show_intro -> { startActivity(Intent(this, AppIntroduction::class.java)) return true - } + } R.id.preferences_quick_chat -> { val fragmentManager: FragmentManager = supportFragmentManager val fragmentTransaction: FragmentTransaction = fragmentManager.beginTransaction() @@ -1193,7 +1196,10 @@ class MainActivity : BaseActivity(), Logging, val lang = prefs.getString("lang", "zz") debug("Lang from prefs: $lang") - builder.setSingleChoiceItems(languageLabels, languageValues.indexOf(lang)) { dialog, which -> + builder.setSingleChoiceItems( + languageLabels, + languageValues.indexOf(lang) + ) { dialog, which -> val selectedLang = languageValues[which] debug("Set lang pref to $selectedLang") editor.putString("lang", selectedLang) @@ -1203,27 +1209,4 @@ class MainActivity : BaseActivity(), Logging, val dialog = builder.create() dialog.show() } - - private fun chooseMapStyle() { - /// Prepare dialog and its items - val builder = MaterialAlertDialogBuilder(this) - builder.setTitle(getString(R.string.preferences_map_style)) - val mapStyles by lazy { resources.getStringArray(R.array.map_styles) } - - /// Load preferences and its value - val prefs = UIViewModel.getPreferences(this) - val editor: SharedPreferences.Editor = prefs.edit() - val mapStyleId = prefs.getInt("map_style_id", 1) - debug("mapStyleId from prefs: $mapStyleId") - - builder.setSingleChoiceItems(mapStyles, mapStyleId) { dialog, which -> - debug("Set mapStyleId pref to $which") - editor.putInt("map_style_id", which) - editor.apply() - dialog.dismiss() - } - val dialog = builder.create() - dialog.show() - } - } diff --git a/app/src/main/java/com/geeksville/mesh/ui/MapFragment.kt b/app/src/main/java/com/geeksville/mesh/ui/MapFragment.kt index bcda93187..566fce4a0 100644 --- a/app/src/main/java/com/geeksville/mesh/ui/MapFragment.kt +++ b/app/src/main/java/com/geeksville/mesh/ui/MapFragment.kt @@ -13,8 +13,10 @@ import com.geeksville.android.Logging import com.geeksville.mesh.BuildConfig import com.geeksville.mesh.NodeInfo import com.geeksville.mesh.R +import com.geeksville.mesh.databinding.MapViewBinding import com.geeksville.mesh.model.UIViewModel import com.geeksville.util.formatAgo +import com.google.android.material.dialog.MaterialAlertDialogBuilder import dagger.hilt.android.AndroidEntryPoint import org.osmdroid.api.IMapController import org.osmdroid.config.Configuration @@ -31,6 +33,7 @@ import org.osmdroid.views.overlay.Marker @AndroidEntryPoint class MapFragment : ScreenFragment("Map"), Logging { + private lateinit var binding: MapViewBinding private lateinit var map: MapView private lateinit var mapController: IMapController private lateinit var mPrefs: SharedPreferences @@ -54,10 +57,11 @@ class MapFragment : ScreenFragment("Map"), Logging { inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle? ): View { - map = MapView(inflater.context) + binding = MapViewBinding.inflate(inflater, container, false) + map = binding.map map.setDestroyMode(false) map.tag = mapTag - return map + return binding.root } override fun onViewCreated(viewIn: View, savedInstanceState: Bundle?) { @@ -74,6 +78,9 @@ class MapFragment : ScreenFragment("Map"), Logging { val point = GeoPoint(defaultLat, defaultLong) //White House Coordinates, Washington DC mapController.animateTo(point, defaultZoomLevel, defaultZoomSpeed) if (view != null) { + binding.fabStyleToggle.setOnClickListener { + chooseMapStyle() + } model.nodeDB.nodes.value?.let { nodes -> onNodesChanged(nodes.values) } @@ -87,6 +94,28 @@ class MapFragment : ScreenFragment("Map"), Logging { } } + private fun chooseMapStyle() { + /// Prepare dialog and its items + val builder = MaterialAlertDialogBuilder(context!!) + builder.setTitle(getString(R.string.preferences_map_style)) + val mapStyles by lazy { resources.getStringArray(R.array.map_styles) } + + /// Load preferences and its value + val prefs = UIViewModel.getPreferences(context!!) + val editor: SharedPreferences.Editor = prefs.edit() + val mapStyleId = prefs.getInt("map_style_id", 1) + debug("mapStyleId from prefs: $mapStyleId") + + builder.setSingleChoiceItems(mapStyles, mapStyleId) { dialog, which -> + debug("Set mapStyleId pref to $which") + editor.putInt("map_style_id", which) + editor.apply() + dialog.dismiss() + } + val dialog = builder.create() + dialog.show() + } + private fun onNodesChanged(nodes: Collection) { val nodesWithPosition = nodes.filter { it.validPosition != null } diff --git a/app/src/main/res/layout/map_view.xml b/app/src/main/res/layout/map_view.xml index a1a6e1265..7ed1b0c44 100644 --- a/app/src/main/res/layout/map_view.xml +++ b/app/src/main/res/layout/map_view.xml @@ -8,9 +8,19 @@ - + android:layout_height="match_parent" /> + \ No newline at end of file diff --git a/app/src/main/res/menu/menu_main.xml b/app/src/main/res/menu/menu_main.xml index 12ba21d62..d7817540f 100644 --- a/app/src/main/res/menu/menu_main.xml +++ b/app/src/main/res/menu/menu_main.xml @@ -32,10 +32,6 @@ android:id="@+id/preferences_language" android:title="@string/preferences_language" app:showAsAction="withText" /> - Date: Wed, 24 Aug 2022 13:38:06 -0400 Subject: [PATCH 08/20] updated strings to be constants, updated comment --- .../main/java/com/geeksville/mesh/ui/MapFragment.kt | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/app/src/main/java/com/geeksville/mesh/ui/MapFragment.kt b/app/src/main/java/com/geeksville/mesh/ui/MapFragment.kt index 566fce4a0..f5582b44d 100644 --- a/app/src/main/java/com/geeksville/mesh/ui/MapFragment.kt +++ b/app/src/main/java/com/geeksville/mesh/ui/MapFragment.kt @@ -103,12 +103,12 @@ class MapFragment : ScreenFragment("Map"), Logging { /// Load preferences and its value val prefs = UIViewModel.getPreferences(context!!) val editor: SharedPreferences.Editor = prefs.edit() - val mapStyleId = prefs.getInt("map_style_id", 1) - debug("mapStyleId from prefs: $mapStyleId") + val mapStyleInt = prefs.getInt(mapStyleId, 1) + debug("mapStyleId from prefs: $mapStyleInt") - builder.setSingleChoiceItems(mapStyles, mapStyleId) { dialog, which -> + builder.setSingleChoiceItems(mapStyles, mapStyleInt) { dialog, which -> debug("Set mapStyleId pref to $which") - editor.putInt("map_style_id", which) + editor.putInt(mapStyleId, which) editor.apply() dialog.dismiss() } @@ -159,7 +159,7 @@ class MapFragment : ScreenFragment("Map"), Logging { private fun setupMapProperties() { if (this::map.isInitialized) { map.isTilesScaledToDpi = - true // scales the map tiles to the display density of the + true // scales the map tiles to the display density of the screen map.minZoomLevel = defaultMinZoom // sets the minimum zoom level (the furthest out you can zoom) map.setMultiTouchControls(true) // Sets gesture controls to true From 6a6dbad0ee5fdf93e065430a2ffe9ad28abe0dad Mon Sep 17 00:00:00 2001 From: PWRxPSYCHO Date: Wed, 24 Aug 2022 14:27:12 -0400 Subject: [PATCH 09/20] Trying to get nodes to show better and defaulting to smaller tiles --- .../com/geeksville/mesh/ui/MapFragment.kt | 34 ++++++++----------- 1 file changed, 15 insertions(+), 19 deletions(-) diff --git a/app/src/main/java/com/geeksville/mesh/ui/MapFragment.kt b/app/src/main/java/com/geeksville/mesh/ui/MapFragment.kt index f5582b44d..4c89dedb9 100644 --- a/app/src/main/java/com/geeksville/mesh/ui/MapFragment.kt +++ b/app/src/main/java/com/geeksville/mesh/ui/MapFragment.kt @@ -39,9 +39,6 @@ class MapFragment : ScreenFragment("Map"), Logging { private lateinit var mPrefs: SharedPreferences private val model: UIViewModel by activityViewModels() - - private val defaultLat = 38.8976763 - private val defaultLong = -77.0365298 private val defaultMinZoom = 3.0 private val defaultZoomLevel = 6.0 private val defaultZoomSpeed = 3000L @@ -75,23 +72,22 @@ class MapFragment : ScreenFragment("Map"), Logging { setupMapProperties() loadOnlineTileSourceBase() mapController = map.controller - val point = GeoPoint(defaultLat, defaultLong) //White House Coordinates, Washington DC - mapController.animateTo(point, defaultZoomLevel, defaultZoomSpeed) - if (view != null) { - binding.fabStyleToggle.setOnClickListener { - chooseMapStyle() + map.let { + if (view != null) { + binding.fabStyleToggle.setOnClickListener { + chooseMapStyle() + } + model.nodeDB.nodes.value?.let { nodes -> + onNodesChanged(nodes.values) + } } - model.nodeDB.nodes.value?.let { nodes -> - onNodesChanged(nodes.values) - } - - zoomToNodes(mapController) - // Any times nodes change update our map - model.nodeDB.nodes.observe(viewLifecycleOwner) { nodes -> - onNodesChanged(nodes.values) - } - } + + // Any times nodes change update our map + model.nodeDB.nodes.observe(viewLifecycleOwner) { nodes -> + onNodesChanged(nodes.values) + } + zoomToNodes(mapController) } private fun chooseMapStyle() { @@ -205,7 +201,7 @@ class MapFragment : ScreenFragment("Map"), Logging { 5 -> TileSourceFactory.CLOUDMADESMALLTILES 6 -> TileSourceFactory.ChartbundleENRH 7 -> TileSourceFactory.ChartbundleWAC - else -> TileSourceFactory.MAPNIK + else -> TileSourceFactory.CLOUDMADESMALLTILES } return mapSource } From 3e81abb6383be9ffcbacdc32a1d27da9941bd54c Mon Sep 17 00:00:00 2001 From: PWRxPSYCHO Date: Wed, 24 Aug 2022 16:47:50 -0400 Subject: [PATCH 10/20] fixed zooming to nodes (lat/lon were reversed) --- .../com/geeksville/mesh/ui/MapFragment.kt | 26 +++++++++++-------- 1 file changed, 15 insertions(+), 11 deletions(-) diff --git a/app/src/main/java/com/geeksville/mesh/ui/MapFragment.kt b/app/src/main/java/com/geeksville/mesh/ui/MapFragment.kt index 4c89dedb9..9f7f0b135 100644 --- a/app/src/main/java/com/geeksville/mesh/ui/MapFragment.kt +++ b/app/src/main/java/com/geeksville/mesh/ui/MapFragment.kt @@ -1,6 +1,5 @@ package com.geeksville.mesh.ui - import android.content.Context import android.content.SharedPreferences import android.os.Bundle @@ -29,7 +28,6 @@ import org.osmdroid.views.MapView import org.osmdroid.views.overlay.CopyrightOverlay import org.osmdroid.views.overlay.Marker - @AndroidEntryPoint class MapFragment : ScreenFragment("Map"), Logging { @@ -40,7 +38,8 @@ class MapFragment : ScreenFragment("Map"), Logging { private val model: UIViewModel by activityViewModels() private val defaultMinZoom = 3.0 - private val defaultZoomLevel = 6.0 + + private val nodeZoomLevel = 8.5 private val defaultZoomSpeed = 3000L private val prefsName = "org.andnav.osm.prefs" private val prefsZoomLevelDouble = "prefsZoomLevelDouble" @@ -56,7 +55,6 @@ class MapFragment : ScreenFragment("Map"), Logging { ): View { binding = MapViewBinding.inflate(inflater, container, false) map = binding.map - map.setDestroyMode(false) map.tag = mapTag return binding.root } @@ -134,7 +132,7 @@ class MapFragment : ScreenFragment("Map"), Logging { requireActivity(), R.drawable.ic_twotone_person_pin_24 ) - map.invalidate() + map.overlays.add(marker) } f @@ -168,22 +166,28 @@ class MapFragment : ScreenFragment("Map"), Logging { val nodesWithPosition = model.nodeDB.nodes.value?.values?.filter { it.validPosition != null } if ((nodesWithPosition != null) && nodesWithPosition.isNotEmpty()) { - val unit = if (nodesWithPosition.size >= 2) { + if (nodesWithPosition.size >= 2) { // Multiple nodes, make them all fit on the map view nodesWithPosition.forEach { points.add( GeoPoint( - it.position!!.longitude, - it.position!!.latitude + it.position!!.latitude, + it.position!!.longitude ) ) } - map.zoomToBoundingBox(BoundingBox.fromGeoPoints(points), true) + map.zoomToBoundingBox( + BoundingBox.fromGeoPoints(points), + true, + 15, + nodeZoomLevel, + defaultZoomSpeed + ) } else { // Only one node, just zoom in on it val it = nodesWithPosition[0].position!! - points.add(GeoPoint(it.longitude, it.latitude)) - controller.animateTo(points[0], defaultZoomLevel, defaultZoomSpeed) + points.add(GeoPoint(it.latitude, it.longitude)) + controller.animateTo(points[0], nodeZoomLevel, defaultZoomSpeed) } } } From 19a847604e334ac807f445b10304f3da652db12b Mon Sep 17 00:00:00 2001 From: PWRxPSYCHO Date: Wed, 24 Aug 2022 23:15:48 -0400 Subject: [PATCH 11/20] fixed map being null on switch --- .../com/geeksville/mesh/ui/MapFragment.kt | 29 +++++++++++++------ 1 file changed, 20 insertions(+), 9 deletions(-) diff --git a/app/src/main/java/com/geeksville/mesh/ui/MapFragment.kt b/app/src/main/java/com/geeksville/mesh/ui/MapFragment.kt index 9f7f0b135..e959df185 100644 --- a/app/src/main/java/com/geeksville/mesh/ui/MapFragment.kt +++ b/app/src/main/java/com/geeksville/mesh/ui/MapFragment.kt @@ -53,9 +53,7 @@ class MapFragment : ScreenFragment("Map"), Logging { inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle? ): View { - binding = MapViewBinding.inflate(inflater, container, false) - map = binding.map - map.tag = mapTag + binding = MapViewBinding.inflate(inflater) return binding.root } @@ -63,7 +61,7 @@ class MapFragment : ScreenFragment("Map"), Logging { super.onViewCreated(viewIn, savedInstanceState) Configuration.getInstance().userAgentValue = BuildConfig.APPLICATION_ID // Required to get online tiles - + map = viewIn.findViewById(R.id.map) mPrefs = context!!.getSharedPreferences(prefsName, Context.MODE_PRIVATE) addCopyright() // Copyright is required for certain map sources @@ -132,7 +130,6 @@ class MapFragment : ScreenFragment("Map"), Logging { requireActivity(), R.drawable.ic_twotone_person_pin_24 ) - map.overlays.add(marker) } f @@ -152,6 +149,7 @@ class MapFragment : ScreenFragment("Map"), Logging { private fun setupMapProperties() { if (this::map.isInitialized) { + map.setDestroyMode(false) map.isTilesScaledToDpi = true // scales the map tiles to the display density of the screen map.minZoomLevel = @@ -202,10 +200,9 @@ class MapFragment : ScreenFragment("Map"), Logging { 2 -> TileSourceFactory.USGS_SAT 3 -> TileSourceFactory.OpenTopo 4 -> TileSourceFactory.ROADS_OVERLAY_NL - 5 -> TileSourceFactory.CLOUDMADESMALLTILES 6 -> TileSourceFactory.ChartbundleENRH 7 -> TileSourceFactory.ChartbundleWAC - else -> TileSourceFactory.CLOUDMADESMALLTILES + else -> TileSourceFactory.OpenTopo } return mapSource } @@ -227,11 +224,25 @@ class MapFragment : ScreenFragment("Map"), Logging { TileSourceFactory.DEFAULT_TILE_SOURCE.name() ) try { - val tileSource = TileSourceFactory.getTileSource(tileSourceName) - map.setTileSource(tileSource) + map.setTileSource(matchOnlineTileSourceBase(tileSourceName!!)) } catch (e: IllegalArgumentException) { map.setTileSource(TileSourceFactory.DEFAULT_TILE_SOURCE) } + map.onResume() + } + + private fun matchOnlineTileSourceBase(name: String): OnlineTileSourceBase { + val tileSourceBase = when (name) { + TileSourceFactory.MAPNIK.name() -> TileSourceFactory.MAPNIK + TileSourceFactory.USGS_TOPO.name() -> TileSourceFactory.USGS_TOPO + TileSourceFactory.USGS_SAT.name() -> TileSourceFactory.USGS_SAT + TileSourceFactory.ROADS_OVERLAY_NL.name() -> TileSourceFactory.ROADS_OVERLAY_NL + TileSourceFactory.ChartbundleENRH.name() -> TileSourceFactory.ChartbundleENRH + TileSourceFactory.ChartbundleWAC.name() -> TileSourceFactory.ChartbundleWAC + else -> TileSourceFactory.DEFAULT_TILE_SOURCE + } + return tileSourceBase + } override fun onDestroy() { From c57cee569f15855f54bdd2b8d4e24f2be164f462 Mon Sep 17 00:00:00 2001 From: PWRxPSYCHO Date: Wed, 24 Aug 2022 23:21:01 -0400 Subject: [PATCH 12/20] removed unused item --- app/src/main/res/values/arrays.xml | 82 ++++++++++++++++++++---------- 1 file changed, 54 insertions(+), 28 deletions(-) diff --git a/app/src/main/res/values/arrays.xml b/app/src/main/res/values/arrays.xml index 357dc973a..7b2d35efa 100644 --- a/app/src/main/res/values/arrays.xml +++ b/app/src/main/res/values/arrays.xml @@ -4,33 +4,60 @@ Use Custom URI? - @string/preferences_system_default - English - Čeština - Chinese 中文 - Deutsch - Español - Français - Gaeilge - Greek ελληνικά - Haiti - Italiano - Japanese 日本語 - Korean 한국어 - Magyar - Nederlands - Norge - Polski - Português - Português do Brasil - Română - Russian Pусский - Shqip - Slovenský - Slovenščina - Suomi - Svenska - Türkçe + + @string/preferences_system_default + + English + + Čeština + + Chinese 中文 + + Deutsch + + Español + + Français + + Gaeilge + + Greek ελληνικά + + Haiti + + Italiano + + Japanese 日本語 + + Korean 한국어 + + Magyar + + Nederlands + + Norge + + Polski + + Português + + Português do Brasil + + Română + + Russian Pусский + + Shqip + + Slovenský + + Slovenščina + + Suomi + + Svenska + + Türkçe @@ -68,7 +95,6 @@ USGS Satellite OpenTopo Roads Overlay NL - Cloud Made Small Tiles Chartbundle ENRH Chartbundle WAC From 29c1fe75d4c69cd2e4feadcc8483ed91ec74def0 Mon Sep 17 00:00:00 2001 From: PWRxPSYCHO Date: Thu, 25 Aug 2022 10:14:19 -0400 Subject: [PATCH 13/20] Removed map sources and added custom --- .../com/geeksville/mesh/ui/MapFragment.kt | 47 ++++++++++++++----- app/src/main/res/values/arrays.xml | 5 +- 2 files changed, 36 insertions(+), 16 deletions(-) diff --git a/app/src/main/java/com/geeksville/mesh/ui/MapFragment.kt b/app/src/main/java/com/geeksville/mesh/ui/MapFragment.kt index e959df185..30509b4e4 100644 --- a/app/src/main/java/com/geeksville/mesh/ui/MapFragment.kt +++ b/app/src/main/java/com/geeksville/mesh/ui/MapFragment.kt @@ -21,8 +21,10 @@ import org.osmdroid.api.IMapController import org.osmdroid.config.Configuration import org.osmdroid.tileprovider.tilesource.OnlineTileSourceBase import org.osmdroid.tileprovider.tilesource.TileSourceFactory +import org.osmdroid.tileprovider.tilesource.TileSourcePolicy import org.osmdroid.util.BoundingBox import org.osmdroid.util.GeoPoint +import org.osmdroid.util.MapTileIndex import org.osmdroid.views.CustomZoomButtonsController import org.osmdroid.views.MapView import org.osmdroid.views.overlay.CopyrightOverlay @@ -37,15 +39,15 @@ class MapFragment : ScreenFragment("Map"), Logging { private lateinit var mPrefs: SharedPreferences private val model: UIViewModel by activityViewModels() - private val defaultMinZoom = 3.0 + private lateinit var esriTileSource: OnlineTileSourceBase + private val defaultMinZoom = 3.0 private val nodeZoomLevel = 8.5 private val defaultZoomSpeed = 3000L private val prefsName = "org.andnav.osm.prefs" private val prefsZoomLevelDouble = "prefsZoomLevelDouble" private val prefsTileSource = "prefsTileSource" private val mapStyleId = "map_style_id" - private val mapTag = "mapView" private val uiPrefs = "ui-prefs" @@ -149,13 +151,14 @@ class MapFragment : ScreenFragment("Map"), Logging { private fun setupMapProperties() { if (this::map.isInitialized) { - map.setDestroyMode(false) + map.setDestroyMode(false) // keeps map instance alive when in the background. map.isTilesScaledToDpi = true // scales the map tiles to the display density of the screen map.minZoomLevel = defaultMinZoom // sets the minimum zoom level (the furthest out you can zoom) - map.setMultiTouchControls(true) // Sets gesture controls to true + map.setMultiTouchControls(true) // Sets gesture controls to true. map.zoomController.setVisibility(CustomZoomButtonsController.Visibility.NEVER) // Disables default +/- button for zooming + setESRITileSource() } } @@ -190,6 +193,30 @@ class MapFragment : ScreenFragment("Map"), Logging { } } + private fun setESRITileSource() { + esriTileSource = object : OnlineTileSourceBase( + "ESRI Clarity", 0, 18, 256, "", arrayOf( + "https://wayback.maptiles.arcgis.com/arcgis/rest/services/World_Imagery/WMTS/1.0.0/default028mm/MapServer/tile/" + ), "Esri, Maxar, Earthstar Geographics, and the GIS User Community" + + "URL\n" + + "View\n", + TileSourcePolicy( + 2, TileSourcePolicy.FLAG_NO_BULK + or TileSourcePolicy.FLAG_NO_PREVENTIVE + or TileSourcePolicy.FLAG_USER_AGENT_MEANINGFUL + or TileSourcePolicy.FLAG_USER_AGENT_NORMALIZED + ) + ) { + override fun getTileURLString(pMapTileIndex: Long): String { + return baseUrl + (MapTileIndex.getZoom(pMapTileIndex) + .toString() + "/" + MapTileIndex.getY(pMapTileIndex) + + "/" + MapTileIndex.getX(pMapTileIndex) + + mImageFilenameEnding) + } + + } + } + private fun loadOnlineTileSourceBase(): OnlineTileSourceBase { val prefs = context?.getSharedPreferences(uiPrefs, Context.MODE_PRIVATE) val mapSourceId = prefs?.getInt(mapStyleId, 1) @@ -198,11 +225,8 @@ class MapFragment : ScreenFragment("Map"), Logging { 0 -> TileSourceFactory.MAPNIK 1 -> TileSourceFactory.USGS_TOPO 2 -> TileSourceFactory.USGS_SAT - 3 -> TileSourceFactory.OpenTopo - 4 -> TileSourceFactory.ROADS_OVERLAY_NL - 6 -> TileSourceFactory.ChartbundleENRH - 7 -> TileSourceFactory.ChartbundleWAC - else -> TileSourceFactory.OpenTopo + 3 -> esriTileSource + else -> TileSourceFactory.DEFAULT_TILE_SOURCE } return mapSource } @@ -219,6 +243,7 @@ class MapFragment : ScreenFragment("Map"), Logging { override fun onResume() { super.onResume() + map.invalidate() val tileSourceName = mPrefs.getString( prefsTileSource, TileSourceFactory.DEFAULT_TILE_SOURCE.name() @@ -236,9 +261,7 @@ class MapFragment : ScreenFragment("Map"), Logging { TileSourceFactory.MAPNIK.name() -> TileSourceFactory.MAPNIK TileSourceFactory.USGS_TOPO.name() -> TileSourceFactory.USGS_TOPO TileSourceFactory.USGS_SAT.name() -> TileSourceFactory.USGS_SAT - TileSourceFactory.ROADS_OVERLAY_NL.name() -> TileSourceFactory.ROADS_OVERLAY_NL - TileSourceFactory.ChartbundleENRH.name() -> TileSourceFactory.ChartbundleENRH - TileSourceFactory.ChartbundleWAC.name() -> TileSourceFactory.ChartbundleWAC + esriTileSource.name() -> esriTileSource else -> TileSourceFactory.DEFAULT_TILE_SOURCE } return tileSourceBase diff --git a/app/src/main/res/values/arrays.xml b/app/src/main/res/values/arrays.xml index 7b2d35efa..60d35fbe3 100644 --- a/app/src/main/res/values/arrays.xml +++ b/app/src/main/res/values/arrays.xml @@ -93,9 +93,6 @@ OpenStreetMap USGS TOPO USGS Satellite - OpenTopo - Roads Overlay NL - Chartbundle ENRH - Chartbundle WAC + ESRI \ No newline at end of file From 2a2aacf7c35b076adffe2f3288de87ec57335437 Mon Sep 17 00:00:00 2001 From: PWRxPSYCHO Date: Thu, 25 Aug 2022 12:28:05 -0400 Subject: [PATCH 14/20] fixed zoom level and "unlimited" scroll --- app/src/main/java/com/geeksville/mesh/ui/MapFragment.kt | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/app/src/main/java/com/geeksville/mesh/ui/MapFragment.kt b/app/src/main/java/com/geeksville/mesh/ui/MapFragment.kt index 30509b4e4..0b35ef783 100644 --- a/app/src/main/java/com/geeksville/mesh/ui/MapFragment.kt +++ b/app/src/main/java/com/geeksville/mesh/ui/MapFragment.kt @@ -41,7 +41,7 @@ class MapFragment : ScreenFragment("Map"), Logging { private lateinit var esriTileSource: OnlineTileSourceBase - private val defaultMinZoom = 3.0 + private val defaultMinZoom = 1.5 private val nodeZoomLevel = 8.5 private val defaultZoomSpeed = 3000L private val prefsName = "org.andnav.osm.prefs" @@ -152,6 +152,12 @@ class MapFragment : ScreenFragment("Map"), Logging { private fun setupMapProperties() { if (this::map.isInitialized) { map.setDestroyMode(false) // keeps map instance alive when in the background. + map.isVerticalMapRepetitionEnabled = false // disables map repetition + map.setScrollableAreaLimitLatitude( + map.overlayManager.tilesOverlay.bounds.actualNorth, + map.overlayManager.tilesOverlay.bounds.actualSouth, + 0 + ) // bounds scollable map map.isTilesScaledToDpi = true // scales the map tiles to the display density of the screen map.minZoomLevel = From d491722e65467217d826516e5ca684d24cea5a54 Mon Sep 17 00:00:00 2001 From: PWRxPSYCHO Date: Thu, 25 Aug 2022 14:32:55 -0400 Subject: [PATCH 15/20] added style changing on the fly (will need to refactor) --- app/src/main/java/com/geeksville/mesh/ui/MapFragment.kt | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/app/src/main/java/com/geeksville/mesh/ui/MapFragment.kt b/app/src/main/java/com/geeksville/mesh/ui/MapFragment.kt index 0b35ef783..cc18f2113 100644 --- a/app/src/main/java/com/geeksville/mesh/ui/MapFragment.kt +++ b/app/src/main/java/com/geeksville/mesh/ui/MapFragment.kt @@ -66,8 +66,8 @@ class MapFragment : ScreenFragment("Map"), Logging { map = viewIn.findViewById(R.id.map) mPrefs = context!!.getSharedPreferences(prefsName, Context.MODE_PRIVATE) - addCopyright() // Copyright is required for certain map sources setupMapProperties() + addCopyright() // Copyright is required for certain map sources loadOnlineTileSourceBase() mapController = map.controller map.let { @@ -105,6 +105,7 @@ class MapFragment : ScreenFragment("Map"), Logging { editor.putInt(mapStyleId, which) editor.apply() dialog.dismiss() + map.setTileSource(loadOnlineTileSourceBase()) } val dialog = builder.create() dialog.show() @@ -157,7 +158,7 @@ class MapFragment : ScreenFragment("Map"), Logging { map.overlayManager.tilesOverlay.bounds.actualNorth, map.overlayManager.tilesOverlay.bounds.actualSouth, 0 - ) // bounds scollable map + ) // bounds scrollable map map.isTilesScaledToDpi = true // scales the map tiles to the display density of the screen map.minZoomLevel = @@ -201,7 +202,7 @@ class MapFragment : ScreenFragment("Map"), Logging { private fun setESRITileSource() { esriTileSource = object : OnlineTileSourceBase( - "ESRI Clarity", 0, 18, 256, "", arrayOf( + "ESRI World Overview", 0, 18, 256, "", arrayOf( "https://wayback.maptiles.arcgis.com/arcgis/rest/services/World_Imagery/WMTS/1.0.0/default028mm/MapServer/tile/" ), "Esri, Maxar, Earthstar Geographics, and the GIS User Community" + "URL\n" + From e23b226b550ec59e75d44762e9ead3e03ae4e888 Mon Sep 17 00:00:00 2001 From: PWRxPSYCHO Date: Thu, 25 Aug 2022 16:58:13 -0400 Subject: [PATCH 16/20] updated map reload --- app/src/main/java/com/geeksville/mesh/ui/MapFragment.kt | 1 + 1 file changed, 1 insertion(+) diff --git a/app/src/main/java/com/geeksville/mesh/ui/MapFragment.kt b/app/src/main/java/com/geeksville/mesh/ui/MapFragment.kt index cc18f2113..2ce93bf83 100644 --- a/app/src/main/java/com/geeksville/mesh/ui/MapFragment.kt +++ b/app/src/main/java/com/geeksville/mesh/ui/MapFragment.kt @@ -134,6 +134,7 @@ class MapFragment : ScreenFragment("Map"), Logging { R.drawable.ic_twotone_person_pin_24 ) map.overlays.add(marker) + map.invalidate() } f } From 767fb6059de356f3176a5d157ed07484863e4e7a Mon Sep 17 00:00:00 2001 From: PWRxPSYCHO Date: Thu, 25 Aug 2022 23:35:11 -0400 Subject: [PATCH 17/20] Updated ESRI name, Andre patch to add text over icon fixed zoomToBounding box fixed node locations duplicating on map --- .../com/geeksville/mesh/ui/MapFragment.kt | 99 ++++++++++++------- app/src/main/res/values/arrays.xml | 2 +- 2 files changed, 66 insertions(+), 35 deletions(-) diff --git a/app/src/main/java/com/geeksville/mesh/ui/MapFragment.kt b/app/src/main/java/com/geeksville/mesh/ui/MapFragment.kt index 2ce93bf83..192d7f6f5 100644 --- a/app/src/main/java/com/geeksville/mesh/ui/MapFragment.kt +++ b/app/src/main/java/com/geeksville/mesh/ui/MapFragment.kt @@ -2,6 +2,9 @@ package com.geeksville.mesh.ui import android.content.Context import android.content.SharedPreferences +import android.graphics.Canvas +import android.graphics.Color +import android.graphics.Paint import android.os.Bundle import android.view.LayoutInflater import android.view.View @@ -49,6 +52,8 @@ class MapFragment : ScreenFragment("Map"), Logging { private val prefsTileSource = "prefsTileSource" private val mapStyleId = "map_style_id" private val uiPrefs = "ui-prefs" + private var nodePositions = listOf() + private val nodeLayer = 1 override fun onCreateView( @@ -67,25 +72,25 @@ class MapFragment : ScreenFragment("Map"), Logging { mPrefs = context!!.getSharedPreferences(prefsName, Context.MODE_PRIVATE) setupMapProperties() - addCopyright() // Copyright is required for certain map sources loadOnlineTileSourceBase() - mapController = map.controller map.let { if (view != null) { + mapController = map.controller binding.fabStyleToggle.setOnClickListener { chooseMapStyle() } model.nodeDB.nodes.value?.let { nodes -> onNodesChanged(nodes.values) + drawOverlays() } } + // Any times nodes change update our map + model.nodeDB.nodes.observe(viewLifecycleOwner) { nodes -> + onNodesChanged(nodes.values) + drawOverlays() + } + zoomToNodes(mapController) } - - // Any times nodes change update our map - model.nodeDB.nodes.observe(viewLifecycleOwner) { nodes -> - onNodesChanged(nodes.values) - } - zoomToNodes(mapController) } private fun chooseMapStyle() { @@ -118,26 +123,34 @@ class MapFragment : ScreenFragment("Map"), Logging { * Using the latest nodedb, generate GeoPoint */ // Find all nodes with valid locations - - nodesWithPosition.map { node -> - val p = node.position!! - debug("Showing on map: $node") - val f = GeoPoint(p.latitude, p.longitude) - - node.user?.let { - val marker = Marker(map) - marker.title = it.longName + " " + formatAgo(p.time) - marker.setAnchor(Marker.ANCHOR_BOTTOM, Marker.ANCHOR_CENTER) - marker.position = f - marker.icon = ContextCompat.getDrawable( - requireActivity(), - R.drawable.ic_twotone_person_pin_24 - ) - map.overlays.add(marker) - map.invalidate() + fun getCurrentNodes(): List { + val mrkr = nodesWithPosition.map { node -> + val p = node.position!! + debug("Showing on map: $node") + val f = GeoPoint(p.latitude, p.longitude) + lateinit var marker: MarkerWithLabel + node.user?.let { + val label = it.longName + " " + formatAgo(p.time) + marker = MarkerWithLabel(map, label) + marker.title = label + marker.setAnchor(Marker.ANCHOR_CENTER, Marker.ANCHOR_CENTER) + marker.position = f + marker.icon = ContextCompat.getDrawable( + requireActivity(), + R.drawable.ic_twotone_person_pin_24 + ) + } + marker } - f + return mrkr } + nodePositions = getCurrentNodes() + } + + private fun drawOverlays() { + map.overlayManager.overlays().clear() + addCopyright() // Copyright is required for certain map sources + map.overlayManager.addAll(nodeLayer, nodePositions) } /** @@ -185,13 +198,9 @@ class MapFragment : ScreenFragment("Map"), Logging { ) ) } - map.zoomToBoundingBox( - BoundingBox.fromGeoPoints(points), - true, - 15, - nodeZoomLevel, - defaultZoomSpeed - ) + val box = BoundingBox.fromGeoPoints(points) + val point = GeoPoint(box.centerLatitude, box.centerLongitude) + controller.animateTo(point, nodeZoomLevel, defaultZoomSpeed) } else { // Only one node, just zoom in on it val it = nodesWithPosition[0].position!! @@ -241,7 +250,7 @@ class MapFragment : ScreenFragment("Map"), Logging { override fun onPause() { val edit = mPrefs.edit() - edit.putString(prefsTileSource, loadOnlineTileSourceBase().name()) + edit.putString(prefsTileSource, map.tileProvider.tileSource.name()) edit.putFloat(prefsZoomLevelDouble, map.zoomLevelDouble.toFloat()) edit.commit() @@ -280,6 +289,28 @@ class MapFragment : ScreenFragment("Map"), Logging { super.onDestroyView() map.onDetach() } + + private inner class MarkerWithLabel(mapView: MapView?, label: String) : Marker(mapView) { + val mLabel = label + + override fun draw(c: Canvas, osmv: MapView?, shadow: Boolean) { + draw(c, osmv) + } + + fun draw(c: Canvas, osmv: MapView?) { + super.draw(c, osmv, false) + + val p = mPositionPixels + + val textPaint = Paint() + textPaint.textSize = 50f + textPaint.color = Color.RED + textPaint.isAntiAlias = true + textPaint.textAlign = Paint.Align.CENTER + + c.drawText(mLabel, (p.x - 0).toFloat(), (p.y - 60).toFloat(), textPaint) + } + } } diff --git a/app/src/main/res/values/arrays.xml b/app/src/main/res/values/arrays.xml index 60d35fbe3..d5ae69b1c 100644 --- a/app/src/main/res/values/arrays.xml +++ b/app/src/main/res/values/arrays.xml @@ -93,6 +93,6 @@ OpenStreetMap USGS TOPO USGS Satellite - ESRI + ESRI World Overview \ No newline at end of file From 426bde986a1b65567166974c5e3a40afe28838b7 Mon Sep 17 00:00:00 2001 From: PWRxPSYCHO Date: Fri, 26 Aug 2022 17:00:08 -0400 Subject: [PATCH 18/20] Cleaned up code based on comments on PR --- .../geeksville/mesh/model/CustomTileSource.kt | 52 +++++++++++++++ .../com/geeksville/mesh/ui/MapFragment.kt | 65 ++----------------- 2 files changed, 56 insertions(+), 61 deletions(-) create mode 100644 app/src/main/java/com/geeksville/mesh/model/CustomTileSource.kt diff --git a/app/src/main/java/com/geeksville/mesh/model/CustomTileSource.kt b/app/src/main/java/com/geeksville/mesh/model/CustomTileSource.kt new file mode 100644 index 000000000..f6f915ea1 --- /dev/null +++ b/app/src/main/java/com/geeksville/mesh/model/CustomTileSource.kt @@ -0,0 +1,52 @@ +package com.geeksville.mesh.model + +import org.osmdroid.tileprovider.tilesource.ITileSource +import org.osmdroid.tileprovider.tilesource.OnlineTileSourceBase +import org.osmdroid.tileprovider.tilesource.TileSourceFactory +import org.osmdroid.tileprovider.tilesource.TileSourcePolicy +import org.osmdroid.util.MapTileIndex + + +class CustomTileSource { + companion object { + + val ESRI_IMAGERY = object : OnlineTileSourceBase( + "ESRI World Overview", 0, 18, 256, "", arrayOf( + "https://wayback.maptiles.arcgis.com/arcgis/rest/services/World_Imagery/WMTS/1.0.0/default028mm/MapServer/tile/" + ), "Esri, Maxar, Earthstar Geographics, and the GIS User Community" + + "URL\n" + + "View\n", + TileSourcePolicy( + 2, TileSourcePolicy.FLAG_NO_BULK + or TileSourcePolicy.FLAG_NO_PREVENTIVE + or TileSourcePolicy.FLAG_USER_AGENT_MEANINGFUL + or TileSourcePolicy.FLAG_USER_AGENT_NORMALIZED + ) + ) { + override fun getTileURLString(pMapTileIndex: Long): String { + return baseUrl + (MapTileIndex.getZoom(pMapTileIndex) + .toString() + "/" + MapTileIndex.getY(pMapTileIndex) + + "/" + MapTileIndex.getX(pMapTileIndex) + + mImageFilenameEnding) + } + } + val MAPNIK: OnlineTileSourceBase = TileSourceFactory.MAPNIK + val USGS_TOPO: OnlineTileSourceBase = TileSourceFactory.USGS_TOPO + val USGS_SAT: OnlineTileSourceBase = TileSourceFactory.USGS_SAT + val DEFAULT_TILE_SOURCE: OnlineTileSourceBase = TileSourceFactory.DEFAULT_TILE_SOURCE + + val mTileSources: List = + listOf(MAPNIK, USGS_TOPO, USGS_SAT, ESRI_IMAGERY) + + + fun getTileSource(aName: String): ITileSource { + for (tileSource: ITileSource in mTileSources) { + if (tileSource.name().equals(aName)) { + return tileSource; + } + } + throw IllegalArgumentException("No such tile source: $aName") + } + } + +} \ No newline at end of file diff --git a/app/src/main/java/com/geeksville/mesh/ui/MapFragment.kt b/app/src/main/java/com/geeksville/mesh/ui/MapFragment.kt index 192d7f6f5..19a627dcd 100644 --- a/app/src/main/java/com/geeksville/mesh/ui/MapFragment.kt +++ b/app/src/main/java/com/geeksville/mesh/ui/MapFragment.kt @@ -16,12 +16,14 @@ import com.geeksville.mesh.BuildConfig import com.geeksville.mesh.NodeInfo import com.geeksville.mesh.R import com.geeksville.mesh.databinding.MapViewBinding +import com.geeksville.mesh.model.CustomTileSource import com.geeksville.mesh.model.UIViewModel import com.geeksville.util.formatAgo import com.google.android.material.dialog.MaterialAlertDialogBuilder import dagger.hilt.android.AndroidEntryPoint import org.osmdroid.api.IMapController import org.osmdroid.config.Configuration +import org.osmdroid.tileprovider.tilesource.ITileSource import org.osmdroid.tileprovider.tilesource.OnlineTileSourceBase import org.osmdroid.tileprovider.tilesource.TileSourceFactory import org.osmdroid.tileprovider.tilesource.TileSourcePolicy @@ -179,7 +181,6 @@ class MapFragment : ScreenFragment("Map"), Logging { defaultMinZoom // sets the minimum zoom level (the furthest out you can zoom) map.setMultiTouchControls(true) // Sets gesture controls to true. map.zoomController.setVisibility(CustomZoomButtonsController.Visibility.NEVER) // Disables default +/- button for zooming - setESRITileSource() } } @@ -210,81 +211,23 @@ class MapFragment : ScreenFragment("Map"), Logging { } } - private fun setESRITileSource() { - esriTileSource = object : OnlineTileSourceBase( - "ESRI World Overview", 0, 18, 256, "", arrayOf( - "https://wayback.maptiles.arcgis.com/arcgis/rest/services/World_Imagery/WMTS/1.0.0/default028mm/MapServer/tile/" - ), "Esri, Maxar, Earthstar Geographics, and the GIS User Community" + - "URL\n" + - "View\n", - TileSourcePolicy( - 2, TileSourcePolicy.FLAG_NO_BULK - or TileSourcePolicy.FLAG_NO_PREVENTIVE - or TileSourcePolicy.FLAG_USER_AGENT_MEANINGFUL - or TileSourcePolicy.FLAG_USER_AGENT_NORMALIZED - ) - ) { - override fun getTileURLString(pMapTileIndex: Long): String { - return baseUrl + (MapTileIndex.getZoom(pMapTileIndex) - .toString() + "/" + MapTileIndex.getY(pMapTileIndex) - + "/" + MapTileIndex.getX(pMapTileIndex) - + mImageFilenameEnding) - } - - } - } - - private fun loadOnlineTileSourceBase(): OnlineTileSourceBase { + private fun loadOnlineTileSourceBase(): ITileSource { val prefs = context?.getSharedPreferences(uiPrefs, Context.MODE_PRIVATE) val mapSourceId = prefs?.getInt(mapStyleId, 1) debug("mapStyleId from prefs: $mapSourceId") - val mapSource = when (mapSourceId) { - 0 -> TileSourceFactory.MAPNIK - 1 -> TileSourceFactory.USGS_TOPO - 2 -> TileSourceFactory.USGS_SAT - 3 -> esriTileSource - else -> TileSourceFactory.DEFAULT_TILE_SOURCE - } - return mapSource + return CustomTileSource.mTileSources[mapSourceId!!] } override fun onPause() { - val edit = mPrefs.edit() - edit.putString(prefsTileSource, map.tileProvider.tileSource.name()) - edit.putFloat(prefsZoomLevelDouble, map.zoomLevelDouble.toFloat()) - edit.commit() - map.onPause() super.onPause() } override fun onResume() { super.onResume() - map.invalidate() - val tileSourceName = mPrefs.getString( - prefsTileSource, - TileSourceFactory.DEFAULT_TILE_SOURCE.name() - ) - try { - map.setTileSource(matchOnlineTileSourceBase(tileSourceName!!)) - } catch (e: IllegalArgumentException) { - map.setTileSource(TileSourceFactory.DEFAULT_TILE_SOURCE) - } map.onResume() } - private fun matchOnlineTileSourceBase(name: String): OnlineTileSourceBase { - val tileSourceBase = when (name) { - TileSourceFactory.MAPNIK.name() -> TileSourceFactory.MAPNIK - TileSourceFactory.USGS_TOPO.name() -> TileSourceFactory.USGS_TOPO - TileSourceFactory.USGS_SAT.name() -> TileSourceFactory.USGS_SAT - esriTileSource.name() -> esriTileSource - else -> TileSourceFactory.DEFAULT_TILE_SOURCE - } - return tileSourceBase - - } - override fun onDestroy() { super.onDestroyView() map.onDetach() From 18d9541d9b97f1cd073a9054ab1feafe177110ac Mon Sep 17 00:00:00 2001 From: PWRxPSYCHO Date: Sat, 27 Aug 2022 08:57:01 -0400 Subject: [PATCH 19/20] removed unused variables and imports --- .../java/com/geeksville/mesh/model/CustomTileSource.kt | 3 +++ app/src/main/java/com/geeksville/mesh/ui/MapFragment.kt | 7 ------- 2 files changed, 3 insertions(+), 7 deletions(-) diff --git a/app/src/main/java/com/geeksville/mesh/model/CustomTileSource.kt b/app/src/main/java/com/geeksville/mesh/model/CustomTileSource.kt index f6f915ea1..e7b680115 100644 --- a/app/src/main/java/com/geeksville/mesh/model/CustomTileSource.kt +++ b/app/src/main/java/com/geeksville/mesh/model/CustomTileSource.kt @@ -35,6 +35,9 @@ class CustomTileSource { val USGS_SAT: OnlineTileSourceBase = TileSourceFactory.USGS_SAT val DEFAULT_TILE_SOURCE: OnlineTileSourceBase = TileSourceFactory.DEFAULT_TILE_SOURCE + /** + * The order in this list must match that in the arrays.xml under map_styles + */ val mTileSources: List = listOf(MAPNIK, USGS_TOPO, USGS_SAT, ESRI_IMAGERY) diff --git a/app/src/main/java/com/geeksville/mesh/ui/MapFragment.kt b/app/src/main/java/com/geeksville/mesh/ui/MapFragment.kt index 19a627dcd..45f055df0 100644 --- a/app/src/main/java/com/geeksville/mesh/ui/MapFragment.kt +++ b/app/src/main/java/com/geeksville/mesh/ui/MapFragment.kt @@ -25,11 +25,8 @@ import org.osmdroid.api.IMapController import org.osmdroid.config.Configuration import org.osmdroid.tileprovider.tilesource.ITileSource import org.osmdroid.tileprovider.tilesource.OnlineTileSourceBase -import org.osmdroid.tileprovider.tilesource.TileSourceFactory -import org.osmdroid.tileprovider.tilesource.TileSourcePolicy import org.osmdroid.util.BoundingBox import org.osmdroid.util.GeoPoint -import org.osmdroid.util.MapTileIndex import org.osmdroid.views.CustomZoomButtonsController import org.osmdroid.views.MapView import org.osmdroid.views.overlay.CopyrightOverlay @@ -44,14 +41,10 @@ class MapFragment : ScreenFragment("Map"), Logging { private lateinit var mPrefs: SharedPreferences private val model: UIViewModel by activityViewModels() - private lateinit var esriTileSource: OnlineTileSourceBase - private val defaultMinZoom = 1.5 private val nodeZoomLevel = 8.5 private val defaultZoomSpeed = 3000L private val prefsName = "org.andnav.osm.prefs" - private val prefsZoomLevelDouble = "prefsZoomLevelDouble" - private val prefsTileSource = "prefsTileSource" private val mapStyleId = "map_style_id" private val uiPrefs = "ui-prefs" private var nodePositions = listOf() From af78188d6eb3084526fb9c9088da22fb4a65fa5e Mon Sep 17 00:00:00 2001 From: PWRxPSYCHO Date: Sat, 27 Aug 2022 12:38:42 -0400 Subject: [PATCH 20/20] clean up unused files. (Patch from Andre) --- .../com/geeksville/mesh/ui/MapFragment.kt | 1 - .../drawable/baseline_download_white_24dp.xml | 6 ------ .../baseline_location_on_white_24dp.xml | 6 ------ .../main/res/layout/dialog_map_download.xml | 19 ------------------- .../main/res/layout/item_gesture_alert.xml | 14 -------------- .../res/layout/offline_region_manager.xml | 14 -------------- app/src/main/res/layout/user_icon_menu.xml | 19 ------------------- app/src/main/res/values/arrays.xml | 3 --- 8 files changed, 82 deletions(-) delete mode 100644 app/src/main/res/drawable/baseline_download_white_24dp.xml delete mode 100644 app/src/main/res/drawable/baseline_location_on_white_24dp.xml delete mode 100644 app/src/main/res/layout/dialog_map_download.xml delete mode 100644 app/src/main/res/layout/item_gesture_alert.xml delete mode 100644 app/src/main/res/layout/offline_region_manager.xml delete mode 100644 app/src/main/res/layout/user_icon_menu.xml diff --git a/app/src/main/java/com/geeksville/mesh/ui/MapFragment.kt b/app/src/main/java/com/geeksville/mesh/ui/MapFragment.kt index 45f055df0..fcfc5f9d9 100644 --- a/app/src/main/java/com/geeksville/mesh/ui/MapFragment.kt +++ b/app/src/main/java/com/geeksville/mesh/ui/MapFragment.kt @@ -24,7 +24,6 @@ import dagger.hilt.android.AndroidEntryPoint import org.osmdroid.api.IMapController import org.osmdroid.config.Configuration import org.osmdroid.tileprovider.tilesource.ITileSource -import org.osmdroid.tileprovider.tilesource.OnlineTileSourceBase import org.osmdroid.util.BoundingBox import org.osmdroid.util.GeoPoint import org.osmdroid.views.CustomZoomButtonsController diff --git a/app/src/main/res/drawable/baseline_download_white_24dp.xml b/app/src/main/res/drawable/baseline_download_white_24dp.xml deleted file mode 100644 index 41ed7875b..000000000 --- a/app/src/main/res/drawable/baseline_download_white_24dp.xml +++ /dev/null @@ -1,6 +0,0 @@ - - - - - - diff --git a/app/src/main/res/drawable/baseline_location_on_white_24dp.xml b/app/src/main/res/drawable/baseline_location_on_white_24dp.xml deleted file mode 100644 index 8b4720d58..000000000 --- a/app/src/main/res/drawable/baseline_location_on_white_24dp.xml +++ /dev/null @@ -1,6 +0,0 @@ - - - - - - diff --git a/app/src/main/res/layout/dialog_map_download.xml b/app/src/main/res/layout/dialog_map_download.xml deleted file mode 100644 index 7c205e88b..000000000 --- a/app/src/main/res/layout/dialog_map_download.xml +++ /dev/null @@ -1,19 +0,0 @@ - - - - - \ No newline at end of file diff --git a/app/src/main/res/layout/item_gesture_alert.xml b/app/src/main/res/layout/item_gesture_alert.xml deleted file mode 100644 index 797354b11..000000000 --- a/app/src/main/res/layout/item_gesture_alert.xml +++ /dev/null @@ -1,14 +0,0 @@ - - - - - - \ No newline at end of file diff --git a/app/src/main/res/layout/offline_region_manager.xml b/app/src/main/res/layout/offline_region_manager.xml deleted file mode 100644 index 397e1a8c6..000000000 --- a/app/src/main/res/layout/offline_region_manager.xml +++ /dev/null @@ -1,14 +0,0 @@ - - - - - - \ No newline at end of file diff --git a/app/src/main/res/layout/user_icon_menu.xml b/app/src/main/res/layout/user_icon_menu.xml deleted file mode 100644 index 88d8f5ec1..000000000 --- a/app/src/main/res/layout/user_icon_menu.xml +++ /dev/null @@ -1,19 +0,0 @@ - - - - - - diff --git a/app/src/main/res/values/arrays.xml b/app/src/main/res/values/arrays.xml index d5ae69b1c..38fea1c72 100644 --- a/app/src/main/res/values/arrays.xml +++ b/app/src/main/res/values/arrays.xml @@ -1,8 +1,5 @@ - - Use Custom URI? - @string/preferences_system_default