Geofence only triggered when opening another GPS based app - android

So i've built a location-based reminder app using geofences.
Everything is working but one thing - the geofences are not triggering when the app is closed.
This kinda loses the entire idea of the app - sending notifications.
So i digged a bit and found out that if I open google maps, and press the GPS kinda thing to take the map to my location, the geofences trigger perfectly. But when I close it (or even put it in background), they won't trigger. I checked - and they get added like desired.
My question is - is this a known issue with the android studio emulator?
I'm using pixel 3 XL on API 33, if that is relevant.
Also, here's the broadcast receiver for my Geofences, if that is relevant too.
public class GeofenceBroadcastReceiver extends BroadcastReceiver
{
private static final String activityName = "GeofenceBroadcastReceiver";
#Override
public void onReceive(Context context, Intent intent)
{
Log.d(activityName, "Broadcast received: geofence triggered");
try
{
boolean isAppInForeground = new ForegroundCheckTask().execute(context).get();
if (isAppInForeground)
{
Log.d(activityName, "But app is not closed. Skip and do not send notification.");
return;
}
}
catch (Exception e)
{
e.printStackTrace();
}
NotificationHelper notificationHelper = new NotificationHelper(context);
GeofencingEvent geofencingEvent = GeofencingEvent.fromIntent(intent);
if (geofencingEvent.hasError())
{
Log.d(activityName, "onReceive: error");
return;
}
SharedPreferences sharedPref = context.getSharedPreferences("remindify_sp", MODE_PRIVATE);
String connectedUsername = sharedPref.getString("connected username", null);
List<Geofence> triggeredGeofences = geofencingEvent.getTriggeringGeofences();
ArrayList<LocationClass> locationsList = UtilityClass.getLocationListForUser(activityName, connectedUsername);
LocationClass notifiedLocation = findNotifiedLocationByGeofenceId(triggeredGeofences, locationsList);
int transitionType = geofencingEvent.getGeofenceTransition();
switch (transitionType)
{
case Geofence.GEOFENCE_TRANSITION_ENTER:
Toast.makeText(context, "Entered geofence", Toast.LENGTH_SHORT).show();
notificationHelper.sendHighPriorityNotification(
"Entered location: " + notifiedLocation.getName(),
"Click here to view it's task list!",
LoginActivity.class, notifiedLocation);
break;
case Geofence.GEOFENCE_TRANSITION_DWELL:
// Toast.makeText(context, "Dwelled geofence", Toast.LENGTH_SHORT).show();
break;
case Geofence.GEOFENCE_TRANSITION_EXIT:
// Toast.makeText(context, "Exited geofence", Toast.LENGTH_SHORT).show();
break;
}
}
private LocationClass findNotifiedLocationByGeofenceId(List<Geofence> triggeredGeofences,
ArrayList<LocationClass> locationsList)
{
Geofence geofence = triggeredGeofences.get(0);
String geofenceId = geofence.getRequestId();
for (LocationClass location : locationsList)
{
if (geofenceId.equals(String.valueOf(location.getId())))
{
// found location with corresponding geofence id
return location;
}
}
return null;
}
}

Related

Android Geofence Transition PendingIntent seems not to run (react-native bridge)

I am following the android guide android guide to build a simple native bridge for react-native for geofencing.
But I do not get any response when entering or leaving a geofence. It seems like the PendingIntent / IntentService for Transitions is not running properly.
MyModule looks basically like this. It also creates mGeofenceList like in the docs populated with data from react-native.
MyModule:
public class MyModule extends ReactContextBaseJavaModule {
//Build geofences
private GeofencingRequest getGeofencingRequest() {
GeofencingRequest.Builder builder = new GeofencingRequest.Builder();
builder.setInitialTrigger(GeofencingRequest.INITIAL_TRIGGER_ENTER);
builder.addGeofences(mGeofenceList);
return builder.build();
}
//Build pending intent
private PendingIntent getGeofencePendingIntent() {
// Reuse the PendingIntent if we already have it.
if (mGeofencePendingIntent != null) {
return mGeofencePendingIntent;
}
Intent intent = new Intent(reactContext, GeofenceTransitionsIntentService.class);
// We use FLAG_UPDATE_CURRENT so that we get the same pending intent back when
// calling addGeofences() and removeGeofences().
mGeofencePendingIntent = PendingIntent.getService(reactContext, 0, intent, PendingIntent.
FLAG_UPDATE_CURRENT);
return mGeofencePendingIntent;
}
#ReactMethod
public void startMonitoring() {
mGeofencingClient.addGeofences(getGeofencingRequest(), getGeofencePendingIntent())
.addOnSuccessListener(new OnSuccessListener<Void>() {
#Override
public void onSuccess(Void aVoid) {
Log.i(TAG, "Start Monitoring");
postNotification("Start Monitoring", "Pressed Start Monitoring");
}
})
.addOnFailureListener(new OnFailureListener() {
#Override
public void onFailure(#NonNull Exception e) {
Log.e(TAG, "Start Monitoring: " + e.getMessage());
}
});
}
}
When running startMonitoring(), the notification (Start Monitoring) and the log gets produced, so I assume that the error is not in this part.
The IntentService looks also pretty basic /similar to the docs.
IntentService:
public class GeofenceTransitionsIntentService extends IntentService {
private static final String TAG = "GeofenceService";
private Handler handler;
SharedPreferences sp;
public GeofenceTransitionsIntentService(){
super(TAG);
}
#Override
public void onCreate() {
super.onCreate();
sp = PreferenceManager.getDefaultSharedPreferences(this);
handler = new Handler();
Log.i(TAG, "Intent created");
}
protected void onHandleIntent(Intent intent) {
Log.i(TAG, "onHandleIntent");
GeofencingEvent geofencingEvent = GeofencingEvent.fromIntent(intent);
if (geofencingEvent.hasError()) {
String errorMessage = "Error Code: " + String.valueOf(geofencingEvent.getErrorCode());
Log.e(TAG, errorMessage);
return;
}
// Get the transition type.
int geofenceTransition = geofencingEvent.getGeofenceTransition();
// Test that the reported transition was of interest.
if (geofenceTransition == Geofence.GEOFENCE_TRANSITION_ENTER ||
geofenceTransition == Geofence.GEOFENCE_TRANSITION_EXIT) {
// Get the geofences that were triggered. A single event can trigger
// multiple geofences.
List<Geofence> triggeringGeofences = geofencingEvent.getTriggeringGeofences();
// Get the transition details as a String.
String geofenceTransitionDetails = getGeofenceTransitionDetails(
geofenceTransition,
triggeringGeofences
);
// Send notification and log the transition details.
//sendNotification(geofenceTransitionDetails);
handler.post(new Runnable() {
#Override
public void run() {
Toast.makeText(getApplicationContext(), "Enter/Exit", Toast.LENGTH_SHORT).show();
}
});
Log.i(TAG, geofenceTransitionDetails);
} else {
// Log the error.
Log.e(TAG, "Invalid transition");
handler.post(new Runnable() {
#Override
public void run() {
Toast.makeText(getApplicationContext(), "ERROR", Toast.LENGTH_SHORT).show();
}
});
}
}
/*
Helpfunctions for logging
*/
private String getGeofenceTransitionDetails(
int geofenceTransition,
List<Geofence> triggeringGeofences) {
String geofenceTransitionString = getTransitionString(geofenceTransition);
// Get the Ids of each geofence that was triggered.
ArrayList<String> triggeringGeofencesIdsList = new ArrayList<>();
for (Geofence geofence : triggeringGeofences) {
triggeringGeofencesIdsList.add(geofence.getRequestId());
}
String triggeringGeofencesIdsString = TextUtils.join(", ", triggeringGeofencesIdsList);
return geofenceTransitionString + ": " + triggeringGeofencesIdsString;
}
private String getTransitionString(int transitionType) {
switch (transitionType) {
case Geofence.GEOFENCE_TRANSITION_ENTER:
return "entered Geofence";
case Geofence.GEOFENCE_TRANSITION_EXIT:
return "exit Geofence";
default:
return "unknown Transition";
}
}
}
But none of the outputs of this class gets produced!
In the manifest of my native module I added the permission:
<uses-permission android:name="android.permission.ACCESS_FINE_LOCATION"/>
And in the manifest of the TestApplication that uses this module I added this permission as well and in the application tag I added
<service android:name="com.mymodule.GeofenceTransitionsIntentService" android:exported="false"/>
I could not add this last line in the module's manifest, cause it was missing the application tag and has no activity. I am not sure if this is the right place.
I am testing in the emulator and change the location to a list of GPS data playback.
Questions
How can I verify that the ServiceIntent is running? Can I get Status of it?
Where does the logs appear? In com.TestApplication or somewhere else?
and of course:
3. Where is my error?
Ok, answering my own question, or specific only question 3:
The code above has no error, or at least and works as expected on a hardware device.
So, how to properly debug Geofencing on an emulator?

Android 7.0 Kills App Even When Foreground Service is Running

I have tried every suggestion I could find on the Internet to use Foreground Service to keep my app running beyond sleep and deep sleep modes but nothing has been successful so far.
I am working on a taxi booking application. I designed it to start emitting driver's location to server whenever the driver turns himself Online and stop emitting when Offline.
The following is the Foreground Service code that is started whenever driver turns himself Online and stopped when he presses online button which changes Common.CustomSocketOn to 0.
It work fine during screen wake and also works when the screen is off before the app gets killed.
However, even with WAKE_LOCK acquired, it still can't stay more than few minutes in sleep mode before getting killed by Android 7.
This failure to keep running in sleep mode breaks down many other features of the app because when the app gets killed silently, it does not get the chance to turn the driver Offline nor sign him out. As a result, the driver gets booking requests when his app is not running and therefore, cannot attend to it, and that keeps the booking from going to the next available driver. In fact, this causes so many other anomalies.
Please, can somebody tell me any other thing I need to do to keep Android from killing the Foreground Service.
public class OnlineForeGroundService extends Service {
private static final String TAG_FOREGROUND_SERVICE = "FOREGROUND_SERVICE";
public static final String ACTION_START_FOREGROUND_SERVICE = "ACTION_START_FOREGROUND_SERVICE";
public static final String ACTION_STOP_FOREGROUND_SERVICE = "ACTION_STOP_FOREGROUND_SERVICE";
private static LocationListener locationListener;
private static LocationManager locationManager;
private PowerManager.WakeLock wakeLock;
public OnlineForeGroundService() {
}
#Override
public IBinder onBind(Intent intent) {
// TODO: Return the communication channel to the service.
//throw new UnsupportedOperationException("Not yet implemented");
return null;
}
#Override
public void onCreate() {
super.onCreate();
Log.d(TAG_FOREGROUND_SERVICE, "My foreground service.");
final PowerManager powerManager = (PowerManager) getSystemService(Context.POWER_SERVICE);
try {
wakeLock = powerManager.newWakeLock(PowerManager.PARTIAL_WAKE_LOCK, "KEEP_AWAKE");
}
catch (Exception e){
e.printStackTrace();
}
}
#Override
public int onStartCommand(Intent intent, int flags, int startId) {
if(intent != null)
{
String action = intent.getAction();
if(action != null) {
switch (action) {
case ACTION_START_FOREGROUND_SERVICE:
startForegroundService();
Toast.makeText(getApplicationContext(), getText(R.string.going_online), Toast.LENGTH_SHORT).show();
wakeLock.acquire();
break;
case ACTION_STOP_FOREGROUND_SERVICE:
stopForegroundService();
//Toast.makeText(getApplicationContext(), getText(R.string.going_offline), Toast.LENGTH_SHORT).show();
break;
}
}
}
return super.onStartCommand(intent, flags, startId);
//return START_STICKY;
}
/* Used to build and start foreground service. */
#SuppressLint("MissingPermission")
private void startForegroundService()
{
if(OnlineForeGroundService.locationManager == null) {
OnlineForeGroundService.locationManager = (LocationManager) getApplicationContext().getSystemService(Context.LOCATION_SERVICE);
}
if(OnlineForeGroundService.locationListener == null) {
OnlineForeGroundService.locationListener = new LocationListener() {
#Override
public void onLocationChanged(Location location) {
if (Common.CustomSocketOn == 1) {
SharedPreferences userPref = PreferenceManager.getDefaultSharedPreferences(getApplicationContext());
if (Common.OldLatitude != 0 && Common.OldLongitude != 0) {
float distance[] = new float[1];
Location.distanceBetween(Common.OldLatitude, Common.OldLongitude, location.getLatitude(), location.getLongitude(), distance);
//Distance - 100
if (distance.length > 0 && distance[0] > 30) {
try {
JSONArray locAry = new JSONArray();
locAry.put(location.getLatitude());
locAry.put(location.getLongitude());
JSONObject emitobj = new JSONObject();
emitobj.put("coords", locAry);
emitobj.put("driver_name", userPref.getString("user_name", ""));
emitobj.put("driver_id", userPref.getString("id", ""));
emitobj.put("driver_status", "1"); //change by sir
emitobj.put("car_type", userPref.getString("car_type", ""));
emitobj.put("isdevice", "1");
emitobj.put("booking_status", userPref.getString("booking_status", ""));
emitobj.put("isLocationChange", 1);
if (location.getLatitude() != 0.0 && location.getLongitude() != 0.0 && Common.socket != null && Common.socket.connected()) {
Common.socket.emit("Create Driver Data", emitobj);
} else if (location.getLatitude() != 0.0 && location.getLongitude() != 0.0 && Common.socket == null) {
Common.socket = null;
SocketSingleObject.instance = null;
Common.socket = SocketSingleObject.get(getApplicationContext()).getSocket();
Common.socket.connect();
Common.socket.emit("Create Driver Data", emitobj);
} else if (location.getLatitude() != 0.0 && location.getLongitude() != 0.0 && Common.socket != null && !Common.socket.connected()) {
Common.socket.connect();
Common.socket.emit("Create Driver Data", emitobj);
}
} catch (JSONException e) {
e.printStackTrace();
} catch (Exception e) {
e.printStackTrace();
}
Common.OldLatitude = location.getLatitude();
Common.OldLongitude = location.getLongitude();
}
}
if (Common.OldLatitude == 0 && Common.OldLongitude == 0) {
Common.OldLatitude = location.getLatitude();
Common.OldLongitude = location.getLongitude();
}
}
else{
stopForegroundService();
}
}
#Override
public void onProviderDisabled(String provider) {
Log.d("Latitude", "disable");
}
#Override
public void onProviderEnabled(String provider) {
Log.d("Latitude", "enable");
}
#Override
public void onStatusChanged(String provider, int status, Bundle extras) {
}
};
}
if(Common.isPermission){
if(Common.CustomSocketOn == 1){
try {
OnlineForeGroundService.locationManager.requestLocationUpdates(LocationManager.GPS_PROVIDER, Common.DriverDistanceTime, Common.DriverDistance, OnlineForeGroundService.locationListener);
OnlineForeGroundService.locationManager.requestLocationUpdates(LocationManager.NETWORK_PROVIDER, Common.DriverDistanceTime, Common.DriverDistance, OnlineForeGroundService.locationListener);
}
catch (Exception e){
e.printStackTrace();
}
}
}
Log.d(TAG_FOREGROUND_SERVICE, "Starting foreground service.");
String onlineSticker = getText(R.string.app_name)+" - Online";
Intent notificationIntent = new Intent(this, HomeActivity.class);
notificationIntent.addFlags(Intent.FLAG_ACTIVITY_CLEAR_TASK|Intent.FLAG_ACTIVITY_NEW_TASK);
PendingIntent pendingIntent =
PendingIntent.getActivity(this, 0, notificationIntent, 0);
Notification notification;
/*if(android.os.Build.VERSION.SDK_INT >= 26) {
notification = new Notification.Builder(HomeActivity.class, NotificationManager.IMPORTANCE_HIGH)
.setContentTitle(getText(R.string.app_name))
.setContentText(getText(R.string.you_are_online))
.setSmallIcon(R.mipmap.ic_launcher)
.setContentIntent(pendingIntent)
.setTicker(onlineSticker)
.build();
//startForeground(ONGOING_NOTIFICATION_ID, notification);
// Start foreground service.
}
else{*/
notification = new Notification.Builder(this)
.setContentTitle(getText(R.string.app_name))
.setContentText(getText(R.string.you_are_online))
.setPriority(Notification.PRIORITY_HIGH)
.setSmallIcon(R.mipmap.ic_launcher)
.setContentIntent(pendingIntent)
.setTicker(onlineSticker)
.build();
//}
startForeground(397, notification);
}
private void stopForegroundService()
{
Toast.makeText(getApplicationContext(), getText(R.string.going_offline), Toast.LENGTH_SHORT).show();
if(Common.isPermission){
if(Common.CustomSocketOn == 0){
try {
OnlineForeGroundService.locationManager.removeUpdates(OnlineForeGroundService.locationListener);
//OnlineForeGroundService.locationListener = null;
}
catch (Exception e){
e.printStackTrace();
}
}
}
Log.d(TAG_FOREGROUND_SERVICE, "Stop foreground service.");
if (null != wakeLock && wakeLock.isHeld()) {
wakeLock.release();
}
// Stop foreground service and remove the notification.
stopForeground(true);
// Stop the foreground service.
stopSelf();
}
}
Here is the androidManifest entry for the service and WAKE_LOCK permission:
<uses-permission android:name="android.permission.WAKE_LOCK" />
<service
android:name=".driver.service.OnlineForeGroundService"
android:process=".process"
android:enabled="true"
android:exported="true" ></service>
Please see this excellent site which provides a vast amount of information covering various different handset vendors and Android API versions.
This has helped me massively understand the very common Android developer problem of dealing with reports and feedback of foreground services being killed despite following the documented steps to ensure your service is setup correctly to avoid being shutdown.
https://dontkillmyapp.com/stock_android
The site includes mention of the Dianne Hackborn comments which are now no longer accessible on the Google plus (due to it's end of life).
Ultimately it seems that the solution to prevent your Foreground Service from being shutdown may vary across Android OS version and device manufacturer, but this site provides a good summary of the steps users can be directed to follow and also developers can implement (where possible) to try and mitigate this issue.
Check how you are starting your OnlineForeGroundService.
On Android Oreo and above it needs to be started with startForegroundService(Intent intent), not startService(Intent intent)
For example something like:
final Intent serviceIntent = new Intent(context, OnlineForeGroundService.class);
serviceIntent.setAction(OnlineForeGroundService.ACTION_START_FOREGROUND_SERVICE);
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
startForegroundService(serviceIntent);
} else {
startService(serviceIntent);
}

Awareness Fence API:- LocationFence not working, Fence registered successfully but Broadcast Receiver failed to receive any thing

I am trying to register Fence LocationFence API for tracking the user enters, exit or IN in a particular location, The Fence was register successfully but the registered Broadcast receiver failed to catch any LocationFence.in , LocationFence.entering or LocationFence.exiting
Is I'm missing something?(my location is in INDIA +5:30 GMT).
Please find below my code:-
NOTE: I tried fences with HeadphoneFence.pluggingIn and HeadphoneFence.unplugging and able to get both events in same broadcast receiver.
private final String FENCE_LOCATION_RECEIVER_ACTION =
BuildConfig.APPLICATION_ID + "FENCE_LOCATION_RECEIVER_ACTION";
Intent intent1 = new Intent(FENCE_LOCATION_RECEIVER_ACTION);
mLocationPendingIntent=PendingIntent.getBroadcast(MainActivity.this,0,intent1, 0);
FenceLocationReceiver fenceLOcationReceiver = new FenceLOcationReceiver();
registerReceiver(fenceLOcationReceiver, new IntentFilter(FENCE_LOCATION_RECEIVER_ACTION));
checkLocationPermission();
AwarenessFence myFence = AwarenessFence.or(LocationFence.in(28.557659, 77.2459485, 10, 60000L), LocationFence.entering(28.557659, 77.2459485, 10), LocationFence.exiting(28.557659, 77.2459485, 10));
Awareness.FenceApi.updateFences(
mGoogleApiClient,
new FenceUpdateRequest.Builder()
.addFence(LOCATION_FENCE_KEY, myFence, mLocationPendingIntent)
.build())
.setResultCallback(new ResultCallback<Status>() {
#Override
public void onResult(#NonNull Status status) {
if (status.isSuccess()) {
Log.i(TAG, "here location Fence was successfully registered.");
} else {
Log.e(TAG, "here location Fence could not be registered: " + status);
}
}
});
Here is my Broadcast Receiver code:-
public class FenceLocationReceiver extends BroadcastReceiver {
#Override
public void onReceive(Context context, Intent intent) {
if (!TextUtils.equals(FENCE_LOCATION_RECEIVER_ACTION, intent.getAction())) {
txt.setText("Received an unsupported action in FenceReceiver: action="
+ intent.getAction());
return;
}
// The state information for the given fence is em
FenceState fenceState = FenceState.extract(intent);
if (TextUtils.equals(fenceState.getFenceKey(), FENCE_LOCATION_RECEIVER_ACTION)) {
String fenceStateStr;
switch (fenceState.getCurrentState()) {
case FenceState.TRUE:
fenceStateStr = "true";
txt.setText(fenceStateStr);
break;
case FenceState.FALSE:
fenceStateStr = "false";
txt.setText(fenceStateStr);
break;
case FenceState.UNKNOWN:
fenceStateStr = "unknown";
txt.setText(fenceStateStr);
break;
default:
fenceStateStr = "unknown value";
txt.setText(fenceStateStr);
}
txt.setText("Fence state:" + fenceStateStr);
}
}
}
Here permissions defined in Manifest:-
<uses-permission android:name="android.permission.ACCESS_FINE_LOCATION" />
<uses-permission android:name="com.google.android.gms.permission.ACTIVITY_RECOGNITION" />

Consistent Android Geofence Monitoring

I've implemented some geofences into an app and have been testing them using mock locations on my test device (Samsung S4 running Android 5.0.1). While using mock locations, the transition detection has been working 100% of the time. I've now moved onto other Android devices and put the app on some phones which frequently (physically) enter and leave the geofence location, and I've noticed that the detection OFTEN doesn't work. This is really inconvenient so I was hoping there would be some way to make the detection more consistent.
My code which calls the geofence to be created:
private void startGeofenceMonitoring() {
Log.d(TAG, "startGeofenceMonitoring called");
try {
Geofence geofence = new Geofence.Builder()
.setRequestId(GEOFENCE_ID)
.setCircularRegion(51.364516, -0.189643, 150)
.setExpirationDuration(Geofence.NEVER_EXPIRE)
.setNotificationResponsiveness(1000)
.setTransitionTypes(Geofence.GEOFENCE_TRANSITION_ENTER | Geofence.GEOFENCE_TRANSITION_EXIT)
.build();
GeofencingRequest geofencingRequest = new GeofencingRequest.Builder()
.setInitialTrigger(GeofencingRequest.INITIAL_TRIGGER_ENTER | GeofencingRequest.INITIAL_TRIGGER_EXIT)
.addGeofence(geofence)
.build();
Intent intent = new Intent(this, GeofenceService.class);
PendingIntent pendingIntent = PendingIntent.getService(this, 0, intent, PendingIntent.FLAG_UPDATE_CURRENT);
if (!googleApiClient.isConnected()) {
Log.d(TAG, "GoogleApiClient is not connected");
} else {
if (ActivityCompat.checkSelfPermission(this, Manifest.permission.ACCESS_FINE_LOCATION) != PackageManager.PERMISSION_GRANTED) {
ActivityCompat.requestPermissions(MapsActivity.this, new String[]{Manifest.permission.ACCESS_FINE_LOCATION}, LOCATION);
return;
}
LocationServices.GeofencingApi.addGeofences(googleApiClient, geofencingRequest, pendingIntent)
.setResultCallback(new ResultCallback<Status>() {
#Override
public void onResult(#NonNull Status status) {
if (status.isSuccess()) {
Log.d(TAG, "Successfully added Geofence");
} else {
Log.d(TAG, "Failed to add geofence - " + status.getStatus());
}
}
});
}
} catch (SecurityException e) {
Log.d(TAG, "SecurityException - " + e.getMessage());
}
}
GeofenceService.java:
public class GeofenceService extends IntentService {
public static final String TAG = "GeofenceService";
DatabaseReference mRootRef = FirebaseDatabase.getInstance().getReference();
public GeofenceService() {
super(TAG);
}
#Override
protected void onHandleIntent(Intent intent) {
GeofencingEvent event = GeofencingEvent.fromIntent(intent);
if (event.hasError()) {
//TODO:
} else {
double longitude = 0;
double latitude = 0;
int transition = event.getGeofenceTransition();
List<Geofence> geofences = event.getTriggeringGeofences();
Geofence geofence = geofences.get(0);
String requestID = geofence.getRequestId();
longitude = event.getTriggeringLocation().getLongitude();
latitude = event.getTriggeringLocation().getLatitude();
final FirebaseUser user = FirebaseAuth.getInstance().getCurrentUser();
if (longitude != 0 && latitude != 0) {
if (transition == Geofence.GEOFENCE_TRANSITION_ENTER) {
Log.d(TAG, "Entering geofence - " + requestID);
//My on enter code
} else if (transition == Geofence.GEOFENCE_TRANSITION_EXIT) {
Log.d(TAG, "Exited geofence - " + requestID);
//My on exit code
}
} else {
mRootRef.child("users/" + user.getUid() + "/error").setValue("lat/long = 0");
}
}
}
I've seen online that say using a broadcast receiver works better than what I've done but embarrassingly, I'm not quite good enough to really understand how to convert what I have done to what others have suggested.
Thanks.
check out this answer there is an implementation of broadcast receiver with geofence
Android Geofencing Notifications when app is closed

programmatically register Receivers and services in android

I'm trying to register two receivers, one that will receive messages from my app server through GCM and onother that will load messages from my server.
all this are in an activity called ChatActivity
private BroadcastReceiver mMessageReceiver = new BroadcastReceiver() {
#Override
public void onReceive(Context context, Intent intent) {
d("Broadcast received FROM MMESSAGERECEIVER");
Toast.makeText(context, "mMessageReceiver started", Toast.LENGTH_LONG).show();
if(cust != null && adapter != null){
SharedPreferences sharedPref = ChatActivity.this.getSharedPreferences(PREFERENCES_FILE, Context.MODE_PRIVATE);
long userID = sharedPref.getLong(AllSystems.PREFERENCES_KEY_LOGGED_IN_USER_ID, -1);
// Extract data included in the Intent
String message = intent.getStringExtra("message");
String dateCreated = intent.getStringExtra("dateCreated");
Date d = new Date(Long.parseLong(dateCreated));
long senderId = Long.parseLong(intent.getStringExtra("senderId"));
Toast.makeText(context, "mMessageReceiver in the first if", Toast.LENGTH_LONG).show();
if(senderId == userID || senderId == cust.getId()){
Toast.makeText(context, "mMessageReceiver in the second if", Toast.LENGTH_LONG).show();
adapter.add(new ChatMessageData(senderId == cust.getId(), message, new DateTime(d)));
Bundle results = getResultExtras(true);
results.putBoolean(INTERCEPTED, true);
playSound();
}
}
}
};
private BroadcastReceiver mLoadedReceiver = new BroadcastReceiver() {
#Override
public void onReceive(Context context, Intent intent) {
d("Broadcast received");
d("Conversation loaded broadcast received");
if(task != null && cust != null){
d("Contact and task not null");
long contactId = intent.getLongExtra("contactId", -1);
if(contactId == cust.getId()){
d("Executing conversation loading task");
task.execute();
}
}
}
};
private void playSound(){
try {
Uri notification = Uri.parse("android.resource://com.me.myapp/" + R.raw.notif);
Ringtone r = RingtoneManager.getRingtone(getApplicationContext(), notification);
r.play();
} catch (Exception e) {
e.printStackTrace();
}
}
#Override
protected void onResume() {
super.onResume();
registerReceiver(mMessageReceiver, new IntentFilter("com.google.android.c2dm.intent.RECEIVE"));
LocalBroadcastManager.getInstance(this).registerReceiver(mLoadedReceiver, loadedFilter);
}
//Must unregister onPause()
#Override
protected void onPause() {
super.onPause();
unregisterReceiver(mMessageReceiver);
LocalBroadcastManager.getInstance(this).unregisterReceiver(mLoadedReceiver);
}
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_chats);
LocalBroadcastManager.getInstance(this).registerReceiver(mLoadedReceiver, loadedFilter);
registerReceiver(mMessageReceiver,new IntentFilter("com.google.android.c2dm.intent.RECEIVE"));
}
PROBLEM
the broadcast instance mMessageReceiver (the 1st line) isn't been registered since dialog(Toast) that are supposed to be activated in its onReceive method aren't been activated. this instance should receive GCM messages that why i have registed it like this ` registerReceiver(mMessageReceiver, new IntentFilter("com.google.android.c2dm.intent.RECEIVE"));
Question
Where am going wrong ? i have tried to follow the Try Cloud Messaging for Android and even the example at gitlab but all in vain. my previous question relation to this issue is here.
You need to declare a few permissions, services and GCMReceiver inside the manifest in order for GCM to work as intended.
Different page in the official documentation addresses GCM set up on an Android client in more depth. (refer here and sample here)
Hope this helped.

Categories

Resources