Geofence understanding Geofence lifetime - android

I've built Geofence as:
GeofenceModel modelExit = new GeofenceModel.Builder("id_oi_456")
.setTransition(Geofence.GEOFENCE_TRANSITION_DWELL)
.setExpiration(Geofence.NEVER_EXPIRE)
.setLatitude(40.414341)
.setLongitude(49.928548)
.setRadius(CLIENT_GEOFENCE_RADIUS)
.build();
SmartLocation.with(this).geofencing()
.add(modelExit)
.start(this);
When set to NEVER_EXPIRE, it gets triggered. When setExpiration() is not set geofence will not be triggered though. The question is that What isdefault expiration time for single geofence?

In regards to Android's Geofence class: it is not possible to create a Geofence using Geofence.Builder without setting an expiration. If you try to, it will throw java.lang.IllegalArgumentException: Expiration not set.
As for your GeofenceModel class, I'm not sure.

Assuming you're using com.google.android.gms.location.Geofence
underneath your GeofenceModel class.
You have an instance variable named modelExit indicates that you're waiting for the exit transition. while in your geofence configuration you're only listening to GEOFENCE_TRANSITION_DWELL. You should set the transition to GEOFENCE_TRANSITION_EXIT.

Related

How to access BatteryManager's BATTERY_PROPERTY_CURRENT_NOW?

I'm trying to get the current from the API. There's a function at the bottom of the documentation (https://developer.android.com/reference/android/os/BatteryManager.html) called getIntProperty, so I presume that'd be the function I'd need. However, up to now I've been simply using the getIntExtra function on an ActionBatteryChanged intent, and that same method doesn't work for this. What do I need to do different?
That function is used to get the current value, not get updates like you do with a Broadcast and an Intent. You'd call batteryManager.getIntProperty(BATTERY_PROPERTY_CURRENT_NOW) to get the value. Any of the BATTERY_PROPERTY_X constants could work, but not every phone supports all of them.
A more comprehensive code samples:
Declare this at the class level
private BatteryManager mBatteryManager = null;
onCreate()
{
mBatteryManager = (BatteryManager) getSystemService(Context.BATTERY_SERVICE);
}
Create a timer and inside the timer routine, add this
int mBatteryCurrent = mBatteryManager.getIntProperty(BatteryManager.BATTERY_PROPERTY_CURRENT_NOW);
The current is in uA unit. a positive integer means drawing current out of
battery and a negative integer means charging current into battery.

Get event when replacing node with the same value?

is it possible to get an event in a Listener when I replace value of a node with the same value? seams like if firebase notice that the value is the same no event accures..:s
The Firebase Database synchronizes state between clients. If a write operation doesn't change the state, there is nothing to synchronize to the other listening clients.
In simple code:
ref.setValue(1);
ref.setValue(1); // won't trigger listeners
ref.setValue(2); // will trigger active listeners
ref.setValue(2); // won't trigger listeners
It sounds like you want to instead pass messages between clients. This is totally feasible, but means that you should model your data differently. Instead of storing the value in your database, store the fact that the client wrote a value.
In simple code:
ref.push(1);
ref.push(1);
ref.push(2);
ref.push(2);
In this last sample each write will trigger listeners on ref, since each write is new.
This is a common pattern: instead of storing the final state, you're storing the state changes. It essentially similar the mechanism behind oplogs in databases and many other systems.
Because nothing happens there is no event that is triggered. What can you do in stead, is to check the value before you are setting it.
if(myValue.equals(firebaseValue)) {
//do something
} else {
//do something else
}
Hope it helps.

Stop initial triggering if device is already inside Geofence android

I am using Geofencing on android, and when creating a geo-fence the device is getting notified if the user was already inside the geo-fence, which is not the behavior I'm looking for, I only want to notify on transition ENTER and EXIT.
This is how I'm creating the geofence request:
private GeofencingRequest createGeoFenceRequest(List<Geofence> geofenceList) {
return new GeofencingRequest.Builder()
//The INITIAL_TRIGGER_ENTER is used to notify the user initially if he/she/other
//is already inside the geo-fence zone
//.setInitialTrigger(GeofencingRequest.INITIAL_TRIGGER_ENTER)
.addGeofences(geofenceList)
.build();
}
And inside my GeofenceTransitionService.java:
#Override
protected void onHandleIntent(#Nullable Intent intent) {
if (intent != null) {
geofencingEvent = GeofencingEvent.fromIntent(intent);
// Retrieve the transition type.
geoFenceTransition = geofencingEvent.getGeofenceTransition();
}
}
The transition type is returned as Geofence.GEOFENCE_TRANSITION_ENTER even though I am not entering, I am already inside the geofence.
Anyone know how I can stop this initial trigger ?
Why you got the initial trigger
tl;dr
It's the default behavior
I got here with a similar problem of yours:
The transition type is returned as Geofence.GEOFENCE_TRANSITION_ENTER even though I am not entering, I am already inside the geofence.
After some research, I found this behavior stated on the GeofencingRequest.Builder documentation:
Public Methods
public GeofencingRequest.Builder setInitialTrigger (int initialTrigger)
Sets the geofence notification behavior at the moment when the geofences are added. The default behavior is INITIAL_TRIGGER_ENTER and INITIAL_TRIGGER_DWELL.
To understand what those constants actually mean, we need to check the documentation for the enclosing class, GeofencingRequest:
Constant Summary
int INITIAL_TRIGGER_DWELL
A flag indicating that geofencing service should trigger GEOFENCE_TRANSITION_DWELL notification at the moment when the geofence is added and if the device is already inside that geofence for some time.
int INITIAL_TRIGGER_ENTER
A flag indicating that geofencing service should trigger GEOFENCE_TRANSITION_ENTER notification at the moment when the geofence is added and if the device is already inside that geofence.
int INITIAL_TRIGGER_EXIT
A flag indicating that geofencing service should trigger GEOFENCE_TRANSITION_EXIT notification at the moment when the geofence is added and if the device is already outside that geofence.
This explains why you were notified of a GEOFENCE_TRANSITION_ENTER even though you didn't use setInitialTrigger() - it's the default behavior.
While investigating this, I found out something interesting. If you subscribe to entrances and departures of geofences and then set the initial trigger to INITIAL_TRIGGER_ENTER | INITIAL_TRIGGER_EXIT (bitwise OR; summing both constants together would also work), you will be notified of all the geofences you're currently inside (with GEOFENCE_TRANSITION_ENTER) and also of all the geofences you're currently outside (with GEOFENCE_TRANSITION_EXIT). I haven't thought about a good use case for this, but found it interesting anyway.
How to stop the initial trigger
tl;dr
Set the initial trigger to 0, using a constant to attribute meaning to the number (e.g., private static final int NO_INITIAL_TRIGGER = 0)
Taking a closer look into the documentation of setInitialTrigger() it's possible to read:
Parameters
initialTrigger the notification behavior. It's a bit-wise of INITIAL_TRIGGER_ENTER and/or INITIAL_TRIGGER_EXIT and/or INITIAL_TRIGGER_DWELL.
The hint of using a bitwise operation, combined with the documentation found for those constants (which work as flags for each type of transition) led me to question what would happen if all of the bits were turned off.
So I tried to pass the value of 0 to setInitialTrigger(), in order to override the default behavior and turn off all of the initial triggers without having to resort to the workaround proposed by rfn123:
private GeofencingRequest createGeofencingRequest(List<Geofence> geofences) {
return new GeofencingRequest.Builder()
.setInitialTrigger(0)
.addGeofences(geofences)
.build();
}
Or - perhaps even better - giving some meaning to the magic number:
private static final int NO_INITIAL_TRIGGER = 0;
private GeofencingRequest createGeofencingRequest(List<Geofence> geofences) {
return new GeofencingRequest.Builder()
.setInitialTrigger(NO_INITIAL_TRIGGER)
.addGeofences(geofences)
.build();
}
After some hours of testing this seems to be a sensible approach even if it relies on a poorly documented behavior (as keepTrackOfYourStack has noticed, the documentation has been updated to clarify this).
Please note: From the tests I performed, it's still possible to get an almost instant trigger for a transition, depending on chosen geofences' radii and current location's precision.
For instance, you might be slightly away from the geofence and then suddenly your position is updated, putting you inside the geofence: this will trigger a geofence entrance notification.
However, this entrance notification is not related to the initial trigger you've configured, but to the update in your perceived position.
On a leaving note, if you don't mind, I have a suggestion for an alternate way to implement the onHandleIntent() method.
Instead of checking for the intent object's nullity, just pass that responsibility to the GeofencingEvent#fromIntent() call.
You can then check the validity of the returned event object, using a guard clause - which will increase your method's readability (at least in my opinion).
This will allow you to both test for nullity and check if the event has an error.
Something like this:
#Override
protected void onHandleIntent(#Nullable Intent intent) {
GeofencingEvent event = GeofencingEvent.fromIntent(intent);
if (event == null || event.hasError()) {
logInvalidEvent(event);
return;
}
// Process the event...
}
A workaround might be passing INITIAL_TRIGGER_DWELL to the setInitialTrigger() method.
This will only trigger a notification if the device is already inside the geofence for some time. You can set this time to a very large number.
However this only works if you solely use GEOFENCE_TRANSITION_DWELL in the initial triggering and are otherwise not interested in adding a dwell notification.
Check this link: https://developers.google.com/android/reference/com/google/android/gms/location/GeofencingRequest#INITIAL_TRIGGER_ENTER
it looks like they fixed the documentation and 0 works even though there is no constant
documentation update
From the documentation
initialTrigger the notification behavior.
It's a bit-wise of GeofencingRequest.INITIAL_TRIGGER_ENTER and/or GeofencingRequest.INITIAL_TRIGGER_EXIT and/or GeofencingRequest.INITIAL_TRIGGER_DWELL. When initialTrigger is set to 0 (setInitialTrigger(0)), initial trigger would be disabled.

Screen tracking support - Firebase 9.8

According Firebase Android SDK Release Notes with 9.8 update we have screen tracking support with android screens and activities... The documentation says that this event works like that:
mFirebaseAnalytics.setCurrentScreen(activity,class_name,class_override_name);
In my case, I don't need overrides class name and I send null value... But i'm waiting 48h and my firebase analytics console doesn't show info about this event, any ideas?
Thanks in advance!
Another very important thing that I've noticed only after two days of intensive struggling: the setCurrentScreen method MUST be called on the UI thread.
I was only able to see that after looking for a light in the Firebase decompiled code:
#MainThread
#Keep
public final void setCurrentScreen(#NonNull Activity var1, #Size(min = 1L,max = 36L) #Nullable String var2, #Size(min = 1L,max = 36L) #Nullable String var3) {
//...
}
Whenever this method is called a event of type screen_view is logged.
And keep in mind the Firebase size restrictions. The maximum size of a screen name is 36 characters long.
First I had the same question: where is my event with current screen name on the Firebase dashboard?
I've called method mFirebaseAnalytics.setCurrentScreen(this, "MainActivity", null); with no result.
Thanks to the comment by Benoit I realized that this method indicates the value of implicit parameter that is automatically attached to any event you send.
That means it's not independent event, it's a parameter that will stick to all your events since you set it.
This will be useful if you have changing screens within single Activity. For example when you have multiple fragments with one hosting Activity. And you call this method in each fragment in onResume().
If you want to have distinct metric with the name of your screen - fire explicitly a new event for that.
Bundle params = new Bundle();
params.putString(FirebaseAnalytics.Param.ITEM_CATEGORY, "screen");
params.putString(FirebaseAnalytics.Param.ITEM_NAME, "MainActivity");
mFirebaseAnalytics.logEvent(FirebaseAnalytics.Event.VIEW_ITEM, params);
val bundle = Bundle()
bundle.putString(FirebaseAnalytics.Param.SCREEN_NAME, "YOUR SCREEN NAME")
mFirebaseAnalytics.logEvent(FirebaseAnalytics.Event.SCREEN_VIEW, bundle)
Also Firebase Analytic's screen tracking is automatic. No need for explicit separate event tracking.
Sets the current screen name, which specifies the current visual context in your app. This helps identify the areas in your app where users spend their time and how they interact with your app.
Note that screen reporting is enabled automatically and records the class name of the current Activity for you without requiring you to call this function. The class name can optionally be overridden by calling this function in the onResume callback of your Activity and specifying the screenClassOverride parameter.
If your app does not use a distinct Activity for each screen, you should call this function and specify a distinct screenName each time a new screen is presented to the user.
The name and classOverride remain in effect until the current Activity changes or a new call to setCurrentScreen is made. I will try to add this method to onResume Method. I do not know the result but i will share my experience.
firebaseAnalytics.setCurrentScreen(activity,screeenName,activity.getClass().getSimpleName());
firebaseAnalytics.setMinimumSessionDuration(100L);
params = new Bundle();
params.putString(FirebaseAnalytics.Param.ITEM_CATEGORY, "screen");
params.putString(FirebaseAnalytics.Param.ITEM_NAME, screeenName);
firebaseAnalytics.logEvent(FirebaseAnalytics.Event.VIEW_ITEM, params);
Try using setCurrentScreen as well as manual event fire as firebase doesn't send data immediately to the console...but if event is fired up..all the remaining data is sent to firebase..
Just call that method in onResume(), and check the tracking through DebugView. it worked for me.
Check out the documentation.

How to get calendar event updates on Android device?

I want to get calendar event updates (when a new event is added or an existing event is deleted ) on android 2.2 devices ?
In other words, my program wants to get notifications for any calendar event changes
Anyone has any thoughts regarding how to do this?
whenever the Calendar update is made,u can get notification by using Content Observer,u have to register first observer using
this.getContentResolver().registerContentObserver(uri, true, observer);
where uri is the the calendar uri like "content://com.android.calendar/events" and observer is the object of the class extending Content Observer which overrides on change method,invoked when the change occurs
you have to notify this observer using
this.getContentResolver().notifyChange(eventsUri, null)
wherever u r performing changes like in read or delete operation of the calendar

Categories

Resources