checkpoint
This commit is contained in:
		
							parent
							
								
									d943b206fa
								
							
						
					
					
						commit
						e26bd2bf9a
					
				
					 9 changed files with 106 additions and 49 deletions
				
			
		|  | @ -53,11 +53,11 @@ class Database(val trackbook: Trackbook) | |||
|         this.connection.endTransaction() | ||||
|     } | ||||
| 
 | ||||
|     fun insert_trkpt(device_id: String, trkpt: Trkpt) | ||||
|     fun insert_trkpt(trkpt: Trkpt) | ||||
|     { | ||||
|         Log.i("VOUSSOIR", "Database.insert_trkpt") | ||||
|         val values = ContentValues().apply { | ||||
|             put("device_id", device_id) | ||||
|             put("device_id", trkpt.device_id) | ||||
|             put("lat", trkpt.latitude) | ||||
|             put("lon", trkpt.longitude) | ||||
|             put("time", GregorianCalendar.getInstance().time.time) | ||||
|  |  | |||
|  | @ -98,7 +98,7 @@ object Keys { | |||
|     const val DEFAULT_ACCURACY: Float = 300f                                    // in meters | ||||
|     const val DEFAULT_ALTITUDE: Double = 0.0 | ||||
|     const val DEFAULT_TIME: Long = 0L | ||||
|     const val COMMIT_INTERVAL: Int = 30 | ||||
|     const val COMMIT_INTERVAL: Long = 30 * ONE_SECOND_IN_MILLISECONDS | ||||
|     const val DEFAULT_THRESHOLD_LOCATION_ACCURACY: Int = 30                     // 30 meters | ||||
|     const val DEFAULT_THRESHOLD_LOCATION_AGE: Long = 5_000_000_000L             // 5s in nanoseconds | ||||
|     const val DEFAULT_THRESHOLD_DISTANCE: Float = 15f                           // 15 meters | ||||
|  |  | |||
|  | @ -40,6 +40,7 @@ import androidx.fragment.app.Fragment | |||
| import com.google.android.material.floatingactionbutton.ExtendedFloatingActionButton | ||||
| import com.google.android.material.floatingactionbutton.FloatingActionButton | ||||
| import com.google.android.material.snackbar.Snackbar | ||||
| import org.osmdroid.api.IGeoPoint | ||||
| import org.osmdroid.api.IMapController | ||||
| import org.osmdroid.events.MapEventsReceiver | ||||
| import org.osmdroid.tileprovider.tilesource.TileSourceFactory | ||||
|  | @ -136,8 +137,7 @@ class MapFragment : Fragment() | |||
|         mapView.setTileSource(TileSourceFactory.MAPNIK) | ||||
|         mapView.setMultiTouchControls(true) | ||||
|         mapView.zoomController.setVisibility(org.osmdroid.views.CustomZoomButtonsController.Visibility.NEVER) | ||||
|         zoomLevel = PreferencesHelper.loadZoomLevel() | ||||
|         mapView.controller.setZoom(zoomLevel) | ||||
|         mapView.controller.setZoom(Keys.DEFAULT_ZOOM_LEVEL) | ||||
| 
 | ||||
|         if (AppThemeHelper.isDarkModeOn(requireActivity())) | ||||
|         { | ||||
|  | @ -214,7 +214,6 @@ class MapFragment : Fragment() | |||
| 
 | ||||
|         mapView.setOnTouchListener { v, event -> | ||||
|             continuous_auto_center = false | ||||
|             zoomLevel = mapView.zoomLevelDouble | ||||
|             false | ||||
|         } | ||||
| 
 | ||||
|  | @ -226,12 +225,10 @@ class MapFragment : Fragment() | |||
|             centerMap(currentBestLocation, animated=true) | ||||
|         } | ||||
|         zoom_in_button.setOnClickListener { | ||||
|             zoomLevel += 0.5 | ||||
|             mapView.controller.zoomTo(mapView.zoomLevelDouble + 0.5, 0) | ||||
|             mapView.controller.setZoom(mapView.zoomLevelDouble + 0.5) | ||||
|         } | ||||
|         zoom_out_button.setOnClickListener { | ||||
|             zoomLevel -= 0.5 | ||||
|             mapView.controller.zoomTo(mapView.zoomLevelDouble - 0.5, 0) | ||||
|             mapView.controller.setZoom(mapView.zoomLevelDouble - 0.5) | ||||
|         } | ||||
| 
 | ||||
|         requireActivity().window.addFlags(WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON) | ||||
|  | @ -533,15 +530,15 @@ class MapFragment : Fragment() | |||
|     } | ||||
| 
 | ||||
|     /* Overlay current track on map */ | ||||
|     fun create_current_track_overlay(trkpts: Collection<Trkpt>, trackingState: Int) | ||||
|     fun create_current_track_overlay(geopoints: MutableList<IGeoPoint>, trackingState: Int) | ||||
|     { | ||||
|         if (currentTrackOverlay != null) | ||||
|         { | ||||
|             mapView.overlays.remove(currentTrackOverlay) | ||||
|         } | ||||
|         if (trkpts.isNotEmpty()) | ||||
|         if (geopoints.isNotEmpty()) | ||||
|         { | ||||
|             currentTrackOverlay = createTrackOverlay(requireContext(), mapView, trkpts, trackingState) | ||||
|             currentTrackOverlay = createTrackOverlay(requireContext(), mapView, geopoints, trackingState) | ||||
|         } | ||||
|     } | ||||
| 
 | ||||
|  | @ -620,7 +617,7 @@ class MapFragment : Fragment() | |||
|             trackingState = trackerService.trackingState | ||||
|             // update location and track | ||||
|             create_current_position_overlays(currentBestLocation, trackingState) | ||||
|             create_current_track_overlay(trackerService.recent_trkpts, trackingState) | ||||
|             create_current_track_overlay(trackerService.recent_trackpoints_for_mapview, trackingState) | ||||
|             // center map, if it had not been dragged/zoomed before | ||||
|             if (continuous_auto_center) | ||||
|             { | ||||
|  |  | |||
|  | @ -42,6 +42,9 @@ data class Track ( | |||
|     fun delete() | ||||
|     { | ||||
|         Log.i("VOUSSOIR", "Track.delete ${device_id} ${start_time} -- ${end_time}.") | ||||
|         database.begin_transaction() | ||||
|         database.connection.delete("trkpt", "device_id = ? AND time > ? AND time < ?", arrayOf(device_id, start_time.time.toString(), end_time.time.toString())) | ||||
|         database.commit() | ||||
|     } | ||||
| 
 | ||||
|     fun export_gpx(context: Context, fileuri: Uri): Uri? | ||||
|  | @ -183,6 +186,7 @@ data class Track ( | |||
|             while (cursor.moveToNext()) | ||||
|             { | ||||
|                 val trkpt = Trkpt( | ||||
|                     device_id=device_id, | ||||
|                     provider="", | ||||
|                     latitude=cursor.getDouble(COLUMN_LAT), | ||||
|                     longitude=cursor.getDouble(COLUMN_LON), | ||||
|  |  | |||
|  | @ -38,7 +38,9 @@ import androidx.constraintlayout.widget.Group | |||
| import androidx.core.widget.NestedScrollView | ||||
| import androidx.fragment.app.Fragment | ||||
| import com.google.android.material.bottomsheet.BottomSheetBehavior | ||||
| import com.google.android.material.floatingactionbutton.FloatingActionButton | ||||
| import com.google.android.material.textview.MaterialTextView | ||||
| import org.osmdroid.api.IGeoPoint | ||||
| import org.osmdroid.api.IMapController | ||||
| import org.osmdroid.events.MapListener | ||||
| import org.osmdroid.events.ScrollEvent | ||||
|  | @ -65,6 +67,8 @@ class TrackFragment : Fragment(), MapListener, YesNoDialog.YesNoDialogListener | |||
|     lateinit var rootView: View | ||||
|     lateinit var save_track_button: ImageButton | ||||
|     lateinit var deleteButton: ImageButton | ||||
|     lateinit var zoom_in_button: FloatingActionButton | ||||
|     lateinit var zoom_out_button: FloatingActionButton | ||||
|     lateinit var trackNameView: MaterialTextView | ||||
|     lateinit var track_query_start_date: DatePicker | ||||
|     lateinit var track_query_start_time: TimePicker | ||||
|  | @ -113,6 +117,8 @@ class TrackFragment : Fragment(), MapListener, YesNoDialog.YesNoDialogListener | |||
|         mapView = rootView.findViewById(R.id.map) | ||||
|         save_track_button = rootView.findViewById(R.id.save_button) | ||||
|         deleteButton = rootView.findViewById(R.id.delete_button) | ||||
|         zoom_in_button = rootView.findViewById(R.id.zoom_in_button) | ||||
|         zoom_out_button = rootView.findViewById(R.id.zoom_out_button) | ||||
|         trackNameView = rootView.findViewById(R.id.statistics_track_name_headline) | ||||
| 
 | ||||
|         controller = mapView.controller | ||||
|  | @ -235,6 +241,13 @@ class TrackFragment : Fragment(), MapListener, YesNoDialog.YesNoDialogListener | |||
|             ) | ||||
|         } | ||||
| 
 | ||||
|         zoom_in_button.setOnClickListener { | ||||
|             mapView.controller.zoomTo(mapView.zoomLevelDouble + 0.5, 0) | ||||
|         } | ||||
|         zoom_out_button.setOnClickListener { | ||||
|             mapView.controller.zoomTo(mapView.zoomLevelDouble - 0.5, 0) | ||||
|         } | ||||
| 
 | ||||
|         statisticsSheetBehavior = BottomSheetBehavior.from<View>(statisticsSheet) | ||||
|         statisticsSheetBehavior.state = BottomSheetBehavior.STATE_COLLAPSED | ||||
| 
 | ||||
|  | @ -260,9 +273,14 @@ class TrackFragment : Fragment(), MapListener, YesNoDialog.YesNoDialogListener | |||
|         { | ||||
|             mapView.overlays.remove(track_overlay) | ||||
|         } | ||||
|         val geopoints: MutableList<IGeoPoint> = mutableListOf() | ||||
|         for (trkpt in track.trkpts) | ||||
|         { | ||||
|             geopoints.add(trkpt) | ||||
|         } | ||||
|         if (track.trkpts.isNotEmpty()) | ||||
|         { | ||||
|             track_overlay = createTrackOverlay(requireContext(), mapView, track.trkpts, Keys.STATE_TRACKING_STOPPED) | ||||
|             track_overlay = createTrackOverlay(requireContext(), mapView, geopoints, Keys.STATE_TRACKING_STOPPED) | ||||
|             special_points_overlay = create_start_end_markers(requireContext(), mapView, track.trkpts) | ||||
|         } | ||||
|         setupStatisticsViews() | ||||
|  |  | |||
|  | @ -30,6 +30,9 @@ import android.Manifest | |||
| import android.os.* | ||||
| import android.util.Log | ||||
| import androidx.core.content.ContextCompat | ||||
| import org.osmdroid.api.IGeoPoint | ||||
| import org.osmdroid.util.GeoPoint | ||||
| import org.osmdroid.views.overlay.simplefastpoint.LabelledGeoPoint | ||||
| import java.util.* | ||||
| import org.y20k.trackbook.helpers.* | ||||
| 
 | ||||
|  | @ -53,6 +56,7 @@ class TrackerService: Service() | |||
|     private val RECENT_TRKPT_COUNT = 7200 | ||||
|     lateinit var recent_trkpts: Deque<Trkpt> | ||||
|     lateinit var recent_displacement_trkpts: Deque<Trkpt> | ||||
|     var recent_trackpoints_for_mapview: MutableList<IGeoPoint> = mutableListOf() | ||||
|     var gpsLocationListenerRegistered: Boolean = false | ||||
|     var networkLocationListenerRegistered: Boolean = false | ||||
|     var bound: Boolean = false | ||||
|  | @ -197,14 +201,20 @@ class TrackerService: Service() | |||
|                     return | ||||
|                 } | ||||
| 
 | ||||
|                 val trkpt = Trkpt(location=location) | ||||
|                 trackbook.database.insert_trkpt(device_id, trkpt) | ||||
|                 val trkpt = Trkpt(device_id=device_id, location=location) | ||||
|                 trackbook.database.insert_trkpt(trkpt) | ||||
|                 recent_trkpts.add(trkpt) | ||||
|                 while (recent_trkpts.size > RECENT_TRKPT_COUNT) | ||||
|                 { | ||||
|                     recent_trkpts.removeFirst() | ||||
|                 } | ||||
| 
 | ||||
|                 recent_trackpoints_for_mapview.add(trkpt) | ||||
|                 while (recent_trackpoints_for_mapview.size > RECENT_TRKPT_COUNT) | ||||
|                 { | ||||
|                     recent_trackpoints_for_mapview.removeFirst() | ||||
|                 } | ||||
| 
 | ||||
|                 recent_displacement_trkpts.add(trkpt) | ||||
|                 while (recent_displacement_trkpts.size > 5) | ||||
|                 { | ||||
|  | @ -266,6 +276,7 @@ class TrackerService: Service() | |||
|         trackbook.load_homepoints() | ||||
|         recent_trkpts = ArrayDeque<Trkpt>(RECENT_TRKPT_COUNT) | ||||
|         recent_displacement_trkpts = ArrayDeque<Trkpt>(5) | ||||
|         recent_trackpoints_for_mapview = mutableListOf() | ||||
|         use_gps_location = PreferencesHelper.load_location_gps() | ||||
|         use_network_location = PreferencesHelper.load_location_network() | ||||
|         device_id = PreferencesHelper.load_device_id() | ||||
|  |  | |||
|  | @ -17,19 +17,23 @@ | |||
| package org.y20k.trackbook | ||||
| 
 | ||||
| import android.location.Location | ||||
| import org.osmdroid.api.IGeoPoint | ||||
| import org.osmdroid.util.GeoPoint | ||||
| import org.y20k.trackbook.helpers.getNumberOfSatellites | ||||
| 
 | ||||
| data class Trkpt( | ||||
| class Trkpt( | ||||
|     val device_id: String, | ||||
|     val provider: String, | ||||
|     val latitude: Double, | ||||
|     val longitude: Double, | ||||
|     val altitude: Double, | ||||
|     latitude: Double, | ||||
|     longitude: Double, | ||||
|     altitude: Double, | ||||
|     val accuracy: Float, | ||||
|     val time: Long, | ||||
|     val numberSatellites: Int = 0, | ||||
| ) | ||||
| ) : GeoPoint(latitude, longitude, altitude) | ||||
| { | ||||
|     constructor(location: Location) : this ( | ||||
|     constructor(device_id: String, location: Location) : this( | ||||
|         device_id=device_id, | ||||
|         provider=location.provider.toString(), | ||||
|         latitude=location.latitude, | ||||
|         longitude=location.longitude, | ||||
|  | @ -48,4 +52,4 @@ data class Trkpt( | |||
|         location.time = this.time | ||||
|         return location | ||||
|     } | ||||
| } | ||||
| } | ||||
|  | @ -37,16 +37,10 @@ import java.text.DecimalFormat | |||
| import java.text.SimpleDateFormat | ||||
| import java.util.* | ||||
| 
 | ||||
| fun createTrackOverlay(context: Context, map_view: MapView, trkpts: Collection<Trkpt>, trackingState: Int): SimpleFastPointOverlay | ||||
| fun createTrackOverlay(context: Context, map_view: MapView, geopoints: MutableList<IGeoPoint>, trackingState: Int): SimpleFastPointOverlay | ||||
| { | ||||
|     Log.i("VOUSSOIR", "MapOverlayHelper.createTrackOverlay") | ||||
|     val trackpoints: MutableList<IGeoPoint> = mutableListOf() | ||||
|     for (trkpt in trkpts) | ||||
|     { | ||||
|         val label = "${context.getString(R.string.marker_description_time)}: ${SimpleDateFormat.getTimeInstance(SimpleDateFormat.MEDIUM, Locale.getDefault()).format(trkpt.time)} | ${context.getString(R.string.marker_description_accuracy)}: ${DecimalFormat("#0.00").format(trkpt.accuracy)} (${trkpt.provider})" | ||||
|         trackpoints.add(LabelledGeoPoint(trkpt.latitude, trkpt.longitude, trkpt.altitude, label)) | ||||
|     } | ||||
|     val pointTheme = SimplePointTheme(trackpoints, false) | ||||
|     val pointTheme = SimplePointTheme(geopoints, false) | ||||
|     val style = Paint() | ||||
|     style.style = Paint.Style.FILL | ||||
|     style.color = if (trackingState == Keys.STATE_TRACKING_ACTIVE) context.getColor(R.color.default_red) else context.getColor(R.color.default_blue) | ||||
|  | @ -60,23 +54,24 @@ fun createTrackOverlay(context: Context, map_view: MapView, trkpts: Collection<T | |||
|         .setCellSize(12) // Sets the grid cell size used for indexing, in pixels. Larger cells result in faster rendering speed, but worse fidelity. Default is 10 pixels, for large datasets (>10k points), use 15. | ||||
|     var overlay = SimpleFastPointOverlay(pointTheme, overlayOptions) | ||||
| 
 | ||||
|     // overlay.setOnClickListener(object : SimpleFastPointOverlay.OnClickListener { | ||||
|     //     override fun onClick(points: SimpleFastPointOverlay.PointAdapter?, point: Int?) | ||||
|     //     { | ||||
|     //         if (points == null || point == null || point == 0) | ||||
|     //         { | ||||
|     //             return | ||||
|     //         } | ||||
|     //         Log.i("VOUSSOIR", "Clicked ${points[point]}") | ||||
|     //         trackpoints.remove(points[point]) | ||||
|     //         map_view.overlays.remove(overlay) | ||||
|     //         overlay = SimpleFastPointOverlay(pointTheme, overlayOptions) | ||||
|     //         overlay.setOnClickListener(this) | ||||
|     //         map_view.overlays.add(overlay) | ||||
|     //         map_view.postInvalidate() | ||||
|     //         return | ||||
|     //     } | ||||
|     // }) | ||||
|     overlay.setOnClickListener(object : SimpleFastPointOverlay.OnClickListener { | ||||
|         override fun onClick(points: SimpleFastPointOverlay.PointAdapter?, point: Int?) | ||||
|         { | ||||
|             if (points == null || point == null || point == 0) | ||||
|             { | ||||
|                 return | ||||
|             } | ||||
|             val trkpt = (points[point]) as Trkpt | ||||
|             Log.i("VOUSSOIR", "Clicked ${trkpt.device_id} ${trkpt.time}") | ||||
|             // trackpoints.remove(points[point]) | ||||
|             // map_view.overlays.remove(overlay) | ||||
|             // overlay = SimpleFastPointOverlay(pointTheme, overlayOptions) | ||||
|             // overlay.setOnClickListener(this) | ||||
|             // map_view.overlays.add(overlay) | ||||
|             // map_view.postInvalidate() | ||||
|             return | ||||
|         } | ||||
|     }) | ||||
| 
 | ||||
|     map_view.overlays.add(overlay) | ||||
|     return overlay | ||||
|  |  | |||
|  | @ -79,7 +79,35 @@ | |||
| 
 | ||||
|         </org.osmdroid.views.MapView> | ||||
| 
 | ||||
|         <com.google.android.material.floatingactionbutton.FloatingActionButton | ||||
|             android:id="@+id/zoom_out_button" | ||||
|             style="@style/Widget.MaterialComponents.FloatingActionButton" | ||||
|             android:layout_width="wrap_content" | ||||
|             android:layout_height="56dp" | ||||
|             android:layout_marginEnd="16dp" | ||||
|             android:layout_marginBottom="70dp" | ||||
|             android:contentDescription="@string/descr_button_zoom_out" | ||||
|             android:src="@drawable/ic_zoom_out_24dp" | ||||
|             app:backgroundTint="@color/location_button_background" | ||||
|             app:fabSize="mini" | ||||
|             app:layout_constraintBottom_toBottomOf="parent" | ||||
|             app:layout_constraintEnd_toEndOf="parent" | ||||
|             app:tint="@color/location_button_icon" /> | ||||
| 
 | ||||
|         <com.google.android.material.floatingactionbutton.FloatingActionButton | ||||
|             android:id="@+id/zoom_in_button" | ||||
|             style="@style/Widget.MaterialComponents.FloatingActionButton" | ||||
|             android:layout_width="wrap_content" | ||||
|             android:layout_height="56dp" | ||||
|             android:layout_marginEnd="16dp" | ||||
|             android:layout_marginBottom="16dp" | ||||
|             android:contentDescription="@string/descr_button_zoom_in" | ||||
|             android:src="@drawable/ic_zoom_in_24dp" | ||||
|             app:backgroundTint="@color/location_button_background" | ||||
|             app:fabSize="mini" | ||||
|             app:layout_constraintBottom_toTopOf="@+id/zoom_out_button" | ||||
|             app:layout_constraintEnd_toEndOf="parent" | ||||
|             app:tint="@color/location_button_icon" /> | ||||
| 
 | ||||
|     </androidx.constraintlayout.widget.ConstraintLayout> | ||||
| 
 | ||||
|  |  | |||
		Loading…
	
		Reference in a new issue