Neat new feature: Quick Settings tile for starting / stopping a recording
This commit is contained in:
parent
4351926415
commit
97b64dfd59
4 changed files with 199 additions and 7 deletions
|
@ -27,6 +27,7 @@
|
||||||
android:theme="@style/AppTheme"
|
android:theme="@style/AppTheme"
|
||||||
tools:ignore="GoogleAppIndexingWarning">
|
tools:ignore="GoogleAppIndexingWarning">
|
||||||
|
|
||||||
|
<!-- MAIN ACTIVITY -->
|
||||||
<activity android:name=".MainActivity">
|
<activity android:name=".MainActivity">
|
||||||
<intent-filter>
|
<intent-filter>
|
||||||
<action android:name="android.intent.action.MAIN"/>
|
<action android:name="android.intent.action.MAIN"/>
|
||||||
|
@ -46,7 +47,18 @@
|
||||||
</intent-filter>
|
</intent-filter>
|
||||||
</service>
|
</service>
|
||||||
|
|
||||||
|
<!-- TRACKING TOGGLE SERVICE SYSTEM QUICK SETTINGS -->
|
||||||
|
<service
|
||||||
|
android:name=".TrackingToggleTileService"
|
||||||
|
android:label="@string/quick_settings_tile_title_default"
|
||||||
|
android:icon="@drawable/ic_notification_icon_small_24dp"
|
||||||
|
android:permission="android.permission.BIND_QUICK_SETTINGS_TILE">
|
||||||
|
<intent-filter>
|
||||||
|
<action android:name="android.service.quicksettings.action.QS_TILE" />
|
||||||
|
</intent-filter>
|
||||||
|
</service>
|
||||||
|
|
||||||
|
<!-- FILE PROVIDER GPX -->
|
||||||
<provider
|
<provider
|
||||||
android:name="androidx.core.content.FileProvider"
|
android:name="androidx.core.content.FileProvider"
|
||||||
android:authorities="${applicationId}.provider"
|
android:authorities="${applicationId}.provider"
|
||||||
|
@ -60,6 +72,4 @@
|
||||||
</application>
|
</application>
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
</manifest>
|
</manifest>
|
||||||
|
|
|
@ -19,10 +19,7 @@ package org.y20k.trackbook
|
||||||
|
|
||||||
import YesNoDialog
|
import YesNoDialog
|
||||||
import android.Manifest
|
import android.Manifest
|
||||||
import android.content.ComponentName
|
import android.content.*
|
||||||
import android.content.Context
|
|
||||||
import android.content.Intent
|
|
||||||
import android.content.ServiceConnection
|
|
||||||
import android.content.pm.PackageManager
|
import android.content.pm.PackageManager
|
||||||
import android.location.Location
|
import android.location.Location
|
||||||
import android.os.Build
|
import android.os.Build
|
||||||
|
@ -35,6 +32,7 @@ import android.view.ViewGroup
|
||||||
import androidx.core.content.ContextCompat
|
import androidx.core.content.ContextCompat
|
||||||
import androidx.fragment.app.Fragment
|
import androidx.fragment.app.Fragment
|
||||||
import androidx.navigation.fragment.findNavController
|
import androidx.navigation.fragment.findNavController
|
||||||
|
import androidx.preference.PreferenceManager
|
||||||
import kotlinx.coroutines.GlobalScope
|
import kotlinx.coroutines.GlobalScope
|
||||||
import kotlinx.coroutines.launch
|
import kotlinx.coroutines.launch
|
||||||
import org.y20k.trackbook.core.Track
|
import org.y20k.trackbook.core.Track
|
||||||
|
@ -235,6 +233,22 @@ class MapFragment : Fragment(), YesNoDialog.YesNoDialogListener {
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Defines the listener for changes in shared preferences
|
||||||
|
*/
|
||||||
|
private val sharedPreferenceChangeListener = SharedPreferences.OnSharedPreferenceChangeListener { sharedPreferences, key ->
|
||||||
|
when (key) {
|
||||||
|
Keys.PREF_TRACKING_STATE -> {
|
||||||
|
trackingState = PreferencesHelper.loadTrackingState(activity as Context)
|
||||||
|
layout.updateRecordingButton(trackingState)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
/*
|
||||||
|
* End of declaration
|
||||||
|
*/
|
||||||
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Defines callbacks for service binding, passed to bindService()
|
* Defines callbacks for service binding, passed to bindService()
|
||||||
*/
|
*/
|
||||||
|
@ -244,12 +258,16 @@ class MapFragment : Fragment(), YesNoDialog.YesNoDialogListener {
|
||||||
val binder = service as TrackerService.LocalBinder
|
val binder = service as TrackerService.LocalBinder
|
||||||
trackerService = binder.service
|
trackerService = binder.service
|
||||||
bound = true
|
bound = true
|
||||||
|
// register listener for changes in shared preferences
|
||||||
|
PreferenceManager.getDefaultSharedPreferences(activity as Context).registerOnSharedPreferenceChangeListener(sharedPreferenceChangeListener)
|
||||||
// start listening for location updates
|
// start listening for location updates
|
||||||
handler.removeCallbacks(periodicLocationRequestRunnable)
|
handler.removeCallbacks(periodicLocationRequestRunnable)
|
||||||
handler.postDelayed(periodicLocationRequestRunnable, 0)
|
handler.postDelayed(periodicLocationRequestRunnable, 0)
|
||||||
}
|
}
|
||||||
override fun onServiceDisconnected(arg0: ComponentName) {
|
override fun onServiceDisconnected(arg0: ComponentName) {
|
||||||
bound = false
|
bound = false
|
||||||
|
// unregister listener for changes in shared preferences
|
||||||
|
PreferenceManager.getDefaultSharedPreferences(activity as Context).unregisterOnSharedPreferenceChangeListener(sharedPreferenceChangeListener)
|
||||||
// stop receiving location updates
|
// stop receiving location updates
|
||||||
handler.removeCallbacks(periodicLocationRequestRunnable)
|
handler.removeCallbacks(periodicLocationRequestRunnable)
|
||||||
}
|
}
|
||||||
|
|
|
@ -0,0 +1,159 @@
|
||||||
|
/*
|
||||||
|
* TrackingToggleTileService.kt
|
||||||
|
* Implements the TrackingToggleTileService service
|
||||||
|
* A TrackingToggleTileService toggles the recording state from a quick settings tile
|
||||||
|
*
|
||||||
|
* This file is part of
|
||||||
|
* TRACKBOOK - Movement Recorder for Android
|
||||||
|
*
|
||||||
|
* Copyright (c) 2016-20 - Y20K.org
|
||||||
|
* Licensed under the MIT-License
|
||||||
|
* http://opensource.org/licenses/MIT
|
||||||
|
*
|
||||||
|
* Trackbook uses osmdroid - OpenStreetMap-Tools for Android
|
||||||
|
* https://github.com/osmdroid/osmdroid
|
||||||
|
*/
|
||||||
|
|
||||||
|
|
||||||
|
package org.y20k.trackbook
|
||||||
|
|
||||||
|
import android.content.*
|
||||||
|
import android.graphics.drawable.Icon
|
||||||
|
import android.os.IBinder
|
||||||
|
import android.service.quicksettings.Tile
|
||||||
|
import android.service.quicksettings.TileService
|
||||||
|
import androidx.preference.PreferenceManager
|
||||||
|
import org.y20k.trackbook.helpers.LogHelper
|
||||||
|
import org.y20k.trackbook.helpers.PreferencesHelper
|
||||||
|
|
||||||
|
|
||||||
|
/*
|
||||||
|
* TrackingToggleTileService class
|
||||||
|
*/
|
||||||
|
class TrackingToggleTileService(): TileService() {
|
||||||
|
|
||||||
|
/* Define log tag */
|
||||||
|
private val TAG: String = LogHelper.makeLogTag(TrackingToggleTileService::class.java)
|
||||||
|
|
||||||
|
|
||||||
|
/* Main class variables */
|
||||||
|
private var bound: Boolean = false
|
||||||
|
private var trackingState: Int = Keys.STATE_NOT_TRACKING
|
||||||
|
private lateinit var trackerService: TrackerService
|
||||||
|
|
||||||
|
|
||||||
|
/* Overrides onTileAdded from TileService */
|
||||||
|
override fun onTileAdded() {
|
||||||
|
super.onTileAdded()
|
||||||
|
// get saved tracking state
|
||||||
|
trackingState = PreferencesHelper.loadTrackingState(this)
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Overrides onTileRemoved from TileService */
|
||||||
|
override fun onTileRemoved() {
|
||||||
|
super.onTileRemoved()
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/* Overrides onStartListening from TileService */
|
||||||
|
override fun onStartListening() {
|
||||||
|
super.onStartListening()
|
||||||
|
// tile becomes visible - bind tracker service
|
||||||
|
bindService(Intent(this, TrackerService::class.java), connection, Context.BIND_AUTO_CREATE)
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/* Overrides onClick from TileService */
|
||||||
|
override fun onClick() {
|
||||||
|
super.onClick()
|
||||||
|
when (trackingState) {
|
||||||
|
Keys.STATE_TRACKING_ACTIVE -> {
|
||||||
|
trackerService.stopTracking()
|
||||||
|
}
|
||||||
|
else -> {
|
||||||
|
trackerService.startTracking(newTrack = false)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/* Overrides onStopListening from TileService */
|
||||||
|
override fun onStopListening() {
|
||||||
|
super.onStopListening()
|
||||||
|
// tile no longer visible - unbind tracker service
|
||||||
|
unbindService(connection)
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/* Overrides onDestroy from Service */
|
||||||
|
override fun onDestroy() {
|
||||||
|
super.onDestroy()
|
||||||
|
if (bound) unbindService(connection)
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/* Update quick settings tile */
|
||||||
|
private fun updateTile() {
|
||||||
|
val tile: Tile = qsTile
|
||||||
|
tile.icon = Icon.createWithResource(this, R.drawable.ic_notification_icon_small_24dp)
|
||||||
|
when (trackingState) {
|
||||||
|
Keys.STATE_TRACKING_ACTIVE -> {
|
||||||
|
tile.label = getString(R.string.quick_settings_tile_title_stop)
|
||||||
|
tile.contentDescription = getString(R.string.descr_quick_settings_tile_title_stop)
|
||||||
|
tile.state = Tile.STATE_ACTIVE
|
||||||
|
}
|
||||||
|
else -> {
|
||||||
|
tile.label = getString(R.string.quick_settings_tile_title_start)
|
||||||
|
tile.contentDescription = getString(R.string.descr_quick_settings_tile_title_start)
|
||||||
|
tile.state = Tile.STATE_INACTIVE
|
||||||
|
}
|
||||||
|
}
|
||||||
|
tile.updateTile()
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Defines the listener for changes in shared preferences
|
||||||
|
*/
|
||||||
|
private val sharedPreferenceChangeListener = SharedPreferences.OnSharedPreferenceChangeListener { sharedPreferences, key ->
|
||||||
|
when (key) {
|
||||||
|
Keys.PREF_TRACKING_STATE -> {
|
||||||
|
trackingState = PreferencesHelper.loadTrackingState(this)
|
||||||
|
updateTile()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
/*
|
||||||
|
* End of declaration
|
||||||
|
*/
|
||||||
|
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Defines callbacks for service binding, passed to bindService()
|
||||||
|
*/
|
||||||
|
private val connection = object : ServiceConnection {
|
||||||
|
override fun onServiceConnected(className: ComponentName, service: IBinder) {
|
||||||
|
// We've bound to LocalService, cast the IBinder and get LocalService instance
|
||||||
|
val binder = service as TrackerService.LocalBinder
|
||||||
|
trackerService = binder.service
|
||||||
|
trackingState = trackerService.trackingState
|
||||||
|
bound = true
|
||||||
|
// update state of tile
|
||||||
|
updateTile()
|
||||||
|
// register listener for changes in shared preferences
|
||||||
|
PreferenceManager.getDefaultSharedPreferences(this@TrackingToggleTileService).registerOnSharedPreferenceChangeListener(sharedPreferenceChangeListener)
|
||||||
|
|
||||||
|
}
|
||||||
|
override fun onServiceDisconnected(arg0: ComponentName) {
|
||||||
|
bound = false
|
||||||
|
// unregister listener for changes in shared preferences
|
||||||
|
PreferenceManager.getDefaultSharedPreferences(this@TrackingToggleTileService).unregisterOnSharedPreferenceChangeListener(sharedPreferenceChangeListener)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
/*
|
||||||
|
* End of declaration
|
||||||
|
*/
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
}
|
|
@ -57,7 +57,10 @@
|
||||||
<string name="statistics_sheet_p_min_altitude">Lowest waypoint:</string>
|
<string name="statistics_sheet_p_min_altitude">Lowest waypoint:</string>
|
||||||
<string name="statistics_sheet_p_positive_elevation">Elevation (uphill):</string>
|
<string name="statistics_sheet_p_positive_elevation">Elevation (uphill):</string>
|
||||||
<string name="statistics_sheet_p_negative_elevation">Elevation (downhill):</string>
|
<string name="statistics_sheet_p_negative_elevation">Elevation (downhill):</string>
|
||||||
<!-- Menu Actions -->
|
<!-- Recording Quick Settings Tile -->
|
||||||
|
<string name="quick_settings_tile_title_default">Recording</string>
|
||||||
|
<string name="quick_settings_tile_title_start">Start Recording</string>
|
||||||
|
<string name="quick_settings_tile_title_stop">Stop Recording</string>
|
||||||
<!-- Onboarding Layout -->
|
<!-- Onboarding Layout -->
|
||||||
<string name="layout_onboarding_description_app_icon">Trackbook App Icon</string>
|
<string name="layout_onboarding_description_app_icon">Trackbook App Icon</string>
|
||||||
<!-- Track Tab Onboarding -->
|
<!-- Track Tab Onboarding -->
|
||||||
|
@ -88,6 +91,8 @@
|
||||||
<string name="descr_fab_sub_menu_button_clear">Clear button</string>
|
<string name="descr_fab_sub_menu_button_clear">Clear button</string>
|
||||||
<string name="descr_fab_sub_menu_button_resume">Resume button</string>
|
<string name="descr_fab_sub_menu_button_resume">Resume button</string>
|
||||||
<string name="descr_mark_starred_button">Mark as starred button</string>
|
<string name="descr_mark_starred_button">Mark as starred button</string>
|
||||||
|
<string name="descr_quick_settings_tile_title_start">Start Recording</string>
|
||||||
|
<string name="descr_quick_settings_tile_title_stop">Stop Recording</string>
|
||||||
<string name="descr_statistics_sheet_delete_button">Track delete button</string>
|
<string name="descr_statistics_sheet_delete_button">Track delete button</string>
|
||||||
<string name="descr_statistics_sheet_edit_button">Track edit button</string>
|
<string name="descr_statistics_sheet_edit_button">Track edit button</string>
|
||||||
<string name="descr_statistics_sheet_share_button">Share as GPX button</string>
|
<string name="descr_statistics_sheet_share_button">Share as GPX button</string>
|
||||||
|
|
Loading…
Reference in a new issue