@@ -29,7 +29,6 @@ import androidx.activity.result.ActivityResultLauncher
29
29
import androidx.activity.result.contract.ActivityResultContracts
30
30
import androidx.activity.viewModels
31
31
import androidx.compose.material.ExperimentalMaterialApi
32
- import androidx.compose.runtime.getValue
33
32
import androidx.lifecycle.lifecycleScope
34
33
import androidx.navigation.findNavController
35
34
import androidx.navigation.fragment.NavHostFragment
@@ -40,6 +39,7 @@ import dagger.hilt.android.AndroidEntryPoint
40
39
import io.sentry.android.navigation.SentryNavigationListener
41
40
import java.time.Instant
42
41
import javax.inject.Inject
42
+ import kotlinx.coroutines.async
43
43
import kotlinx.coroutines.launch
44
44
import kotlinx.coroutines.withContext
45
45
import org.hl7.fhir.r4.model.IdType
@@ -62,6 +62,8 @@ import org.smartregister.fhircore.quest.R
62
62
import org.smartregister.fhircore.quest.event.AppEvent
63
63
import org.smartregister.fhircore.quest.event.EventBus
64
64
import org.smartregister.fhircore.quest.ui.questionnaire.QuestionnaireActivity
65
+ import org.smartregister.fhircore.quest.ui.shared.ActivityOnResultType
66
+ import org.smartregister.fhircore.quest.ui.shared.ON_RESULT_TYPE
65
67
import org.smartregister.fhircore.quest.ui.shared.QuestionnaireHandler
66
68
import org.smartregister.fhircore.quest.ui.shared.models.QuestionnaireSubmission
67
69
import timber.log.Timber
@@ -81,13 +83,34 @@ open class AppMainActivity : BaseMultiLanguageActivity(), QuestionnaireHandler,
81
83
val appMainViewModel by viewModels<AppMainViewModel >()
82
84
private val sentryNavListener =
83
85
SentryNavigationListener (enableNavigationBreadcrumbs = true , enableNavigationTracing = true )
84
- private lateinit var locationPermissionLauncher: ActivityResultLauncher <Array <String >>
85
- private lateinit var activityResultLauncher: ActivityResultLauncher <Intent >
86
+
87
+ private val locationPermissionLauncher: ActivityResultLauncher <Array <String >> =
88
+ registerForActivityResult(ActivityResultContracts .RequestMultiplePermissions ()) {
89
+ permissions: Map <String , Boolean > ->
90
+ PermissionUtils .getLocationPermissionLauncher(
91
+ permissions = permissions,
92
+ onFineLocationPermissionGranted = { fetchLocation() },
93
+ onCoarseLocationPermissionGranted = { fetchLocation() },
94
+ onLocationPermissionDenied = {
95
+ showToast(
96
+ getString(R .string.location_permissions_denied),
97
+ Toast .LENGTH_SHORT ,
98
+ )
99
+ },
100
+ )
101
+ }
102
+
86
103
private lateinit var fusedLocationClient: FusedLocationProviderClient
87
104
88
105
override val startForResult =
89
- registerForActivityResult(ActivityResultContracts .StartActivityForResult ()) { activityResult ->
90
- if (activityResult.resultCode == Activity .RESULT_OK ) {
106
+ registerForActivityResult(ActivityResultContracts .StartActivityForResult ()) {
107
+ activityResult: ActivityResult ->
108
+ val onResultType = activityResult.data?.extras?.getString(ON_RESULT_TYPE )
109
+ if (
110
+ activityResult.resultCode == Activity .RESULT_OK &&
111
+ ! onResultType.isNullOrBlank() &&
112
+ ActivityOnResultType .valueOf(onResultType) == ActivityOnResultType .QUESTIONNAIRE
113
+ ) {
91
114
lifecycleScope.launch { onSubmitQuestionnaire(activityResult) }
92
115
}
93
116
}
@@ -127,6 +150,7 @@ open class AppMainActivity : BaseMultiLanguageActivity(), QuestionnaireHandler,
127
150
retrieveAppMainUiState()
128
151
withContext(dispatcherProvider.io()) { schedulePeriodicJobs(this @AppMainActivity) }
129
152
}
153
+
130
154
setupLocationServices()
131
155
132
156
findViewById<View >(R .id.mainScreenProgressBar).apply { visibility = View .GONE }
@@ -188,92 +212,61 @@ open class AppMainActivity : BaseMultiLanguageActivity(), QuestionnaireHandler,
188
212
fusedLocationClient = LocationServices .getFusedLocationProviderClient(this )
189
213
190
214
if (! LocationUtils .isLocationEnabled(this )) {
191
- openLocationServicesSettings()
215
+ showLocationSettingsDialog(
216
+ Intent (Settings .ACTION_LOCATION_SOURCE_SETTINGS ).apply {
217
+ putExtra(ON_RESULT_TYPE , ActivityOnResultType .LOCATION .name)
218
+ },
219
+ )
192
220
}
193
221
194
- if (! hasLocationPermissions()) {
195
- launchLocationPermissionsDialog()
222
+ if (! PermissionUtils .hasLocationPermissions(this )) {
223
+ locationPermissionLauncher.launch(
224
+ arrayOf(
225
+ Manifest .permission.ACCESS_FINE_LOCATION ,
226
+ Manifest .permission.ACCESS_COARSE_LOCATION ,
227
+ ),
228
+ )
196
229
}
197
230
198
- if (LocationUtils .isLocationEnabled(this ) && hasLocationPermissions()) {
231
+ if (LocationUtils .isLocationEnabled(this ) && PermissionUtils . hasLocationPermissions(this )) {
199
232
fetchLocation()
200
233
}
201
234
}
202
235
}
203
236
204
- fun hasLocationPermissions (): Boolean {
205
- return PermissionUtils .checkPermissions(
206
- this ,
207
- listOf (
208
- Manifest .permission.ACCESS_COARSE_LOCATION ,
209
- Manifest .permission.ACCESS_FINE_LOCATION ,
210
- ),
211
- )
212
- }
213
-
214
- private fun openLocationServicesSettings () {
215
- activityResultLauncher =
216
- PermissionUtils .getStartActivityForResultLauncher(this ) { resultCode, _ ->
217
- if (resultCode == RESULT_OK || hasLocationPermissions()) {
218
- Timber .d(" Location or permissions successfully enabled" )
219
- }
220
- }
221
-
222
- val intent = Intent (Settings .ACTION_LOCATION_SOURCE_SETTINGS )
223
- showLocationSettingsDialog(intent)
224
- }
225
-
226
237
private fun showLocationSettingsDialog (intent : Intent ) {
227
238
AlertDialog .Builder (this )
228
239
.setMessage(getString(R .string.location_services_disabled))
229
240
.setCancelable(true )
230
- .setPositiveButton(getString(R .string.yes)) { _, _ -> activityResultLauncher .launch(intent) }
241
+ .setPositiveButton(getString(R .string.yes)) { _, _ -> startForResult .launch(intent) }
231
242
.setNegativeButton(getString(R .string.no)) { dialog, _ -> dialog.cancel() }
232
243
.show()
233
244
}
234
245
235
- fun launchLocationPermissionsDialog () {
236
- locationPermissionLauncher =
237
- PermissionUtils .getLocationPermissionLauncher(
238
- this ,
239
- onFineLocationPermissionGranted = { fetchLocation() },
240
- onCoarseLocationPermissionGranted = { fetchLocation() },
241
- onLocationPermissionDenied = {
242
- Toast .makeText(
243
- this ,
244
- getString(R .string.location_permissions_denied),
245
- Toast .LENGTH_SHORT ,
246
- )
247
- .show()
248
- },
249
- )
250
-
251
- locationPermissionLauncher.launch(
252
- arrayOf(
253
- Manifest .permission.ACCESS_FINE_LOCATION ,
254
- Manifest .permission.ACCESS_COARSE_LOCATION ,
255
- ),
256
- )
257
- }
258
-
259
246
private fun fetchLocation () {
260
247
val context = this
261
248
lifecycleScope.launch {
262
249
val retrievedLocation =
263
- if (PermissionUtils .hasFineLocationPermissions(context)) {
264
- LocationUtils .getAccurateLocation(fusedLocationClient)
265
- } else if (PermissionUtils .hasCoarseLocationPermissions(context)) {
266
- LocationUtils .getApproximateLocation(fusedLocationClient)
267
- } else {
268
- null
269
- }
270
- retrievedLocation?.let {
271
- protoDataStore.writeLocationCoordinates(
272
- LocationCoordinate (it.latitude, it.longitude, it.altitude, Instant .now()),
273
- )
274
- }
250
+ async(dispatcherProvider.io()) {
251
+ when {
252
+ PermissionUtils .hasFineLocationPermissions(context) ->
253
+ LocationUtils .getAccurateLocation(fusedLocationClient)
254
+ PermissionUtils .hasCoarseLocationPermissions(context) ->
255
+ LocationUtils .getApproximateLocation(fusedLocationClient)
256
+ else -> null
257
+ }
258
+ }
259
+ .await()
260
+ ?.also {
261
+ protoDataStore.writeLocationCoordinates(
262
+ LocationCoordinate (it.latitude, it.longitude, it.altitude, Instant .now()),
263
+ )
264
+ }
265
+
275
266
if (retrievedLocation == null ) {
276
- this @AppMainActivity.showToast(" Failed to get GPS location" , Toast .LENGTH_LONG )
267
+ withContext(dispatcherProvider.main()) {
268
+ showToast(getString(R .string.failed_to_get_gps_location), Toast .LENGTH_LONG )
269
+ }
277
270
}
278
271
}
279
272
}
0 commit comments