diff --git a/android/navi-coin/src/main/java/com/navi/coin/ui/compose/screen/CoinHomeScreenV2.kt b/android/navi-coin/src/main/java/com/navi/coin/ui/compose/screen/CoinHomeScreenV2.kt index 4e1c96e12e..aa26ccc794 100644 --- a/android/navi-coin/src/main/java/com/navi/coin/ui/compose/screen/CoinHomeScreenV2.kt +++ b/android/navi-coin/src/main/java/com/navi/coin/ui/compose/screen/CoinHomeScreenV2.kt @@ -136,6 +136,7 @@ import com.navi.common.navigation.clearResult import com.navi.common.navigation.rememberNavigatorWithResultAndParams import com.navi.common.permission.PermissionResult import com.navi.common.permission.rememberMultiplePermissions +import com.navi.common.uitron.handler.HandleTriggerGpsAction import com.navi.common.uitron.model.action.CtaAction import com.navi.common.uitron.model.action.ExecuteActionsCorrespondingToKey import com.navi.common.utils.CommonNaviAnalytics @@ -195,6 +196,8 @@ fun CoinHomeScreenV2( val bottomSheetData by viewModel.bottomSheetDataAlchemist.collectAsState(null) + HandleTriggerGpsAction(context, viewModel) + val bottomSheetState = rememberModalBottomSheetState( initialValue = ModalBottomSheetValue.Hidden, @@ -255,7 +258,11 @@ fun CoinHomeScreenV2( fun sendLocationUpdates() { if (viewModel.locationManager.isLocationOn(context)) { - viewModel.locationManager.requestLocationUpdates(context, postLocation = true) + viewModel.locationManager.requestLocationUpdates( + context, + postLocation = true, + shouldTriggerGpsIntentOnFailure = false, + ) } } diff --git a/android/navi-common/src/main/java/com/navi/common/uitron/deserializer/UiTronActionDeserializer.kt b/android/navi-common/src/main/java/com/navi/common/uitron/deserializer/UiTronActionDeserializer.kt index f500bcf827..de49582d6a 100644 --- a/android/navi-common/src/main/java/com/navi/common/uitron/deserializer/UiTronActionDeserializer.kt +++ b/android/navi-common/src/main/java/com/navi/common/uitron/deserializer/UiTronActionDeserializer.kt @@ -20,6 +20,7 @@ import com.navi.common.uitron.model.action.PostLocationAction import com.navi.common.uitron.model.action.PostPermissionAction import com.navi.common.uitron.model.action.SystemUiAction import com.navi.common.uitron.model.action.ThirdPartySdkAction +import com.navi.common.uitron.model.action.TriggerGpsCheckAction import com.navi.common.uitron.model.action.UpdateStateHandleActionV2 import com.navi.common.uitron.model.action.UpdateViewStateActionV2 import com.navi.common.uitron.model.action.UpdateWidgetsStateAction @@ -77,6 +78,8 @@ open class UiTronActionDeserializer : BaseUiTronActionDeserializer() { context?.deserialize(jsonObject, SystemUiAction::class.java) ApActionType.PostPermissionAction.name -> context?.deserialize(jsonObject, PostPermissionAction::class.java) + UiTronActionType.TriggerGpsCheckAction.name -> + context?.deserialize(jsonObject, TriggerGpsCheckAction::class.java) else -> super.deserialize(json, typeOfT, context) } } diff --git a/android/navi-common/src/main/java/com/navi/common/uitron/handler/TriggerGpsActionHandler.kt b/android/navi-common/src/main/java/com/navi/common/uitron/handler/TriggerGpsActionHandler.kt new file mode 100644 index 0000000000..4be89654dc --- /dev/null +++ b/android/navi-common/src/main/java/com/navi/common/uitron/handler/TriggerGpsActionHandler.kt @@ -0,0 +1,93 @@ +/* + * + * * Copyright © 2025 by Navi Technologies Limited + * * All rights reserved. Strictly confidential + * + */ + +package com.navi.common.uitron.handler + +import android.app.Activity +import android.content.Context +import android.location.LocationManager +import androidx.activity.compose.rememberLauncherForActivityResult +import androidx.activity.result.IntentSenderRequest +import androidx.activity.result.contract.ActivityResultContracts +import androidx.compose.runtime.Composable +import androidx.compose.runtime.LaunchedEffect +import androidx.compose.runtime.getValue +import androidx.compose.runtime.mutableStateOf +import androidx.compose.runtime.remember +import androidx.compose.runtime.setValue +import com.google.android.gms.common.api.ResolvableApiException +import com.google.android.gms.location.LocationRequest +import com.google.android.gms.location.LocationServices +import com.google.android.gms.location.LocationSettingsRequest +import com.google.android.gms.location.Priority +import com.navi.common.uitron.model.action.TriggerGpsCheckAction +import com.navi.uitron.viewmodel.UiTronViewModel + +@Composable +fun HandleTriggerGpsAction(context: Context, viewModel: UiTronViewModel) { + var action by remember { mutableStateOf(null) } + val locationManager = context.getSystemService(Context.LOCATION_SERVICE) as LocationManager + + val launcher = + rememberLauncherForActivityResult(ActivityResultContracts.StartIntentSenderForResult()) { + result -> + if (result.resultCode == Activity.RESULT_OK) { + if (locationManager.isProviderEnabled(LocationManager.GPS_PROVIDER)) { + action?.onSuccess?.let { viewModel.handleActions(it) } + } else { + action?.onFailure?.let { viewModel.handleActions(it) } + } + } else { + action?.onDismiss?.let { viewModel.handleActions(it) } + } + } + + LaunchedEffect(Unit) { + viewModel.getActionCallback().collect { uiTronAction -> + if (uiTronAction is TriggerGpsCheckAction) { + action = uiTronAction + val isGpsEnabled = locationManager.isProviderEnabled(LocationManager.GPS_PROVIDER) + + if (isGpsEnabled) { + uiTronAction.onSuccess?.let { viewModel.handleActions(it) } + return@collect + } + + val locationRequest = + LocationRequest.Builder(Priority.PRIORITY_HIGH_ACCURACY, 10000L) + .setMinUpdateIntervalMillis(5000L) + .build() + + val builder = + LocationSettingsRequest.Builder() + .addLocationRequest(locationRequest) + .setAlwaysShow(true) + + val client = LocationServices.getSettingsClient(context) + val task = client.checkLocationSettings(builder.build()) + + task.addOnSuccessListener { + uiTronAction.onSuccess?.let { viewModel.handleActions(it) } + } + + task.addOnFailureListener { exception -> + if (exception is ResolvableApiException) { + try { + val intentSenderRequest = + IntentSenderRequest.Builder(exception.resolution).build() + launcher.launch(intentSenderRequest) + } catch (e: Exception) { + uiTronAction.onFailure?.let { viewModel.handleActions(it) } + } + } else { + uiTronAction.onFailure?.let { viewModel.handleActions(it) } + } + } + } + } + } +} diff --git a/android/navi-common/src/main/java/com/navi/common/uitron/model/action/TriggerGpsCheckAction.kt b/android/navi-common/src/main/java/com/navi/common/uitron/model/action/TriggerGpsCheckAction.kt new file mode 100644 index 0000000000..8d54f79300 --- /dev/null +++ b/android/navi-common/src/main/java/com/navi/common/uitron/model/action/TriggerGpsCheckAction.kt @@ -0,0 +1,24 @@ +/* + * + * * Copyright © 2025 by Navi Technologies Limited + * * All rights reserved. Strictly confidential + * + */ + +package com.navi.common.uitron.model.action + +import com.navi.uitron.model.data.ActionDetails +import com.navi.uitron.model.data.UiTronAction +import com.navi.uitron.model.data.UiTronActionData + +data class TriggerGpsCheckAction( + val onSuccess: UiTronActionData? = null, + val onFailure: UiTronActionData? = null, + val onDismiss: UiTronActionData? = null, +) : UiTronAction() { + + override suspend fun manageAction(actionDetails: ActionDetails) { + val action = actionDetails.uiTronAction as? TriggerGpsCheckAction + actionDetails.actionCallbackFlow?.emit(action) + } +} diff --git a/android/navi-common/src/main/java/com/navi/common/uitron/serializer/UiTronActionSerializer.kt b/android/navi-common/src/main/java/com/navi/common/uitron/serializer/UiTronActionSerializer.kt index ff7b950799..0f7e2c1a63 100644 --- a/android/navi-common/src/main/java/com/navi/common/uitron/serializer/UiTronActionSerializer.kt +++ b/android/navi-common/src/main/java/com/navi/common/uitron/serializer/UiTronActionSerializer.kt @@ -20,6 +20,7 @@ import com.navi.common.uitron.model.action.PostLocationAction import com.navi.common.uitron.model.action.PostPermissionAction import com.navi.common.uitron.model.action.SystemUiAction import com.navi.common.uitron.model.action.ThirdPartySdkAction +import com.navi.common.uitron.model.action.TriggerGpsCheckAction import com.navi.common.uitron.model.action.UpdateStateHandleActionV2 import com.navi.common.uitron.model.action.UpdateViewStateActionV2 import com.navi.common.uitron.model.action.UpdateWidgetsStateAction @@ -92,6 +93,8 @@ open class UiTronActionSerializer : BaseUiTronActionSerializer() { context?.serialize(src as PaymentStatusAction, PaymentStatusAction::class.java) ApActionType.PostPermissionAction.name -> context?.serialize(src as PostPermissionAction, PostPermissionAction::class.java) + UiTronActionType.TriggerGpsCheckAction.name -> + context?.serialize(src as TriggerGpsCheckAction, TriggerGpsCheckAction::class.java) else -> super.serialize(src, typeOfSrc, context) } }