We continue with part 3 of our three-part series on our discussion of Developing Proximity Alerts for Mobile Applications using the Android Platform. Click appropriately for Part 1 and Part 2.
Bonus: I have just added Part 4 to discuss important new enhancements to the Proximity Alert Application!
Capturing Proximity Alert Events
For the record, capturing proximity alerts is a fancy pants way of saying “set up a proximity alert reminder”. The process is similar, in thought, to setting up an event reminder within your favorite calendaring tool.
We will capture a proximity alert event by creating a custom BroadcastReceiver that receives events upon the triggering of an actual alert by the LocationManager Service. In general, there are six steps necessary to capture proximity alerts as follows:
- Create a ProximityAlert object containing the fields of your proximity alert. For example, name and description.
- Create a BroadcastReceiver for receiving proximity alerts and override onReceive(…).
- Create a ProximityAlertActivity.
- Register the BroadcastReceiver by associating it to your ProximityAlertActivity as an IntentFilter, and registering all to the application context.
- Retrieve a PendingIntent from the broadcast associated to the registered IntentFilter of your ProximityAlertActivity.
- Add a proximity alert to the LocationManager by associating your ProximityAlert object to the PendingIntent.
Note, you handle the actual proximity alert event within your BroadcastReceiver‘s onReceive(…) method. For example, you may simply write a Toast, displaying a description of the proximity, or location, found within the ProximityAlert object located within the bundle supplied within onReceive(…)’s intent parameter.
Details – Capturing Proximity Alert Events
The first thing our application needs to do, is register a BroadcastReceiver by associating it to a ProximityAlertActivity (see 4 above). Let’s look at the code that supports this BroadcastReceiver registration process.
public class ProximityAlertHomeActivity extends ListActivity {
private ArrayList<ProximityAlert> reminders = null;
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
String context = Context.LOCATION_SERVICE;
ProximityAlertHelper.getInstance().initializeLocationManager(this, (LocationManager) getSystemService(context));
loadReminders();
}
}
public class ProximityAlertHelper {
public static ProximityAlertHelper getInstance() {
if (instanceOf == null) {
instanceOf = new ProximityAlertHelper();
}
return instanceOf;
}
public String Provider;
private static ProximityAlertHelper instanceOf;
private static boolean initialized = false;
private ProximityIntentReceiver receiver = null;
public boolean initializeLocationManager(Context context, LocationManager locationManager) {
Criteria criteria = new Criteria();
criteria.setAccuracy(Criteria.ACCURACY_FINE);
criteria.setAltitudeRequired(false);
criteria.setBearingRequired(false);
criteria.setCostAllowed(true);
criteria.setPowerRequirement(Criteria.POWER_LOW);
this.Provider = locationManager.getBestProvider(criteria, false);
this.receiver = new ProximityIntentReceiver();
IntentFilter filter = new IntentFilter(ProximityAlertActivity.class.getName());
context.registerReceiver(this.receiver, filter);
return initialized = true;
}
}
Above, I show the call to ProximityAlertHelper.getInstance().initializeLocationManager(…) from the ProximityAlertHomeActivity’s onCreate(…) method. This happens immediately at application startup. Immediately afterwards, we see the ProximityAlertHelper.getInstance().initializeLocationManager(…) method that carries out the actual BroadcastReceiver registration.
Next, let’s look at the details involved in creating the BroadcastReceiver. We implement our ProximityIntentReceiver class by inheriting from the BroadcastReceiver class as follows:
public class ProximityIntentReceiver extends BroadcastReceiver implements IDebugSwitch {
@Override
public void onReceive(Context context, Intent intent) {
String key = LocationManager.KEY_PROXIMITY_ENTERING;
Boolean entering = intent.getBooleanExtra(key, false);
if (entering) {
ProximityAlert alert;
try {
alert = new ProximityAlert(intent.getStringExtra("current"));
Msg.ToastLong(context, "entered " + alert.Name);
NotifierHelper.vibrate(context);
} catch (JSONException ex) {
ex.printStackTrace();
}
}
}
}
Upon receiving an alert, we simply display a toast and vibrate the phone (lines 12 and 13). Note that we retrieve the serialized AlertProximity object from the intent bundle, and deserialize it to an actual instance of AlertProximity by supplying the serialized string to the constructor (line 11). This object contains the proximity alert information we can use to display to the user. For more details on the AlertProximity class, see Part 2.
More coming soon!
Setting Proximity Alert Preferences
We will use Android’s PreferencesActivity class to manage our configuration settings. We need to be able to configure the following preferences for our proximity alert mobile application:
- the minimum frequency to update location (to set a proximity alert),
- the minimum distance to update location (to set a proximity alert), and
- the proximity radius required to trigger a proximity alert
Before discussing further, let’s take a quick look at the actual Proximity Alert Preferences Screen.
Our ProximityAlertPreferencesActivity class provides the settings management we require.
public class ProximityAlertPreferencesActivity extends PreferenceActivity implements IDebugSwitch {
public ProximityAlertPreferencesActivity() {
}
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(null);
addPreferencesFromResource(R.xml.settings);
}
}
As you can see, all of the functionality is provided by Android’s PreferenceActivity base class. We simply supply the resource file. The following is the settings.xml resource file referenced by our AlertProximityPreferencesActivity class displayed above, and required to manage our proximity alert settings:
<?xml version="1.0" encoding="utf-8"?>
<PreferenceScreen xmlns:android="http://schemas.android.com/apk/res/android">
<PreferenceCategory android:title="Location Update Frequency" android:key="locupdate">
<ListPreference
android:title="Set Minimum Frequency"
android:summary="How often to update location"
android:key="mintimeinc"
android:defaultValue="2000"
android:entries="@array/minTimeIncs"
android:entryValues="@array/minTimeVals" />
<ListPreference
android:title="Set Minimum Distance"
android:summary="Minimum distance of movement necessary to update location"
android:key="mindistance"
android:defaultValue="2"
android:entries="@array/minDistance"
android:entryValues="@array/minDistanceVals"
/>
</PreferenceCategory>
<PreferenceCategory android:title="Proximity Radius" android:key="locupdatefreq">
<ListPreference
android:title="Set Proximity Radius"
android:summary="Proximity radius necessary to trigger alert"
android:key="proxradius"
android:defaultValue="2"
android:entries="@array/proxRadius"
android:entryValues="@array/proxRadiusVals"
/>
</PreferenceCategory>
</PreferenceScreen>
And lastly, the following settingvalues.xml resource file contains the actual values required by the settings.xml resource file:
<?xml version="1.0" encoding="utf-8"?>
<resources>
<string-array name="minTimeIncs">
<item name="0">0</item>
<item name="1000">Every 1 second</item>
<item name="2000">Every 2 seconds</item>
<item name="5000">Every 5 seconds</item>
<item name="10000">Every 10 seconds</item>
<item name="30000">Every 30 seconds</item>
<item name="60000">Every 1 minute</item>
<item name="300000">Every 5 minutes</item>
<item name="1800000">Every 30 minutes</item>
</string-array>
<string-array name="minTimeVals">
<item name="0">0</item>
<item name="1000">1000</item>
<item name="2000">2000</item>
<item name="5000">5000</item>
<item name="10000">10000</item>
<item name="30000">30000</item>
<item name="60000">60000</item>
<item name="300000">300000</item>
<item name="1800000">1800000</item>
</string-array>
<string-array name="minDistance">
<item name="1">1 meters</item>
<item name="2">2 meters</item>
<item name="3">3 meters</item>
<item name="5">5 meters</item>
<item name="10">10 meters</item>
<item name="25">25 meters</item>
<item name="50">50 meters</item>
<item name="100">100 meters</item>
<item name="250">250 meters</item>
<item name="500">500 meters</item>
<item name="1000">1000 meters</item>
</string-array>
<string-array name="minDistanceVals">
<item name="1">1</item>
<item name="2">2</item>
<item name="3">3</item>
<item name="5">5</item>
<item name="10">10</item>
<item name="25">25</item>
<item name="50">50</item>
<item name="100">100</item>
<item name="250">250</item>
<item name="500">500</item>
<item name="1000">1000</item>
</string-array>
<string-array name="proxRadius">
<item name="1">1 meters</item>
<item name="2">2 meters</item>
<item name="3">3 meters</item>
<item name="5">5 meters</item>
<item name="10">10 meters</item>
<item name="25">25 meters</item>
<item name="50">50 meters</item>
<item name="100">100 meters</item>
<item name="250">250 meters</item>
<item name="500">500 meters</item>
<item name="1000">1000 meters</item>
</string-array>
<string-array name="proxRadiusVals">
<item name="1">1</item>
<item name="2">2</item>
<item name="3">3</item>
<item name="5">5</item>
<item name="10">10</item>
<item name="25">25</item>
<item name="50">50</item>
<item name="100">100</item>
<item name="250">250</item>
<item name="500">500</item>
<item name="1000">1000</item>
</string-array>
</resources>
And that’s it! I believe Google’s Android platform is paving the way for both advancing mobile technologies and getting them quickly, and affordably, into consumers’ hands.
I hope this helps you design and create innovative, mobile-based Android applications.
Bonus: Please see Part 4 as I discuss important new enhancements to this Proximity Alert Application!
This is Brian Buikema. See you next time!


I really like the way you explained everything. I’ve been struggling with the proximity alerts for almost 2 days now.. I was hoping that I could build your app to see if your implementation does work. Unfortuanatly a lot of files seem to be missing.
Would it be possible to provide the entire project’s source code? A stripped down version would be sufficient!
Thanks in advance!
I appreciate your interest. I will try and add a zip of the project source to part 3 this weekend. I’m currently swamped at work!