Android Question Understanding geofence error codes using JavaObjects, GetMethod, etc

Sandman

Expert
Licensed User
Longtime User
NOTE: This is a rewrite of this post, which might contain relevant information (but I doubt it)

I'm working with geofence code posted by Erel: https://www.b4x.com/android/forum/threads/geofence-monitoring-a-region-in-the-background.84767/

In many ways it works just fine, but at some point it fails to add geofences when I relaunch the app. This is evident as the isSuccessful returns FALSE.

The good news is that the geofence thing in Android can tell you what went wrong, using GeofenceStatusCodes. The bad news is that I just can't seem to navigate JavaObjects, GetMethods, etc well enough to find my way to that information.

The example linked above contain the following sub by Erel. I tried to work my way to GeofenceStatusCodes. The last two lines in the sub is as far as I came, but I suspect I'm on the wrong path.
B4X:
Public Sub AddGeofence(Callback As Object, geo As Geofence)
    Dim gb As JavaObject = CreateGeofenceBuilder(geo)
    Dim req As JavaObject = CreateGeofenceRequest(gb)
    Dim task As JavaObject = client.RunMethod("addGeofences", Array(req, PendingIntent))
    Do While task.RunMethod("isComplete", Null) = False
        Sleep(50)
    Loop
    CallSubDelayed2(Callback, "Geofence_Added", task.RunMethod("isSuccessful", Null))

    ' Below added by me
    Dim exc As JavaObject = task.RunMethod("getException", Null)
    Log(exc.RunMethod("getStatusCode", Null))
End Sub

Given what we have in the sub, can somebody help me find my way to the value for GeofenceStatusCodes so I can understand what the problem is?


Relevant (I think) documentation at Google:
 

Sandman

Expert
Licensed User
Longtime User
I'm not 100% certain, I haven't been able to reproduce that isSuccessful return false all the time. But for a period, when experimenting with trying to find the error code, I got the number 13 over and over. That's assuming I did things right, which is a big assumption.

The geofence status codes are in the range 1000..1004, so I thought 13 was way wrong.
 
Upvote 0

Sandman

Expert
Licensed User
Longtime User
You shouldn't call getException of isSuccessful = True.
Yeah, I noticed that will create its own crash. :)

After answering you above, I tried searching for "android exception 13", and guess what the first hit was? A surprisingly relevant post at Stack Overflow:

Adding Geofence gives ApiException status 13

Seems this is a known issue, and judging by the discussion it might be related to some combination of OS version, API version, and whether or not one has allowed the app to get position in foreground only.

I will do some more tests and post a follow-up here if I can find out something solid.
 
Upvote 0

drgottjr

Expert
Licensed User
Longtime User
i didn't want to speak out of turn last night, but i noticed a couple things regarding your code:
you can't assume the result of your "getException" call is not null. the documentation indicates that's a possibility. to use it (in the next statement) without having checked if it's valid will probably cause a crash). in java, you would check for null. possibly the same in b4a, but i think the convention is to do something like "if the-javaobject-.isInitialized = false then ...". the assignment alone isn't necessarily enough to cause a crash; it's the using that does.

you could probably also wrap the call in try/catch.

second, "getStatusCode" is a method of the geofences(client) api, not a method of the exc ("getException"). how you get back to the geofences api seems tricky, given the code shown. there is also the matter of an "apiexception", which is actually what appears to contain the status code. that's clearly mentioned in the task or geofences(client) api documentation. this exception is triggered additionally by the "addgeofences" method (as part of the callback). how you access it, i can't say. i don't use the api. but the documentation indicates pretty clearly that this exception does contain things similar to what you are looking for with "getStatusCode", but not with that method. i think. it was kind of late in the evening to start with documentation for task, geofencesclient api and apiexception all at once.

i know you saw the error 13 posts (i did too), but, in addition, many people have described the same problem as you did regarding mysterious failures. it seems to have been acknowledged by google and was related to its gms or play services version. not sure if you saw those posts as well.
 
Upvote 0

Sandman

Expert
Licensed User
Longtime User
i didn't want to speak out of turn last night
It's a forum, no need to wait for your turn - just go ahead and post. :)

you can't assume the result of your "getException" call is not null
Yeah, I know. Erel and I touched upon that in #4 and #5 above. I'm not doing rock-solid production code here, I'm just taking Erels example and experimenting with it a little bit.

second, "getStatusCode" is a method of the geofences(client) api, not a method of the exc ("getException") <snip>
Yeah, I was pleasantly surprised when Erel said my code was (almost) correct. Now your post has fully restored my confusion. :) Oh, it would be so great to have a nice tutorial here on how to use the Android API with JavaObjects etc. I'll post a wish about it, I suppose.
 
Upvote 0

Sandman

Expert
Licensed User
Longtime User
UPDATE. Now I've gone through all combinations of these, to figure out when geofences can be added:
  • Android OS version (6.0, 8.1 and 11.0 - the ones I had available)
  • API versions (26, 27, 28, 29 and 30(*))
  • All possible user responses when device ask for permission to use location services
I uninstalled the app between each run, just to be certain nothing was remembered about previously chosen options.

Summary

Older versions of Android

They simply ask whether the user want to Allow or Deny access to location. Both Deny and Allow work as expected, without errors. The former does not produce geofences, and the latter does.


Newer versions of Android (**)

They give more nuanced alternatives for the user:
  • Allow all the time
    This is the only acceptable option, if we want geofences to be available when app is in background (or not even started).
    For API 26..28 the dialog present three buttons with the below options, and "Allow all the time" as a link to the setting page for the app.
    For API 29 the link is gone. Now the user need to manually find the app setting page to enable this option. (***)
    For API 30 the link is still gone, and the app settings page doesn't even have the option anymore.

  • While using the app
    Trying to create a geofence with this option produce an error 13, with no geofence created.

  • Only this time
    Trying to create a geofence with this option produce an error 13, with no geofence created.

  • Deny
    Works as expected: No error, no geofences added.

I'm attaching my notes, in case somebody want to see all combinations I tried.

UPDATE 2: To get the settings page in API 29 and 30 to show the option "Allow all the time", add this to the manifest: (source)
B4X:
AddPermission(android.permission.ACCESS_BACKGROUND_LOCATION)


(*) API level 30 only tested on Android 11
(**) I don't know anything about versions between 8.1 and 11, I didn't have access to any for these tests
(***) I'm not sure this result is correct. It seems that API 29 might be exactly like API 30
 

Attachments

  • notes.txt
    3.2 KB · Views: 158
Last edited:
Upvote 0
Top