MOBILE

Building Android Apps : Controlling the Phone with JavaScript (part 2) - Geolocation

1/16/2011 3:31:21 PM

2. Geolocation

Let’s update Kilo to save the location when entries are created. Once we have that information, we’ll add a Map Location button that will open the built-in Maps application and drop a pin at the point where the entry was created.

The first step is to add latitude and longitude columns to the database to store the information. To do so, replace the CREATE TABLE statement in ~/Desktop/KiloGap/assets/www/kilo.js with the following:

db.transaction(
function(transaction) {
transaction.executeSql(
'CREATE TABLE IF NOT EXISTS entries ' +
' (id INTEGER NOT NULL PRIMARY KEY AUTOINCREMENT, ' +
' date DATE NOT NULL, food TEXT NOT NULL, ' +
' calories INTEGER NOT NULL, ' +
' longitude TEXT NOT NULL, latitude TEXT NOT NULL);'
);
}
);

Replace the existing createEntry() function in kilo.js with this:

function createEntry() {
navigator.geolocation.getCurrentPosition(
function(position){
var latitude = position.coords.latitude;
var longitude = position.coords.longitude;
insertEntry(latitude, longitude);
},
function(){
insertEntry();
}
);
return false;
}

Wondering where the SQL INSERT statement got to? Let’s take a look at the insertEntry() function. This new function creates the entry in the database. Add the following to kilo.js:

function insertEntry(latitude, longitude) {
var date = sessionStorage.currentDate;
var calories = $('#calories').val();
var food = $('#food').val();
db.transaction(
function(transaction) {
transaction.executeSql(
'INSERT INTO entries (date, calories, food, latitude, longitude) ' +
'VALUES (?, ?, ?, ?, ?);',
[date, calories, food, latitude, longitude],
function(){
refreshEntries();
checkBudget();
jQT.goBack();
},
errorHandler
);
}
);
}

To confirm that Kilo is actually saving these location values, we’ll want to display them somewhere in the interface. Let’s add an Inspect Entry panel to display the stored values. We’ll include a Map Location button on the panel that will display where the entry was created. Add the following to index.html, right before the closing body tag (</body>):
<div id="inspectEntry">
<div class="toolbar">
<h1>Inspect Entry</h1>
<a class="button cancel" href="#">Cancel</a>
</div>
<form method="post">
<ul class="rounded">
<li><input type="text" placeholder="Food" name="food" value="" /></li>
<li><input type="tel" placeholder="Calories"
name="calories" value="" /></li>
<li><input type="submit" value="Save Changes" /></li>
</ul>
<ul class="rounded">
<li><input type="text" name="latitude" value="" /></li>
<li><input type="text" name="longitude" value="" /></li>
<li><p class="whiteButton" id="mapLocation">Map Location</p></li>
</ul>
</form>
</div>


Now we need to give the user a way to navigate to this Inspect Entry panel, so we’ll modify the behavior of the Date panel such that when the user taps an entry in the list, the Inspect Entry panel will slide up from the bottom of the screen.

The first step is to wire up the click event handler (which we’ll create next), and also modify the way clicks on the Delete button are processed. Add the three highlighted changes below to the refreshEntries() function in kilo.js:

function refreshEntries() {
var currentDate = sessionStorage.currentDate;
$('#date h1').text(currentDate);
$('#date ul li:gt(0)').remove();
db.transaction(
function(transaction) {
transaction.executeSql(
'SELECT * FROM entries WHERE date = ? ORDER BY food;',
[currentDate],
function (transaction, result) {
for (var i=0; i < result.rows.length; i++) {
var row = result.rows.item(i);
var newEntryRow = $('#entryTemplate').clone();
newEntryRow.removeAttr('id');
newEntryRow.removeAttr('style');
newEntryRow.data('entryId', row.id);
newEntryRow.appendTo('#date ul');
newEntryRow.find('.label').text(row.food);
newEntryRow.find('.calories').text(row.calories);
newEntryRow.find('.delete').click(function(e){
var clickedEntry = $(this).parent();
var clickedEntryId = clickedEntry.data('entryId');
deleteEntryById(clickedEntryId);
clickedEntry.slideUp();
e.stopPropagation();
});
newEntryRow.click(entryClickHandler);
}
},
errorHandler
);
}
);
}

Now let’s add the entryClickHandler() function to kilo.js:
function entryClickHandler(e){
sessionStorage.entryId = $(this).data('entryId');
db.transaction(
function(transaction) {
transaction.executeSql(
'SELECT * FROM entries WHERE id = ?;',
[sessionStorage.entryId],
function (transaction, result) {
var row = result.rows.item(0);
var food = row.food;
var calories = row.calories;
var latitude = row.latitude;
var longitude = row.longitude;
$('#inspectEntry input[name="food"]').val(food);
$('#inspectEntry input[name="calories"]').val(calories);
$('#inspectEntry input[name="latitude"]').val(latitude);
$('#inspectEntry input[name="longitude"]').val(longitude);
$('#mapLocation').click(function(){
window.location = 'http://maps.google.com/maps?z=15&q='+
food+'@'+latitude+','+longitude;
});
jQT.goTo('#inspectEntry', 'slideup');
},
errorHandler
);
}
);
}


To test your changes, open a command prompt, cd into the KiloGap directory, and run the following commands to recompile and install the app on your phone:

ant debug
adb -d install -r ~/Desktop/KiloGap/bin/Kilo-debug.apk
Other  
  •  Building Your First Windows Phone 7 Application (part 5) - Styling Your Application
  •  Building Your First Windows Phone 7 Application (part 4) - Customizing Your First Windows Phone Application
  •  Building Your First Windows Phone 7 Application (part 3) - Writing Your First Windows Phone Code
  •  Building Your First Windows Phone 7 Application (part 2) - Using Your First Windows Phone Silverlight Controls
  •  Building Your First Windows Phone 7 Application (part 1) - Creating a Windows Phone Project
  •  Introducing Windows Phone 7 and the Windows Phone Platform
  •  Windows Phone Application Platform
  •  iPhone Application Development : Basic User Input and Output
  •  Mobile Phone Game Programming : A Quick J2ME Primer
  •  Mobile Phone Game Programming : Java As a Mobile Game Platform
  •  Mobile Phone Game Programming : Getting to Know Mobile Platforms
  •  Mobile Application Security : The Apple iPhone - Local Data Storage: Files, Permissions, and Encryption
  •  Mobile Application Security : The Apple iPhone - Permissions and User Controls
  •  iPhone Application Developmen : Using the View-Based Application Template (part 3)
  •  iPhone Application Developmen : Using the View-Based Application Template (part 2) - Preparing the View Controller Outlets and Actions
  •  iPhone Application Developmen : Using the View-Based Application Template (part 1)
  •  Mobile Application Security: Application Format
  •  Mobile Application Security: Security Testing
  •  Mobile Application Security: The Apple iPhone - Development
  •  Building Android Apps : Installing KiloGap in the Emulator
  •  
    Most View
    Sony VAIO Tap 20 - Sony's 20in Tablet Is An All-In-One PC
    GIGABYTE GA-Z77X-UP4 TH - Thunderbolt Technology Bonus
    Kid developers (Part 1)
    Examining Real-World SharePoint 2010 Deployments
    GPS Log Book - Record Journey Automatically In Car
    The World At Your Fingertips
    Samsung Galaxy Camera - The Future Of Digital Photography (Part 1)
    Adobe Flash Catalyst CS5 : Wireframing an Application in Flash Catalyst - Run a Project
    Gaming Headset Shootout (Part 2) : CM Storm Sirius S 5.1, Razer Tiamat 7.1
    Windows Vista : Windows PowerShell (part 2) - PowerShell Variables, PowerShell Scripts, Automate Scripts with the Task Scheduler
    Top 10
    Windows Phone 8 In-Depth Review (Part 6)
    Windows Phone 8 In-Depth Review (Part 5)
    Windows Phone 8 In-Depth Review (Part 4)
    Windows Phone 8 In-Depth Review (Part 3)
    Windows Phone 8 In-Depth Review (Part 2)
    Windows Phone 8 In-Depth Review (Part 1)
    Xiaomi Phone 2 - High-End Specifications In A Surprisingly Cheap Package (Part 5)
    Xiaomi Phone 2 - High-End Specifications In A Surprisingly Cheap Package (Part 4)
    Xiaomi Phone 2 - High-End Specifications In A Surprisingly Cheap Package (Part 3)
    Xiaomi Phone 2 - High-End Specifications In A Surprisingly Cheap Package (Part 2)