Skip to content

Commit

Permalink
Merge pull request #213 from redlink-gmbh/forkmain
Browse files Browse the repository at this point in the history
Added Permission Alert dialog and fixed multiple bugs
  • Loading branch information
alirezafatehi authored Feb 9, 2024
2 parents 4a7979b + c8f2bbc commit de6735a
Show file tree
Hide file tree
Showing 46 changed files with 633 additions and 184 deletions.
4 changes: 3 additions & 1 deletion androidApp/src/main/AndroidManifest.xml
Original file line number Diff line number Diff line change
Expand Up @@ -77,7 +77,9 @@
android:foregroundServiceType="location" />
<service
android:name=".firebase.FCMService"
android:exported="false">
android:exported="false"
android:foregroundServiceType=""
>
<intent-filter>
<action android:name="com.google.firebase.MESSAGING_EVENT" />
</intent-filter>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@ package io.redlink.more.app.android

import android.app.Application
import android.content.Context
import androidx.compose.runtime.mutableStateOf
import androidx.lifecycle.DefaultLifecycleObserver
import androidx.lifecycle.LifecycleOwner
import androidx.lifecycle.ProcessLifecycleOwner
Expand Down Expand Up @@ -71,6 +72,7 @@ class MoreApplication : Application(), DefaultLifecycleObserver {
var polarConnector: PolarConnector? = null
private set

val openSettings = mutableStateOf(false)

fun initShared(context: Context) {
if (shared == null) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -86,7 +86,8 @@ fun LoginBLESetupView(viewModel: BLESetupViewModel, showDescrPart2: Boolean) {
showBackButton = true,
onBackButtonClick = {
(context as? Activity)?.finish()
}
},
alertDialogModel = viewModel.alertDialogOpen.value
) {
LazyColumn {
item {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -15,13 +15,15 @@ import androidx.compose.runtime.mutableStateOf
import androidx.lifecycle.ViewModel
import androidx.lifecycle.viewModelScope
import io.redlink.more.app.android.MoreApplication
import io.redlink.more.more_app_mutliplatform.models.AlertDialogModel
import io.redlink.more.more_app_mutliplatform.observations.ObservationFactory
import io.redlink.more.more_app_mutliplatform.services.bluetooth.BluetoothConnector
import io.redlink.more.more_app_mutliplatform.services.bluetooth.BluetoothDevice
import io.redlink.more.more_app_mutliplatform.services.bluetooth.BluetoothState
import io.redlink.more.more_app_mutliplatform.viewModels.startupConnection.CoreBLESetupViewModel
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.launch
import kotlinx.coroutines.withContext

class BLESetupViewModel: ViewModel() {
private val coreBLESetupViewModel = CoreBLESetupViewModel(MoreApplication.shared!!.observationFactory, MoreApplication.shared!!.coreBluetooth)
Expand All @@ -33,7 +35,17 @@ class BLESetupViewModel: ViewModel() {

val neededDevices = mutableStateListOf<String>()

val alertDialogOpen = mutableStateOf<AlertDialogModel?>(null)


init {
viewModelScope.launch(Dispatchers.IO) {
MoreApplication.shared!!.mainContentCoreViewModel.alertDialogModel.collect {
withContext(Dispatchers.Main) {
alertDialogOpen.value = it
}
}
}
viewModelScope.launch(Dispatchers.Default) {
coreBLESetupViewModel.coreBluetooth.discoveredDevices.collect {
discoveredDevices.clear()
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,6 @@
*/
package io.redlink.more.app.android.activities

import android.content.Intent
import android.net.Uri
import android.os.Bundle
import androidx.activity.ComponentActivity
Expand Down Expand Up @@ -46,14 +45,15 @@ class ContentActivity: ComponentActivity() {
ContentView(viewModel = viewModel)
}
}

}

@Composable
fun ContentView(viewModel: ContentViewModel) {
if (viewModel.hasCredentials.value) {
viewModel.openMainActivity(LocalContext.current)
} else {
MoreBackground(showBackButton = false) {
MoreBackground(showBackButton = false, alertDialogModel = viewModel.alertDialogOpen.value) {
if (viewModel.loginViewScreenNr.value == 0) {
LoginView(model = viewModel.loginViewModel)
AppVersion()
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -26,11 +26,15 @@ import io.redlink.more.app.android.activities.login.LoginViewModelListener
import io.redlink.more.app.android.activities.main.MainActivity
import io.redlink.more.app.android.extensions.showNewActivityAndClearStack
import io.redlink.more.app.android.workers.ScheduleUpdateWorker
import io.redlink.more.more_app_mutliplatform.models.AlertDialogModel
import io.redlink.more.more_app_mutliplatform.models.StudyState
import io.redlink.more.more_app_mutliplatform.services.network.RegistrationService
import io.redlink.more.more_app_mutliplatform.services.network.openapi.model.Study
import io.redlink.more.more_app_mutliplatform.viewModels.CoreContentViewModel
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.flow.collect
import kotlinx.coroutines.launch
import kotlinx.coroutines.withContext
import java.util.concurrent.TimeUnit

class ContentViewModel : ViewModel(), LoginViewModelListener, ConsentViewModelListener {
Expand All @@ -42,6 +46,18 @@ class ContentViewModel : ViewModel(), LoginViewModelListener, ConsentViewModelLi
val hasCredentials = mutableStateOf(MoreApplication.shared!!.credentialRepository.hasCredentials())
val loginViewScreenNr = mutableStateOf(0)

val alertDialogOpen = mutableStateOf<AlertDialogModel?>(null)

init {
viewModelScope.launch(Dispatchers.IO) {
MoreApplication.shared!!.mainContentCoreViewModel.alertDialogModel.collect {
withContext(Dispatchers.Main) {
alertDialogOpen.value = it
}
}
}
}

fun openMainActivity(context: Context) {
(context as? Activity)?.let {
val workManager = WorkManager.getInstance(context)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,16 @@
*/
package io.redlink.more.app.android.activities.consent

import androidx.compose.foundation.layout.*
import android.content.Intent
import android.net.Uri
import android.provider.Settings
import androidx.compose.foundation.layout.Arrangement
import androidx.compose.foundation.layout.Box
import androidx.compose.foundation.layout.Spacer
import androidx.compose.foundation.layout.fillMaxHeight
import androidx.compose.foundation.layout.fillMaxWidth
import androidx.compose.foundation.layout.height
import androidx.compose.foundation.layout.padding
import androidx.compose.foundation.lazy.LazyColumn
import androidx.compose.foundation.lazy.items
import androidx.compose.material.Text
Expand All @@ -32,23 +41,6 @@ import io.redlink.more.app.android.ui.theme.MoreColors

@Composable
fun ConsentView(model: ConsentViewModel) {
val context = LocalContext.current
model.error.value?.let {
MessageAlertDialog(title = getStringResource(id = R.string.more_permission_message_dialog_title),
message = "$it\n ${getStringResource(id = R.string.more_permission_message_dialog_message_retry)}",
positiveButtonTitle = getStringResource(id = R.string.more_permission_message_dialog_message_retry_button),
onPositive = {
model.acceptConsent(context)
model.error.value = null
},
negativeButtonTitle = getStringResource(id = R.string.more_permission_message_dialog_message_cancel_button),
onNegative = {
model.decline()
model.error.value = null
}
)
}

LazyColumn(
verticalArrangement = Arrangement.Top,
horizontalAlignment = Alignment.CenterHorizontally,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -10,16 +10,15 @@
*/
package io.redlink.more.app.android.activities.consent

import android.Manifest
import android.content.Context
import android.os.Build
import androidx.compose.runtime.mutableStateOf
import androidx.lifecycle.ViewModel
import androidx.lifecycle.viewModelScope
import io.redlink.more.app.android.MoreApplication
import io.redlink.more.app.android.R
import io.redlink.more.app.android.extensions.getSecureID
import io.redlink.more.app.android.extensions.stringResource
import io.redlink.more.more_app_mutliplatform.models.AlertDialogModel
import io.redlink.more.more_app_mutliplatform.models.PermissionModel
import io.redlink.more.more_app_mutliplatform.services.extensions.toMD5
import io.redlink.more.more_app_mutliplatform.services.network.RegistrationService
Expand All @@ -44,7 +43,6 @@ class ConsentViewModel(
mutableStateOf(PermissionModel("Title", "Participation Info", "Study Consent Info", emptyList()))
val loading = mutableStateOf(false)
val error = mutableStateOf<String?>(null)
val permissionsNotGranted = mutableStateOf(false)
val permissions = mutableSetOf<String>()

init {
Expand All @@ -66,12 +64,6 @@ class ConsentViewModel(
}
}

fun getNeededPermissions() {
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.TIRAMISU) {
permissions.add(Manifest.permission.POST_NOTIFICATIONS)
}
}

fun setConsentInfo(info: String) {
this.consentInfo = info
}
Expand All @@ -90,6 +82,39 @@ class ConsentViewModel(
}
}

fun openPermissionDeniedAlertDialog(context: Context) {
MoreApplication.shared!!.mainContentCoreViewModel.openAlertDialog(AlertDialogModel(
title = stringResource(R.string.required_permissions_not_granted_title),
message = stringResource(R.string.required_permission_not_granted_message),
positiveTitle = stringResource(R.string.proceed_to_settings_button),
negativeTitle = stringResource(R.string.proceed_without_granting_button),
onPositive = {
MoreApplication.openSettings.value = true
MoreApplication.shared!!.mainContentCoreViewModel.closeAlertDialog()
},
onNegative = {
acceptConsent(context)
MoreApplication.shared!!.mainContentCoreViewModel.closeAlertDialog()
}
))
}

fun openNotificationPermissionDeniedAlertDialog() {
MoreApplication.shared!!.mainContentCoreViewModel.openAlertDialog(AlertDialogModel(
title = stringResource(R.string.notification_permission_not_granted_title),
message = stringResource(R.string.notification_permission_not_granted_message),
positiveTitle = stringResource(R.string.proceed_to_settings_button),
negativeTitle = stringResource(R.string.proceed_without_granting_button),
onPositive = {
MoreApplication.openSettings.value = true
MoreApplication.shared!!.mainContentCoreViewModel.closeAlertDialog()
},
onNegative = {
MoreApplication.shared!!.mainContentCoreViewModel.closeAlertDialog()
}
))
}

fun decline() {
consentViewModelListener.decline()
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@ import android.Manifest
import android.app.AlertDialog
import android.content.Context
import android.content.pm.PackageManager
import android.os.Build
import androidx.activity.compose.ManagedActivityResultLauncher
import androidx.activity.compose.rememberLauncherForActivityResult
import androidx.activity.result.contract.ActivityResultContracts
Expand All @@ -40,14 +41,31 @@ fun ConsentButtons(model: ConsentViewModel) {
val launcher = rememberLauncherForActivityResult(
ActivityResultContracts.RequestMultiplePermissions()
) { permissionsMap ->
val areGranted = permissionsMap.values.reduce { acc, next -> acc && next }
if (areGranted) {
model.acceptConsent(context = context)
val notificationPermission = if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.TIRAMISU) {
Manifest.permission.POST_NOTIFICATIONS
} else {
model.permissionsNotGranted.value = true
null
}

val mutablePermissionMap = permissionsMap.toMutableMap()

notificationPermission?.let {
if (mutablePermissionMap[it] == false) {
model.openNotificationPermissionDeniedAlertDialog()
mutablePermissionMap.remove(it)
}
}

val anyPermissionDenied = mutablePermissionMap.values.any { !it }

if (anyPermissionDenied) {
model.openPermissionDeniedAlertDialog(context)
} else {
model.acceptConsent(context)
}
}


if (!model.loading.value) {
Column(
verticalArrangement = Arrangement.Bottom,
Expand All @@ -57,8 +75,7 @@ fun ConsentButtons(model: ConsentViewModel) {
) {
Button(
onClick = {
model.getNeededPermissions()
checkAndRequestLocationPermissions(context, launcher, model)
checkAndRequestPermissions(context, launcher, model)
},
colors = ButtonDefaults
.buttonColors(backgroundColor = MoreColors.Primary,
Expand Down Expand Up @@ -100,21 +117,26 @@ fun ConsentButtons(model: ConsentViewModel) {
}
}

fun checkAndRequestLocationPermissions(
fun checkAndRequestPermissions(
context: Context,
launcher: ManagedActivityResultLauncher<Array<String>, Map<String, Boolean>>,
model: ConsentViewModel,
extraPermissions: Set<String> = emptySet()
) {
val permissions = model.permissions
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.TIRAMISU) {
permissions.add(Manifest.permission.POST_NOTIFICATIONS)
}
permissions.addAll(extraPermissions)

val hasBackgroundLocationPermission = permissions.contains(Manifest.permission.ACCESS_BACKGROUND_LOCATION)
if (hasBackgroundLocationPermission) {
permissions.remove(Manifest.permission.ACCESS_BACKGROUND_LOCATION)
}
if (checkPermissions(context, launcher, permissions)) {
if (hasBackgroundLocationPermission) {
checkPermissionForBackgroundLocationAccess(context, launcher, model)
}
model.acceptConsent(context = context)
if (hasBackgroundLocationPermission) {
checkPermissionForBackgroundLocationAccess(context, launcher, model)
} else {
checkPermissions(context, launcher, permissions)
}
}

Expand Down Expand Up @@ -147,13 +169,13 @@ fun checkPermissionForBackgroundLocationAccess(
AlertDialog.Builder(context)
.setTitle(R.string.background_location_permission_title)
.setMessage(R.string.background_location_permission_message)
.setPositiveButton("Accept") { _, _ ->
launcher.launch(arrayOf(Manifest.permission.ACCESS_BACKGROUND_LOCATION))

.setPositiveButton("Accept") { dialog, _ ->
checkAndRequestPermissions(context, launcher, model, setOf(Manifest.permission.ACCESS_BACKGROUND_LOCATION))
dialog.dismiss()
}
.setNegativeButton("Decline") { dialog, _ ->
checkAndRequestPermissions(context, launcher, model)
dialog.dismiss()
model.decline()
}
.create()
.show()
Expand Down
Loading

0 comments on commit de6735a

Please sign in to comment.