@@ -2,7 +2,6 @@ package com.pigo.areo
2
2
3
3
import android.Manifest
4
4
import android.annotation.SuppressLint
5
- import android.content.ComponentName
6
5
import android.content.Context
7
6
import android.content.Intent
8
7
import android.content.pm.PackageManager
@@ -47,6 +46,7 @@ class MainActivity : AppCompatActivity(), OnMapReadyCallback {
47
46
48
47
companion object {
49
48
private const val PERMISSION_REQUEST_CODE = 123
49
+ private const val RETRY_DELAY_MS = 10000L // 10 seconds
50
50
}
51
51
52
52
private lateinit var binding: ActivityMainBinding
@@ -58,15 +58,17 @@ class MainActivity : AppCompatActivity(), OnMapReadyCallback {
58
58
}
59
59
60
60
private var cameraUpdateJob: Job ? = null
61
+ private var permissionRetryJob: Job ? = null
61
62
62
63
private val requestPermissionLauncher = registerForActivityResult(
63
64
ActivityResultContracts .RequestMultiplePermissions ()
64
65
) { permissions ->
65
- if (permissions[Manifest .permission.ACCESS_FINE_LOCATION ] == true && permissions[Manifest .permission.ACCESS_COARSE_LOCATION ] == true && permissions[Manifest .permission.WAKE_LOCK ] == true ) {
66
+ val allPermissionsGranted = permissions.all { it.value }
67
+ if (allPermissionsGranted) {
66
68
checkBatteryOptimization()
67
69
} else {
68
- Log .e(" PermissionError" , " Location or wake lock permissions denied." )
69
- // Handle permission denial (e.g., show a message to the user )
70
+ Log .e(" PermissionError" , " Required permissions denied." )
71
+ startPermissionRetryCoroutine( )
70
72
}
71
73
}
72
74
@@ -92,78 +94,104 @@ class MainActivity : AppCompatActivity(), OnMapReadyCallback {
92
94
93
95
appBarConfiguration = AppBarConfiguration (
94
96
setOf (
95
- R .id.tripDetailsFragment, R .id.createTripFragment, R .id.currentTripFragment
97
+ R .id.tripDetailsFragment,
98
+ R .id.createTripFragment,
99
+ R .id.currentTripFragment
96
100
)
97
101
)
98
102
binding.bottomNavigation.setupWithNavController(navController)
99
103
}
100
104
101
105
private fun requestLocationPermissions () {
102
- val permissionsToRequest = mutableListOf (
106
+ val locationPermissions = arrayOf (
103
107
Manifest .permission.ACCESS_FINE_LOCATION ,
104
108
Manifest .permission.ACCESS_COARSE_LOCATION ,
105
- )
106
-
107
- // Request background location permission on Android 10 (API level 29) and higher
108
- if ( Build . VERSION . SDK_INT >= Build . VERSION_CODES . Q ) {
109
- permissionsToRequest.add( Manifest .permission. ACCESS_BACKGROUND_LOCATION )
109
+ Manifest .permission. WAKE_LOCK
110
+ ). apply {
111
+ if ( Build . VERSION . SDK_INT >= Build . VERSION_CODES . Q ) {
112
+ plus( Manifest .permission. ACCESS_BACKGROUND_LOCATION )
113
+ }
110
114
}
111
115
112
- if (permissionsToRequest.all {
113
- ContextCompat .checkSelfPermission(this , it) == PackageManager .PERMISSION_GRANTED
114
- }) {
115
- // All permissions already granted
116
- checkBatteryOptimization()
116
+ val permissionsToRequest = locationPermissions.filter {
117
+ ActivityCompat .checkSelfPermission(this , it) != PackageManager .PERMISSION_GRANTED
118
+ }.toTypedArray()
119
+
120
+ if (permissionsToRequest.isNotEmpty()) {
121
+ requestPermissionLauncher.launch(permissionsToRequest)
117
122
} else {
118
- // Request permissions
119
- requestPermissionLauncher.launch(
120
- permissionsToRequest.toTypedArray()
121
- )
123
+ checkBatteryOptimization()
122
124
}
123
125
}
126
+
127
+ private fun startPermissionRetryCoroutine () {
128
+ permissionRetryJob = lifecycleScope.launch {
129
+ while (isActive) {
130
+ if (arePermissionsGranted()) {
131
+ permissionRetryJob?.cancel()
132
+ checkBatteryOptimization()
133
+ return @launch
134
+ }
135
+ Log .d(" PermissionRetry" , " Retrying permission request..." )
136
+ delay(RETRY_DELAY_MS )
137
+ requestLocationPermissions()
138
+ }
139
+ }
140
+ }
141
+
142
+ private fun arePermissionsGranted (): Boolean {
143
+ val requiredPermissions = arrayOf(
144
+ Manifest .permission.ACCESS_FINE_LOCATION ,
145
+ Manifest .permission.ACCESS_COARSE_LOCATION ,
146
+ Manifest .permission.WAKE_LOCK
147
+ ).apply {
148
+ if (Build .VERSION .SDK_INT >= Build .VERSION_CODES .Q ) {
149
+ plus(Manifest .permission.ACCESS_BACKGROUND_LOCATION )
150
+ }
151
+ }
152
+ return requiredPermissions.all {
153
+ ActivityCompat .checkSelfPermission(this , it) == PackageManager .PERMISSION_GRANTED
154
+ }
155
+ }
156
+
124
157
private fun checkBatteryOptimization () {
125
- val powerManager = getSystemService(POWER_SERVICE ) as PowerManager
158
+ val powerManager = getSystemService(Context . POWER_SERVICE ) as PowerManager
126
159
if (! powerManager.isIgnoringBatteryOptimizations(packageName)) {
127
160
requestDisableBatteryOptimization()
128
161
} else {
129
- // Battery optimization is disabled, now check for GPS
130
162
checkGpsAndStartService()
131
163
}
132
164
}
133
165
166
+ @SuppressLint(" BatteryLife" )
167
+ private fun requestDisableBatteryOptimization () {
168
+ val intent = Intent (Settings .ACTION_REQUEST_IGNORE_BATTERY_OPTIMIZATIONS ).apply {
169
+ data = Uri .parse(" package:$packageName " )
170
+ }
171
+ startActivity(intent)
172
+ }
173
+
134
174
private fun checkGpsAndStartService () {
135
175
val locationManager = getSystemService(Context .LOCATION_SERVICE ) as LocationManager
136
176
if (locationManager.isProviderEnabled(LocationManager .GPS_PROVIDER )) {
137
- // GPS is enabled, start location service
138
177
startLocationService()
139
178
} else {
140
- // GPS is not enabled, prompt user to enable it
141
179
openLocationSettings()
142
180
}
143
181
}
144
182
145
-
146
183
private fun startLocationService () {
147
-
148
- // Start location updates after starting the service
149
184
fetchLastKnownLocation()
150
185
startPeriodicCameraUpdate()
151
186
}
152
187
153
- @SuppressLint(" BatteryLife" )
154
- private fun requestDisableBatteryOptimization () {
155
- val intent = Intent ().apply {
156
- action = Settings .ACTION_REQUEST_IGNORE_BATTERY_OPTIMIZATIONS
157
- data = Uri .parse(" package:$packageName " )
158
- }
159
- startActivity(intent)
160
- }
161
-
162
188
private fun fetchLastKnownLocation () {
163
189
if (ActivityCompat .checkSelfPermission(
164
- this , Manifest .permission.ACCESS_FINE_LOCATION
190
+ this ,
191
+ Manifest .permission.ACCESS_FINE_LOCATION
165
192
) != PackageManager .PERMISSION_GRANTED && ActivityCompat .checkSelfPermission(
166
- this , Manifest .permission.ACCESS_COARSE_LOCATION
193
+ this ,
194
+ Manifest .permission.ACCESS_COARSE_LOCATION
167
195
) != PackageManager .PERMISSION_GRANTED
168
196
) {
169
197
return
@@ -179,10 +207,7 @@ class MainActivity : AppCompatActivity(), OnMapReadyCallback {
179
207
override fun onLocationResult (locationResult : LocationResult ) {
180
208
locationResult.lastLocation?.let { location ->
181
209
updateLocationOnMap(location)
182
- sharedViewModel.addTripLocation(
183
- LatLng (location.latitude, location.longitude)
184
- )
185
-
210
+ sharedViewModel.addTripLocation(LatLng (location.latitude, location.longitude))
186
211
}
187
212
}
188
213
}, null )
@@ -195,13 +220,11 @@ class MainActivity : AppCompatActivity(), OnMapReadyCallback {
195
220
}
196
221
}
197
222
198
-
199
223
private fun startPeriodicCameraUpdate () {
200
224
cameraUpdateJob = lifecycleScope.launch {
201
225
while (isActive) {
202
- val userRole = sharedViewModel.userRole.value
203
226
sharedViewModel.updateCameraPosition()
204
- delay(if (userRole == SharedViewModel .UserRole .DRIVER ) 1500 else 5000 )
227
+ delay(if (sharedViewModel. userRole.value == SharedViewModel .UserRole .DRIVER ) 1500 else 5000 )
205
228
}
206
229
}
207
230
}
@@ -215,46 +238,39 @@ class MainActivity : AppCompatActivity(), OnMapReadyCallback {
215
238
sharedViewModel.updateCurrentMarkerAndAddMarkers(gMap)
216
239
Log .d(" LocationUpdate" , " Updated current marker and added markers" )
217
240
}
218
-
219
241
}
220
242
221
243
private fun animateCameraToLocation (latLng : LatLng ) {
222
- val cameraUpdate = CameraUpdateFactory .newLatLngZoom(latLng, 16f )
223
- gMap.animateCamera(cameraUpdate)
244
+ gMap.animateCamera(CameraUpdateFactory .newLatLngZoom(latLng, 16f ))
224
245
Log .d(" LocationUpdate" , " Animated camera to new location: $latLng " )
225
246
}
226
247
227
-
228
248
override fun onMapReady (googleMap : GoogleMap ) {
229
- sharedViewModel.setGoogleMap(googleMap)
230
249
gMap = googleMap
231
- val uiSettings = gMap.uiSettings
232
-
233
- uiSettings.isCompassEnabled = false
234
- uiSettings.isMyLocationButtonEnabled = false
235
- uiSettings.isMapToolbarEnabled = false
236
- uiSettings.isIndoorLevelPickerEnabled = false
250
+ val uiSettings = gMap.uiSettings. apply {
251
+ isCompassEnabled = false
252
+ isMyLocationButtonEnabled = false
253
+ isMapToolbarEnabled = false
254
+ isIndoorLevelPickerEnabled = false
255
+ }
237
256
238
257
changeMapStyle()
258
+ sharedViewModel.setGoogleMap(gMap)
239
259
}
240
260
241
261
override fun onDestroy () {
242
262
super .onDestroy()
243
- cameraUpdateJob?.cancel() // Cancel coroutine job when activity is destroyed
263
+ cameraUpdateJob?.cancel()
264
+ permissionRetryJob?.cancel()
244
265
}
245
266
246
267
private fun changeMapStyle () {
247
268
val style = MapStyleOptions .loadRawResourceStyle(this , R .raw.map_style)
248
269
gMap.setMapStyle(style)
249
270
}
250
271
251
-
252
272
private fun openLocationSettings () {
253
- val intent = Intent ().apply {
254
- component = ComponentName (
255
- " com.android.settings" , " com.android.settings.Settings\$ LocationSettingsActivity"
256
- )
257
- }
273
+ val intent = Intent (Settings .ACTION_LOCATION_SOURCE_SETTINGS )
258
274
startActivity(intent)
259
275
}
260
- }
276
+ }
0 commit comments