I'm developing an Android app in Java that allows a user to log and view any reviewed photography locations near them.
When the Map Fragment is opened, all locations are loaded in from a Firestore database. Once loaded, geofences are created for all locations. I have an onSuccessListener for this which logs whenever a geofence is added, so I know that this is working.
What I am trying to do is get my app to send the user a notification, and display a toast, when they have entered a geofence, regardless of if the app is open or closed. However, I am only receiving these notifications when either my app is open, or another app that is actively using the GPS is open, i.e., Google Maps.
I understand that there is a bug in the emulator which means for testing this in an emulator, you must have Google Maps open. As expected, this works. However, I am also experiencing the same issue on a real device running Android 10 (SDK 29).
My custom Broadcast Receiver is below:
public class GeofenceBroadcastReceiver extends BroadcastReceiver {
private static final String TAG = "GeofenceBroadcastReceiver";
@Override
public void onReceive(Context context, Intent intent) {
NotificationUtils notificationUtils = new NotificationUtils(context);
GeofencingEvent geofencingEvent = GeofencingEvent.fromIntent(intent);
if(geofencingEvent.hasError()) {
Log.e(TAG, "onReceive: Error receiving geofence event...");
return;
}
List<Geofence> geofenceList = geofencingEvent.getTriggeringGeofences();
for(Geofence geofence : geofenceList) {
Log.d(TAG, "onReceive: " + geofence.getRequestId());
}
Location location = geofencingEvent.getTriggeringLocation();
int transitionType = geofencingEvent.getGeofenceTransition();
if(transitionType == Geofence.GEOFENCE_TRANSITION_ENTER) {
Toast.makeText(context, "Geofence Entered...", Toast.LENGTH_SHORT).show();
notificationUtils.sendHighPriorityNotification("Location Entered!", "location has been entered", MainActivity.class);
} else if (transitionType == Geofence.GEOFENCE_TRANSITION_DWELL) {
Toast.makeText(context, "Geofence Dwelled...", Toast.LENGTH_SHORT).show();
notificationUtils.sendHighPriorityNotification("Location Dwelled!", "location has been dwelled", MainActivity.class);
}
}
}
My GeofenceUtils class is:
public class GeofenceUtils extends ContextWrapper {
private static final String TAG = "GeofenceUtils";
PendingIntent pendingIntent;
public GeofenceUtils(Context base) {
super(base);
}
public GeofencingRequest getGeofencingRequest(Geofence geofence) {
return new GeofencingRequest.Builder()
.addGeofence(geofence)
.setInitialTrigger(GeofencingRequest.INITIAL_TRIGGER_ENTER)
.build();
}
public Geofence getGeofence(String id, LatLng latLng, float radius, int transitionTypes){
return new Geofence.Builder()
.setCircularRegion(latLng.latitude, latLng.longitude, radius)
.setRequestId(id)
.setTransitionTypes(transitionTypes)
.setLoiteringDelay(0)
.setExpirationDuration(Geofence.NEVER_EXPIRE)
.build();
}
public PendingIntent getPendingIntent() {
if(this.pendingIntent != null) {
return this.pendingIntent;
}
Intent intent = new Intent(this, GeofenceBroadcastReceiver.class);
pendingIntent = PendingIntent.getBroadcast(this, 1010, intent, PendingIntent.FLAG_UPDATE_CURRENT);
return pendingIntent;
}
public String getErrorString(Exception e)
{
if (e instanceof ApiException) {
ApiException apiException = (ApiException) e;
switch (apiException.getStatusCode()){
case GeofenceStatusCodes
.GEOFENCE_NOT_AVAILABLE:
return "GEOFENCE_NOT_AVAILABLE";
case GeofenceStatusCodes
.GEOFENCE_TOO_MANY_GEOFENCES:
return "GEOFENCE_TOO_MANY_GEOFENCES";
case GeofenceStatusCodes
.GEOFENCE_TOO_MANY_PENDING_INTENTS:
return "GEOFENCE_TOO_MANY_PENDING_INTENTS";
}
}
return e.getLocalizedMessage();
}
}
From reading similar problems, I have made sure to have PendingIntent.getBroadcast instead of PendingIntent.getService, but I still haven't had any luck.
Any help would be much appreciated!