-
-
Notifications
You must be signed in to change notification settings - Fork 45
Added Receiver to listen location service status #3427
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -1,33 +1,43 @@ | ||
| package org.commcare.location | ||
|
|
||
| import android.content.BroadcastReceiver | ||
| import android.content.Context | ||
| import android.content.Intent | ||
| import android.content.IntentFilter | ||
| import android.location.Location | ||
| import android.location.LocationManager | ||
| import android.os.Build | ||
| import com.google.android.gms.location.LocationCallback | ||
| import com.google.android.gms.location.LocationRequest | ||
| import com.google.android.gms.location.LocationResult | ||
| import com.google.android.gms.location.LocationServices | ||
| import com.google.android.gms.location.LocationSettingsRequest | ||
| import org.commcare.utils.GeoUtils.locationServicesEnabledGlobally | ||
|
|
||
| /** | ||
| * @author $|-|!˅@M | ||
| */ | ||
| class CommCareFusedLocationController( | ||
| private var mContext: Context?, private var mListener: CommCareLocationListener?) : CommCareLocationController { | ||
|
|
||
| private var mContext: Context?, | ||
| private var mListener: CommCareLocationListener?, | ||
| ) : CommCareLocationController { | ||
|
Comment on lines
+21
to
+23
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Add null-safety checks in BroadcastReceiver. The Consider adding null checks in the receiver's inner class LocationChangeReceiverBroadcast : BroadcastReceiver() {
override fun onReceive(
context: Context,
intent: Intent,
) {
+ if (mContext == null || mListener == null) return
if (LocationManager.PROVIDERS_CHANGED_ACTION == intent.getAction()) {
val lm = context.getSystemService(Context.LOCATION_SERVICE) as LocationManager
val locationServiceEnabled = locationServicesEnabledGlobally(lm)
if (locationServiceEnabled) {
start()
} else {
stop()
}
mListener?.onLocationServiceChange(locationServiceEnabled)
}
}
}
🤖 Prompt for AI Agents
Contributor
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. onReceive is not using mContext, also mListener is checked for null using kotlin ? operator There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. @Jignesh-dimagi You're correct on both points:
However, there's an indirect concern: That said, given that:
The risk is quite low. If you're confident that the receiver will be properly unregistered before 🧠 Learnings used
Contributor
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. isLocationPermissionGranted is already checking for mContext null and if so it assign application context There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 🧩 Analysis chain🏁 Script executed: Length of output: 0 🏁 Script executed: Length of output: 3135 @Jignesh-dimagi You're absolutely right! I can see that val context = mContext ?: CommCareApplication.instance()This ensures null-safety even if Thank you for walking through the null-safety measures - the code is properly safeguarded. 👍 🐰✨ 🧠 Learnings used |
||
| private val mFusedLocationClient = LocationServices.getFusedLocationProviderClient(mContext!!) | ||
| private val settingsClient = LocationServices.getSettingsClient(mContext!!) | ||
| private val mLocationRequest = LocationRequest.create().apply { | ||
| priority = LocationRequest.PRIORITY_HIGH_ACCURACY | ||
| interval = LOCATION_UPDATE_INTERVAL | ||
| } | ||
| private val mLocationServiceChangeReceiver = LocationChangeReceiverBroadcast() | ||
| private val mLocationRequest = | ||
| LocationRequest.create().apply { | ||
| priority = LocationRequest.PRIORITY_HIGH_ACCURACY | ||
| interval = LOCATION_UPDATE_INTERVAL | ||
| } | ||
| private var mCurrentLocation: Location? = null | ||
| private val mLocationCallback = object: LocationCallback() { | ||
| override fun onLocationResult(result: LocationResult) { | ||
| result ?: return | ||
| mCurrentLocation = result.lastLocation | ||
| mListener?.onLocationResult(mCurrentLocation!!) | ||
| private val mLocationCallback = | ||
| object : LocationCallback() { | ||
| override fun onLocationResult(result: LocationResult) { | ||
| result ?: return | ||
| mCurrentLocation = result.lastLocation | ||
| mListener?.onLocationResult(mCurrentLocation!!) | ||
| } | ||
| } | ||
| } | ||
|
|
||
| companion object { | ||
| const val LOCATION_UPDATE_INTERVAL = 5000L | ||
|
|
@@ -42,16 +52,19 @@ class CommCareFusedLocationController( | |
| } | ||
|
|
||
| override fun start() { | ||
| val locationSettingsRequest = LocationSettingsRequest.Builder() | ||
| .addLocationRequest(mLocationRequest) | ||
| .setAlwaysShow(true) | ||
| .build() | ||
| settingsClient.checkLocationSettings(locationSettingsRequest) | ||
| val locationSettingsRequest = | ||
| LocationSettingsRequest | ||
| .Builder() | ||
| .addLocationRequest(mLocationRequest) | ||
| .setAlwaysShow(true) | ||
| .build() | ||
| settingsClient | ||
| .checkLocationSettings(locationSettingsRequest) | ||
| .addOnSuccessListener { | ||
| mListener?.onLocationRequestStart() | ||
| requestUpdates() | ||
| } | ||
| .addOnFailureListener { exception -> | ||
| restartLocationServiceChangeReceiver() // if already started listening, it should be stopped before starting new | ||
coderabbitai[bot] marked this conversation as resolved.
Show resolved
Hide resolved
|
||
| }.addOnFailureListener { exception -> | ||
| mListener?.onLocationRequestFailure(CommCareLocationListener.Failure.ApiException(exception)) | ||
| } | ||
| } | ||
|
|
@@ -60,12 +73,51 @@ class CommCareFusedLocationController( | |
| mFusedLocationClient.removeLocationUpdates(mLocationCallback) | ||
| } | ||
|
|
||
| override fun getLocation(): Location? { | ||
| return mCurrentLocation | ||
| } | ||
| override fun getLocation(): Location? = mCurrentLocation | ||
|
|
||
| override fun destroy() { | ||
| stopLocationServiceChangeReceiver() | ||
| mContext = null | ||
| mListener = null | ||
| } | ||
|
|
||
| fun restartLocationServiceChangeReceiver() { | ||
| stopLocationServiceChangeReceiver() | ||
| startLocationServiceChangeReceiver() | ||
| } | ||
|
|
||
| fun startLocationServiceChangeReceiver() { | ||
| val intentFilter = IntentFilter(LocationManager.PROVIDERS_CHANGED_ACTION) | ||
| if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.TIRAMISU) { | ||
| mContext?.registerReceiver(mLocationServiceChangeReceiver, intentFilter, Context.RECEIVER_EXPORTED) | ||
| } else { | ||
| mContext?.registerReceiver(mLocationServiceChangeReceiver, intentFilter) | ||
| } | ||
| } | ||
|
|
||
| fun stopLocationServiceChangeReceiver() { | ||
| try { | ||
| mContext?.unregisterReceiver(mLocationServiceChangeReceiver) | ||
| } catch (e: IllegalArgumentException) { | ||
| // This can happen if stop is called multiple times | ||
conroy-ricketts marked this conversation as resolved.
Show resolved
Hide resolved
|
||
| } | ||
| } | ||
|
|
||
| inner class LocationChangeReceiverBroadcast : BroadcastReceiver() { | ||
| override fun onReceive( | ||
| context: Context, | ||
| intent: Intent, | ||
| ) { | ||
| if (LocationManager.PROVIDERS_CHANGED_ACTION == intent.getAction()) { | ||
| val lm = context.getSystemService(Context.LOCATION_SERVICE) as LocationManager | ||
| val locationServiceEnabled = locationServicesEnabledGlobally(lm) | ||
| if (locationServiceEnabled) { | ||
| start() | ||
| } else { | ||
| stop() | ||
| } | ||
| mListener?.onLocationServiceChange(locationServiceEnabled) | ||
| } | ||
| } | ||
| } | ||
| } | ||
Uh oh!
There was an error while loading. Please reload this page.