Skip to content

Commit

Permalink
#200: Fixed an issue where the Polar observation would not start, as …
Browse files Browse the repository at this point in the history
…the HR function needs a bit to activate and the framework returned immediatly an error

Also fixed an issue, where the permission dialog would immediatly pop up on the consent screen on Android
  • Loading branch information
janoliver20 committed Jun 4, 2024
1 parent 178e65b commit e434613
Show file tree
Hide file tree
Showing 21 changed files with 73 additions and 57 deletions.
4 changes: 2 additions & 2 deletions androidApp/build.gradle.kts
Original file line number Diff line number Diff line change
Expand Up @@ -13,8 +13,8 @@ android {
applicationId = "ac.at.lbg.dhp.more"
minSdk = 29
targetSdk = 34
versionCode = 8
versionName = "4.0.9"
versionCode = 9
versionName = "4.0.10"
}
buildFeatures {
compose = true
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -152,9 +152,7 @@ class ContentViewModel : ViewModel(), LoginViewModelListener, ConsentViewModelLi
}

override fun credentialsStored() {
viewModelScope.launch(Dispatchers.Main) {
hasCredentials.value = true
}
hasCredentials.value = true
}

override fun decline() {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,7 @@ import io.redlink.more.more_app_mutliplatform.services.bluetooth.BluetoothDevice
import io.redlink.more.more_app_mutliplatform.util.Scope
import kotlinx.coroutines.Job
import kotlinx.coroutines.flow.MutableStateFlow
import kotlinx.coroutines.flow.update

private val permissions =
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.S) {
Expand Down Expand Up @@ -124,6 +125,8 @@ class PolarHeartRateObservation :
if (!MoreApplication.shared!!.bluetoothController.observerDeviceAccessible(deviceIdentifier)) {
errors.add("device_not_connected")
errors.add(ERROR_DEVICE_NOT_CONNECTED)
} else if (!hrReady.value) {
errors.add("hr_unavailable")
}
return errors
}
Expand Down Expand Up @@ -169,16 +172,24 @@ class PolarHeartRateObservation :
companion object {
val hrReady: MutableStateFlow<Boolean> = MutableStateFlow(false)

fun setHRReady() {
if (!hrReady.value) {
hrReady.set(true)
MoreApplication.shared!!.observationManager.startObservationType(
fun setHRFeature(state: Boolean) {
if (state) {
if (!hrReady.value) {
MoreApplication.shared!!.observationManager.startObservationType(
PolarVerityHeartRateType(
emptySet()
).observationType
)
Napier.d(tag = "PolarHeartRateObservation::Companion::setHRFeature") { "HR Feature Ready!" }
}
} else {
Observation.pauseObservation(
PolarVerityHeartRateType(
emptySet()
).observationType
)
)
Napier.d(tag = "PolarHeartRateObservation::Companion::polarDeviceDisconnected") { "HR Feature Ready!" }
}
hrReady.update { state }
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,7 @@ fun Observation.showPermissionAlertDialog() {
))
}

fun Observation.pauseObservation(observationType: ObservationType) {
fun Observation.Companion.pauseObservation(observationType: ObservationType) {
MoreApplication.shared!!.observationManager.pauseObservationType(
observationType.observationType
)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -124,7 +124,7 @@ class PolarConnector(context: Context) : BluetoothConnector, PolarConnectorListe
override fun onPolarFeatureReady(feature: PolarBleApi.PolarBleSdkFeature) {
if (feature == PolarBleApi.PolarBleSdkFeature.FEATURE_HR) {
Napier.i(tag = "PolarConnector::onPolarFeatureReady") { "HR ready!" }
PolarHeartRateObservation.setHRReady()
PolarHeartRateObservation.setHRFeature(false)
}
}

Expand Down
1 change: 1 addition & 0 deletions androidApp/src/main/res/values-de/error-strings.xml
Original file line number Diff line number Diff line change
Expand Up @@ -12,4 +12,5 @@
<string name="observation_error">Aufzeichnungfehler</string>
<string name="observation_cannot_start">Beobachtung kann nicht gestartet werden! Bitte stellen Sie sicher, dass Bluetooth aktiviert ist und alle notwendigen Geräte verbunden sind!</string>
<string name="observation_bluetooth_error">Fehler beim Fortsetzen der Beobachtung! Es gab ein Verbindungsproblem mit einem Bluetooth-Sensor. Bitte stellen Sie sicher, dass Bluetooth aktiviert ist und alle notwendigen Geräte verbunden sind!</string>
<string name="hr_unavailable">Funktion zur Messung der Herzfrequenz nicht verfügbar</string>
</resources>
1 change: 1 addition & 0 deletions androidApp/src/main/res/values/error-strings.xml
Original file line number Diff line number Diff line change
Expand Up @@ -12,4 +12,5 @@
<string name="observation_error">Observation Error</string>
<string name="observation_cannot_start">Cannot start Observation! Please make sure to enable bluetooth and connect all necessary devices!</string>
<string name="observation_bluetooth_error">Error continuing Observation! There was a connection issue to a bluetooth sensor. Please make sure to enable bluetooth and connect all necessary devices!</string>
<string name="hr_unavailable">Heart-rate measurement feature unavailable</string>
</resources>
4 changes: 2 additions & 2 deletions iosApp/iosApp.xcodeproj/project.pbxproj
Original file line number Diff line number Diff line change
Expand Up @@ -1798,7 +1798,7 @@
"$(inherited)",
"@executable_path/Frameworks",
);
MARKETING_VERSION = 4.0.9;
MARKETING_VERSION = 4.0.10;
OTHER_LDFLAGS = (
"$(inherited)",
"-framework",
Expand Down Expand Up @@ -1838,7 +1838,7 @@
"$(inherited)",
"@executable_path/Frameworks",
);
MARKETING_VERSION = 4.0.9;
MARKETING_VERSION = 4.0.10;
OTHER_LDFLAGS = (
"$(inherited)",
"-framework",
Expand Down
2 changes: 1 addition & 1 deletion iosApp/iosApp/Extensions/ObservationExtension.swift
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,7 @@ protocol ObservationCollector {
}

extension Observation_ {
func pauseObservation(_ observationType: ObservationType) {
static func pauseObservation(_ observationType: ObservationType) {
AppDelegate.shared.observationManager.pauseObservationType(type: observationType.observationType)
}
}
4 changes: 2 additions & 2 deletions iosApp/iosApp/Info.plist
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,7 @@
<key>CFBundlePackageType</key>
<string>$(PRODUCT_BUNDLE_PACKAGE_TYPE)</string>
<key>CFBundleShortVersionString</key>
<string>4.0.9</string>
<string>4.0.10</string>
<key>CFBundleURLTypes</key>
<array>
<dict>
Expand All @@ -36,7 +36,7 @@
</dict>
</array>
<key>CFBundleVersion</key>
<string>4.0.9</string>
<string>4.0.10</string>
<key>FirebaseAppDelegateProxyEnabled</key>
<false/>
<key>ITSAppUsesNonExemptEncryption</key>
Expand Down
19 changes: 12 additions & 7 deletions iosApp/iosApp/Observations/PolarVerityHeartRateObservation.swift
Original file line number Diff line number Diff line change
Expand Up @@ -23,11 +23,15 @@ import UIKit
class PolarVerityHeartRateObservation: Observation_ {
static var hrReady = false

static func setHRReady() {
if !hrReady {
hrReady = true
AppDelegate.shared.observationManager.startObservationType(type: PolarVerityHeartRateType(sensorPermissions: []).observationType)
static func setHRFeature(state: Bool) {
if state {
if !hrReady {
AppDelegate.shared.observationManager.startObservationType(type: PolarVerityHeartRateType(sensorPermissions: []).observationType)
}
} else {
Observation_.pauseObservation(PolarVerityHeartRateType(sensorPermissions: []))
}
hrReady = state
}

private let deviceIdentificer: Set<String> = ["Polar"]
Expand Down Expand Up @@ -60,7 +64,7 @@ class PolarVerityHeartRateObservation: Observation_ {
print(error)
if let self {
showObservationErrorNotification(notificationBody: "Error continuing Observation! There was a connection issue to a bluetooth sensor. Please make sure to enable bluetooth and connect all necessary devices!".localize(withComment: "Error continuing Observation! There was a connection issue to a bluetooth sensor. Please make sure to enable bluetooth and connect all necessary devices!", useTable: errorStringTable), fallbackTitle: "Observation Error".localize(withComment: "Observation Error", useTable: errorStringTable))
self.pauseObservation(self.observationType)
Observation_.pauseObservation(self.observationType)
}
})
return true
Expand Down Expand Up @@ -89,6 +93,8 @@ class PolarVerityHeartRateObservation: Observation_ {
if !AppDelegate.shared.bluetoothController.observerDeviceAccessible(bleDevices: deviceIdentificer) {
errors.insert("No polar device connected")
errors.insert(Observation_.companion.ERROR_DEVICE_NOT_CONNECTED)
} else if !PolarVerityHeartRateObservation.hrReady {
errors.insert("Heart-rate measurement feature unavailable")
}
return errors
}
Expand All @@ -108,8 +114,7 @@ class PolarVerityHeartRateObservation: Observation_ {
private func listenToDeviceConnection() {
deviceListener = deviceManager.connectedDevicesAsClosure { [weak self] devices in
if let self, !self.deviceIdentificer.anyNameIn(items: devices) {
self.pauseObservation(self.observationType)
PolarVerityHeartRateObservation.hrReady = false
PolarVerityHeartRateObservation.setHRFeature(state: false)
self.deviceListener?.close()
}
}
Expand Down
1 change: 1 addition & 0 deletions iosApp/iosApp/Resources/Strings/de.lproj/Errors.strings
Original file line number Diff line number Diff line change
Expand Up @@ -19,3 +19,4 @@
"Cannot start Observation! Please make sure to enable Bluetooth and connect all necessary devices!" = "Beobachtung kann nicht gestartet werden! Bitte stellen Sie sicher, dass Bluetooth aktiviert ist und alle notwendigen Geräte verbunden sind!";
"Error continuing Observation! There was a connection issue to a bluetooth sensor. Please make sure to enable bluetooth and connect all necessary devices!" = "Fehler beim Fortsetzen der Beobachtung! Es gab ein Verbindungsproblem mit einem Bluetooth-Sensor. Bitte stellen Sie sicher, dass Bluetooth aktiviert ist und alle notwendigen Geräte verbunden sind!";
"Observation Error" = "Aufzeichnungfehler";
"Heart-rate measurement feature unavailable" = "Funktion zur Messung der Herzfrequenz nicht verfügbar";
1 change: 1 addition & 0 deletions iosApp/iosApp/Resources/Strings/en.lproj/Errors.strings
Original file line number Diff line number Diff line change
Expand Up @@ -19,3 +19,4 @@
"Cannot start Observation! Please make sure to enable bluetooth and connect all necessary devices!" = "Cannot start Observation! Please make sure to enable bluetooth and connect all necessary devices!";
"Error continuing Observation! There was a connection issue to a bluetooth sensor. Please make sure to enable bluetooth and connect all necessary devices!" = "Error continuing Observation! There was a connection issue to a bluetooth sensor. Please make sure to enable bluetooth and connect all necessary devices!";
"Observation Error" = "Observation Error";
"Heart-rate measurement feature unavailable" = "Heart-rate measurement feature unavailable";
4 changes: 1 addition & 3 deletions iosApp/iosApp/Services/Bluetooth/PolarConnector.swift
Original file line number Diff line number Diff line change
Expand Up @@ -267,11 +267,9 @@ extension PolarConnector: PolarBleApiDeviceFeaturesObserver {
func bleSdkFeatureReady(_ identifier: String, feature: PolarBleSdk.PolarBleSdkFeature) {
if feature == .feature_hr {
print("HR ready")
PolarVerityHeartRateObservation.setHRReady()
PolarVerityHeartRateObservation.setHRFeature(state: true)
}
}


}

extension PolarConnector: PolarBleApiDeviceInfoObserver {
Expand Down
5 changes: 3 additions & 2 deletions iosApp/iosApp/Services/FCMService.swift
Original file line number Diff line number Diff line change
Expand Up @@ -50,12 +50,13 @@ extension FCMService: UNUserNotificationCenterDelegate {
@MainActor
func userNotificationCenter(_ center: UNUserNotificationCenter, didReceive response: UNNotificationResponse) async {
let data = response.notification.request.content.userInfo.notNilStringDictionary()
let msgId = data[NotificationManager.companion.MSG_ID]
let msgId = data[NotificationManager.companion.MSG_ID] ?? response.notification.request.identifier
if let deepLinkString = data[NotificationManager.companion.DEEP_LINK] {
if let deepLink = URL(string: deepLinkString) {
AppDelegate.navigationScreenHandler.openWithDeepLink(url: deepLink, notificationId: msgId)
}
} else if let msgId {
} else {
AppDelegate.navigationScreenHandler.clearViews()
AppDelegate.navigationScreenHandler.tagState = 1
AppDelegate.shared.notificationManager.markNotificationAsRead(notificationId: msgId)
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -40,6 +40,7 @@ import io.redlink.more.more_app_mutliplatform.viewModels.ViewManager
import io.redlink.more.more_app_mutliplatform.viewModels.bluetoothConnection.BluetoothController
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.IO
import kotlinx.coroutines.Job
import kotlinx.coroutines.flow.firstOrNull
import kotlinx.coroutines.sync.Mutex
import kotlinx.coroutines.sync.withLock
Expand Down Expand Up @@ -75,11 +76,13 @@ class Shared(

val currentStudyState = studyStateRepository.currentStudyState
var finishText: String? = null
private var bluetoothListener: Job? = null

private val mutex = Mutex()

init {
onApplicationStart()
observationFactory.setCredentialsRepository(credentialRepository)
observationFactory.setNotificationManager(notificationManager)
}

Expand All @@ -97,12 +100,12 @@ class Shared(
if (credentialRepository.hasCredentials()) {
updateStudyBlocking()
notificationManager.createNewFCMIfNecessary()
StudyScope.launch {
bluetoothListener?.cancel()
bluetoothListener = StudyScope.launch {
bluetoothController.listenToConnectionChanges(
observationFactory,
observationManager
observationFactory
)
}
}.second
observationFactory.updateObservationErrors()
updateTaskStates()
}
Expand Down Expand Up @@ -242,14 +245,14 @@ class Shared(
finishText = StudyRepository().getStudy().firstOrNull()?.finishText
}
activateObservationWatcher()
StudyScope.launch {
updateTaskStates()
observationFactory.updateObservationErrors()
bluetoothListener?.cancel()
bluetoothListener = StudyScope.launch {
bluetoothController.listenToConnectionChanges(
observationFactory,
observationManager
observationFactory
)
}
observationFactory.updateObservationErrors()
updateTaskStates()
}.second
}

fun exitStudy(onDeletion: () -> Unit) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,7 @@ abstract class Observation(val observationType: ObservationType) {
private val scheduleRepository = ScheduleRepository()
private var dataManager: ObservationDataManager? = null
private var notificationManager: NotificationManager? = null

private var running = false
private val observationIds = mutableSetOf<String>()
private val scheduleIds = mutableMapOf<String, String>()
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@ import io.redlink.more.more_app_mutliplatform.extensions.set
import io.redlink.more.more_app_mutliplatform.observations.limesurvey.LimeSurveyObservation
import io.redlink.more.more_app_mutliplatform.observations.simpleQuestionObservation.SimpleQuestionObservation
import io.redlink.more.more_app_mutliplatform.services.notification.NotificationManager
import io.redlink.more.more_app_mutliplatform.services.store.CredentialRepository
import io.redlink.more.more_app_mutliplatform.util.Scope
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.IO
Expand All @@ -31,6 +32,7 @@ import kotlinx.coroutines.flow.update


abstract class ObservationFactory(private val dataManager: ObservationDataManager) {
private var credentialRepository: CredentialRepository? = null
val observations = mutableSetOf<Observation>()

private val _studyObservationTypes: MutableStateFlow<Set<String>> = MutableStateFlow(emptySet())
Expand All @@ -53,12 +55,9 @@ abstract class ObservationFactory(private val dataManager: ObservationDataManage
}
Scope.launch(Dispatchers.IO) {
studyObservationTypes.collect {
Napier.d(tag = "ObservationFactory::init::StudyObservationTypes") { it.toString() }
if (it.isNotEmpty()) {
Napier.d { "Study types not empty" }
listenToObservationErrors()
} else {
Napier.d { "Study types empty" }
observationErrorWatcher?.cancel()
observationErrorWatcher = null
_observationErrors.update { emptyMap() }
Expand All @@ -79,6 +78,10 @@ abstract class ObservationFactory(private val dataManager: ObservationDataManage
_observationErrors.update { emptyMap() }
}

fun setCredentialsRepository(credentialRepository: CredentialRepository) {
this.credentialRepository = credentialRepository
}

fun studySensorPermissions() =
observations.filter { it.observationType.observationType in studyObservationTypes.value }
.map { it.observationType.sensorPermissions }.flatten().toSet()
Expand Down Expand Up @@ -124,7 +127,9 @@ abstract class ObservationFactory(private val dataManager: ObservationDataManage
}

fun updateObservationErrors() {
studyObservations().forEach { it.updateObservationErrors() }
if (this.credentialRepository?.hasCredentials() == true) {
studyObservations().forEach { it.updateObservationErrors() }
}
}

fun observation(type: String): Observation? {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -117,12 +117,11 @@ class RegistrationService(
onError(NetworkServiceError(null, "Could not get study: ${error.message}"))
} else {
study?.let { study ->
Napier.i { study.toString() }
shared.observationFactory.clearNeededObservationTypes()
StudyRepository().storeStudy(study)
addObservationPermissions(study)
shared.resetFirstStartUp()
onSuccess(shared.credentialRepository.hasCredentials())
} ?: kotlin.run {
} ?: run {
onError(NetworkServiceError(null, "Could not get study"))
}
}
Expand Down
Loading

0 comments on commit e434613

Please sign in to comment.