Location Proximity Alert

15 views
Skip to first unread message

Zero

unread,
Mar 20, 2008, 6:43:39 AM3/20/08
to OpenIntents
Ok, new thread :)

i'll start with wrapping up what i had in mind in the first place.
there's a service running in the background reading gps data.
this service exposes at least two functions to the outisde world:
proximityAlert(Url position,long distance) you are distance units away
from positioin

proximityAlert(Url[] positions,long[] distances)
you're near 2 or more positions on the list, with distance[i]

why this? imagine a service that needs to do certain things
then user reaches position A , like checking the A shop for prices.
AFAIK this can't be done via intentreceivers. Every service has to
extend android.app.service , and this class hasn't the funtionality
onReceiveIntent(Context context, Intent intent) that is used to
check for broadcasted intents. And the number one major drawback
on java is you can't extend multiple classes. :(
but you should be able to bind to another service via aidl
(although i have to try that first to be sure).

There is the possibiliy i'm missing something about services and
intentreceivers here, because services do have a function
registerReceiver(IntentReceiver receiver, IntentFilter filter)
but i don't see how these registerd intents can be evaluated
by the service itself.


if we had a functionality like described above, there will be an easy
way to do a lot of cool things, like using favorite locations to get
simple alerts ("wake up, you reached ur train station") or
automatic price checks ("the shop behind you got your favorite
java coffe for only 5 EURO") and many more.

Peli

unread,
Mar 20, 2008, 7:20:06 AM3/20/08
to OpenIntents
Sometimes it pays to read through the Developer group discussion. They
do a lot with MediaPlayer currently, and I saw a related topic to
services just today:

http://groups.google.com/group/android-developers/browse_frm/thread/bef63c1d572673a3/be02eb559ef67e95#be02eb559ef67e95

hackbod explains how one should do it:

No service should remain in the memory for all time.
"Instead, you can use the alarm manager to schedule a
receiver at the desired schedule, and when the receiver is launched
start your service to do the check (and then it can stop itself). "

The same can obviously be done with the ProximityAlert.

Further below:
"(Btw, in an upcoming SDK you will be able to have the alarm manager
directly start a service without needing the intermediate broadcast
receiver.) "

and I think the same will be available for Proximity Alert.

I doubt that the upcoming SDK will be in time before the deadline, so
we should start from what we have, and that is m5-rc15.

From this information it is clear that it would not be very
advantageous to use aidl for this purpose.

I would really opt for building something around
Locationmanager.addProximityAlert, rather than coding this
functionality by hand.

http://code.google.com/android/reference/android/location/LocationManager.html#addProximityAlert(double,%20double,%20float,%20long,%20android.content.Intent)

Google will surely optimize this routine for battery saving, and it
will work optimally with different location providers, like GPS,
CELL_ID, ...

Although I have not tried it, I'm quite confident that you can pass
several intents (that may differ by parameters given) to set several
"hot spots", so that each intent is fired when you are close to a
place.

1) So, the simplest to try out would be to use intent with
VIEW_ACTION, and some content URI. Your Intent should open at the
desired location. (Note that expiration=-1 does not work due to the
bug mentioned in the other thread, but a very large number works (it
is in milliseconds!))

2) If this works, write an intent receiver that receives the intent
and fires a notification. Somehow one would have to pass the data
which text to display in the notification and the intent to be fired
when the user clicks on the notification along with the original
intent to addProximityAlert.

3) Even more abstract: Add a new ContentProvider that stores all
ProximityAlerts. Android's LocationManager allows to add and remove
ProximityAlerts, but not to view them. So if you want to edit the
alerts, they would have to be stored somewhere else:

e.g.
content://org.openintents.locations/alerts/123

where alerts corresponds to a table (the list of locations that you
mentioned in your post)

double latitude, double longitude, float radius, long expiration,
Intent intent, String notificationText

Now, your IntentReceiver waits for .../alerts/*, and when one arrives,
it can look up the content provider for the notificationText and the
"true" intent to be fired.

So, actually, for this you don't need to implement a service. A
receiver that pops up the notification will be fine enough.

Does this make sense?

Hm, another possibility may be to have a general alert provider:
content://org.openintents.alerts/locations/123
then one could also have
content://org.openintents.alerts/alarms/43

so there could be alerts connected to location or to alarms. (later
also: alerts/people - to be fired when a certain person calls, or an
sms from a certain person arrives.)

So, what do you think about this ContentProvider?

Peli

Zero

unread,
Mar 20, 2008, 8:07:13 AM3/20/08
to OpenIntents
an general alarm provider. nice idea.
the scenario you describe defnielty feels more "the android way",
then dealing with services.
i think i'll go this way, though there are two things that concern me.

1) startup times. on my emulator, startup time of anything called by
an
broadcastet intent is horrible. but i can't tell if this is the
emulator,
the emulator on my system in special, or a general thing with android.
this will probably need re-thinkin after real-live devices are out.

2)overlapping locations. there's a certain minimum proximity
for these alerts to be usefull, about 30~50 meters i guess.
if the user enters locations via the map / by address these can
easily overlapp.
i think this is easier solved by using
requestUpdates(LocationProvider provider, long minTime, float
minDistance, Intent intent)
doing periodically checks and letting the user decide
on the action if there are two or more overlapping locations.

On Mar 20, 12:20 pm, Peli <peli0...@googlemail.com> wrote:
> Sometimes it pays to read through the Developer group discussion. They
> do a lot with MediaPlayer currently, and I saw a related topic to
> services just today:
>
> http://groups.google.com/group/android-developers/browse_frm/thread/b...
>
> hackbod explains how one should do it:
>
> No service should remain in the memory for all time.
> "Instead, you can use the alarm manager to schedule a
> receiver at the desired schedule, and when the receiver is launched
> start your service to do the check (and then it can stop itself). "
>
> The same can obviously be done with the ProximityAlert.
>
> Further below:
> "(Btw, in an upcoming SDK you will be able to have the alarm manager
> directly start a service without needing the intermediate broadcast
> receiver.) "
>
> and I think the same will be available for Proximity Alert.
>
> I doubt that the upcoming SDK will be in time before the deadline, so
> we should start from what we have, and that is m5-rc15.
>
> From this information it is clear that it would not be very
> advantageous to use aidl for this purpose.
>
> I would really opt for building something around
> Locationmanager.addProximityAlert, rather than coding this
> functionality by hand.
>
> http://code.google.com/android/reference/android/location/LocationMan...)

Peli

unread,
Mar 20, 2008, 8:26:13 AM3/20/08
to OpenIntents
Zero,

ad 1)
if I walk into a 30 m area, it does not matter whether I receive the
notification 30 ms after I entered the area, or 5 seconds after, so I
don't think performance is a bottleneck in this case.

ad 2)
Also overlapping regions can be checked by addProximityAlerts. Note
that you receive the event every time you enter the region or you exit
the region. So you could have an intent that stores in the
ContentProvider whether you are inside or outside.

There is no need to do continuous checks. Just check whatever you
would like to know when you enter or exit a region.

For example: Let's say, you want to fire an intent if you are in
region A AND in region B:
Then you would do this:
1) First you are outside:
2) You enter region B: Your IntentReceiver is launched. It writes into
the content Provider that you are now inside region B. It then looks
into the ContentProvider to see whether you are also in region A. No,
you are not. So nothing happens, no notification is fired.
(intent receiver can shut down, phone runs on low power for some
hours.)
3) Now you also enter region A: Your IntentReceiver is launched again.
it writes into the ContentProvider that you are in region A. It looks
in the ContentProvider, and sees that you are also in region B.
Therefore it launches the intent that it can find in the
ContentProvider to tell you that you are now in both, region A and
region B.

Continuous checks take a lot of battery. The locationManager may shift
this work to the location providers, like GPS or CELL_ID, and save
battery when you are far away from any of your proximity alert regions
by not checking very often.

So, the ContentProvider needs an additional column "is_inside"

Peli

Zero

unread,
Mar 20, 2008, 8:56:22 AM3/20/08
to OpenIntents
1) ok, i tend to get a bit picky about performance. point taken. ;)

2) it probably needs an is_overlapping as well. then it might work
out with asyncrhronus calls.
thing is, that can be a race condition: do the same intent for
A and B. enter overlapping region, intents get fired. whoever
recevies it first thinks it's ok and starts some thread.
for instance, a networking transaction call running in background.
the one coming later might see that this is problem,
might even be able to ask the user about it, but if the
process started by the first one is already running there's no
simple way of stoping it without messing up it's data and state.
of cause one could do a lot of code handling all this, but it seems
better to avoid it in the first place.
maybe like this:
if alerts are entered, it's checked against other region if there's
someone overlapping.
if so, discard the first event fired and mark that regions, so the
last intent in the queue
can decide what to do.
still complicated thing...but i just *know* that's going to happen
sooner or later.

Zero

unread,
Mar 20, 2008, 10:16:28 AM3/20/08
to OpenIntents
ok, had some time to think.
maybe its easier to just see which location is nearer by distance,
than use this. every following event does the same and discards
itself automatically if the nearest is alredy marked as "is_inside".

Peli

unread,
Mar 20, 2008, 1:00:17 PM3/20/08
to OpenIntents
Of course, the "AND" was just an example. It is likewise easy to do a
logical "OR" so that the notification is fired as soon as one enters
anywhere in the greater region, but no additional notifications are
fired once you are inside. Only when you leave the area completely you
could receive the "exit" notification if you wish.

In any case, applications should not be too picky and handle the
notifications with tolerance:
For example when you are just close to the border, it may be due to
GPS inaccuracy or walls or whatever that you receive several in / out
events. Whatever service you start there should be tolerant enough to
handle these cases.

In fact, for most applications the "race condition" should also not
matter: For example, you define one area to receive a notification to
call a certain person, and in a second area a notification that you
should look at your shopping list. What happens is simply that you
have 2 notifications in your status bar, so the user can choose which
to click first, and only then the appropriate intent is opened.

So, I'd suggest, back to KISS:
1) ContentProvider with all alerts/locations
2) addProximityAlert will call your intentReceiver with an intent that
has a number that corresponds to a row in your ContentProvider.
3) From that row read the NotificationText and Intent and start a
notification with that intent.

This should be a basic expandable approach, so once this works, one
can think of more difficult conditions, combining proximityAlert,
AlarmNotification, or even Sensors:

Notify me, if I am in this region between 8-12 a.m., weekday, and the
phone is pointing South.

Peli
> ...
>
> Erfahren Sie mehr »- Zitierten Text ausblenden -
>
> - Zitierten Text anzeigen -

Zero

unread,
Mar 20, 2008, 2:06:48 PM3/20/08
to OpenIntents
there's a certain reason why i'm so insistent about that point,
but i guess i found a solution that will go with a KISS alert
provider. i'll reveal my strange idea later...

one more thing though: to make it more easy to expand,
i'd would not split alerts in tables but combine them in one,
while having differten types;
alert_id | type | condition | rule | intent | active | activate on
boot |
type could be location, time, sensor,[..] or combined
if type is combined and condition is true, use rule to make
another lookup in alert table.
of course the parts of an combined alert must have the same resulting
event.
we could still use uri to acces certain types of alerts
like org.openintents.alerts/location
etc, but they would share the table and therefore the _id space

the activity creating the alert would have to register the suiting
Intentreceiver.
activate on boot could be done with a small service that registers
everything and then
stops.
> ...
>
> read more »

Peli

unread,
Mar 20, 2008, 2:15:27 PM3/20/08
to OpenIntents
I had thought about combining as well, but there are also reasons that
speak against it:

for a location alert you need "latitude", "longitude".
For time alert you need "date start" "date end"
For contact alert you need "contact"...

Then again, on the other hand, one could use URIs:
for example, the geo URI for lat/long
contact URI for people
and for date and calendar one would have to create a new URI.

Then everything would fit into one table as you suggested - and would
even be more general! :-)

Peli

Zero

unread,
Mar 20, 2008, 5:39:14 PM3/20/08
to OpenIntents
yep, i was thinking about URIs here.
of course, if one knows the datatype in a string field, one
could use some separators for each type
like
type_geo conditon="0.03/3456.663"
type_date conditon="2222345ms/349495ms"

but i think URIs are more general. Just needs some
convient way to make geo uri into location classes,
but thats probably easy.
> ...
>
> read more »
Reply all
Reply to author
Forward
0 new messages