Tuesday, March 17, 2009

Mapping Services for iPhone Applications

For my next iPhone project, I'm considering an application that uses geolocation to render a map of the user's current location. I therefore need to find a mapping service that I can use free of charge since I won’t be charging for the application.

Listed below are some of the services I've considered. I don't plan to do anything more than to render the user's current location and allow him or her to adjust it slightly if it's not accurate. No need for routing or other extra features. So most mapping services should work, the only issue is the terms and conditions that will allow me to use it free of charge.


1) Google Maps

http://code.google.com/apis/maps/

This is my first choice based on my experience using it as the Maps application on the iPhone. I have also played around with Google Maps on my web site and have found the API very easy to use.

The terms of service might be a problem.

ToS: http://code.google.com/apis/maps/signup.html


9.1 Free, Public Accessibility to Your Maps API Implementation. Your Maps
API Implementation must be generally accessible to users without charge. You
may require users to log in to your Maps API Implementation if you do not
require users to pay a fee. Unless you have entered into a separate written
agreement with Google or obtained Google's written permission, your Maps
API Implementation must not:

(a) require a fee-based subscription or other fee-based restricted access; or
(b) operate only behind a firewall or only on an internal network (except
during the development and testing phase).


Since I'm not charging, this should be OK.


10. License Restrictions. Except as expressly permitted under the Terms, or
unless you have received prior written authorization from Google (or, as
applicable, from the provider of particular Content), Google's licenses above
are subject to your adherence to all of the restrictions below. Except as
explicitly permitted in Section 7, you must not (nor may you permit anyone
else to):

10.8 use the Static Maps API other than in an implementation in a web
browser;


However, this does not look OK. Since my plan is to use the map in the UIWebView object, I think this might violate the ToS. After doing some searching, I came across this thread:

http://groups.google.com/group/Google-Maps-API/browse_thread/thread/2f42bc5e4c3368d8/fbdc4ecdc3b96096?pli=1

A Google employee weighed in and said basically that if the application were accessing a web site that could be viewed separate from the application, than the UIWebView use case should be OK.

I have seen applications that use Google Maps which can’t be used in a separately in a browser. One example is iBus, a free Portland mass transit application:

http://zhenwang.yao.googlepages.com/ibus-portland

So it appears the way I’d use Google Maps falls into the gray area of the ToS.

I should also point out that there is a nice, BSD licensed library that can help to integrate the Google Maps API into an iPhone project. This helps to make a simple API even easier to use.

http://code.google.com/p/iphone-google-maps-component/


2) Yahoo Maps

http://developer.yahoo.com/maps/

I’ve used Yahoo Maps with Flickr geotagging and the maps look just as good as Google’s. I have not, however, seen any iPhone applications that use this service.

ToS: http://info.yahoo.com/legal/us/yahoo/maps/mapsapi/mapsapi-2141.html

One big issue with the ToS is the attribution part:

http://developer.yahoo.com/attribution/

Yahoo Maps require displaying an attribution badge or label that is not overlaid on the map. It’s placed below the map. This will take away from valuable screen real estate, and for me is enough of a reason to not use Yahoo Maps. Perhaps this is why I haven’t seen it used in any iPhone applications.


3) Microsoft Virtual Earth

http://www.microsoft.com/virtualearth/

I’ve used Microsoft’s Virtual Earth from a browser and have been really impressed. I’ve also seen it used with the Loopt iPhone application.

ToS: http://www.microsoft.com/virtualearth/product/terms.html

The ToS looks OK for Non-Commercial use. That is, of course, if deploying a free iPhone application is considered Non-Commerical use.

There’s a good write-up about using Virtual Earth with the iPhone here:

http://www.geo2web.com/2008/11/13/developing-virtual-earth-iphone-applications-with-objective-c/

From reading this, it seems use of the Virtual Earth API is non-trivial. Apparently, it requires the use of SOAP requests instead of JavaScript (which Google Maps uses). Also, the returned tile images have to be programmatically assembled into a nice iPhone image. The blog post directs you to a 3rd party framework library (BSD license) that can ease implementation:

http://consonancesw.com/developers/virtualearthkit/


4) CloudMade

http://cloudmade.com/

CloudMade uses the maps from OpenStreetMap (http://www.openstreetmap.org/). I’ve seem OpenStreetMap used with the iPhone application MotionX-GPS, however, I’m not sure if it’s used through the CloudMade API.

According to the following link, they place no restrictions on the API.

http://developers.cloudmade.com/projects/show/iphone-api


Just like our other APIs, we don't want to restrict the uses of this API - you are
free to create applications that use our maps in any way you like, as long as
they comply with the terms of the iPhone SDK agreement.


To implement, the user needs to download the API code and integrate with the iPhone application. CloudMade provides some iPhone application examples to learn from.

CloudMade looks like a viable solution. And I’d prefer to use an open source solution, given that Google/Yahoo/Microsoft all seem to have vague terms of service agreements that allow them to cut off service for a variety of reasons.


Summary

So which one have I chosen? I think I’ll go with Google Maps. The ToS does give me some pause, however, my application is free and just for my own experience. If they shut it down, I’ll just switch to another mapping API.

Friday, March 13, 2009

Ruby/Rails With Apache/MySQL on Mac OS (Leopard)

I'm a new Mac user after many years of working on both Linux and Microsoft systems. This last week I went through the process of setting up my system for web development using the Ruby/Rails/Apache/MySQL platform. I was a little surprised to find out it was not as straightforward as working on Linux, given the Mac OS has a BSD core and is the development platform of a lot of high profile programmers.

I'm writing this blog post primarily for my own reference. However, if it can help any others, all the better. Plus I welcome any feedback that may improve my setup.


Terminal Application

All command line actions should be done through the Terminal application. This can be found at Application/Utilities/Terminal.app.


MacPorts

MacPorts is a faculty similar to Aptitude in Ubuntu/Debian for installing software packages from the command line.

MacPorts software is installed in a separate location under /opt/local/. Therefore, you can always determine whether or not an executable is part of MacPorts by running a which [command] and seeing if it's located under this directory.

The current Leopard .dmg installer is version 1.7.0 and can be downloaded here:

http://www.macports.org/install.php


Once installed, open up a Terminal window and run the following command to make sure MacPorts is up to date


$ sudo port selfupdate



The Terminal PATH should have the MacPorts directories (/opt/local/bin, /opt/local/sbin) preceding the standard directories. The MacPorts installer set this for me automatically. If this is not the case for you, be sure to change this in the /etc/profile file.


$ echo $PATH
/opt/local/bin:/opt/local/sbin:/usr/bin:/bin:/usr/sbin:/sbin:/usr/local/bin:/usr/X11/bin



Ruby

Install Ruby and RubyGems via MacPorts.


$ sudo port install ruby
$ sudo port install rb-rubygems



The Leopard Mac OS includes older versions of both of these programs which we do not want to use. Check to make sure that the MacPorts version is the version called from the command line:


$ which ruby
/opt/local/bin/ruby

$ which gem
/opt/local/bin/gem



These are the current versions


$ ruby ‐v
ruby 1.8.7 (2008-08-11 patchlevel 72) [i686-darwin9]

$ gem ‐v
1.3.1



Rails Framework

Install Rails framework files via RubyGems package manager.


$ sudo gem install rake
$ sudo gem install rails
$ sudo gem install capistrano
$ sudo gem install mongrel



This will install these packages with all dependencies. The following files should be installed


$ gem list

*** LOCAL GEMS ***

actionmailer (2.3.2)
actionpack (2.3.2)
activerecord (2.3.2)
activeresource (2.3.2)
activesupport (2.3.2)
capistrano (2.5.5)
cgi_multipart_eof_fix (2.5.0)
daemons (1.0.10)
fastthread (1.0.1)
gem_plugin (0.2.3)
highline (1.5.0)
mongrel (1.1.5)
net-scp (1.0.2)
net-sftp (2.0.2)
net-ssh (2.0.11)
net-ssh-gateway (1.0.1)
rails (2.3.2)
rake (0.8.4)



MySQL

MySQL can be installed through MacPorts or through a dmg installer. Since it’s not that important to me to have the latest version, I chose the dmg installer for simplicity.

The installer can be downloaded here. The current version is 5.1.32.

http://dev.mysql.com/downloads/mysql/5.1.html#macosx-dmg


The installer includes three parts:

Database: mysql-5.1.32-osx10.5-x86.pkg
Preference Pane: MySQL.prefPane
Launch Manager: MySQLStartupItem.pkg

I installed all three parts.

Now install the Ruby MySQL interface package:


$ sudo gem install mysql -- --with-mysql-dir=/usr/local/mysql



Add the MySQL bin folder to the PATH variable for command line use. Append the following line to the local profile file (~/.profile).


# MySQL Command Line
export PATH=$PATH:/usr/local/mysql/bin



Apache

For Apache, I used the version included with the Mac OS.

The Passenger gem package integrates Apache with the Rails framework. Install using the following commands.


$ sudo gem install passenger
$ sudo passenger-install-apache2-module



The output of the last command should list some config settings to add to the Apache configuration. I added a separate file to put these in.


/etc/apache2/other/Passenger.conf

LoadModule passenger_module \
/opt/local/lib/ruby/gems/1.8/gems/passenger-2.0.6/ext/apache2/mod_passenger.so
PassengerRoot /opt/local/lib/ruby/gems/1.8/gems/passenger-2.0.6
PassengerRuby /opt/local/bin/ruby



I create a config file for each separate Rails project. The following example is for a project called ‘project1’.


/etc/apache2/other/project1.conf

<VirtualHost *:80>

ServerName www.project1.com
ServerAdmin admin@project1.com
DocumentRoot /Users/username/Work/web/project1/public
ServerSignature On

CustomLog /var/log/apache2/project1_access.log combined
ErrorLog /var/log/apache2/project1_error.log
LogLevel info

<Directory />
Options FollowSymLinks
AllowOverride None
</Directory>
<Directory /Users/username/Work/project1/public/>
Options Indexes FollowSymLinks MultiViews
AllowOverride None
Order allow,deny
Allow from all
</Directory>

</VirtualHost>



In order to view my web site in a local browser, I need to add a setting in the hosts file to redirect to the local host. See the last line of the following file. Of course, you need to make sure to remove this once you deploy your web site to a real server.


/etc/hosts

#
# Host Database
#
# localhost is used to configure the loopback interface
# when the system is booting. Do not change this entry.
##
127.0.0.1 localhost
255.255.255.255 broadcasthost
::1 localhost
fe80::1%lo0 localhost

127.0.0.1 www.project1.com project1.com

Followers

About Me