<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0"
	xmlns:content="http://purl.org/rss/1.0/modules/content/"
	xmlns:wfw="http://wellformedweb.org/CommentAPI/"
	xmlns:dc="http://purl.org/dc/elements/1.1/"
	xmlns:atom="http://www.w3.org/2005/Atom"
	xmlns:sy="http://purl.org/rss/1.0/modules/syndication/"
	xmlns:slash="http://purl.org/rss/1.0/modules/slash/"
	>

<channel>
	<title>iBlog, iByte, iBrianiBlog, iByte, iBrian &#187; Location-Based</title>
	<atom:link href="http://blog.brianbuikema.com/category/locationbased/feed/" rel="self" type="application/rss+xml" />
	<link>http://blog.brianbuikema.com</link>
	<description>Technology Moves as Fast as We Move It by Brian Buikema</description>
	<lastBuildDate>Tue, 05 Mar 2013 15:33:33 +0000</lastBuildDate>
	<language>en-US</language>
	<sy:updatePeriod>hourly</sy:updatePeriod>
	<sy:updateFrequency>1</sy:updateFrequency>
	
		<item>
		<title>Android Development &#8211; Part 3:  Using Google&#8217;s Places API to Develop Compelling Location Based Mobile Applications</title>
		<link>http://blog.brianbuikema.com/2010/08/android-development-part-3-using-googles-places-api-to-develop-compelling-location-based-mobile-applications/</link>
		<comments>http://blog.brianbuikema.com/2010/08/android-development-part-3-using-googles-places-api-to-develop-compelling-location-based-mobile-applications/#comments</comments>
		<pubDate>Tue, 24 Aug 2010 03:21:44 +0000</pubDate>
		<dc:creator>Brian Buikema</dc:creator>
				<category><![CDATA[Android]]></category>
		<category><![CDATA[Business]]></category>
		<category><![CDATA[Enterprise]]></category>
		<category><![CDATA[Java]]></category>
		<category><![CDATA[Location-Based]]></category>
		<category><![CDATA[Mobile]]></category>
		<category><![CDATA[Proximity Alerts]]></category>
		<category><![CDATA[Technology]]></category>

		<guid isPermaLink="false">http://blog.brianbuikema.com/?p=1141</guid>
		<description><![CDATA[In this post, we will develop the code for our location-based mobile application.  Remember we designed our application in Part 2, and now we ready to tackle the code! Developing the &#8220;Places In My Proximity&#8221; Android Service More coming soon! Developing the &#8220;Retailer Rewards&#8221; Class &#8211; a POJO Requesting Campaign Details from the &#8220;Retailer Campaign&#8221; [...]]]></description>
			<content:encoded><![CDATA[<p>In this post, we will develop the code for our location-based mobile application.   Remember we designed our application in <a href="http://blog.brianbuikema.com/2010/08/android-development-part-2-using-googles-places-api-to-develop-compelling-location-based-mobile-applications/" target="_blank">Part 2</a>, and now we ready to tackle the code!</p>
<h2>Developing the &#8220;Places In My Proximity&#8221; Android Service</h2>
<p>More coming soon!</p>
<h2>Developing the &#8220;Retailer Rewards&#8221; Class &#8211; a POJO Requesting Campaign Details from the &#8220;Retailer Campaign&#8221; Server-side RESTful Service</h2>
<p>More coming soon!</p>
<h2>Developing the &#8220;Consumer Settings Activity&#8221; and Supporting XML Configuration Files</h2>
<p>More coming soon!</p>
<h2>Developing the &#8220;Rewards Notification&#8221; Class</h2>
<p>More coming soon!</p>
<h2>Developing the &#8220;Display Retailer Reward Activity&#8221; Class</h2>
<p>More coming soon!</p>
]]></content:encoded>
			<wfw:commentRss>http://blog.brianbuikema.com/2010/08/android-development-part-3-using-googles-places-api-to-develop-compelling-location-based-mobile-applications/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Android Development &#8211; Part 2:  Using Google&#8217;s Places API to Develop Compelling Location Based Mobile Applications</title>
		<link>http://blog.brianbuikema.com/2010/08/android-development-part-2-using-googles-places-api-to-develop-compelling-location-based-mobile-applications/</link>
		<comments>http://blog.brianbuikema.com/2010/08/android-development-part-2-using-googles-places-api-to-develop-compelling-location-based-mobile-applications/#comments</comments>
		<pubDate>Sun, 15 Aug 2010 03:21:48 +0000</pubDate>
		<dc:creator>Brian Buikema</dc:creator>
				<category><![CDATA[Android]]></category>
		<category><![CDATA[Enterprise]]></category>
		<category><![CDATA[Java]]></category>
		<category><![CDATA[Location-Based]]></category>
		<category><![CDATA[Mobile]]></category>
		<category><![CDATA[Proximity Alerts]]></category>
		<category><![CDATA[Technology]]></category>

		<guid isPermaLink="false">http://blog.brianbuikema.com/2010/08/android-development-part-2-using-googles-places-api-to-develop-compelling-location-based-mobile-applications/</guid>
		<description><![CDATA[In Part 1, we discussed how to get started using Google&#8217;s Places API, including all necessary registrations. We also delved lightly on the differences between Place searches and Place details. Now let&#8217;s actually create something fun and useful.  First we need an idea.  And I have a good one! Exercising Core Location-Based Features Using the [...]]]></description>
			<content:encoded><![CDATA[<p>In <a href="http://blog.brianbuikema.com/2010/08/android-development-part-1-using-googles-places-api-to-develop-compelling-location-based-mobile-applications/" target="_blank">Part 1</a>, we discussed how to get started using <a href="http://code.google.com/apis/maps/documentation/places/" target="_blank">Google&#8217;s Places API</a>, including all necessary registrations.  We also delved lightly on the differences between Place searches and Place details.</p>
<p>Now let&#8217;s actually create something fun and useful.   First we need an idea.   And I have a good one!  <img src='http://blog.brianbuikema.com/wp-includes/images/smilies/icon_wink.gif' alt=';)' class='wp-smiley' /> </p>
<h2>Exercising Core Location-Based Features Using the Places API</h2>
<p>Let&#8217;s quickly identify some core location-based features.  These features are made possible by the ability of smart phones to track their <a href="http://en.wikipedia.org/wiki/Global_Positioning_System" target="_blank">GPS location</a> and use GPS coordinates within applications to correlate user location to people and places in proximity to that location.  Generally, the following is a list of such features:</p>
<ul>
<li>Ability to identify and publish current location</li>
<li>Search for places that are in proximity to a given location</li>
<li>Obtain details about a specific place, usually selected from a proximity search</li>
<li>Generate a <a href="http://blog.brianbuikema.com/2010/07/part-1-developing-proximity-alerts-for-mobile-applications-using-the-android-platform/" target="_blank">proximity alert</a> upon entering a location proximity</li>
<li>Generate a <a href="http://blog.brianbuikema.com/2010/07/part-1-developing-proximity-alerts-for-mobile-applications-using-the-android-platform/" target="_blank">proximity alert</a> upon exiting a location proximity</li>
</ul>
<p>Now, real innovation comes from your <em>ability to enhance those features</em>.  For example, let&#8217;s say your smart phone contains an application that alerts you to store specials as you come within proximity to participating stores.  So one day you are driving by and a proximity alert <em>alerts </em>you to a store special (or discount) at your favorite store.  But you don&#8217;t have time, and drive on by.</p>
<p>Now let&#8217;s say you drive by the same store on your return home.  Since you are within proximity to that store again, you get another proximity alert.  However, this time the application somehow <em>knows </em>you were nearby about an hour ago, and doubles the discount offered earlier.  You are excited and drive straight to the store.</p>
<p>That&#8217;s real innovation enhancing the core location-based features we discussed earlier.</p>
<h2>Developing an Android-Based Mobile Application Using the Places API &#8211; Getting Started</h2>
<p>As developers, we tend to learn new concepts and techniques best through examples.  Given the example we discussed earlier in enhancing the core location-based features, let&#8217;s develop this into a working mobile application using the Android platform.  To review, we stated the following:</p>
<blockquote><p>For example, let&#8217;s say your smart phone contains an application that alerts you to store specials as you come within proximity to participating stores.  So one day you are driving by and a proximity alert <em>&#8220;alerts&#8221; </em>you to a store special (or discount) at your favorite store.  But you don&#8217;t have time, and drive on by.</p>
<p>Now let&#8217;s say you drive by the same store on your return home.  Since you are within proximity to that store again, you get another proximity alert.  However, this time the application somehow <em>&#8220;knows&#8221; </em>you were nearby about an hour ago, and doubles the discount offered earlier.  You are excited and drive straight to the store.</p></blockquote>
<p>In order to tackle this, we need to better understand are requirements and end goals.</p>
<h3>Use Cases</h3>
<p>A great place to start is defining the Use Cases.  Of course we need to identify our key <em>Actors </em>first.  I see the following:</p>
<ul>
<li>Retailer</li>
<li>Consumer</li>
<li>System</li>
</ul>
<p>Per Actor, the Use Cases are as follows:</p>
<ol>
<li><em>Retailer </em>- ability to manage discounts and rules by defining campaigns, similar to CRM and relational marketing</li>
<li><em>Retailer </em>- report results of campaigns</li>
<li><em>Consumer </em>- enable/disable proximity alerts</li>
<li><em>Consumer </em>- ability to select/filter retailers of interest</li>
<li><em>Consumer </em>- ability to select proximity alert radius</li>
<li><em>Consumer </em>- provide <em>display</em>, <em>store</em>, and <em>retrieve </em>functionality for store specials/discounts</li>
<li><em>System </em>- record all consumer proximity alert activities</li>
<li><em>System </em>- manage retailer registrations</li>
</ol>
<h3>Considerations</h3>
<p>Let&#8217;s identify some considerations and assumptions to make our development simple and well-defined.</p>
<p>We will track retailers and campaigns, and consumer proximity alert activities on the server using <a href="http://blog.brianbuikema.com/2010/03/part-3-support-your-future-critical-enterprise-software-initiatives-such-as-integration-with-popular-mobile-platforms-with-a-well-defined-soa/" target="_blank">RESTful</a> services.  We&#8217;ll generate a quick report of customer proximity alert activities by querying the database and returning results in either JSON or XML.</p>
<p>We will assume a standard campaign with simple rules used by all retailers and <em>exclude a full-blown retailer campaign management process</em>.  We will assume two or three registered retailers and <em>exclude a full-blown retailer registration process</em>.</p>
<p>And we will assume store specials/discounts never expire!  <img src='http://blog.brianbuikema.com/wp-includes/images/smilies/icon_wink.gif' alt=';)' class='wp-smiley' /> </p>
<p>Now did you think we were done?  We need to think about how we should manage the actual redemption of a reward.  We can&#8217;t assume the consumer will just click a button.  Therefore we need a website for the retailer to access and manage consumer reward redemption&#8217;s and basic reporting needs.</p>
<p>And lastly, you may wonder what technology I have chosen for the server-side.  It is <a href="http://www.microsoft.com/downloads/details.aspx?FamilyID=3b537c55-0948-4e6a-bf8c-aa1a78878da0&amp;displaylang=en" target="_blank">ASP.NET MVC</a>. as it is easy to create <a href="http://aspnet.codeplex.com/releases/view/24471" target="_blank">RESTful</a> services supported by POCO&#8217;s, as Business Objects, and working with DTO&#8217;s and Repositories.  <a href="../2010/05/speed-up-your-mobile-enterprise-development-by-creating-a-lightweight-business-object-framework-for-android/" target="_blank">Click here to review my previous post for more information on POCO&#8217;s, as Business Objects, DTO&#8217;s, and Repositories</a>.</p>
<h2>Design Overview</h2>
<p>Per our Considerations above,</p>
<ul>
<li>we will require a database to store retailer and customer information</li>
<li>we will also require RESTful services to support the retailer and client requests (just a handful)</li>
<li>and lastly, we need to provide several application screens for management of user configuration settings and display and persistence of store specials/discounts</li>
</ul>
<h3>Entity Diagram</h3>
<p>We will define our data model (or entity diagram) as follows:</p>
<div id="attachment_1118" class="wp-caption aligncenter" style="width: 510px"><a href="http://blog.brianbuikema.com/wp-content/uploads/2010/08/EntityDiagram2.jpg"><img class="size-medium wp-image-1118" title="Entity Diagram" src="http://blog.brianbuikema.com/wp-content/uploads/2010/08/EntityDiagram2-500x357.jpg" alt="Entity Diagram" width="500" height="357" /></a><p class="wp-caption-text">Entity Diagram</p></div>
<p>Note that there is no relationship between <em>Retailers </em>and <em>Campaigns</em>.  Normally one would exist (e.g., one-to-many), but we are assuming that all retailers are using the same campaign since we are excluding the retailer campaign management process per our considerations.</p>
<h3>Services</h3>
<p>Our mobile application is considered a client that requires services to provide the complete <em>system functionality</em>.  Remember that system functionality is required by both retailers and consumers, and all retailer relevant information is stored on the server.  Therefore, we define our required services as follows:</p>
<ol>
<li><strong>Retrieve campaign reward for retailer</strong> <strong>service </strong>(assumes consumer has entered retailer proximity).</li>
<li><strong>Record consumer proximity visitation</strong> <strong>service </strong>(consumer enters retailer proximity).</li>
<li><strong>Redeem consumer reward</strong> <strong>service </strong>(consumer makes a purchase at the retailer and redeems reward).</li>
<li><strong>Retrieve campaign results</strong> <strong>service </strong>(used to report on campaign success).</li>
<li><em>Optional</em>:  If we decided to manage campaigns, we would add a <strong>campaign management service</strong>.</li>
</ol>
<h3>Application Screens</h3>
<p>Our mobile application needs several screens to provide basic <em>settings management</em> and <em>rewards display/management</em> functionality.</p>
<p>The required screens are:</p>
<ol>
<li><em>Mobile Client</em> &#8211; User Configuration Settings</li>
<li><em>Mobile Client</em> &#8211; List of Retailer Rewards Display</li>
<li><em>Mobile Client</em> &#8211; Detail Retailer Reward Display</li>
<li><em>Server </em>- Redeem Consumer Reward</li>
</ol>
<h3>More on Design &#8211; Flushing Out the Details</h3>
<p>We&#8217;ve already designed our data model, spec&#8217;ed our services, and identified our application screens.  Since we are tapping into location-based features, we need to discuss and agree on certain design strategies to allow us to be a mobile friendly mobile application, and not one that sucks battery life, or lives in the user thread (thus, being a bad <em>citizen</em>), etc&#8230;</p>
<p>We need a way to identify the places that match the user&#8217;s selected categories, and are within the user&#8217;s target proximity radius.</p>
<p>Therefore it makes sense for us to create a service that periodically call&#8217;s the place&#8217;s search API, and return those places that are within the user&#8217;s current proximity. From these results, we can easily filter those that match the user&#8217;s selected categories.</p>
<p>In general, our mobile application will need the following:</p>
<ul>
<li> A service that provides &#8220;who is within my proximity&#8221;.</li>
<li>A service that provides details on a retailer, e.g., currently running campaigns and relevant rewards.</li>
<li>A class that manages and retrieves user proximity, category, and enable/disable settings.</li>
<li>An activity to display &#8220;who is in my proximity&#8221;, on-demand.</li>
<li>A POJO requesting retailer campaign attributes, e.g., rewards.  Note, this requires a server-side RESTful service.</li>
<li>An notification to notify user of retailer reward.</li>
<li>An activity to display retailer reward.</li>
<li>An activity to display and manage &#8220;user received&#8221; retailer rewards.  Note, we&#8217;ll use local persistence.</li>
</ul>
<p>And our server-side application will require the following:</p>
<ul>
<li>A retailer campaign manager class.</li>
<li>A &#8220;look up&#8221; consumer&#8217;s information and reward(s) class.</li>
<li>A redeem consumer reward(s) class.</li>
<li>A generate reports class.</li>
</ul>
<h3>UML Diagrams</h3>
<p>Let&#8217;s describe some general classes that depict our system design as follows:</p>
<div id="attachment_1150" class="wp-caption aligncenter" style="width: 510px"><a href="http://blog.brianbuikema.com/wp-content/uploads/2010/08/Class-Diagram-Places-In-Proximity2.jpg"><img class="size-medium wp-image-1150" title="Class Diagram - Places In Proximity" src="http://blog.brianbuikema.com/wp-content/uploads/2010/08/Class-Diagram-Places-In-Proximity2-500x265.jpg" alt="Class Diagram - Places In Proximity" width="500" height="265" /></a><p class="wp-caption-text">Class Diagram - Places In Proximity</p></div>
<p>For brevity, I am showing classes that belong to <em>all </em>components found in our system, without showing a more detailed architectural, or component diagram.</p>
<p>And we&#8217;ll describe the sequence through those classes for the core use cases in retrieving places in proximity as follows:</p>
<div id="attachment_1151" class="wp-caption aligncenter" style="width: 510px"><a href="http://blog.brianbuikema.com/wp-content/uploads/2010/08/Sequence-Diagram-Places-in-Proximity1.jpg"><img class="size-medium wp-image-1151" title="Sequence Diagram - Places in Proximity" src="http://blog.brianbuikema.com/wp-content/uploads/2010/08/Sequence-Diagram-Places-in-Proximity1-500x279.jpg" alt="Sequence Diagram - Places in Proximity" width="500" height="279" /></a><p class="wp-caption-text">Sequence Diagram - Places in Proximity</p></div>
<p>Note that I did skip some important calls to the Android API to help keep our focus on the main sequence per our use cases.</p>
<p>We&#8217;ll start developing the mobile application next.</p>
<h3>Enhancements Excluded</h3>
<p>The following enhancements are my opinions of details required to make this a practical application.  Since my intention focuses on <em>location-based concepts</em>, not full application development, some application features are excluded as follows:</p>
<ul>
<li>Proper handling (both system and user interface) of the volume of reward notifications received by client.  If left unchecked, this will get messy, real fast!</li>
<li>Consumer reward deletion.  The item above should actually manage this.</li>
<li>Avoid duplicate reward notifications.  Again, the top item should manage this.</li>
<li>Retailer campaign management.</li>
<li>Expiring rewards by date at client.</li>
<li>Expiring/deletion rewards after redemption at client.</li>
</ul>
<p>In <a href="http://blog.brianbuikema.com/2010/08/android-development-part-3-using-googles-places-api-to-develop-compelling-location-based-mobile-applications/" target="_blank">Part 3</a> we will start tackling the code for our location-based mobile application.  See you in <a href="http://blog.brianbuikema.com/2010/08/android-development-part-3-using-googles-places-api-to-develop-compelling-location-based-mobile-applications/" target="_blank">Part 3</a>.</p>
]]></content:encoded>
			<wfw:commentRss>http://blog.brianbuikema.com/2010/08/android-development-part-2-using-googles-places-api-to-develop-compelling-location-based-mobile-applications/feed/</wfw:commentRss>
		<slash:comments>3</slash:comments>
		</item>
		<item>
		<title>Android Development &#8211; Part 1:  Using Google&#8217;s Places API to Develop Compelling Location Based Mobile Applications</title>
		<link>http://blog.brianbuikema.com/2010/08/android-development-part-1-using-googles-places-api-to-develop-compelling-location-based-mobile-applications/</link>
		<comments>http://blog.brianbuikema.com/2010/08/android-development-part-1-using-googles-places-api-to-develop-compelling-location-based-mobile-applications/#comments</comments>
		<pubDate>Sat, 14 Aug 2010 01:00:51 +0000</pubDate>
		<dc:creator>Brian Buikema</dc:creator>
				<category><![CDATA[Android]]></category>
		<category><![CDATA[Enterprise]]></category>
		<category><![CDATA[Java]]></category>
		<category><![CDATA[Location-Based]]></category>
		<category><![CDATA[Mobile]]></category>
		<category><![CDATA[Proximity Alerts]]></category>
		<category><![CDATA[Technology]]></category>

		<guid isPermaLink="false">http://blog.brianbuikema.com/?p=1088</guid>
		<description><![CDATA[Google released its Places API last month (July 2010) and this is exciting news for developers. Why? Because, as developers, we have access to an extremely important database of information, allowing us to develop compelling mobile applications that publish a mobile user&#8217;s location, and provide information on places that are in proximity to that location. [...]]]></description>
			<content:encoded><![CDATA[<p>Google released its <a href="http://code.google.com/apis/maps/documentation/places/" target="_blank">Places API</a> last month (July 2010) and this is exciting news for developers.  Why?  Because, as developers, we have access to an extremely important database of information, allowing us to develop compelling mobile applications that publish a mobile user&#8217;s location, and provide information on places that are in proximity to that location.</p>
<p>This will open up innovative thinking for businesses trying to attract more customers, and enhance the services of existing customers.</p>
<p>As developers, we have a great opportunity to move mobile application development from cheap Soundboard applications, to powerful, business savvy applications capable of legitimizing mobile&#8217;s presence as a significant business contributor.</p>
<p>I plan to discuss all details required for you to get started developing these truly innovative mobile applications on the Android platform.</p>
<p>And as a bonus, I will discuss the difference between <a href="http://blog.brianbuikema.com/2010/07/part-1-developing-proximity-alerts-for-mobile-applications-using-the-android-platform/" target="_blank">Proximity Alert</a> and Location-based Mobile Applications, and how the two can be combined to create an even higher level of innovation.  We will discuss these details in the last part.</p>
<p>Let&#8217;s get started with Part 1 to identify the items we need to complete before we can develop using the Places API.  If you&#8217;re wondering if it&#8217;s more involved than the other API&#8217;s.  You&#8217;re right.  It is!</p>
<h2>Requirements for Using Google&#8217;s Places API</h2>
<p>The easy answer is that you need to fill out a <a href="http://gmaps-ws-console.appspot.com/" target="_blank">registration form</a>.  However, you will notice that an <strong><em>Adsense publisher id</em></strong> is required, and you may not have this.  Don&#8217;t fret.  You can fill out the application <a href="https://www.google.com/adsense/g-app-single-1" target="_blank">here</a> to obtain your Adsense account.  It may take several days to get approved, so be patient.  <img src='http://blog.brianbuikema.com/wp-includes/images/smilies/icon_wink.gif' alt=';)' class='wp-smiley' /> </p>
<p>BTW, Once you have your Adsense account, you can register to use Google&#8217;s Places API by filling out this <a href="http://gmaps-ws-console.appspot.com/" target="_blank">registration form</a>.<a href="http://code.google.com/apis/maps/documentation/places/" target="_blank"><br />
</a></p>
<p>Additionally, say you want to track your Adsense performance using <a href="https://www.google.com/adsense/support/bin/answer.py?hl=en&amp;answer=13993" target="_blank">URL Channels</a>.  The aforementioned link will provide all the information you need.</p>
<h3>Required:  Google Map API Key</h3>
<p>In order to use <a href="http://code.google.com/apis/maps/documentation/places/" target="_blank">Google&#8217;s Places API</a>, you will need to register and obtain a <a href="http://code.google.com/apis/maps/documentation/webservices/index.html#URLSigning" target="_blank">Google Map&#8217;s API Key</a>.  I created a post detailing exactly how to do this <a href="http://blog.brianbuikema.com/2010/06/obtaining-a-google-maps-api-key/" target="_blank">found here</a>.</p>
<h3>Getting Familiar with <em>URL Authentication</em></h3>
<p>Requests to certain Maps API web services now require <em>digital signatures</em> using a cryptographic key.  In fact, <strong><em>all Places API service requests</em></strong> require URL Authentication.  <a href="http://code.google.com/apis/maps/documentation/webservices/index.html#URLSigning" target="_blank">Click here to learn more</a>.</p>
<h3>Getting Familiar with <em>Place Searches</em> and <em>Place Details</em></h3>
<p>Per Google, and I quote</p>
<blockquote><p>The Google Places API is a service that returns information about a &#8220;place&#8221; (hereafter referred to as a Place) — defined within this API as an establishment, a geographic location, or prominent point of interest — using an HTTP request. Place requests  specify locations as latitude/longitude coordinates.</p>
<p>Two basic Place requests are available: a <a href="http://code.google.com/apis/maps/documentation/places/#PlaceSearches" target="_blank"><em>Place Search request</em></a> and a <a href="http://code.google.com/apis/maps/documentation/places/#PlaceDetails" target="_blank"><em>Place Details request</em></a>. Generally, a Place Search request is used to return candidate matches, while a Place Details request returns more specific information about a Place.</p>
<p>This service is designed for processing place requests generated by a user for placement of application content on a map; this service is <strong>not</strong> designed to respond to batch of offline queries, which are a violation of its terms of use.</p></blockquote>
<p>As a developer, keep in mind that you usually first obtain a list of places that satisfy your filter, and allow a user drill-down into the details of a specific <em>place</em>.  Thus the existence of the two API&#8217;s.</p>
<h3>Getting Familiar Calling the Places API</h3>
<p>In general, calls to the Places API are made as follows.  This is an example of a call to the <em><strong>Place Search Service</strong></em>, and the <em>client Id</em> and <em>signature</em> are intentionally supplied as invalid:</p>
<pre class="brush: plain; light: true; title: ; notranslate">
// JSON:  http://maps.google.com/maps/api/place/search/json?location=40.717859,-73.9577937&amp;radius=1600&amp;client=clientId&amp;sensor=true_or_false&amp;signature=SIGNATURE

// XML:  http://maps.google.com/maps/api/place/search/xml?location=40.717859,-73.9577937&amp;radius=1600&amp;client=clientId&amp;sensor=true_or_false&amp;signature=SIGNATURE
</pre>
<p>This is asking for places for about a mile around Williamsburg, Brooklyn.</p>
<p>And you can expect a response formatted in JSON as follows:</p>
<pre class="brush: xml; title: ; notranslate">
{
 &quot;status&quot;: &quot;OK&quot;,
 &quot;results&quot;: [ {
 &quot;name&quot;: &quot;Williamsburg&quot;,
 &quot;types&quot;: [ &quot;locality&quot;, &quot;political&quot; ],
 &quot;icon&quot;: &quot;http://maps.gstatic.com/mapfiles/place_api/icons/geocode-71.png&quot;,
 &quot;reference&quot;: &quot;ClRBAAAAXP...lHAPyHom2aG&quot;
 }, {
 &quot;name&quot;: &quot;Greenpoint&quot;,
 &quot;vicinity&quot;: &quot;New York&quot;,
 &quot;types&quot;: [ &quot;neighborhood&quot;, &quot;political&quot; ],
 &quot;icon&quot;: &quot;http://maps.gstatic.com/mapfiles/place_api/icons/geocode-71.png&quot;,
 &quot;reference&quot;: &quot;CkQ_AAAAhd...MF45fwr44Ek&quot;
 }, {
 &quot;name&quot;: &quot;Peter Luger Steakhouse&quot;,
 &quot;vicinity&quot;: &quot;Broadway, Brooklyn&quot;,
 &quot;types&quot;: [ &quot;restaurant&quot;, &quot;food&quot;, &quot;establishment&quot; ],
 &quot;icon&quot;: &quot;http://maps.gstatic.com/mapfiles/place_api/icons/restaurant-71.png&quot;,
 &quot;reference&quot;: &quot;ClRCAAAAt3...6Nt7k11iQdT&quot;
 }, {
 &quot;name&quot;: &quot;Music Hall of Williamsburg&quot;,
 &quot;vicinity&quot;: &quot;North 6th Street, Brooklyn&quot;,
 &quot;types&quot;: [ &quot;establishment&quot; ],
 &quot;icon&quot;: &quot;http://maps.gstatic.com/mapfiles/place_api/icons/generic_business-71.png&quot;,
 &quot;reference&quot;: &quot;ClRFAAAAN...6UOKCbjv7Sxy&quot;
 },
 ...additional results ...
 ],
 &quot;html_attributions&quot;: [ ]
}
</pre>
<p>Or in XML as follows:</p>
<pre class="brush: xml; title: ; notranslate">
&lt;PlaceSearchResponse&gt;
 &lt;status&gt;OK&lt;/status&gt;
 &lt;result&gt;
   &lt;name&gt;Williamsburg&lt;/name&gt;
   &lt;type&gt;locality&lt;/type&gt;
   &lt;type&gt;political&lt;/type&gt;
   &lt;icon&gt;http://maps.gstatic.com/mapfiles/place_api/icons/geocode-71.png&lt;/icon&gt;
   &lt;reference&gt;CkRAAAAAUhZG...Yy0b4-sd1zCUu9P8&lt;/reference&gt;
 &lt;/result&gt;
 &lt;result&gt;
   &lt;name&gt;Greenpoint&lt;/name&gt;
   &lt;vicinity&gt;New York&lt;/vicinity&gt;
   &lt;type&gt;neighborhood&lt;/type&gt;
   &lt;type&gt;political&lt;/type&gt;
   &lt;icon&gt;http://maps.gstatic.com/mapfiles/place_api/icons/geocode-71.png&lt;/icon&gt;
   &lt;reference&gt;CkQ-AAAAHIDo...nYmSR8l52FmkMH6c&lt;/reference&gt;
   &lt;name&gt;Peter Luger Steakhouse&lt;/name&gt;
   &lt;vicinity&gt;Broadway, Brooklyn&lt;/vicinity&gt;
   &lt;type&gt;restaurant&lt;/type&gt;
   &lt;type&gt;food&lt;/type&gt;
   &lt;type&gt;establishment&lt;/type&gt;
   &lt;icon&gt;http://maps.gstatic.com/mapfiles/place_api/icons/restaurant-71.png&lt;/icon&gt;
   &lt;reference&gt;ClRBAAAATIpR...mHSxoyiRcr_FVuww&lt;/reference&gt;
 &lt;/result&gt;
 ...additional results...
&lt;/PlaceSearchResponse&gt;
</pre>
<p>In order to make a valid call, you are required to encrypt your URL with your private key and attach result as your signature.  Note that the call above excluded a valid client Id and signature.  In java, for example, you can create your signature as follows:</p>
<pre class="brush: java; title: ; notranslate">
import java.io.IOException;
import java.io.UnsupportedEncodingException;
import java.net.URI;
import java.net.URISyntaxException;
import java.security.InvalidKeyException;
import java.security.NoSuchAlgorithmException;
import javax.crypto.Mac;
import javax.crypto.spec.SecretKeySpec;
import java.net.URL;
import java.io.BufferedReader;
import java.io.InputStreamReader;

public class UrlSigner {

 // Note: Generally, you should store your private key someplace safe
 // and read them into your code

 private static String keyString = &quot;YOUR_PRIVATE_KEY&quot;;

 // The URL shown in these examples is a static URL which should already
 // be URL-encoded. In practice, you will likely have code
 // which assembles your URL from user or web service input
 // and plugs those values into its parameters.
 private static String urlString = &quot;YOUR_URL_TO_SIGN&quot;;

 // This variable stores the binary key, which is computed from the string (Base64) key
 private static byte[] key;

 public static void main(String[] args) throws IOException,
 InvalidKeyException, NoSuchAlgorithmException, URISyntaxException {

   BufferedReader input = new BufferedReader(new InputStreamReader(System.in));

   String inputUrl, inputKey = null;

   // For testing purposes, allow user input for the URL.
   // If no input is entered, use the static URL defined above.
   System.out.println(&quot;Enter the URL (must be URL-encoded) to sign: &quot;);
   inputUrl = input.readLine();
   if (inputUrl.equals(&quot;&quot;)) {
     inputUrl = urlString;
   }

   // Convert the string to a URL so we can parse it
   URL url = new URL(inputUrl);

   // For testing purposes, allow user input for the private key.
   // If no input is entered, use the static key defined above.
   System.out.println(&quot;Enter the Private key to sign the URL: &quot;);
   inputKey = input.readLine();
   if (inputKey.equals(&quot;&quot;)) {
     inputKey = keyString;
   }

   UrlSigner signer = new UrlSigner(inputKey);
   String request = signer.signRequest(url.getPath(),url.getQuery());

   System.out.println(&quot;Signed URL :&quot; + url.getProtocol() + &quot;://&quot; + url.getHost() + request);
 }

 public UrlSigner(String keyString) throws IOException {
   // Convert the key from 'web safe' base 64 to binary
   keyString = keyString.replace('-', '+');
   keyString = keyString.replace('_', '/');
   System.out.println(&quot;Key: &quot; + keyString);
   this.key = Base64.decode(keyString);
 }

 public String signRequest(String path, String query) throws NoSuchAlgorithmException,
 InvalidKeyException, UnsupportedEncodingException, URISyntaxException {

   // Retrieve the proper URL components to sign
   String resource = path + '?' + query;

   // Get an HMAC-SHA1 signing key from the raw key bytes
   SecretKeySpec sha1Key = new SecretKeySpec(key, &quot;HmacSHA1&quot;);

   // Get an HMAC-SHA1 Mac instance and initialize it with the HMAC-SHA1 key
   Mac mac = Mac.getInstance(&quot;HmacSHA1&quot;);
   mac.init(sha1Key);

   // compute the binary signature for the request
   byte[] sigBytes = mac.doFinal(resource.getBytes());

   // base 64 encode the binary signature
   String signature = Base64.encodeBytes(sigBytes);

   // convert the signature to 'web safe' base 64
   signature = signature.replace('+', '-');
   signature = signature.replace('/', '_');

   return resource + &quot;&amp;signature=&quot; + signature;
 }
}
</pre>
<p>Given that you have your client Id, you should now be able to sign your request.</p>
<h2>Next&#8230;</h2>
<p>In <a href="http://blog.brianbuikema.com/2010/08/android-development-part-2-using-googles-places-api-to-develop-compelling-location-based-mobile-applications/" target="_blank">Part 2</a>, to keep things interesting and informing, we will discuss how to develop a mobile application, targeting the core features of this post.  We will create some fun <em>location-based</em> requirements and flush out the design details.</p>
<p>See you next time!</p>
]]></content:encoded>
			<wfw:commentRss>http://blog.brianbuikema.com/2010/08/android-development-part-1-using-googles-places-api-to-develop-compelling-location-based-mobile-applications/feed/</wfw:commentRss>
		<slash:comments>4</slash:comments>
		</item>
		<item>
		<title>Part 4 – Developing Proximity Alerts for Mobile Applications using the Android Platform</title>
		<link>http://blog.brianbuikema.com/2010/07/part-4-developing-proximity-alerts-for-mobile-applications-using-the-android-platform/</link>
		<comments>http://blog.brianbuikema.com/2010/07/part-4-developing-proximity-alerts-for-mobile-applications-using-the-android-platform/#comments</comments>
		<pubDate>Fri, 23 Jul 2010 05:46:31 +0000</pubDate>
		<dc:creator>Brian Buikema</dc:creator>
				<category><![CDATA[Android]]></category>
		<category><![CDATA[Architecture & Design]]></category>
		<category><![CDATA[Java]]></category>
		<category><![CDATA[Location-Based]]></category>
		<category><![CDATA[Mobile]]></category>
		<category><![CDATA[Proximity Alerts]]></category>
		<category><![CDATA[Technology]]></category>
		<category><![CDATA[Uncategorized]]></category>
		<category><![CDATA[architecture]]></category>

		<guid isPermaLink="false">http://blog.brianbuikema.com/?p=1040</guid>
		<description><![CDATA[I&#8217;ve decided to add this fourth part to discuss making some beneficial enhancements to the Proximity Alerts Mobile Application we developed in the earlier posts (Part 1, Part 2, and Part 3).  Our goal in Parts 1- 3 was to create an Android-based mobile application that demonstrated some basic proximity alert functionality.  And we successfully [...]]]></description>
			<content:encoded><![CDATA[<p>I&#8217;ve decided to add this fourth part to discuss making some beneficial enhancements to the <em>Proximity Alerts Mobile Application</em> we developed in the earlier posts (<a href="http://blog.brianbuikema.com/2010/07/part-1-developing-proximity-alerts-for-mobile-applications-using-the-android-platform/" target="_blank">Part 1</a>, <a href="http://blog.brianbuikema.com/2010/07/part-2-developing-proximity-alerts-for-mobile-applications-using-the-android-platform/" target="_blank">Part 2</a>, and <a href="http://blog.brianbuikema.com/2010/07/part-3-developing-proximity-alerts-for-mobile-applications-using-the-android-platform/" target="_blank">Part 3</a>).  Our goal in Parts 1- 3 was to create an Android-based mobile application that demonstrated some basic proximity alert functionality.  And we successfully completed this, but our method of processing proximity alerts was in the foreground, the method of alerting the user was somewhat crude, e.g., vibrate phone and display toast, and the alerts were automatically enabled with no way for the user to control alert enable/disabling.</p>
<h2>Enhancements</h2>
<p>Therefore, we will implement three major enhancements in this post as follows:</p>
<ul>
<li>Process proximity alerts in the background by moving processing to an Android <a href="http://developer.android.com/reference/android/app/Service.html" target="_blank"><em>Service</em></a>.  We will call our service <em>PromityAlertService</em>.</li>
<li>We will use Android&#8217;s built-in <a href="http://developer.android.com/reference/android/app/NotificationManager.html" target="_blank"><em>NotificationManager </em></a>to provide <em>true </em>Android notifications that appear and can be controlled within the status bar.</li>
<li>And we will provide a <em>checkbox </em>in the <em>ProximityAlertSetActivity </em>screen allowing the user to enable/disable alerts anytime.  We will default to <strong>disabled </strong>to ensure that an alert is not fired immediately (since you are standing in the actual proximity of the alert when creating/editing the alert!).</li>
</ul>
<h2>Moving Proximity Alert Detection Processing to the Background by Creating an Android Service</h2>
<p>More coming soon!</p>
<h2>Enhancing Proximity Alert Notifications</h2>
<p>When we add or save a proximity alert, we add the alert to the <a href="http://developer.android.com/reference/android/location/LocationManager.html" target="_blank">LocationManager </a>via our AlertHelper class.  Note:  I have renamed the <em>addProximityAlerts</em>(&#8230;) method we used previously, to <em>addProximityAlertsToLocationManager</em>(&#8230;) to be more precise.  It is within this method that we add a PendingIntent that will perform a broadcast to our <em>ProximityIntentReceiver </em>(you may recall we created the ProximityIntentReceiver in a previous post).</p>
<p>The ProximityAlertHelper&#8217;s addProximityAlertsToLocationManager(&#8230;) method is as follows:</p>
<pre class="brush: java; highlight: [13]; title: ; notranslate">
public boolean addProximityAlertsToLocationManager(Context caller, ArrayList&lt;ProximityAlert&gt; alerts) {
  if (initialized) {
    String context = Context.LOCATION_SERVICE;
    LocationManager mgr = ((LocationManager) caller.getSystemService(context));

    removeAlerts(caller);

    for (int i=1; i &lt;alerts.size(); i++) {
      ProximityAlert alert = alerts.get(i);

      if (alert.Enabled) {
        Intent intent = new Intent(ProximityAlertActivity.class.getName());
        intent.putExtra(&quot;id&quot;, alert.Id);
        PendingIntent proximityIntent = PendingIntent.getBroadcast(caller, i, intent, PendingIntent.FLAG_CANCEL_CURRENT);
        float proxRadius = Float.parseFloat(PreferenceManager.getDefaultSharedPreferences(caller).getString(&quot;proxradius&quot;, &quot;2&quot;));
        mgr.addProximityAlert(alert.Lat, alert.Lng, proxRadius, -1, proximityIntent);
        proximityIntentsMap.put(alert, proximityIntent);
      }
    }
    return true;
  }

  return false;
}
</pre>
<p>Note that we add the alert&#8217;s <strong>id </strong>field to the intent in line 13.  We will use this later to retrieve the alert object upon processing a proximity alert notification event.</p>
<p>Let&#8217;s focus our attention on <em>ProximityIntentReceiver </em>class and discuss one addition to the <em>onReceive</em>(&#8230;) method.  We make our notification request to the NotificationManager here, on line 14, as follows:</p>
<pre class="brush: java; highlight: [10,14]; title: ; notranslate">
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 = ProximityAlertHelper.getInstance().getAlert(intent.getExtras().getLong(&quot;id&quot;));

        ArrayList&lt;ProximityAlert&gt; alerts = new ArrayList&lt;ProximityAlert&gt;();
        alerts.add(alert);
        NotifierHelper.sendNotification(context, ProximityAlertActivity.class, alerts);
      }
      catch (Exception ex) {
        Log.e(AppSettings.DEBUG_TAG, &quot;General failure in ProximityIntentReceiver&quot;, ex);
        throw;
      }
    }
  }
}
</pre>
<p>Note, in line 10 the actual event&#8217;s alert object is retrieved using the <strong>id </strong>field we earlier stored in the intent.</p>
<p>And finally, I have created a helper class called <em>NotifierHelper </em>to handle the heavy lifting of adding a notification to the <a href="http://developer.android.com/reference/android/app/NotificationManager.html" target="_blank">NoticationManager </a>as follows:</p>
<pre class="brush: java; title: ; notranslate">
public class NotifierHelper implements IDebugSwitch {
  private static final int NOTIFY_1 = 0x1001;

  public static void sendNotification(Context context, Class&lt;?&gt; activityToLaunch, ArrayList&lt;ProximityAlert&gt; alerts) {
    // String values should be stored in &quot;strings.xml&quot;
    // I show them here for convenience.

    NotificationManager notifier = (NotificationManager) context.getSystemService(Context.NOTIFICATION_SERVICE);

    // Create this outside the button so we can increment the number drawn over the notification icon,
    // indicating the number of alerts for this event.
    final Notification notify = new Notification(R.drawable.android_32, &quot;&quot;, System.currentTimeMillis());

    // Add status bar notification
    notify.icon = R.drawable.android_32;
    notify.tickerText = &quot;Proximo has new Proximity Alerts!&quot;;
    notify.when = System.currentTimeMillis();
    notify.number = alerts.size();
    notify.flags |= Notification.FLAG_AUTO_CANCEL;

    // Add lights
    notify.flags |= Notification.FLAG_SHOW_LIGHTS;
    notify.ledARGB = Color.WHITE;
    notify.ledOnMS = 500;
    notify.ledOffMS = 500;

// Add vibs
    notify.vibrate = new long[] {100, 200, 200, 200, 200, 200, 1000, 200, 200, 200, 1000, 200};

    Intent toLaunch = new Intent(context, activityToLaunch);
    toLaunch.putExtra(&quot;id&quot;, alerts.get(0).Id);
    PendingIntent intentBack = PendingIntent.getActivity(context, 0, toLaunch, 0);

    notify.setLatestEventInfo(context, &quot;Proximity Alerts&quot;, &quot;You have &quot; + alerts.size() + &quot; proximity alerts!&quot;, intentBack);
    notifier.notify(NOTIFY_1, notify);
  }

  public static void clear(Activity caller) {
    NotificationManager notifier = (NotificationManager) caller.getSystemService(Context.NOTIFICATION_SERVICE);
    notifier.cancelAll();
  }
}
</pre>
<h2>Providing the Ability to Enable and Disable Proximity Alerts</h2>
<p>Enabling and disabling proximity alerts is a fundamental feature that must not be overlooked.  Let&#8217;s first update the ProximityAlert entity to define an <em>Enabled </em>field.  The updates to the class are as follows:</p>
<pre class="brush: java; highlight: [13,16,25,29,47,73]; title: ; notranslate">
public class ProximityAlert extends BaseEntity&lt;ProximityAlert&gt; {
  private static long nextId = 0;
  public long Id = -1;
  public double Lat = 0;
  public double Lng = 0;
  public String Name = &quot;&quot;;
  public String Desc = &quot;&quot;;
  public String Expiration = &quot;&quot;;
  public int Month = -1;
  public int DayOfMonth = -1;
  public int Year = -1;
  public ArrayList&lt;String&gt; Items = new ArrayList&lt;String&gt;();
  public boolean Enabled = false;
  public boolean IsNew = true;

  public ProximityAlert(long id, double lat, double lng, String name, String desc, int month, int dayOfMonth, int year, boolean enabled) {
    this.Lat = lat;
    this.Lng = lng;
    this.Id = id;
    this.Name = name;
    this.Desc = desc;
    this.Month = month;
    this.DayOfMonth = dayOfMonth;
    this.Year = year;
    this.Enabled = enabled;
  }

  public ProximityAlert(double lat, double lng, String name, String desc, int month, int dayOfMonth, int year, boolean enabled) {
    this(nextId++, lat, lng, name,  desc, month, dayOfMonth, year, enabled);
  }

  public ProximityAlert(long id, String name, String desc) {
    this(id, 0.0, 0.0, name, desc, Calendar.getInstance().get(Calendar.MONTH), Calendar.getInstance().get(Calendar.DAY_OF_MONTH), Calendar.getInstance().get(Calendar.YEAR), false);
  }

  public JSONObject serializeToObj() {
    JSONObject serializedObj = new JSONObject();
    try {
      serializedObj.put(&quot;Id&quot;, this.Id);
      serializedObj.put(&quot;Lat&quot;, this.Lat);
      serializedObj.put(&quot;Lng&quot;, this.Lng);
      serializedObj.put(&quot;Name&quot;, this.Name);
      serializedObj.put(&quot;Desc&quot;, this.Desc);
      serializedObj.put(&quot;Month&quot;, this.Month);
      serializedObj.put(&quot;DayOfMonth&quot;, this.DayOfMonth);
      serializedObj.put(&quot;Year&quot;, this.Year);
      serializedObj.put(&quot;Enabled&quot;, this.Enabled);

      ArrayList&lt;JSONObject&gt; itemObjs = new ArrayList&lt;JSONObject&gt;();
      for (String item:this.Items) {
        JSONObject serializedItemObj = new JSONObject();
        serializedItemObj.put(&quot;Item&quot;, item);
        itemObjs.add(serializedItemObj);
      }
      serializedObj.put(&quot;Items&quot;, new JSONArray(itemObjs));
    }
    catch(Exception ex) {
      if (debug) Log.e(AppSettings.DEBUG_TAG, ex.getMessage(), ex);
    }

    return serializedObj;
  }

  public ProximityAlert deserializeFromObj(JSONObject obj) throws JSONException {
    this.Id = obj.getLong(&quot;Id&quot;);
    this.Lat = obj.getDouble(&quot;Lat&quot;);
    this.Lng = obj.getDouble(&quot;Lng&quot;);
    this.Name = obj.getString(&quot;Name&quot;);
    this.Desc = obj.getString(&quot;Desc&quot;);
    this.Month = obj.getInt(&quot;Month&quot;);
    this.DayOfMonth = obj.getInt(&quot;DayOfMonth&quot;);
    this.Year = obj.getInt(&quot;Year&quot;);
    this.Enabled = obj.getBoolean(&quot;Enabled&quot;);

    if (obj.has(&quot;Items&quot;)) {
      JSONArray jsonObjs = obj.getJSONArray(&quot;Items&quot;);
      this.Items = new ArrayList&lt;String&gt;(jsonObjs.length());
      for (int i=0; i&lt;jsonObjs.length(); i++) {
        JSONObject itemObj = jsonObjs.getJSONObject(i);
        this.Items.add(itemObj.getString(&quot;Item&quot;));
      }
    }

    return this;
  }
}
</pre>
<p>The <strong>highlighted</strong> lines above represent the changes required to support the <em>Enabled </em>field.</p>
<p>Now we take a look at how the <em>Enabled </em>field is used within the ProximityAlertHelper&#8217;s <em>addProximityAlertsToLocationManager</em>(&#8230;) method.  Line 9 below now requires that the alert be <em>enabled </em>before adding it to the LocationManager.</p>
<pre class="brush: java; highlight: [11]; title: ; notranslate">
public boolean addProximityAlertsToLocationManager(Context caller, ArrayList&lt;ProximityAlert&gt; alerts) {
  if (initialized) {
    String context = Context.LOCATION_SERVICE;
    LocationManager mgr = ((LocationManager) caller.getSystemService(context));

    removeAlerts(caller);

    for (int i=1; i &lt;alerts.size(); i++) {
      ProximityAlert alert = alerts.get(i);

      if (alert.Enabled) {
        Intent intent = new Intent(ProximityAlertActivity.class.getName());
        intent.putExtra(&quot;id&quot;, alert.Id);
        PendingIntent proximityIntent = PendingIntent.getBroadcast(caller, i, intent, PendingIntent.FLAG_CANCEL_CURRENT);
        float proxRadius = Float.parseFloat(PreferenceManager.getDefaultSharedPreferences(caller).getString(&quot;proxradius&quot;, &quot;2&quot;));
        mgr.addProximityAlert(alert.Lat, alert.Lng, proxRadius, -1, proximityIntent);
        proximityIntentsMap.put(alert, proximityIntent);
      }
    }
    return true;
  }

  return false;
}
</pre>
<p>And lastly, let&#8217;s see the actual <em>enabled </em>field within the <em>ProximityAlertSetActivity </em>screen.</p>
<div id="attachment_1058" class="wp-caption aligncenter" style="width: 335px"><a href="http://blog.brianbuikema.com/wp-content/uploads/2010/07/AdditionOfEnabledField.jpg"><img class="size-full wp-image-1058" title="Addition of Enabled Field into ProximityAlertSetActivity Screen" src="http://blog.brianbuikema.com/wp-content/uploads/2010/07/AdditionOfEnabledField.jpg" alt="Addition of Enabled Field into ProximityAlertSetActivity Screen" width="325" height="431" /></a><p class="wp-caption-text">Addition of Enabled Field into ProximityAlertSetActivity Screen</p></div>
<p>Note that the details of integrating the enabled field into the application are straightforward, and begin as follows:</p>
<pre class="brush: java; title: ; notranslate">
boolean enabled = ((CheckBox) findViewById(R.id.CheckBox_alert_enabled)).isChecked();
</pre>
<p>I hope this discussion of enhancements to the Proximity Alert Mobile Application helps extend your understanding of how to properly build proximity alert applications using the Android platform.</p>
<p>I look forward to discussing new mobile development concepts in my next post!  Please come back soon!</p>
]]></content:encoded>
			<wfw:commentRss>http://blog.brianbuikema.com/2010/07/part-4-developing-proximity-alerts-for-mobile-applications-using-the-android-platform/feed/</wfw:commentRss>
		<slash:comments>8</slash:comments>
		</item>
		<item>
		<title>Part 3 – Developing Proximity Alerts for Mobile Applications using the Android Platform</title>
		<link>http://blog.brianbuikema.com/2010/07/part-3-developing-proximity-alerts-for-mobile-applications-using-the-android-platform/</link>
		<comments>http://blog.brianbuikema.com/2010/07/part-3-developing-proximity-alerts-for-mobile-applications-using-the-android-platform/#comments</comments>
		<pubDate>Thu, 08 Jul 2010 03:18:33 +0000</pubDate>
		<dc:creator>Brian Buikema</dc:creator>
				<category><![CDATA[Android]]></category>
		<category><![CDATA[Architecture & Design]]></category>
		<category><![CDATA[Java]]></category>
		<category><![CDATA[Location-Based]]></category>
		<category><![CDATA[Mobile]]></category>
		<category><![CDATA[Proximity Alerts]]></category>
		<category><![CDATA[Technology]]></category>
		<category><![CDATA[design]]></category>

		<guid isPermaLink="false">http://blog.brianbuikema.com/?p=934</guid>
		<description><![CDATA[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, [...]]]></description>
			<content:encoded><![CDATA[<p>We continue with part 3 of our three-part series on our discussion of <em>Developing Proximity Alerts for Mobile Applications using the Android Platform.</em> Click appropriately for <a href="http://blog.brianbuikema.com/2010/07/part-1-developing-proximity-alerts-for-mobile-applications-using-the-android-platform/" target="_blank">Part 1</a> and <a href="http://blog.brianbuikema.com/2010/07/part-2-developing-proximity-alerts-for-mobile-applications-using-the-android-platform/" target="_blank">Part 2</a>.</p>
<p><em><strong>Bonus:</strong></em> I have just added <a href="http://blog.brianbuikema.com/2010/07/part-4-developing-proximity-alerts-for-mobile-applications-using-the-android-platform/" target="_blank">Part 4</a> to discuss important new enhancements to the <em>Proximity Alert Application!</em></p>
<h3>Capturing Proximity Alert Events</h3>
<p>For the record, capturing proximity alerts is a <em>fancy pants</em> way of saying &#8220;set up a proximity alert reminder&#8221;.  The process is similar, in thought, to setting up an event reminder within your favorite calendaring tool.</p>
<p>We will capture a proximity alert event by creating a custom <strong>BroadcastReceiver </strong>that receives events upon the triggering of an actual alert by the <strong>LocationManager Service</strong>.  In general, there are six steps necessary to capture proximity alerts as follows:</p>
<ol>
<li>Create a <strong>ProximityAlert </strong>object containing the fields of your proximity alert.  For example, name and description.</li>
<li>Create a <strong>BroadcastReceiver </strong>for receiving proximity alerts and override<em> onReceive(&#8230;)</em>.</li>
<li>Create a <strong>ProximityAlertActivity</strong>.</li>
<li>Register the <strong>BroadcastReceiver</strong> by associating it to your <strong>ProximityAlertActivity </strong>as an <em>IntentFilter</em>, and registering all<strong> </strong>to the application context.</li>
<li>Retrieve a <strong>PendingIntent </strong>from the broadcast associated to the registered <em>IntentFilter </em>of your ProximityAlertActivity.</li>
<li>Add a proximity alert to the <strong>LocationManager </strong>by associating your <em>ProximityAlert </em>object to the <em>PendingIntent</em>.</li>
</ol>
<p>Note, you handle the actual proximity alert event within your <em>BroadcastReceiver</em>&#8216;s <em>onReceive(&#8230;)</em> method.  For example, you may simply write a <em>Toast</em>, displaying a description of the proximity, or location, found within the <em>ProximityAlert </em>object located within the bundle supplied within onReceive(&#8230;)&#8217;s<em> intent </em>parameter.</p>
<h4>Details &#8211; Capturing Proximity Alert Events</h4>
<p>The first thing our application needs to do, is register a BroadcastReceiver by associating it to a ProximityAlertActivity (see 4 above).  Let&#8217;s look at the code that supports this BroadcastReceiver registration process.</p>
<pre class="brush: java; title: ; notranslate">
public class ProximityAlertHomeActivity extends ListActivity {
  private ArrayList&lt;ProximityAlert&gt; 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;
  }
}
</pre>
<p>Above, I show the call to ProximityAlertHelper.getInstance().initializeLocationManager(&#8230;) from the ProximityAlertHomeActivity&#8217;s onCreate(&#8230;) method.  This happens immediately at application startup.  Immediately afterwards, we see the ProximityAlertHelper.getInstance().initializeLocationManager(&#8230;) method that carries out the actual BroadcastReceiver registration.</p>
<p>Next, let&#8217;s look at the details involved in creating the BroadcastReceiver.  We implement our <strong>ProximityIntentReceiver </strong>class by inheriting from the <strong>BroadcastReceiver </strong>class as follows:</p>
<pre class="brush: java; highlight: [11,12,13]; title: ; notranslate">
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(&quot;current&quot;));
        Msg.ToastLong(context, &quot;entered &quot; + alert.Name);
        NotifierHelper.vibrate(context);
      } catch (JSONException ex) {
        ex.printStackTrace();
      }
    }
  }
}
</pre>
<p>Upon receiving an alert, we simply display a <em>toast</em> and <em>vibrate </em>the phone (lines 12 and 13).  Note that we retrieve the serialized <strong>AlertProximity </strong>object from the intent bundle, and deserialize it<em> </em>to an actual instance of <em>AlertProximity </em>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 <em>AlertProximity </em>class, see <a href="http://blog.brianbuikema.com/2010/07/part-2-developing-proximity-alerts-for-mobile-applications-using-the-android-platform/" target="_blank">Part 2</a>.</p>
<p>More coming soon!</p>
<h3>Setting Proximity Alert Preferences</h3>
<p>We will use Android&#8217;s PreferencesActivity class to manage our configuration settings.  We need to be able to configure the following preferences for our proximity alert mobile application:</p>
<ul>
<li>the minimum frequency to update location (to set a proximity alert),</li>
<li>the minimum distance to update location (to set a proximity alert), and</li>
<li>the proximity radius required to trigger a proximity alert</li>
</ul>
<p>Before discussing further, let&#8217;s take a quick look at the actual Proximity Alert Preferences Screen.</p>
<div id="attachment_960" class="wp-caption aligncenter" style="width: 342px"><a href="http://blog.brianbuikema.com/wp-content/uploads/2010/07/ProximityAlertPreferencesActivityScreen.jpg"><img class="size-full wp-image-960" title="ProximityAlertPreferencesActivityScreen" src="http://blog.brianbuikema.com/wp-content/uploads/2010/07/ProximityAlertPreferencesActivityScreen.jpg" alt="Proximity Alert Preferences Activity Screen" width="332" height="491" /></a><p class="wp-caption-text">Proximity Alert Preferences Activity Screen</p></div>
<p>Our <strong>ProximityAlertPreferencesActivity </strong>class provides the settings management we require.</p>
<pre class="brush: java; title: ; notranslate">
public class ProximityAlertPreferencesActivity extends PreferenceActivity implements IDebugSwitch {
  public ProximityAlertPreferencesActivity() {
  }

  @Override
  protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(null);
    addPreferencesFromResource(R.xml.settings);
  }
}
</pre>
<p>As you can see, all of the functionality is provided by Android&#8217;s <strong>PreferenceActivity</strong> base class.  We simply supply the resource file.  The following is the <em>settings.xml</em> resource file referenced by our <em>AlertProximityPreferencesActivity </em>class displayed above, and required to manage our proximity alert settings:</p>
<pre class="brush: xml; title: ; notranslate">
&lt;?xml version=&quot;1.0&quot; encoding=&quot;utf-8&quot;?&gt;
  &lt;PreferenceScreen xmlns:android=&quot;http://schemas.android.com/apk/res/android&quot;&gt;
    &lt;PreferenceCategory android:title=&quot;Location Update Frequency&quot; android:key=&quot;locupdate&quot;&gt;
      &lt;ListPreference
        android:title=&quot;Set Minimum Frequency&quot;
        android:summary=&quot;How often to update location&quot;
        android:key=&quot;mintimeinc&quot;
        android:defaultValue=&quot;2000&quot;
        android:entries=&quot;@array/minTimeIncs&quot;
        android:entryValues=&quot;@array/minTimeVals&quot; /&gt;
      &lt;ListPreference
        android:title=&quot;Set Minimum Distance&quot;
        android:summary=&quot;Minimum distance of movement necessary to update location&quot;
        android:key=&quot;mindistance&quot;
        android:defaultValue=&quot;2&quot;
        android:entries=&quot;@array/minDistance&quot;
        android:entryValues=&quot;@array/minDistanceVals&quot;
      /&gt;
    &lt;/PreferenceCategory&gt;
    &lt;PreferenceCategory android:title=&quot;Proximity Radius&quot; android:key=&quot;locupdatefreq&quot;&gt;
      &lt;ListPreference
        android:title=&quot;Set Proximity Radius&quot;
        android:summary=&quot;Proximity radius necessary to trigger alert&quot;
        android:key=&quot;proxradius&quot;
        android:defaultValue=&quot;2&quot;
        android:entries=&quot;@array/proxRadius&quot;
        android:entryValues=&quot;@array/proxRadiusVals&quot;
      /&gt;
    &lt;/PreferenceCategory&gt;
  &lt;/PreferenceScreen&gt;
</pre>
<p>And lastly, the following <em>settingvalues.xml</em> resource file contains the actual values required by the settings.xml resource file:</p>
<pre class="brush: xml; title: ; notranslate">
&lt;?xml version=&quot;1.0&quot; encoding=&quot;utf-8&quot;?&gt;
  &lt;resources&gt;
    &lt;string-array name=&quot;minTimeIncs&quot;&gt;
      &lt;item name=&quot;0&quot;&gt;0&lt;/item&gt;
      &lt;item name=&quot;1000&quot;&gt;Every 1 second&lt;/item&gt;
      &lt;item name=&quot;2000&quot;&gt;Every 2 seconds&lt;/item&gt;
      &lt;item name=&quot;5000&quot;&gt;Every 5 seconds&lt;/item&gt;
      &lt;item name=&quot;10000&quot;&gt;Every 10 seconds&lt;/item&gt;
      &lt;item name=&quot;30000&quot;&gt;Every 30 seconds&lt;/item&gt;
      &lt;item name=&quot;60000&quot;&gt;Every 1 minute&lt;/item&gt;
      &lt;item name=&quot;300000&quot;&gt;Every 5 minutes&lt;/item&gt;
      &lt;item name=&quot;1800000&quot;&gt;Every 30 minutes&lt;/item&gt;
    &lt;/string-array&gt;
    &lt;string-array name=&quot;minTimeVals&quot;&gt;
      &lt;item name=&quot;0&quot;&gt;0&lt;/item&gt;
      &lt;item name=&quot;1000&quot;&gt;1000&lt;/item&gt;
      &lt;item name=&quot;2000&quot;&gt;2000&lt;/item&gt;
      &lt;item name=&quot;5000&quot;&gt;5000&lt;/item&gt;
      &lt;item name=&quot;10000&quot;&gt;10000&lt;/item&gt;
      &lt;item name=&quot;30000&quot;&gt;30000&lt;/item&gt;
      &lt;item name=&quot;60000&quot;&gt;60000&lt;/item&gt;
      &lt;item name=&quot;300000&quot;&gt;300000&lt;/item&gt;
      &lt;item name=&quot;1800000&quot;&gt;1800000&lt;/item&gt;
    &lt;/string-array&gt;
    &lt;string-array name=&quot;minDistance&quot;&gt;
      &lt;item name=&quot;1&quot;&gt;1 meters&lt;/item&gt;
      &lt;item name=&quot;2&quot;&gt;2 meters&lt;/item&gt;
      &lt;item name=&quot;3&quot;&gt;3 meters&lt;/item&gt;
      &lt;item name=&quot;5&quot;&gt;5 meters&lt;/item&gt;
      &lt;item name=&quot;10&quot;&gt;10 meters&lt;/item&gt;
      &lt;item name=&quot;25&quot;&gt;25 meters&lt;/item&gt;
      &lt;item name=&quot;50&quot;&gt;50 meters&lt;/item&gt;
      &lt;item name=&quot;100&quot;&gt;100 meters&lt;/item&gt;
      &lt;item name=&quot;250&quot;&gt;250 meters&lt;/item&gt;
      &lt;item name=&quot;500&quot;&gt;500 meters&lt;/item&gt;
      &lt;item name=&quot;1000&quot;&gt;1000 meters&lt;/item&gt;
    &lt;/string-array&gt;
    &lt;string-array name=&quot;minDistanceVals&quot;&gt;
      &lt;item name=&quot;1&quot;&gt;1&lt;/item&gt;
      &lt;item name=&quot;2&quot;&gt;2&lt;/item&gt;
      &lt;item name=&quot;3&quot;&gt;3&lt;/item&gt;
      &lt;item name=&quot;5&quot;&gt;5&lt;/item&gt;
      &lt;item name=&quot;10&quot;&gt;10&lt;/item&gt;
      &lt;item name=&quot;25&quot;&gt;25&lt;/item&gt;
      &lt;item name=&quot;50&quot;&gt;50&lt;/item&gt;
      &lt;item name=&quot;100&quot;&gt;100&lt;/item&gt;
      &lt;item name=&quot;250&quot;&gt;250&lt;/item&gt;
      &lt;item name=&quot;500&quot;&gt;500&lt;/item&gt;
      &lt;item name=&quot;1000&quot;&gt;1000&lt;/item&gt;
    &lt;/string-array&gt;
    &lt;string-array name=&quot;proxRadius&quot;&gt;
      &lt;item name=&quot;1&quot;&gt;1 meters&lt;/item&gt;
      &lt;item name=&quot;2&quot;&gt;2 meters&lt;/item&gt;
      &lt;item name=&quot;3&quot;&gt;3 meters&lt;/item&gt;
      &lt;item name=&quot;5&quot;&gt;5 meters&lt;/item&gt;
      &lt;item name=&quot;10&quot;&gt;10 meters&lt;/item&gt;
      &lt;item name=&quot;25&quot;&gt;25 meters&lt;/item&gt;
      &lt;item name=&quot;50&quot;&gt;50 meters&lt;/item&gt;
      &lt;item name=&quot;100&quot;&gt;100 meters&lt;/item&gt;
      &lt;item name=&quot;250&quot;&gt;250 meters&lt;/item&gt;
      &lt;item name=&quot;500&quot;&gt;500 meters&lt;/item&gt;
      &lt;item name=&quot;1000&quot;&gt;1000 meters&lt;/item&gt;
    &lt;/string-array&gt;
    &lt;string-array name=&quot;proxRadiusVals&quot;&gt;
      &lt;item name=&quot;1&quot;&gt;1&lt;/item&gt;
      &lt;item name=&quot;2&quot;&gt;2&lt;/item&gt;
      &lt;item name=&quot;3&quot;&gt;3&lt;/item&gt;
      &lt;item name=&quot;5&quot;&gt;5&lt;/item&gt;
      &lt;item name=&quot;10&quot;&gt;10&lt;/item&gt;
      &lt;item name=&quot;25&quot;&gt;25&lt;/item&gt;
      &lt;item name=&quot;50&quot;&gt;50&lt;/item&gt;
      &lt;item name=&quot;100&quot;&gt;100&lt;/item&gt;
      &lt;item name=&quot;250&quot;&gt;250&lt;/item&gt;
      &lt;item name=&quot;500&quot;&gt;500&lt;/item&gt;
      &lt;item name=&quot;1000&quot;&gt;1000&lt;/item&gt;
    &lt;/string-array&gt;
  &lt;/resources&gt;
</pre>
<p>And that&#8217;s it!  I believe Google&#8217;s Android platform is paving the way for both <em>advancing mobile technologies</em> and <em>getting them quickly, and affordably, into consumers&#8217; hands</em>.</p>
<p>I hope this helps you design and create innovative, mobile-based Android applications.</p>
<p><em><strong>Bonus:</strong></em> Please see <a href="http://blog.brianbuikema.com/2010/07/part-4-developing-proximity-alerts-for-mobile-applications-using-the-android-platform/" target="_blank">Part 4</a> as I discuss important new enhancements to this <em>Proximity Alert Application!</em></p>
<p>This is Brian Buikema.  See you next time!</p>
]]></content:encoded>
			<wfw:commentRss>http://blog.brianbuikema.com/2010/07/part-3-developing-proximity-alerts-for-mobile-applications-using-the-android-platform/feed/</wfw:commentRss>
		<slash:comments>5</slash:comments>
		</item>
		<item>
		<title>Part 2 – Developing Proximity Alerts for Mobile Applications using the Android Platform</title>
		<link>http://blog.brianbuikema.com/2010/07/part-2-developing-proximity-alerts-for-mobile-applications-using-the-android-platform/</link>
		<comments>http://blog.brianbuikema.com/2010/07/part-2-developing-proximity-alerts-for-mobile-applications-using-the-android-platform/#comments</comments>
		<pubDate>Tue, 06 Jul 2010 06:02:20 +0000</pubDate>
		<dc:creator>Brian Buikema</dc:creator>
				<category><![CDATA[Android]]></category>
		<category><![CDATA[Architecture & Design]]></category>
		<category><![CDATA[Java]]></category>
		<category><![CDATA[Location-Based]]></category>
		<category><![CDATA[Mobile]]></category>
		<category><![CDATA[Proximity Alerts]]></category>
		<category><![CDATA[Technology]]></category>
		<category><![CDATA[design]]></category>

		<guid isPermaLink="false">http://blog.brianbuikema.com/?p=914</guid>
		<description><![CDATA[We continue our discussion from Part 1 of Developing Proximity Alerts for Mobile Applications using the Android Platform. In this last part of my two-part post, we create the Mobile Proximity Alert Application, implementing the actual design we discussed in Part 1. Now the fun begins! One Data Entity As far as data models go, [...]]]></description>
			<content:encoded><![CDATA[<p>We continue our discussion from <a href="http://blog.brianbuikema.com/2010/07/part-1-developing-proximity-alerts-for-mobile-applications-using-the-android-platform/" target="_blank">Part 1</a> of <em>Developing Proximity Alerts for Mobile Applications using the Android Platform. </em>In this last part of my two-part post,<em> </em>we create the Mobile Proximity Alert Application, implementing the actual design we discussed in Part 1.</p>
<p>Now the fun begins!</p>
<h3>One Data Entity</h3>
<p>As far as data models go, this one is simple.  One entity.  The <em>ProximityAlertEntity</em>.  As well as representing common DTO functionality, we will expand the <em>ProximityEntity </em>to include the repository functionality.  After all, this is a fairly simple application.  First, let&#8217;s look at the DTO functionality.  It includes both the fields representing our alert needs and the necessary JSON serialization/deserialization methods.</p>
<pre class="brush: java; title: ; notranslate">
public class ProximityAlertReminder extends BaseEntity {
  private static long nextId = 0;
  public long Id = -1;
  public double Lat = 0;
  public double Lng = 0;
  public String Name = &quot;&quot;;
  public String Desc = &quot;&quot;;
  public int Month = -1;
  public int DayOfMonth = -1;
  public int Year = -1;
  public ArrayList&lt;String&gt; Items = new ArrayList&lt;String&gt;();

  public ProximityAlertReminder(long id, double lat, double lng, String name, String desc, int month, int dayOfMonth, int year) {
    this.Lat = lat;
    this.Lng = lng;
    this.Id = id;
    this.Name = name;
    this.Desc = desc;
    this.Month = month;
    this.DayOfMonth = dayOfMonth;
    this.Year = year;
  }

  public ProximityAlertReminder(double lat, double lng, String name, String desc, int month, int dayOfMonth, int year) {
    this(nextId++, lat, lng, name,  desc, month, dayOfMonth, year);
  }

  public ProximityAlertReminder(long id, String name, String desc) {
    this(id, 0.0, 0.0, name, desc, Calendar.getInstance().get(Calendar.MONTH), Calendar.getInstance().get(Calendar.DAY_OF_MONTH), Calendar.getInstance().get(Calendar.YEAR));
  }

  public ProximityAlertReminder(JSONObject obj) throws JSONException {
    deserializeFromObj(obj);
  }

  public ProximityAlertReminder(String serializedObj) throws JSONException {
    deserialize(serializedObj);
  }

  public Object getId() {
    return this.Id;
  }

  public JSONObject serializeToObj() {
    JSONObject serializedObj = new JSONObject();
    try {
      serializedObj.put(&quot;Id&quot;, this.Id);
      serializedObj.put(&quot;Lat&quot;, this.Lat);
      serializedObj.put(&quot;Lng&quot;, this.Lng);
      serializedObj.put(&quot;Name&quot;, this.Name);
      serializedObj.put(&quot;Desc&quot;, this.Desc);
      serializedObj.put(&quot;Month&quot;, this.Month);
      serializedObj.put(&quot;DayOfMonth&quot;, this.DayOfMonth);
      serializedObj.put(&quot;Year&quot;, this.Year);

      ArrayList itemObjs = new ArrayList();
      for (String item:this.Items) {
        JSONObject serializedItemObj = new JSONObject();
        serializedItemObj.put(&quot;Item&quot;, item);
        itemObjs.add(serializedItemObj);
      }

      serializedObj.put(&quot;Items&quot;, new JSONArray(itemObjs));
    }
    catch(Exception ex) {
      if (debug) Log.e(AppSettings.DEBUG_TAG, ex.getMessage(), ex);
    }

    return serializedObj;
  }

  public AlertReminder deserializeFromObj(JSONObject obj) throws JSONException {
    this.Id = obj.getLong(&quot;Id&quot;);
    this.Lat = obj.getDouble(&quot;Lat&quot;);
    this.Lng = obj.getDouble(&quot;Lng&quot;);
    this.Name = obj.getString(&quot;Name&quot;);
    this.Desc = obj.getString(&quot;Desc&quot;);
    this.Month = obj.getInt(&quot;Month&quot;);
    this.DayOfMonth = obj.getInt(&quot;DayOfMonth&quot;);
    this.Year = obj.getInt(&quot;Year&quot;);

    if (obj.has(&quot;Items&quot;)) {
      JSONArray jsonObjs = obj.getJSONArray(&quot;Items&quot;);
      this.Items = new ArrayList(jsonObjs.length());
      for (int i=0; i
        JSONObject itemObj = jsonObjs.getJSONObject(i);
        this.Items.add(itemObj.getString(&quot;Item&quot;));
      }
    }

    return this;
  }
}
</pre>
<p>The ProximityAlertReminder repository functions are represented as <em>static</em> methods.  Note that we are writing using SharedPreferences and <em>not </em>the database for persistence.</p>
<pre class="brush: java; title: ; notranslate">
public class ProximityAlertReminder extends BaseEntity&lt;ProximityAlertReminder&gt; {
  public static ArrayList&lt;ProximityAlertReminder&gt; load(Context caller) {
    ArrayList&lt;ProximityAlertReminder&gt; reminders = new ArrayList&lt;ProximityAlertReminder&gt;();
    try {
      SharedPreferences settingsActivity = PreferenceManager.getDefaultSharedPreferences(caller);
      String serializedReminders = settingsActivity.getString(caller.getString(R.string.reminders), &quot;&quot;).trim();
      reminders = new ArrayList&lt;ProximityAlertReminder&gt;();

      if (serializedReminders.length() &gt; 0) {
        JSONArray jsonObjs = new JSONArray(serializedReminders);
        for (int i=0; i&lt;jsonObjs.length(); i++) {
          JSONObject itemObj = jsonObjs.getJSONObject(i);
          reminders.add(new ProximityAlertReminder(itemObj));
        }
      }

      if (reminders.size() == 0) {
        ProximityAlertReminder addReminder = new ProximityAlertReminder(-2, &quot;&lt;click to add new alert&gt;&quot;, &quot;Add&quot;;
        reminders.add(0, addReminder);
      }
    }
    catch (Exception ex) {
      Log.e(AppSettings.DEBUG_TAG, ex.getMessage(), ex);
    }

    return reminders;
  }

  public static ArrayList&lt;ProximityAlertReminder&gt; add(Context caller, ProximityAlertReminder reminder) {
    ArrayList&lt;ProximityAlertReminder&gt; reminders = load(caller);
    reminders.add(reminder);
    save(caller, reminders);

    return reminders;
  }

  public static boolean save(Context caller, ArrayList&lt;ProximityAlertReminder&gt; reminders) {
    boolean success = false;

    try {
      SharedPreferences.Editor prefEditor = PreferenceManager.getDefaultSharedPreferences(caller).edit();

      ArrayList&lt;JSONObject&gt; itemObjs = new ArrayList&lt;JSONObject&gt;(reminders.size());
      for (ProximityAlertReminder item:reminders) {
        JSONObject serializedItemObj = new JSONObject(item.serialize());
        itemObjs.add(serializedItemObj);
      }

      prefEditor.putString(caller.getString(R.string.reminders), new JSONArray(itemObjs).toString());
      prefEditor.commit();
      success = true;
    }
    catch (Exception ex) {
      Log.e(AppSettings.DEBUG_TAG, ex.getMessage(), ex);
      success = false;
    }

    return success;
  }

  public static boolean deleteAll(Context caller) {
    boolean success = false;

    try {
      SharedPreferences.Editor prefEditor = PreferenceManager.getDefaultSharedPreferences(caller).edit();
      prefEditor.putString(caller.getString(R.string.reminders), &quot;&quot;);

      prefEditor.commit();
      success = true;
    }
    catch (Exception ex) {
      Log.e(AppSettings.DEBUG_TAG, ex.getMessage(), ex);
      success = false;
    }

    return success;
  }
}
</pre>
<p>These represent the CRUD based methods used in common entity storage and retrieval.</p>
<h3>Setting Proximity Alerts</h3>
<p>Let&#8217;s discuss how we will actually set a proximity alert.  We will take the approach that we will <em>set </em>a proximity alert based on our current physical location.  First, we must have a user interface that allow us to display the list of current proximity alerts, and add new proximity alerts.  Our <strong><em>ProximityAlertHomeActivity </em></strong>view will encompass the former, and, from an action initiated at the home activity, the <strong><em>ProximityAlertSetActivity </em></strong>will provide the later, the actual create and edit alert functionality.  Additionally, the <strong><em>ProximityAlertHelper</em> </strong>class comprises the proximity alert <em>technical </em>functionality that makes this all work.</p>
<p>A screenshot of our <strong>ProximityAlertHomeActivity </strong>Screen is as follows:</p>
<div id="attachment_967" class="wp-caption aligncenter" style="width: 342px"><a href="http://blog.brianbuikema.com/wp-content/uploads/2010/07/ProximityAlertHomeActivityScreen1.jpg"><img class="size-full wp-image-967" title="Proximity Alert Home Activity Screen" src="http://blog.brianbuikema.com/wp-content/uploads/2010/07/ProximityAlertHomeActivityScreen1.jpg" alt="Proximity Alert Home Activity Screen" width="332" height="492" /></a><p class="wp-caption-text">Proximity Alert Home Activity Screen</p></div>
<p>The <strong>ProximityAlertHomeActivity </strong>class is as follows:</p>
<pre class="brush: java; title: ; notranslate">
public class ProximityAlertHomeActivity extends ListActivity {
  private ArrayList&lt;ProximityAlert&gt; 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 void onListItemClick(ListView parent, View v, int position, long id)
  {
    if (position == 0) {
      Intent intent = new Intent(this, ProximityAlertSetActivity.class);
      startActivityForResult(intent, 0);
      return;
    }

    editReminder(v, position);
  }

  // Creates the menu items
  public boolean onCreateOptionsMenu(android.view.Menu menu) {
    getMenuInflater().inflate(R.menu.home, menu);
    return true;
  }

  // Handles item selections
  public boolean onOptionsItemSelected(android.view.MenuItem item) {
    switch (item.getItemId()) {
      case R.id.home_menu_add:
        Intent intent = new Intent(this, ProximityAlertSetActivity.class);
        startActivityForResult(intent, 0);
        return true;
      case R.id.home_menu_delall:
        DialogHelper.getInstance().displayConfirmationDialog(this, this.dialogResultHandler, &quot;Confirmation&quot;, &quot;Would you like to delete all alerts now?&quot;);
        return true;
      case R.id.home_menu_settings:
        intent = new Intent(this, ProximityAlertPreferencesActivity.class);
        startActivityForResult(intent, 0);
        return true;
      case R.id.home_menu_about:
        showDialog(0);
        return true;
    }

    return false;
  }

  @Override
  public void finish() {
    ProximityAlertHelper.getInstance().closeLocationManager(this);
    super.finish();
  }

  @Override
  public void onBackPressed() {
    ProximityAlertHelper.getInstance().closeLocationManager(this);
    super.onBackPressed();
  }

  protected Handler dialogResultHandler = new Handler() {
    @Override
    public void handleMessage(Message msg) {
      if (Boolean.parseBoolean(msg.obj.toString())) {
        ProximityAlertHomeActivity.this.reminders.clear();
        ProximityAlertHelper.getInstance().removeAlerts(ProximityAlertHomeActivity.this);
        ProximityAlert.deleteAll(ProximityAlertHomeActivity.this);
        Msg.ToastShort(ProximityAlertHomeActivity.this, &quot;All Alerts Deleted&quot;);
        loadReminders();
      }
      else {
        Msg.ToastShort(ProximityAlertHomeActivity.this, &quot;Canceled&quot;);
      }
    }
  };

  @Override
  protected Dialog onCreateDialog(int id) {
    // we have only one - defaulted to 0
    return DialogHelper.getInstance().displayAboutDialog(this);
  }

  @Override
  protected void onResume() {
    super.onResume();
    loadReminders();
  }

  protected void loadReminders() {
    setListAdapter(new ArrayAdapter&lt;String&gt;(this, android.R.layout.simple_list_item_1, loadFormattedAlertReminders()));
    ProximityAlertHelper.getInstance().addProximityAlerts(this, this.reminders);
  }

  protected void editReminder(View v, int position) {
    Intent intent = new Intent(v.getContext(), ProximityAlertSetActivity.class);
    intent.putExtra(&quot;current&quot;, this.reminders.get(position).serialize());
    startActivityForResult(intent, 0);
  }

  protected ArrayList&lt;String&gt; loadFormattedAlertReminders()
  {
    this.reminders = ProximityAlert.load(this);
    ArrayList&lt;String&gt; formattedReminders = new ArrayList&lt;String&gt;();

    for (ProximityAlert reminder:this.reminders) {
      formattedReminders.add(reminder.Name);
    }

    return formattedReminders;
  }
}
</pre>
<p>Note that much of the technical work is done by the <em>ProximityAlertHelper </em>class.</p>
<p>Of particular interest, is the fact that within the <em>loadReminders(&#8230;)</em> method, we both</p>
<ul>
<li>load the proximity alerts from persistent storage (e.g., <em>SharedPreferences </em>in our case) AND</li>
<li>add them to the LocationManager</li>
</ul>
<p>via the <em>ProximityAlertHelper </em>class.</p>
<p>Also of interest, within the <em>onResume(&#8230;)</em> method, we call the <em>loadReminders(&#8230;)</em> method to reload our proximity alerts upon resume.</p>
<p>Lastly, within the <em>finish</em>(&#8230;) method, we call <em>AlertProximityHelper.getInstance(&#8230;).closeLocationManager(&#8230;)</em> to both</p>
<ul>
<li>remove the proximity alerts from the LocationManager AND</li>
<li>unregister our custom <em>BroadcastReceiver</em> called <strong><em>ProximityIntentReceiver</em> </strong>(more on this later).</li>
</ul>
<p>A screenshot of the <strong>ProximityAlertSetActivityScreen </strong>is as follows:</p>
<div id="attachment_968" class="wp-caption aligncenter" style="width: 341px"><a href="http://blog.brianbuikema.com/wp-content/uploads/2010/07/ProximityAlertSetActivityScreen1.jpg"><img class="size-full wp-image-968" title="Proximity Alert Set Activity Screen" src="http://blog.brianbuikema.com/wp-content/uploads/2010/07/ProximityAlertSetActivityScreen1.jpg" alt="Proximity Alert Set Activity Screen" width="331" height="491" /></a><p class="wp-caption-text">Proximity Alert Set Activity Screen</p></div>
<p>The following introduces our <strong>ProximityAlertSetActivity </strong>class.</p>
<pre class="brush: java; title: ; notranslate">
public class ProximityAlertSetActivity extends Activity {
  private double lat = 00;
  private double lng = 00;
  private boolean newReminder = true;

  @Override
  public void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.alert_reminder);

    this.newReminder = !(getIntent().getExtras() != null &amp;&amp; getIntent().getExtras().containsKey(&quot;current&quot;));
    if (this.newReminder) {
      String context = Context.LOCATION_SERVICE;
      updateWithNewLocation(((LocationManager) getSystemService(context)).getLastKnownLocation(ProximityAlertHelper.getInstance().Provider));
    }
    else {
      ProximityAlert current = retrieveCurrentAlertReminder();
      ((TextView) findViewById(R.id.TextView_reminder_location_hdr)).setText(&quot;Lat:&quot; + current.Lat + &quot;\nLong:&quot; + current.Lng);
      ((TextView) findViewById(R.id.EditText_reminder_name)).setText(current.Name);
      ((TextView) findViewById(R.id.EditText_reminder_desc)).setText(current.Desc);
      DatePicker picker = (DatePicker)findViewById(R.id.DatePicker_reminder_expiration);
      picker.updateDate(current.Year, current.Month, current.DayOfMonth);
    }
  }

  // Creates the menu items
  public boolean onCreateOptionsMenu(android.view.Menu menu) {
    getMenuInflater().inflate(R.menu.alert_reminder_add, menu);
    return true;
  }

  // Handles item selections
  public boolean onOptionsItemSelected(android.view.MenuItem item) {
    switch (item.getItemId()) {
      case R.id.add_menu_save:
        addAlert();
        return true;
      case R.id.add_menu_cancel:
        DialogHelper.getInstance().displayConfirmationDialog(this, this.dialogCancelResultHandler, &quot;Confirmation&quot;, &quot;Would you like to cancel adding this alert?&quot;);
        return true;
      case R.id.add_menu_del:
        DialogHelper.getInstance().displayConfirmationDialog(this, this.dialogDeleteResultHandler, &quot;Confirmation&quot;, &quot;Would you like to delete this alert?&quot;);
        return true;
      case R.id.add_menu_settings:
        Intent intent = new Intent(this, ProximityAlertPreferencesActivity.class);
        startActivityForResult(intent, 0);
        return true;
      case R.id.add_menu_about:
        showDialog(0);
        return true;
    }

    return false;
  }

  protected ProximityAlert retrieveCurrentAlertReminder() {
    ProximityAlert current = null;

    try {
      current = new ProximityAlert(getIntent().getExtras().getString(&quot;current&quot;));
    }
    catch (JSONException ex) {
      Log.e(AppSettings.DEBUG_TAG, &quot;JSON failure in AlertReminderActivity&quot;, ex);
    }

    return current;
  }

  protected void addAlert() {
    String name = ((TextView) findViewById(R.id.EditText_reminder_name)).getText().toString();
    String desc = ((TextView) findViewById(R.id.EditText_reminder_desc)).getText().toString();
    DatePicker picker = (DatePicker)findViewById(R.id.DatePicker_reminder_expiration);

    // add proximity alert intent
    if (newReminder) {
      ProximityAlert reminder = new ProximityAlert(this.lat, this.lng, name, desc, picker.getMonth(), picker.getDayOfMonth(), picker.getYear());
      ProximityAlertHelper.getInstance().addProximityAlerts(this, ProximityAlert.add(this, reminder));
    }

    finish();
  }

  protected Handler dialogCancelResultHandler = new Handler() {
    @Override
    public void handleMessage(Message msg) {
      if (Boolean.parseBoolean(msg.obj.toString())) {
        Msg.ToastShort(ProximityAlertSetActivity.this, &quot;Alert has been canceled!&quot;);
        finish();
      }
      else {
        Msg.ToastShort(ProximityAlertSetActivity.this, &quot;Alert has NOT been canceled&quot;);
      }
    }
  };

  protected Handler dialogDeleteResultHandler = new Handler() {
    @Override
    public void handleMessage(Message msg) {
      if (Boolean.parseBoolean(msg.obj.toString())) {
        ProximityAlert current = retrieveCurrentAlertReminder();
        ProximityAlertHelper.getInstance().removeAlert(ProximityAlertSetActivity.this, current);
        Msg.ToastShort(ProximityAlertSetActivity.this, &quot;Alert has been deleted!&quot;);
        finish();
      }
      else {
        Msg.ToastShort(ProximityAlertSetActivity.this, &quot;Alert has NOT been deleted&quot;);
      }
    }
  };

  @Override
  protected Dialog onCreateDialog(int id) {
    // we have only one - defaulted to 0
    return DialogHelper.getInstance().displayAboutDialog(this);
  }

  //Register for the updates when Activity is in foreground
  @Override
  protected void onResume() {
    super.onResume();
    if (this.newReminder) {
      ProximityAlertHelper.getInstance().requestLocationUpdates(this, this.locationListener);
    }
  }

  // Stop the updates when Activity is paused
  @Override
  protected void onPause() {
    super.onPause();
    if (this.newReminder) {
      String context = Context.LOCATION_SERVICE;
      ((LocationManager) getSystemService(context)).removeUpdates(this.locationListener);
    }
  }

  private final LocationListener locationListener = new LocationListener() {
    public void onLocationChanged(Location location) {
      updateWithNewLocation(location);
    }

    public void onProviderDisabled(String provider) {
      updateWithNewLocation(null);
    }

    public void onProviderEnabled(String provider) {
    }

    public void onStatusChanged(String provider, int status, Bundle extras) {
    }
  };

  private void updateWithNewLocation(Location location) {
    String latLongString;
    TextView myLocationText = (TextView) findViewById(R.id.TextView_reminder_location_hdr);
    if (location != null) {
      this.lat = location.getLatitude();
      this.lng = location.getLongitude();
      latLongString = &quot;Lat:&quot; + lat + &quot;\nLong:&quot; + lng;
    } else {
      latLongString = &quot;No location found - Please move more than &quot; + AppSettings.MinDistance + &quot; from current position&quot;;
    }

    myLocationText.setText(&quot;Your Current Position is:\n&quot; + latLongString);
  }
}
</pre>
<p>The <em>LocationListener </em>allows us to refresh the view (e.g., position status) as our longitude and latitude changes due to changes in our physical location.  Or, more specifically, our smart phone detects changes to its physical location.  Again, much of the technical lifting is done by the <em>ProximityAlertHelper </em>class.</p>
<p>And lastly, the <strong>ProximityAlertHelper </strong>class is implemented as follows:</p>
<pre class="brush: java; title: ; notranslate">
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 LocationListener locationListener;
  private HashMap&lt;ProximityAlert, PendingIntent&gt; proximityIntentsMap = new HashMap&lt;ProximityAlert, PendingIntent&gt;();
  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;
  }

  public void requestLocationUpdates(Context caller, LocationListener locationListener) {
    if (initialized) {
      this.locationListener = locationListener;
      String context = Context.LOCATION_SERVICE;
      LocationManager mgr = ((LocationManager) caller.getSystemService(context));
      mgr.removeUpdates(locationListener);

      mgr.removeUpdates(locationListener);
      long minInc = Long.parseLong(PreferenceManager.getDefaultSharedPreferences(caller).getString(&quot;mintimeinc&quot;, &quot;2000&quot;));
      float minDistance = Float.parseFloat(PreferenceManager.getDefaultSharedPreferences(caller).getString(&quot;mindistance&quot;, &quot;2&quot;));
      mgr.requestLocationUpdates(this.Provider, minInc, minDistance, locationListener);
    }
  }

  public boolean addProximityAlerts(Context caller, ArrayList&lt;ProximityAlert&gt; reminders) {
    if (initialized) {
      String context = Context.LOCATION_SERVICE;
      LocationManager mgr = ((LocationManager) caller.getSystemService(context));

      removeAlerts(caller);

      for (int i=1; i &lt;reminders.size(); i++) {
        ProximityAlert reminder = reminders.get(i);
        Intent intent = new Intent(ProximityAlertActivity.class.getName());
        intent.putExtra(&quot;current&quot;, reminder.serialize());
        PendingIntent proximityIntent = PendingIntent.getBroadcast(caller, i, intent, 0);
        float proxRadius = Float.parseFloat(PreferenceManager.getDefaultSharedPreferences(caller).getString(&quot;proxradius&quot;, &quot;2&quot;));
        mgr.addProximityAlert(reminder.Lat, reminder.Lng, proxRadius, -1, proximityIntent);
        proximityIntentsMap.put(reminder, proximityIntent);
      }
      return true;
    }
    return false;
  }

  public void removeAlert(Context caller, ProximityAlert reminder) {
    if (initialized) {
      String context = Context.LOCATION_SERVICE;
      LocationManager mgr = ((LocationManager) caller.getSystemService(context));

      removeAlert(mgr, reminder);
    }
  }

  public void removeAlerts(Context caller) {
    if (initialized) {
      String context = Context.LOCATION_SERVICE;
      LocationManager mgr = ((LocationManager) caller.getSystemService(context));

      for (ProximityAlert reminder:this.proximityIntentsMap.keySet()) {
        removeAlert(mgr, reminder);
      }
    }
  }

  public void closeLocationManager(Context caller) {
    if (initialized) {
      try {
        String context = Context.LOCATION_SERVICE;
        LocationManager mgr = ((LocationManager) caller.getSystemService(context));

        if (this.locationListener != null) {
          mgr.removeUpdates(this.locationListener);
        }

        removeAlerts(caller);

        caller.unregisterReceiver(this.receiver);
      }
      catch(Exception ex) {
        Log.e(AppSettings.DEBUG_TAG, &quot;exception thrown in closeLocationManager(...)&quot;, ex);
      }
    }
  }

  protected void removeAlert(LocationManager mgr, ProximityAlert reminder) {
    if (initialized) {
      if (reminder.Name.trim().length() &gt; 0) {
        mgr.removeProximityAlert(this.proximityIntentsMap.get(reminder));
      }
    }
  }
}
</pre>
<p>As new proximity alerts are added via the <em>LocationManager</em>, we first remove the old ones and add all alerts again.</p>
<p>Note that the actual xml layout and menu files will be included in the download.</p>
<p>We will continue our discussion on</p>
<ul>
<li>Capturing Promity Alert Events and</li>
<li>Setting Proximity Alert Preferences</li>
</ul>
<p>in <a href="http://blog.brianbuikema.com/2010/07/part-3-developing-proximity-alerts-for-mobile-applications-using-the-android-platform/" target="_blank">Part 3</a> of <em>Developing Proximity Alerts for Mobile Applications using the Android Platform</em>.</p>
<p>More coming soon!</p>
]]></content:encoded>
			<wfw:commentRss>http://blog.brianbuikema.com/2010/07/part-2-developing-proximity-alerts-for-mobile-applications-using-the-android-platform/feed/</wfw:commentRss>
		<slash:comments>5</slash:comments>
		</item>
		<item>
		<title>Part 1 &#8211; Developing Proximity Alerts for Mobile Applications using the Android Platform</title>
		<link>http://blog.brianbuikema.com/2010/07/part-1-developing-proximity-alerts-for-mobile-applications-using-the-android-platform/</link>
		<comments>http://blog.brianbuikema.com/2010/07/part-1-developing-proximity-alerts-for-mobile-applications-using-the-android-platform/#comments</comments>
		<pubDate>Sat, 03 Jul 2010 16:12:01 +0000</pubDate>
		<dc:creator>Brian Buikema</dc:creator>
				<category><![CDATA[Android]]></category>
		<category><![CDATA[Architecture & Design]]></category>
		<category><![CDATA[Java]]></category>
		<category><![CDATA[Location-Based]]></category>
		<category><![CDATA[Mobile]]></category>
		<category><![CDATA[Proximity Alerts]]></category>
		<category><![CDATA[Technology]]></category>
		<category><![CDATA[design]]></category>

		<guid isPermaLink="false">http://blog.brianbuikema.com/?p=904</guid>
		<description><![CDATA[This is Part 1 of a three-part four-part series Developing Proximity Alerts for Mobile Applications using the Android Platform.  Please click appropriately if you are looking for Part 2, Part 3, or the bonus Part 4 that discusses important new enhancements. We&#8217;ve all used Event Reminders as a way to remind ourselves of important events.  [...]]]></description>
			<content:encoded><![CDATA[<p>This is Part 1 of a <span style="text-decoration: line-through;">three-part</span> <strong><em>four-part</em></strong> series <em>Developing Proximity Alerts for Mobile Applications using the Android Platform</em>.  Please click appropriately if you are looking for <a href="http://blog.brianbuikema.com/2010/07/part-2-developing-proximity-alerts-for-mobile-applications-using-the-android-platform/" target="_blank">Part 2</a>, <a href="http://blog.brianbuikema.com/2010/07/part-3-developing-proximity-alerts-for-mobile-applications-using-the-android-platform/" target="_blank">Part 3</a>, or the bonus <a href="http://blog.brianbuikema.com/2010/07/part-4-developing-proximity-alerts-for-mobile-applications-using-the-android-platform/" target="_blank"><em>Part 4</em></a> that discusses important new enhancements.</p>
<p>We&#8217;ve all used <em>Event Reminders</em> as a way to remind ourselves of important events.  These reminders are time triggered, that is, our reminders are activated at a specific time in the future.  Birthdays, meetings, time to pay the bills are all examples of Event Reminders.</p>
<p>But let&#8217;s say you don&#8217;t know the specific time of an event, but would like to be reminded, or alerted, of the event when you are actually at a particular place.  For example, Grandma&#8217;s garbage disposal is broken, and you will fix it the next time you go to her house.  And say you don&#8217;t know the next time you are coming over, but would benefit from an alert that is activated when you actually arrive at her house.</p>
<p>Another example is activating an alert that lists some items to pick up the next time you are at the grocery store.</p>
<p>The good news is now we can generate these alerts using our Android-based smart phones.  This is specifically known as <em>proximity alerts</em>, and is the topic of this post.  We will discuss how the <em>LocationManager </em>class helps us in this endeavor.  We will also create a <em>ProximityIntent </em>based on the <em>PendingIntent</em>.  And we will create a <em>ProximityIntentReceiver </em>by extending the <em>BroadcastReceiver</em> in order to receive the proximity intents.</p>
<p>In this post, we will develop a Proximity Alert Mobile Application using the Android Platform.  The final application will look like the following:</p>
<div id="attachment_962" class="wp-caption aligncenter" style="width: 342px"><a href="http://blog.brianbuikema.com/wp-content/uploads/2010/07/ProximityAlertHomeActivityScreen.jpg"><img class="size-full wp-image-962" title="Proximity Alert Mobile Application (Home Screen)" src="http://blog.brianbuikema.com/wp-content/uploads/2010/07/ProximityAlertHomeActivityScreen.jpg" alt="Proximity Alert Mobile Application (Home Screen)" width="332" height="492" /></a><p class="wp-caption-text">Proximity Alert Mobile Application (Home Screen)</p></div>
<p>And we will use the following screen to add proximity alerts:</p>
<div id="attachment_970" class="wp-caption aligncenter" style="width: 341px"><a href="http://blog.brianbuikema.com/wp-content/uploads/2010/07/ProximityAlertSetActivityScreen2.jpg"><img class="size-full wp-image-970" title="Proximity Alert Set Activity Screen" src="http://blog.brianbuikema.com/wp-content/uploads/2010/07/ProximityAlertSetActivityScreen2.jpg" alt="Proximity Alert Set Activity Screen" width="331" height="491" /></a><p class="wp-caption-text">Proximity Alert Set Activity Screen</p></div>
<h2>Let&#8217;s Get Started</h2>
<h3>Mission Statement</h3>
<p>To build a Proximity Alert Mobile Application allowing users to set and receive alerts based on location proximity, similar to setting and receiving traditional time-based event reminders.</p>
<h3>Use Cases</h3>
<ul>
<li>To set one or more location proximity alert(s), configurable by location, radius of proximity (in meters), and expiration date/time</li>
<li>To insert/edit freestyle attributes to the location proximity alerts, e.g., todo list, grocery list, etc&#8230;</li>
<li>To be notified (that is, alerted) when the user enters the location within configured proximity parameters</li>
<li>To delete one, or all, proximity alert(s)</li>
</ul>
<h3>Considerations</h3>
<ul>
<li>In order to &#8220;set&#8221; a location proximity alert, it is necessary to actually <em>take the smart phone to the location being targeted</em> and &#8220;set&#8221; the alert</li>
<li>We will need to create both proximity configuration and proximity alert screens</li>
<li>We will register the application as a &#8220;service&#8221; in order to run it in the background</li>
<li>User Interface style is a low priority!  Also known as <em>lazy author</em>!</li>
</ul>
<h2>Design</h2>
<p>Before we start cutting code, we need to think through our design.  As a minimum, we need the following:</p>
<ol>
<li><strong>Home View</strong> &#8211; all actions start from this screen, and display our active list of proximity alerts</li>
<li><strong>Proximity Alert View</strong> &#8211; this will allow us to add/edit/delete proximity alerts</li>
<li><strong>Proximity Alert Entity</strong> &#8211; represents a single alert, and functions like a DTO</li>
<li><strong>Proximity Alert Repository</strong> &#8211; this will provide persistent storage of our alerts</li>
<li><strong>Proximity Alert Notification View</strong> &#8211; notifies of a proximity alert, i.e., displays an alert screen when an actual alert is fired</li>
<li><strong>Proximity Intent Receiver</strong> &#8211; this is our Broadcast Receiver (more on this later)</li>
<li><strong>Settings &#8220;Preferences&#8221; View</strong> &#8211; we will use Android&#8217;s PreferenceActivity to edit common configuration settings, e.g., proximity radius</li>
</ol>
<p>Ask anyone who has been around the block creating Android applications, and they will tell you to make sure your <em>AndroidManifest.xml</em> file is set up properly.  All Activities referenced by your application, additional libraries used by your application, and all necessary permissions must be set up in this in order for your application to work properly.</p>
<p>With that said, our manifest file is as follows:</p>
<pre class="brush: xml; highlight: [20,21,22]; title: ; notranslate">
&lt;?xml version=&quot;1.0&quot; encoding=&quot;utf-8&quot;?&gt;
  &lt;manifest xmlns:android=&quot;http://schemas.android.com/apk/res/android&quot;
    package=&quot;iqspike.proximityalert.activity&quot;
    android:versionCode=&quot;1&quot; android:versionName=&quot;1.0&quot;&gt;
    &lt;application android:icon=&quot;@drawable/icon&quot; android:label=&quot;@string/app_name&quot;&gt;
      &lt;uses-library android:name=&quot;com.google.android.maps&quot;/&gt;
      &lt;activity android:name=&quot;.ProximityAlertHomeActivity&quot; android:label=&quot;@string/app_name&quot;&gt;
        &lt;intent-filter&gt;
          &lt;action android:name=&quot;android.intent.action.MAIN&quot; /&gt;
          &lt;category android:name=&quot;android.intent.category.LAUNCHER&quot; /&gt;
        &lt;/intent-filter&gt;
      &lt;/activity&gt;
      &lt;activity android:name=&quot;ProximityAlertActivity&quot;&gt;
      &lt;/activity&gt;
      &lt;activity android:name=&quot;ProximityAlertSetActivity&quot;&gt;
      &lt;/activity&gt;
      &lt;activity android:name=&quot;ProximityAlertPreferencesActivity&quot;&gt;
      &lt;/activity&gt;
    &lt;/application&gt;
    &lt;uses-permission android:name=&quot;android.permission.INTERNET&quot;/&gt;
    &lt;uses-permission android:name=&quot;android.permission.ACCESS_FINE_LOCATION&quot;/&gt;
    &lt;uses-permission android:name=&quot;android.permission.VIBRATE&quot;/&gt;
  &lt;/manifest&gt;
</pre>
<p>Note the highlighted lines near the bottom indicating the <em>INTERNET, ACCESS_FINE_LOCATION, and VIBRATE</em> permissions we require.  Note that <em>ACCESS_FINE_LOCATION</em> is a bit more battery intensive than <em>ACCESS_COARSE_LOCATION</em>, but is necessary when you need a finer level of GPS information.</p>
<p>We&#8217;re just getting started.  Please see <a href="http://blog.brianbuikema.com/2010/07/part-2-developing-proximity-alerts-for-mobile-applications-using-the-android-platform/" target="_blank">Part 2</a> as we start cutting code for our <em>Mobile Proximity Alert Application using the Android Platform</em>!</p>
<p>More coming soon!</p>
]]></content:encoded>
			<wfw:commentRss>http://blog.brianbuikema.com/2010/07/part-1-developing-proximity-alerts-for-mobile-applications-using-the-android-platform/feed/</wfw:commentRss>
		<slash:comments>9</slash:comments>
		</item>
	</channel>
</rss>
