checkpoint

master
voussoir 2023-03-10 19:35:27 -08:00
parent 5dad3d6209
commit 1f695958e7
5 changed files with 183 additions and 134 deletions

View File

@ -1,11 +1,14 @@
package org.y20k.trackbook package org.y20k.trackbook
import android.content.ContentValues
import android.database.sqlite.SQLiteDatabase import android.database.sqlite.SQLiteDatabase
import android.database.sqlite.SQLiteDatabase.openOrCreateDatabase import android.database.sqlite.SQLiteDatabase.openOrCreateDatabase
import android.util.Log import android.util.Log
import java.io.File import java.io.File
import java.util.*
class Database() class Database(trackbook: Trackbook)
{ {
val trackbook = trackbook
var ready: Boolean = false var ready: Boolean = false
lateinit var file: File lateinit var file: File
lateinit var connection: SQLiteDatabase lateinit var connection: SQLiteDatabase
@ -14,6 +17,7 @@ class Database()
{ {
this.connection.close() this.connection.close()
this.ready = false this.ready = false
this.trackbook.call_database_changed_listeners()
} }
fun connect(file: File) fun connect(file: File)
@ -23,6 +27,7 @@ class Database()
this.connection = openOrCreateDatabase(file, null) this.connection = openOrCreateDatabase(file, null)
this.initialize_tables() this.initialize_tables()
this.ready = true this.ready = true
Log.i("VOUSSOIR", "Database.open: Calling all listeners")
} }
fun commit() fun commit()
@ -40,11 +45,29 @@ class Database()
this.connection.endTransaction() this.connection.endTransaction()
} }
fun insert_trkpt(device_id: String, trkpt: Trkpt)
{
val values = ContentValues().apply {
put("device_id", device_id)
put("lat", trkpt.latitude)
put("lon", trkpt.longitude)
put("time", GregorianCalendar.getInstance().time.time)
put("accuracy", trkpt.accuracy)
put("sat", trkpt.numberSatellites)
put("ele", trkpt.altitude)
}
if (! connection.inTransaction())
{
connection.beginTransaction()
}
connection.insert("trkpt", null, values)
}
private fun initialize_tables() private fun initialize_tables()
{ {
this.connection.beginTransaction() this.connection.beginTransaction()
this.connection.execSQL("CREATE TABLE IF NOT EXISTS meta(name TEXT PRIMARY KEY, value TEXT)") this.connection.execSQL("CREATE TABLE IF NOT EXISTS meta(name TEXT PRIMARY KEY, value TEXT)")
this.connection.execSQL("CREATE TABLE IF NOT EXISTS trkpt(lat REAL NOT NULL, lon REAL NOT NULL, time INTEGER NOT NULL, accuracy REAL, device_id INTEGER NOT NULL, ele INTEGER, sat INTEGER, star INTEGER, PRIMARY KEY(lat, lon, time, device_id))") this.connection.execSQL("CREATE TABLE IF NOT EXISTS trkpt(lat REAL NOT NULL, lon REAL NOT NULL, time INTEGER NOT NULL, accuracy REAL, device_id INTEGER NOT NULL, ele INTEGER, sat INTEGER, PRIMARY KEY(lat, lon, time, device_id))")
this.connection.execSQL("CREATE TABLE IF NOT EXISTS homepoints(lat REAL NOT NULL, lon REAL NOT NULL, radius REAL NOT NULL, name TEXT, PRIMARY KEY(lat, lon))") this.connection.execSQL("CREATE TABLE IF NOT EXISTS homepoints(lat REAL NOT NULL, lon REAL NOT NULL, radius REAL NOT NULL, name TEXT, PRIMARY KEY(lat, lon))")
this.connection.setTransactionSuccessful() this.connection.setTransactionSuccessful()
this.connection.endTransaction() this.connection.endTransaction()

View File

@ -17,7 +17,6 @@
package org.y20k.trackbook package org.y20k.trackbook
import android.Manifest import android.Manifest
import android.app.Activity
import android.content.* import android.content.*
import android.content.pm.PackageManager import android.content.pm.PackageManager
import android.content.res.Resources import android.content.res.Resources
@ -41,8 +40,8 @@ import org.osmdroid.api.IMapController
import org.osmdroid.tileprovider.tilesource.TileSourceFactory import org.osmdroid.tileprovider.tilesource.TileSourceFactory
import org.osmdroid.util.GeoPoint import org.osmdroid.util.GeoPoint
import org.osmdroid.views.MapView import org.osmdroid.views.MapView
import org.osmdroid.views.overlay.FolderOverlay
import org.osmdroid.views.overlay.ItemizedIconOverlay import org.osmdroid.views.overlay.ItemizedIconOverlay
import org.osmdroid.views.overlay.Overlay
import org.osmdroid.views.overlay.OverlayItem import org.osmdroid.views.overlay.OverlayItem
import org.osmdroid.views.overlay.Polygon import org.osmdroid.views.overlay.Polygon
import org.osmdroid.views.overlay.TilesOverlay import org.osmdroid.views.overlay.TilesOverlay
@ -69,30 +68,44 @@ class MapFragment : Fragment()
private lateinit var currentBestLocation: Location private lateinit var currentBestLocation: Location
private lateinit var trackerService: TrackerService private lateinit var trackerService: TrackerService
private lateinit var trackbook: Trackbook
lateinit var rootView: View lateinit var rootView: View
var userInteraction: Boolean = false var userInteraction: Boolean = false
lateinit var currentLocationButton: FloatingActionButton lateinit var currentLocationButton: FloatingActionButton
lateinit var mainButton: ExtendedFloatingActionButton lateinit var mainButton: ExtendedFloatingActionButton
private lateinit var mapView: MapView private lateinit var mapView: MapView
private lateinit var current_position_folder: FolderOverlay private var current_position_overlays = ArrayList<Overlay>()
private var currentTrackOverlay: SimpleFastPointOverlay? = null private var currentTrackOverlay: SimpleFastPointOverlay? = null
private var currentTrackSpecialMarkerOverlay: ItemizedIconOverlay<OverlayItem>? = null private var currentTrackSpecialMarkerOverlay: ItemizedIconOverlay<OverlayItem>? = null
private lateinit var locationErrorBar: Snackbar private lateinit var locationErrorBar: Snackbar
private lateinit var controller: IMapController private lateinit var controller: IMapController
private var zoomLevel: Double = Keys.DEFAULT_ZOOM_LEVEL private var zoomLevel: Double = Keys.DEFAULT_ZOOM_LEVEL
private lateinit var homepoints_overlay_folder: FolderOverlay private var homepoints_overlays = ArrayList<Overlay>()
private lateinit var database_changed_listener: DatabaseChangedListener
/* Overrides onCreate from Fragment */ /* Overrides onCreate from Fragment */
override fun onCreate(savedInstanceState: Bundle?) override fun onCreate(savedInstanceState: Bundle?)
{ {
Log.i("VOUSSOIR", "MapFragment.onCreate") Log.i("VOUSSOIR", "MapFragment.onCreate")
super.onCreate(savedInstanceState) super.onCreate(savedInstanceState)
// TODO make only MapFragment's status bar transparent - see: this.trackbook = (requireContext().applicationContext as Trackbook)
// https://gist.github.com/Dvik/a3de88d39da9d1d6d175025a56c5e797#file-viewextension-kt and database_changed_listener = object: DatabaseChangedListener
// https://proandroiddev.com/android-full-screen-ui-with-transparent-status-bar-ef52f3adde63 {
// get current best location override fun database_changed()
currentBestLocation = getLastKnownLocation(activity as Context) {
// get saved tracking state Log.i("VOUSSOIR", "MapFragment database_ready_changed to ${trackbook.database.ready}")
if (trackbook.database.ready)
{
create_homepoint_overlays(requireContext(), mapView, trackbook.homepoints)
}
else
{
clear_homepoint_overlays()
}
update_main_button()
}
}
currentBestLocation = getLastKnownLocation(requireContext())
trackingState = PreferencesHelper.loadTrackingState() trackingState = PreferencesHelper.loadTrackingState()
} }
@ -100,7 +113,6 @@ class MapFragment : Fragment()
override fun onCreateView(inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle?): View override fun onCreateView(inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle?): View
{ {
Log.i("VOUSSOIR", "MapFragment.onCreateView") Log.i("VOUSSOIR", "MapFragment.onCreateView")
val context = activity as Context
// find views // find views
rootView = inflater.inflate(R.layout.fragment_map, container, false) rootView = inflater.inflate(R.layout.fragment_map, container, false)
mapView = rootView.findViewById(R.id.map) mapView = rootView.findViewById(R.id.map)
@ -124,26 +136,23 @@ class MapFragment : Fragment()
} }
// store Density Scaling Factor // store Density Scaling Factor
val densityScalingFactor: Float = UiHelper.getDensityScalingFactor(context) val densityScalingFactor: Float = UiHelper.getDensityScalingFactor(requireContext())
// add compass to map // add compass to map
val compassOverlay = CompassOverlay(context, InternalCompassOrientationProvider(context), mapView) val compassOverlay = CompassOverlay(requireContext(), InternalCompassOrientationProvider(requireContext()), mapView)
compassOverlay.enableCompass() compassOverlay.enableCompass()
// compassOverlay.setCompassCenter(36f, 36f + (statusBarHeight / densityScalingFactor)) // TODO uncomment when transparent status bar is re-implemented // compassOverlay.setCompassCenter(36f, 36f + (statusBarHeight / densityScalingFactor)) // TODO uncomment when transparent status bar is re-implemented
val screen_width = Resources.getSystem().displayMetrics.widthPixels; val screen_width = Resources.getSystem().displayMetrics.widthPixels;
compassOverlay.setCompassCenter((screen_width / densityScalingFactor) - 36f, 36f) compassOverlay.setCompassCenter((screen_width / densityScalingFactor) - 36f, 36f)
mapView.overlays.add(compassOverlay) mapView.overlays.add(compassOverlay)
val app: Trackbook = (context.applicationContext as Trackbook) val app: Trackbook = (requireContext().applicationContext as Trackbook)
app.load_homepoints() app.load_homepoints()
homepoints_overlay_folder = FolderOverlay() create_homepoint_overlays(requireContext(), mapView, app.homepoints)
mapView.overlays.add(homepoints_overlay_folder) if (database_changed_listener !in trackbook.database_changed_listeners)
createHomepointOverlays(context, mapView, app.homepoints) {
trackbook.database_changed_listeners.add(database_changed_listener)
// add my location overlay }
current_position_folder = FolderOverlay()
mapView.overlays.add(current_position_folder)
centerMap(currentBestLocation) centerMap(currentBestLocation)
@ -152,7 +161,7 @@ class MapFragment : Fragment()
currentTrackSpecialMarkerOverlay = null currentTrackSpecialMarkerOverlay = null
// initialize main button state // initialize main button state
updateMainButton(trackingState) update_main_button()
// listen for user interaction // listen for user interaction
addInteractionListener() addInteractionListener()
@ -224,9 +233,13 @@ class MapFragment : Fragment()
Log.i("VOUSSOIR", "MapFragment.onDestroy") Log.i("VOUSSOIR", "MapFragment.onDestroy")
super.onDestroy() super.onDestroy()
requireActivity().window.clearFlags(WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON) requireActivity().window.clearFlags(WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON)
if (database_changed_listener in trackbook.database_changed_listeners)
{
trackbook.database_changed_listeners.remove(database_changed_listener)
}
} }
/* Register the permission launcher for requesting location */
private val requestLocationPermissionLauncher = registerForActivityResult(RequestPermission()) { isGranted: Boolean -> private val requestLocationPermissionLauncher = registerForActivityResult(RequestPermission()) { isGranted: Boolean ->
if (isGranted) { if (isGranted) {
// permission was granted - re-bind service // permission was granted - re-bind service
@ -301,9 +314,6 @@ class MapFragment : Fragment()
} }
} }
/*
* Defines the listener for changes in shared preferences
*/
private val sharedPreferenceChangeListener = SharedPreferences.OnSharedPreferenceChangeListener { sharedPreferences, key -> private val sharedPreferenceChangeListener = SharedPreferences.OnSharedPreferenceChangeListener { sharedPreferences, key ->
when (key) when (key)
{ {
@ -312,12 +322,14 @@ class MapFragment : Fragment()
if (activity != null) if (activity != null)
{ {
trackingState = PreferencesHelper.loadTrackingState() trackingState = PreferencesHelper.loadTrackingState()
updateMainButton(trackingState) update_main_button()
} }
} }
} }
} }
private fun addInteractionListener() {
private fun addInteractionListener()
{
mapView.setOnTouchListener { v, event -> mapView.setOnTouchListener { v, event ->
userInteraction = true userInteraction = true
false false
@ -340,10 +352,25 @@ class MapFragment : Fragment()
userInteraction = false userInteraction = false
} }
fun clear_current_position_overlays()
{
for (ov in current_position_overlays)
{
if (ov in mapView.overlays)
{
mapView.overlays.remove(ov)
}
}
current_position_overlays.clear();
}
/* Mark current position on map */ /* Mark current position on map */
fun markCurrentPosition(location: Location, trackingState: Int = Keys.STATE_TRACKING_STOPPED) fun create_current_position_overlays(location: Location, trackingState: Int = Keys.STATE_TRACKING_STOPPED)
{ {
Log.i("VOUSSOIR", "MapFragmentLayoutHolder.markCurrentPosition") Log.i("VOUSSOIR", "MapFragmentLayoutHolder.markCurrentPosition")
clear_current_position_overlays()
val locationIsOld: Boolean = !(isRecentEnough(location)) val locationIsOld: Boolean = !(isRecentEnough(location))
// create marker // create marker
@ -374,47 +401,68 @@ class MapFragment : Fragment()
} }
} }
current_position_folder.items.clear()
val current_location_radius = Polygon() val current_location_radius = Polygon()
current_location_radius.points = Polygon.pointsAsCircle(GeoPoint(location.latitude, location.longitude), location.accuracy.toDouble()) current_location_radius.points = Polygon.pointsAsCircle(GeoPoint(location.latitude, location.longitude), location.accuracy.toDouble())
current_location_radius.fillPaint.color = fillcolor current_location_radius.fillPaint.color = fillcolor
current_location_radius.outlinePaint.color = Color.argb(0, 0, 0, 0) current_location_radius.outlinePaint.color = Color.argb(0, 0, 0, 0)
current_position_folder.add(current_location_radius) current_position_overlays.add(current_location_radius)
val overlayItems: java.util.ArrayList<OverlayItem> = java.util.ArrayList<OverlayItem>() val overlayItems: java.util.ArrayList<OverlayItem> = java.util.ArrayList<OverlayItem>()
val overlayItem: OverlayItem = createOverlayItem(requireContext(), location.latitude, location.longitude, location.accuracy, location.provider.toString(), location.time) val overlayItem: OverlayItem = createOverlayItem(requireContext(), location.latitude, location.longitude, location.accuracy, location.provider.toString(), location.time)
overlayItem.setMarker(newMarker) overlayItem.setMarker(newMarker)
overlayItems.add(overlayItem) overlayItems.add(overlayItem)
current_position_folder.add(createOverlay(requireContext(), overlayItems)) current_position_overlays.add(createOverlay(requireContext(), overlayItems))
for (ov in current_position_overlays)
{
mapView.overlays.add(ov)
}
} }
fun createHomepointOverlays(context: Context, map_view: MapView, homepoints: List<Homepoint>) fun clear_homepoint_overlays()
{
for (ov in homepoints_overlays)
{
if (ov in mapView.overlays)
{
mapView.overlays.remove(ov)
}
}
homepoints_overlays.clear();
}
fun create_homepoint_overlays(context: Context, map_view: MapView, homepoints: List<Homepoint>)
{ {
Log.i("VOUSSOIR", "MapFragmentLayoutHolder.createHomepointOverlays") Log.i("VOUSSOIR", "MapFragmentLayoutHolder.createHomepointOverlays")
val overlayItems: java.util.ArrayList<OverlayItem> = java.util.ArrayList<OverlayItem>() val overlayItems: java.util.ArrayList<OverlayItem> = java.util.ArrayList<OverlayItem>()
val newMarker: Drawable = ContextCompat.getDrawable(context, R.drawable.ic_homepoint_24dp)!! val newMarker: Drawable = ContextCompat.getDrawable(context, R.drawable.ic_homepoint_24dp)!!
homepoints_overlay_folder.items.clear() clear_homepoint_overlays()
for (homepoint in homepoints) for (homepoint in homepoints)
{ {
val overlayItem: OverlayItem = createOverlayItem(context, homepoint.location.latitude, homepoint.location.longitude, homepoint.location.accuracy, homepoint.location.provider.toString(), homepoint.location.time)
overlayItem.setMarker(newMarker)
overlayItems.add(overlayItem)
homepoints_overlay_folder.add(createOverlay(context, overlayItems))
val p = Polygon() val p = Polygon()
p.points = Polygon.pointsAsCircle(GeoPoint(homepoint.location.latitude, homepoint.location.longitude), homepoint.location.accuracy.toDouble()) p.points = Polygon.pointsAsCircle(GeoPoint(homepoint.location.latitude, homepoint.location.longitude), homepoint.location.accuracy.toDouble())
p.fillPaint.color = Color.argb(64, 255, 193, 7) p.fillPaint.color = Color.argb(64, 255, 193, 7)
p.outlinePaint.color = Color.argb(0, 0, 0, 0) p.outlinePaint.color = Color.argb(0, 0, 0, 0)
homepoints_overlay_folder.add(p) homepoints_overlays.add(p)
val overlayItem: OverlayItem = createOverlayItem(context, homepoint.location.latitude, homepoint.location.longitude, homepoint.location.accuracy, homepoint.location.provider.toString(), homepoint.location.time)
overlayItem.setMarker(newMarker)
overlayItems.add(overlayItem)
homepoints_overlays.add(createOverlay(context, overlayItems))
}
for (ov in homepoints_overlays)
{
mapView.overlays.add(ov)
} }
} }
/* Overlay current track on map */ /* Overlay current track on map */
fun overlayCurrentTrack(track: Track, trackingState: Int) { fun create_current_track_overlay(track: Track, trackingState: Int)
{
if (currentTrackOverlay != null) { if (currentTrackOverlay != null) {
mapView.overlays.remove(currentTrackOverlay) mapView.overlays.remove(currentTrackOverlay)
} }
@ -427,22 +475,26 @@ class MapFragment : Fragment()
} }
} }
/* Toggles state of main button and additional buttons (save & resume) */ fun update_main_button()
fun updateMainButton(trackingState: Int) {
mainButton.isEnabled = trackbook.database.ready
currentLocationButton.isVisible = true
if (! trackbook.database.ready)
{
mainButton.text = "Database not ready"
mainButton.icon = null
}
else if (trackingState == Keys.STATE_TRACKING_STOPPED)
{ {
when (trackingState) {
Keys.STATE_TRACKING_STOPPED -> {
mainButton.setIconResource(R.drawable.ic_fiber_manual_record_inactive_24dp) mainButton.setIconResource(R.drawable.ic_fiber_manual_record_inactive_24dp)
mainButton.text = requireContext().getString(R.string.button_start) mainButton.text = requireContext().getString(R.string.button_start)
mainButton.contentDescription = requireContext().getString(R.string.descr_button_start) mainButton.contentDescription = requireContext().getString(R.string.descr_button_start)
currentLocationButton.isVisible = true
} }
Keys.STATE_TRACKING_ACTIVE -> { else if (trackingState == Keys.STATE_TRACKING_ACTIVE)
{
mainButton.setIconResource(R.drawable.ic_fiber_manual_stop_24dp) mainButton.setIconResource(R.drawable.ic_fiber_manual_stop_24dp)
mainButton.text = requireContext().getString(R.string.button_pause) mainButton.text = requireContext().getString(R.string.button_pause)
mainButton.contentDescription = requireContext().getString(R.string.descr_button_pause) mainButton.contentDescription = requireContext().getString(R.string.descr_button_pause)
currentLocationButton.isVisible = true
}
} }
} }
@ -459,13 +511,7 @@ class MapFragment : Fragment()
if (locationErrorBar.isShown) locationErrorBar.dismiss() if (locationErrorBar.isShown) locationErrorBar.dismiss()
} }
} }
/*
* End of declaration
*/
/*
* Defines callbacks for service binding, passed to bindService()
*/
private val connection = object : ServiceConnection { private val connection = object : ServiceConnection {
override fun onServiceConnected(className: ComponentName, service: IBinder) { override fun onServiceConnected(className: ComponentName, service: IBinder) {
bound = true bound = true
@ -474,7 +520,7 @@ class MapFragment : Fragment()
trackerService = binder.service trackerService = binder.service
// get state of tracking and update button if necessary // get state of tracking and update button if necessary
trackingState = trackerService.trackingState trackingState = trackerService.trackingState
updateMainButton(trackingState) update_main_button()
// register listener for changes in shared preferences // register listener for changes in shared preferences
PreferencesHelper.registerPreferenceChangeListener(sharedPreferenceChangeListener) PreferencesHelper.registerPreferenceChangeListener(sharedPreferenceChangeListener)
// start listening for location updates // start listening for location updates
@ -486,13 +532,7 @@ class MapFragment : Fragment()
handleServiceUnbind() handleServiceUnbind()
} }
} }
/*
* End of declaration
*/
/*
* Runnable: Periodically requests location
*/
private val periodicLocationRequestRunnable: Runnable = object : Runnable { private val periodicLocationRequestRunnable: Runnable = object : Runnable {
override fun run() { override fun run() {
// pull current state from service // pull current state from service
@ -502,20 +542,17 @@ class MapFragment : Fragment()
networkProviderActive = trackerService.networkProviderActive networkProviderActive = trackerService.networkProviderActive
trackingState = trackerService.trackingState trackingState = trackerService.trackingState
// update location and track // update location and track
markCurrentPosition(currentBestLocation, trackingState) create_current_position_overlays(currentBestLocation, trackingState)
overlayCurrentTrack(track, trackingState) create_current_track_overlay(track, trackingState)
// center map, if it had not been dragged/zoomed before // center map, if it had not been dragged/zoomed before
if (!userInteraction) if (!userInteraction)
{ {
centerMap(currentBestLocation, true) centerMap(currentBestLocation, true)
} }
// show error snackbar if necessary // show error snackbar if necessary
toggleLocationErrorBar(gpsProviderActive, networkProviderActive) // toggleLocationErrorBar(gpsProviderActive, networkProviderActive)
// use the handler to start runnable again after specified delay // use the handler to start runnable again after specified delay
handler.postDelayed(this, Keys.REQUEST_CURRENT_LOCATION_INTERVAL) handler.postDelayed(this, Keys.REQUEST_CURRENT_LOCATION_INTERVAL)
} }
} }
/*
* End of declaration
*/
} }

View File

@ -31,12 +31,24 @@ import org.y20k.trackbook.helpers.PreferencesHelper
import org.y20k.trackbook.helpers.PreferencesHelper.initPreferences import org.y20k.trackbook.helpers.PreferencesHelper.initPreferences
import java.io.File import java.io.File
/*
* Trackbook.class interface DatabaseChangedListener
*/ {
fun database_changed()
}
class Trackbook(): Application() { class Trackbook(): Application() {
val database: Database = Database() val database: Database = Database(this)
val homepoints: ArrayList<Homepoint> = ArrayList() val homepoints: ArrayList<Homepoint> = ArrayList()
val database_changed_listeners = ArrayList<DatabaseChangedListener>()
fun call_database_changed_listeners()
{
for (listener in this.database_changed_listeners)
{
listener.database_changed()
}
}
override fun onCreate() override fun onCreate()
{ {
@ -63,6 +75,7 @@ class Trackbook(): Application() {
{ {
this.database.ready = false this.database.ready = false
} }
this.call_database_changed_listeners()
} }
fun load_homepoints() fun load_homepoints()
{ {

View File

@ -230,7 +230,8 @@ class TrackerService: Service(), SensorEventListener
} }
/* Overrides onDestroy from Service */ /* Overrides onDestroy from Service */
override fun onDestroy() { override fun onDestroy()
{
LogHelper.i("VOUSSOIR", "TrackerService.onDestroy.") LogHelper.i("VOUSSOIR", "TrackerService.onDestroy.")
super.onDestroy() super.onDestroy()
if (trackingState == Keys.STATE_TRACKING_ACTIVE) if (trackingState == Keys.STATE_TRACKING_ACTIVE)
@ -255,8 +256,10 @@ class TrackerService: Service(), SensorEventListener
/* Overrides onSensorChanged from SensorEventListener */ /* Overrides onSensorChanged from SensorEventListener */
override fun onSensorChanged(sensorEvent: SensorEvent?) { override fun onSensorChanged(sensorEvent: SensorEvent?) {
var steps = 0f var steps = 0f
if (sensorEvent != null) { if (sensorEvent != null)
if (stepCountOffset == 0f) { {
if (stepCountOffset == 0f)
{
// store steps previously recorded by the system // store steps previously recorded by the system
stepCountOffset = (sensorEvent.values[0] - 1) - 0 // subtract any steps recorded during this session in case the app was killed stepCountOffset = (sensorEvent.values[0] - 1) - 0 // subtract any steps recorded during this session in case the app was killed
} }
@ -307,22 +310,28 @@ class TrackerService: Service(), SensorEventListener
/* Adds location listeners to location manager */ /* Adds location listeners to location manager */
fun removeGpsLocationListener() fun removeGpsLocationListener()
{ {
if (ContextCompat.checkSelfPermission(this, Manifest.permission.ACCESS_FINE_LOCATION) == PackageManager.PERMISSION_GRANTED) { if (ContextCompat.checkSelfPermission(this, Manifest.permission.ACCESS_FINE_LOCATION) == PackageManager.PERMISSION_GRANTED)
{
locationManager.removeUpdates(gpsLocationListener) locationManager.removeUpdates(gpsLocationListener)
gpsLocationListenerRegistered = false gpsLocationListenerRegistered = false
LogHelper.v(TAG, "Removed GPS location listener.") LogHelper.v(TAG, "Removed GPS location listener.")
} else { }
else
{
LogHelper.w(TAG, "Unable to remove GPS location listener. Location permission is needed.") LogHelper.w(TAG, "Unable to remove GPS location listener. Location permission is needed.")
} }
} }
fun removeNetworkLocationListener() fun removeNetworkLocationListener()
{ {
if (ContextCompat.checkSelfPermission(this, Manifest.permission.ACCESS_FINE_LOCATION) == PackageManager.PERMISSION_GRANTED) { if (ContextCompat.checkSelfPermission(this, Manifest.permission.ACCESS_FINE_LOCATION) == PackageManager.PERMISSION_GRANTED)
{
locationManager.removeUpdates(networkLocationListener) locationManager.removeUpdates(networkLocationListener)
networkLocationListenerRegistered = false networkLocationListenerRegistered = false
LogHelper.v(TAG, "Removed Network location listener.") LogHelper.v(TAG, "Removed Network location listener.")
} else { }
else
{
LogHelper.w(TAG, "Unable to remove Network location listener. Location permission is needed.") LogHelper.w(TAG, "Unable to remove Network location listener. Location permission is needed.")
} }
} }
@ -330,7 +339,8 @@ class TrackerService: Service(), SensorEventListener
private fun startStepCounter() private fun startStepCounter()
{ {
val stepCounterAvailable = sensorManager.registerListener(this, sensorManager.getDefaultSensor(Sensor.TYPE_STEP_COUNTER), SensorManager.SENSOR_DELAY_UI) val stepCounterAvailable = sensorManager.registerListener(this, sensorManager.getDefaultSensor(Sensor.TYPE_STEP_COUNTER), SensorManager.SENSOR_DELAY_UI)
if (!stepCounterAvailable) { if (!stepCounterAvailable)
{
LogHelper.w(TAG, "Pedometer sensor not available.") LogHelper.w(TAG, "Pedometer sensor not available.")
} }
} }
@ -445,54 +455,31 @@ class TrackerService: Service(), SensorEventListener
} }
return true return true
} }
/*
* Runnable: Periodically track updates (if recording active)
*/
private val periodicTrackUpdate: Runnable = object : Runnable private val periodicTrackUpdate: Runnable = object : Runnable
{ {
override fun run() { override fun run() {
val now: Date = GregorianCalendar.getInstance().time val now: Date = GregorianCalendar.getInstance().time
val trkpt: Trkpt = Trkpt(location=currentBestLocation) val trkpt = Trkpt(location=currentBestLocation)
Log.i("VOUSSOIR", "Processing point ${currentBestLocation.latitude}, ${currentBestLocation.longitude} ${now.time}.") Log.i("VOUSSOIR", "Processing point ${currentBestLocation.latitude}, ${currentBestLocation.longitude} ${now.time}.")
if (should_keep_point((currentBestLocation))) if (should_keep_point((currentBestLocation)))
{ {
val values = ContentValues().apply { trackbook.database.insert_trkpt(device_id, trkpt)
put("device_id", device_id)
put("lat", trkpt.latitude)
put("lon", trkpt.longitude)
put("time", now.time)
put("accuracy", trkpt.accuracy)
put("sat", trkpt.numberSatellites)
put("ele", trkpt.altitude)
put("star", 0)
}
if (! trackbook.database.connection.inTransaction())
{
trackbook.database.connection.beginTransaction()
}
trackbook.database.connection.insert("trkpt", null, values)
track.trkpts.add(trkpt) track.trkpts.add(trkpt)
while (track.trkpts.size > 7200) while (track.trkpts.size > 7200)
{ {
track.trkpts.removeFirst() track.trkpts.removeFirst()
} }
if (now.time - lastCommit.time > Keys.SAVE_TEMP_TRACK_INTERVAL) if (now.time - lastCommit.time > Keys.SAVE_TEMP_TRACK_INTERVAL)
{
if (trackbook.database.connection.inTransaction())
{ {
trackbook.database.commit() trackbook.database.commit()
}
lastCommit = now lastCommit = now
} }
} }
// update notification
displayNotification() displayNotification()
// re-run this in set interval
handler.postDelayed(this, Keys.TRACKING_INTERVAL) handler.postDelayed(this, Keys.TRACKING_INTERVAL)
} }
} }
/*
* End of declaration
*/
} }

View File

@ -30,12 +30,10 @@ import org.osmdroid.util.GeoPoint
import org.osmdroid.views.MapView import org.osmdroid.views.MapView
import org.osmdroid.views.overlay.ItemizedIconOverlay import org.osmdroid.views.overlay.ItemizedIconOverlay
import org.osmdroid.views.overlay.OverlayItem import org.osmdroid.views.overlay.OverlayItem
import org.osmdroid.views.overlay.Polygon
import org.osmdroid.views.overlay.simplefastpoint.LabelledGeoPoint import org.osmdroid.views.overlay.simplefastpoint.LabelledGeoPoint
import org.osmdroid.views.overlay.simplefastpoint.SimpleFastPointOverlay import org.osmdroid.views.overlay.simplefastpoint.SimpleFastPointOverlay
import org.osmdroid.views.overlay.simplefastpoint.SimpleFastPointOverlayOptions import org.osmdroid.views.overlay.simplefastpoint.SimpleFastPointOverlayOptions
import org.osmdroid.views.overlay.simplefastpoint.SimplePointTheme import org.osmdroid.views.overlay.simplefastpoint.SimplePointTheme
import org.y20k.trackbook.Homepoint
import org.y20k.trackbook.Keys import org.y20k.trackbook.Keys
import org.y20k.trackbook.R import org.y20k.trackbook.R
import org.y20k.trackbook.Track import org.y20k.trackbook.Track
@ -44,15 +42,6 @@ import java.text.DecimalFormat
import java.text.SimpleDateFormat import java.text.SimpleDateFormat
import java.util.* import java.util.*
//private var currentPositionOverlay: ItemizedIconOverlay<OverlayItem>
/* Creates icon overlay for current position (used in MapFragment) */
fun createMyLocationOverlay(context: Context, map_view: MapView, currentPositionOverlay: ItemizedIconOverlay<OverlayItem>, location: Location, trackingState: Int)
{
}
/* Creates icon overlay for track */ /* Creates icon overlay for track */
fun createTrackOverlay(context: Context, map_view: MapView, track: Track, trackingState: Int) fun createTrackOverlay(context: Context, map_view: MapView, track: Track, trackingState: Int)
@ -149,12 +138,12 @@ fun createOverlay(context: Context, overlayItems: ArrayList<OverlayItem>): Itemi
{ {
return ItemizedIconOverlay<OverlayItem>(context, overlayItems, return ItemizedIconOverlay<OverlayItem>(context, overlayItems,
object : ItemizedIconOverlay.OnItemGestureListener<OverlayItem> { object : ItemizedIconOverlay.OnItemGestureListener<OverlayItem> {
override fun onItemSingleTapUp(index: Int, item: OverlayItem): Boolean { override fun onItemSingleTapUp(index: Int, item: OverlayItem): Boolean
{
return false return false
} }
override fun onItemLongPress(index: Int, item: OverlayItem): Boolean { override fun onItemLongPress(index: Int, item: OverlayItem): Boolean
val v = context.getSystemService(Context.VIBRATOR_SERVICE) as Vibrator {
v.vibrate(50)
Toast.makeText(context, item.snippet, Toast.LENGTH_LONG).show() Toast.makeText(context, item.snippet, Toast.LENGTH_LONG).show()
return true return true
} }