request permission to use the step counter

master
y20k 2021-05-17 15:44:11 +02:00
parent 583be6d95e
commit 940aa2209b
No known key found for this signature in database
GPG Key ID: 824D4259F41FAFF6
7 changed files with 78 additions and 22 deletions

View File

@ -58,6 +58,7 @@ dependencies {
// AndroidX // AndroidX
def navigationVersion = "2.3.5" def navigationVersion = "2.3.5"
implementation "androidx.activity:activity-ktx:1.2.3"
implementation 'androidx.appcompat:appcompat:1.2.0' implementation 'androidx.appcompat:appcompat:1.2.0'
implementation 'androidx.constraintlayout:constraintlayout:2.0.4' implementation 'androidx.constraintlayout:constraintlayout:2.0.4'
implementation 'androidx.core:core-ktx:1.3.2' implementation 'androidx.core:core-ktx:1.3.2'

View File

@ -16,6 +16,7 @@
<!-- DANGEROUS PERMISSIONS, must request --> <!-- DANGEROUS PERMISSIONS, must request -->
<uses-permission android:name="android.permission.ACCESS_COARSE_LOCATION" /> <uses-permission android:name="android.permission.ACCESS_COARSE_LOCATION" />
<uses-permission android:name="android.permission.ACCESS_FINE_LOCATION" /> <uses-permission android:name="android.permission.ACCESS_FINE_LOCATION" />
<uses-permission android:name="android.permission.ACTIVITY_RECOGNITION" />
<application <application
android:name=".Trackbook" android:name=".Trackbook"

View File

@ -116,7 +116,9 @@ object Keys {
const val MIN_NUMBER_OF_WAYPOINTS_FOR_ELEVATION_CALCULATION: Int = 5 const val MIN_NUMBER_OF_WAYPOINTS_FOR_ELEVATION_CALCULATION: Int = 5
const val MAX_NUMBER_OF_WAYPOINTS_FOR_ELEVATION_CALCULATION: Int = 20 const val MAX_NUMBER_OF_WAYPOINTS_FOR_ELEVATION_CALCULATION: Int = 20
const val ALTITUDE_MEASUREMENT_ERROR_THRESHOLD = 10 // altitude changes of 10 meter or more (per 15 seconds) are being discarded const val ALTITUDE_MEASUREMENT_ERROR_THRESHOLD = 10 // altitude changes of 10 meter or more (per 15 seconds) are being discarded
const val REQUEST_CODE_FOREGROUND = 42 const val REQUEST_CODE_LOCATION = 42
const val REQUEST_CODE_ACTIVITY_START = 23
const val REQUEST_CODE_ACTIVITY_RESUME = 5
// requests // requests
const val REQUEST_SAVE_GPX: Int = 23 const val REQUEST_SAVE_GPX: Int = 23

View File

@ -92,9 +92,7 @@ class MapFragment : Fragment(), YesNoDialog.YesNoDialogListener, MapOverlayHelpe
trackerService.clearTrack() trackerService.clearTrack()
} }
layout.resumeButton.setOnClickListener { layout.resumeButton.setOnClickListener {
// start service via intent so that it keeps running after unbind resumeTracking()
startTrackerService()
trackerService.resumeTracking()
} }
return layout.rootView return layout.rootView
@ -106,7 +104,7 @@ class MapFragment : Fragment(), YesNoDialog.YesNoDialogListener, MapOverlayHelpe
super.onStart() super.onStart()
// request location permission if denied // request location permission if denied
if (ContextCompat.checkSelfPermission(activity as Context, Manifest.permission.ACCESS_FINE_LOCATION) == PackageManager.PERMISSION_DENIED) { if (ContextCompat.checkSelfPermission(activity as Context, Manifest.permission.ACCESS_FINE_LOCATION) == PackageManager.PERMISSION_DENIED) {
this.requestPermissions(arrayOf(Manifest.permission.ACCESS_FINE_LOCATION), Keys.REQUEST_CODE_FOREGROUND) this.requestPermissions(arrayOf(Manifest.permission.ACCESS_FINE_LOCATION), Keys.REQUEST_CODE_LOCATION)
} }
// bind to TrackerService // bind to TrackerService
activity?.bindService(Intent(activity, TrackerService::class.java), connection, Context.BIND_AUTO_CREATE) activity?.bindService(Intent(activity, TrackerService::class.java), connection, Context.BIND_AUTO_CREATE)
@ -147,7 +145,7 @@ class MapFragment : Fragment(), YesNoDialog.YesNoDialogListener, MapOverlayHelpe
override fun onRequestPermissionsResult(requestCode: Int, permissions: Array<String>, grantResults: IntArray) { override fun onRequestPermissionsResult(requestCode: Int, permissions: Array<String>, grantResults: IntArray) {
super.onRequestPermissionsResult(requestCode, permissions, grantResults) super.onRequestPermissionsResult(requestCode, permissions, grantResults)
when (requestCode) { when (requestCode) {
Keys.REQUEST_CODE_FOREGROUND -> { Keys.REQUEST_CODE_LOCATION -> {
if ((grantResults.isNotEmpty() && grantResults[0] == PackageManager.PERMISSION_GRANTED)) { if ((grantResults.isNotEmpty() && grantResults[0] == PackageManager.PERMISSION_GRANTED)) {
// permission was granted - re-bind service // permission was granted - re-bind service
activity?.unbindService(connection) activity?.unbindService(connection)
@ -160,6 +158,30 @@ class MapFragment : Fragment(), YesNoDialog.YesNoDialogListener, MapOverlayHelpe
layout.toggleLocationErrorBar(gpsProviderActive, networkProviderActive) layout.toggleLocationErrorBar(gpsProviderActive, networkProviderActive)
return return
} }
Keys.REQUEST_CODE_ACTIVITY_START -> {
LogHelper.e(TAG, "permissions => ${grantResults.isEmpty()} ${permissions[0]}") // todo remove
if ((grantResults.isNotEmpty() && grantResults[0] == PackageManager.PERMISSION_GRANTED)) {
LogHelper.i(TAG, "Request result: Activity Recognition permission has been granted.")
} else {
LogHelper.i(TAG, "Request result: Activity Recognition permission has NOT been granted.")
}
// start service via intent so that it keeps running after unbind
startTrackerService()
trackerService.startTracking()
return
}
Keys.REQUEST_CODE_ACTIVITY_RESUME -> {
LogHelper.e(TAG, "permissions => ${grantResults.isEmpty()} ${permissions[0]}") // todo remove
if ((grantResults.isNotEmpty() && grantResults[0] == PackageManager.PERMISSION_GRANTED)) {
LogHelper.i(TAG, "Request result: Activity Recognition permission has been granted.")
} else {
LogHelper.i(TAG, "Request result: Activity Recognition permission has NOT been granted.")
}
// start service via intent so that it keeps running after unbind
startTrackerService()
trackerService.resumeTracking()
return
}
} }
} }
@ -191,6 +213,34 @@ class MapFragment : Fragment(), YesNoDialog.YesNoDialogListener, MapOverlayHelpe
} }
/* Start recording waypoints */
private fun startTracking() {
// request activity recognition permission on Android Q+ if denied
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.Q && ContextCompat.checkSelfPermission(activity as Context, Manifest.permission.ACTIVITY_RECOGNITION) == PackageManager.PERMISSION_DENIED) {
LogHelper.e(TAG, "permissions resume DING") // todo remove
this.requestPermissions(arrayOf(Manifest.permission.ACTIVITY_RECOGNITION), Keys.REQUEST_CODE_ACTIVITY_START)
} else {
// start service via intent so that it keeps running after unbind
startTrackerService()
trackerService.startTracking()
}
}
/* Resume recording waypoints */
private fun resumeTracking() {
// request activity recognition permission on Android Q+ if denied
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.Q && ContextCompat.checkSelfPermission(activity as Context, Manifest.permission.ACTIVITY_RECOGNITION) == PackageManager.PERMISSION_DENIED) {
LogHelper.e(TAG, "permissions resume DING") // todo remove
this.requestPermissions(arrayOf(Manifest.permission.ACTIVITY_RECOGNITION), Keys.REQUEST_CODE_ACTIVITY_RESUME)
} else {
// start service via intent so that it keeps running after unbind
startTrackerService()
trackerService.resumeTracking()
}
}
/* Start tracker service */ /* Start tracker service */
private fun startTrackerService() { private fun startTrackerService() {
val intent = Intent(activity, TrackerService::class.java) val intent = Intent(activity, TrackerService::class.java)
@ -219,11 +269,7 @@ class MapFragment : Fragment(), YesNoDialog.YesNoDialogListener, MapOverlayHelpe
when (trackingState) { when (trackingState) {
Keys.STATE_TRACKING_STOPPED -> layout.toggleRecordingButtonSubMenu() Keys.STATE_TRACKING_STOPPED -> layout.toggleRecordingButtonSubMenu()
Keys.STATE_TRACKING_ACTIVE -> trackerService.stopTracking() Keys.STATE_TRACKING_ACTIVE -> trackerService.stopTracking()
Keys.STATE_TRACKING_NOT -> { Keys.STATE_TRACKING_NOT -> startTracking()
// start service via intent so that it keeps running after unbind
startTrackerService()
trackerService.startTracking()
}
} }
} }

View File

@ -449,11 +449,7 @@ class TrackerService: Service(), CoroutineScope, SensorEventListener {
/* Registers a step counter listener */ /* Registers a step counter listener */
private fun startStepCounter() { private fun startStepCounter() {
val stepCounterAvailable = sensorManager.registerListener( val stepCounterAvailable = sensorManager.registerListener(this, sensorManager.getDefaultSensor(Sensor.TYPE_STEP_COUNTER), SensorManager.SENSOR_DELAY_UI)
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.")
track.stepCount = -1f track.stepCount = -1f

View File

@ -77,6 +77,7 @@ data class TrackFragmentLayoutHolder(private var context: Context, private var m
private val statisticsSheet: NestedScrollView private val statisticsSheet: NestedScrollView
private val statisticsView: View private val statisticsView: View
private val distanceView: MaterialTextView private val distanceView: MaterialTextView
private val stepsTitleView: MaterialTextView
private val stepsView: MaterialTextView private val stepsView: MaterialTextView
private val waypointsView: MaterialTextView private val waypointsView: MaterialTextView
private val durationView: MaterialTextView private val durationView: MaterialTextView
@ -118,6 +119,7 @@ data class TrackFragmentLayoutHolder(private var context: Context, private var m
statisticsSheet = rootView.findViewById(R.id.statistics_sheet) statisticsSheet = rootView.findViewById(R.id.statistics_sheet)
statisticsView = rootView.findViewById(R.id.statistics_view) statisticsView = rootView.findViewById(R.id.statistics_view)
distanceView = rootView.findViewById(R.id.statistics_data_distance) distanceView = rootView.findViewById(R.id.statistics_data_distance)
stepsTitleView = rootView.findViewById(R.id.statistics_p_steps)
stepsView = rootView.findViewById(R.id.statistics_data_steps) stepsView = rootView.findViewById(R.id.statistics_data_steps)
waypointsView = rootView.findViewById(R.id.statistics_data_waypoints) waypointsView = rootView.findViewById(R.id.statistics_data_waypoints)
durationView = rootView.findViewById(R.id.statistics_data_duration) durationView = rootView.findViewById(R.id.statistics_data_duration)
@ -202,10 +204,18 @@ data class TrackFragmentLayoutHolder(private var context: Context, private var m
/* Sets up the statistics sheet */ /* Sets up the statistics sheet */
private fun setupStatisticsViews() { private fun setupStatisticsViews() {
// get step count string // get step count string - hide step count if not available
val steps: String val steps: String
if (track.stepCount == -1f) steps = context.getString(R.string.statistics_sheet_p_steps_no_pedometer) if (track.stepCount == -1f) {
else steps = track.stepCount.roundToInt().toString() steps = context.getString(R.string.statistics_sheet_p_steps_no_pedometer)
stepsTitleView.isGone = true
stepsView.isGone = true
}
else {
steps = track.stepCount.roundToInt().toString()
stepsTitleView.isVisible = true
stepsView.isVisible = true
}
// populate views // populate views
trackNameView.text = track.name trackNameView.text = track.name

View File

@ -2,7 +2,7 @@
buildscript { buildscript {
ext { ext {
kotlin_version = '1.4.32' kotlin_version = '1.5.0'
navigation_version = '2.3.3' navigation_version = '2.3.3'
} }
repositories { repositories {
@ -10,7 +10,7 @@ buildscript {
jcenter() jcenter()
} }
dependencies { dependencies {
classpath 'com.android.tools.build:gradle:4.2.0' classpath 'com.android.tools.build:gradle:4.2.1'
classpath "org.jetbrains.kotlin:kotlin-gradle-plugin:$kotlin_version" classpath "org.jetbrains.kotlin:kotlin-gradle-plugin:$kotlin_version"
classpath "androidx.navigation:navigation-safe-args-gradle-plugin:$navigation_version" classpath "androidx.navigation:navigation-safe-args-gradle-plugin:$navigation_version"