Yesterday, I had no idea about how to write programs for smartphones such as iPhone, Android, Windows Phone or BlackBerry.
Today, my first application is already running on my Android phone...
As a first attempt to write a mobile application, I just tried to build an application that retrieves the latest news from my school's atom feed and displays it in a native way on a smartphone (Keio University, Graduate School of SDM).
Yesterday, I had absolutely no knowledge about mobile development, except "iPhone is using the ugly Objective-C and Android is using the heavy Java".
Today, the application looks like that...
...is written in pure Ruby and is 100% native on iPhone, Android, Windows Mobile and BlackBerry!
How come?! Thanks to a powerful, light, easy and intuitive mobile framework: Rhodes (from Rhomobile).
Let see in this post how to do that.
- 1 Introduction
- 2 Appcelerator Titanium
- 3 Rhomobile Rhodes
- 4 Conclusion
When you face a new issue, the first thing you often do is... to Google it!
Well that's what I did, and it quickly appeared that if I want to build native applications for smartphones, I will have to write the application in different languages using different libraries; one for each OS (for example Objective-C for iOS or Java for Android) unless I use some frameworks that do the ugly conversion to native code for you!
And among the frameworks, the most popular one seems to be Appcelerator Titanium.
Sounds exciting right!
So I installed the free Titanium Plateform, downloaded an example from their website, and tried to run the example.
That's the last thing I did with that software... The software never succeed to connect to the Android SDK and I was stuck on the "loading..." (of the Android SDK) that never ran... (even after moving "adb" to the right folder and setting up the path with all the correct values...)
Then I tried the Sandbox where you can run some code snippets.
I took one of the list, the Python Hello World example and clicked "Launch".
I'm sure the problem is me because the soft is pretty popular and many people manage to use it well!
But it did not really persuade me to investigate further in the software...
I gave a try to another one, apparently less popular.
Its name is "Rhodes" from the Rhomobile family.
Unlike Appcelerator Titanium, Rhodes is really "cross-platform". Where Titanium supports only iPhone and Android, Rhodes offers you also Windows Mobile, RIM and Symbian!
However, you won't have choice for programming language: you will have to program in Ruby.
A single Ruby code can be deployed into a native application on all OS supported by Rhomobile.
But is it a drawback to use Ruby? After using it for two days... clearly not!
Rhodes is highly inspired by Rails and takes good ideas from the Rails web framework: Database Abstraction (not as complete as Rails), MVC (Model-View-Controller), auto model generation (similar to Rails scaffolding, also through rake) and many things I still did not see yet.
Let see how I ended up in 2 days with my first application running on my smartphone starting from 0.
First, we need a mobile OS SDK (Development Kit). The easiest to get and available on all platforms (unlike a very close one that you can only use from Macs... ><) is the Android SDK.
You can get the one you want but I'll explain briefly how to set up the Android one here.
Install the Java SDK
To use the Android SDK, you need the Java SDK (as native Android apps are Java apps).
So first if you don't have it, let's install it.
Go to the Java website and download the latest SDK for your system.
On Linux, remember to switch your default SDK to the Sun proprietary one (using "alternatives").
It may also work with the OpenSDK but I never tried.
Install Android SDK
Go to the Android Developers website and install the SDK. Start the SDK Manager (asked after installed on Windows or under tools/android on Linux) and install the packages you want (probably the SDK for Android 2.3 and the updates).
On the same webpage, download the Android NDK that helps us with "performance-critical native applications". You just need to extract the archive somewhere (probably along with the SDK).
Install Ruby and Rhodes
Then you need to install Ruby, RubyGems, Rake and Rhodes.
On Linux, you just need to install the packages "ruby", "rubygems", then the rake and rhodes gems ("sudo gem install rake rhodes").
On Windows, if you already have Ruby and Rubygems you need to "Start command prompt with Ruby" (search from the windows menu) and "gem install rake rhodes".
If you don't have Ruby, you can install Ruby, RubyGems and Rhodes with a all-in-one installer: Instant Rhodes.
That's all you need to use the Rhodes framework.
Let set it up. Start a command prompt with Ruby and type "rhodes-setup".
Follow the instructions to set up Rhodes.
For example for me:
ruby 1.9.2p136 (2010-12-25) [i386-mingw32] C:\Users\Thomas>rhodes-setup We will ask you a few questions below about your dev environment. JDK path (required) (C:/Program Files/Java/jdk1.6.0_23): Android SDK path (blank to skip) (): C:\android-sdk-windows Android NDK path (blank to skip) (C://android-ndk-r5): Windows Mobile 6 SDK CabWiz (blank to skip) (): BlackBerry JDE 4.6 (blank to skip) (): BlackBerry JDE 4.6 MDS (blank to skip) (): BlackBerry JDE 4.2 (blank to skip) (): BlackBerry JDE 4.2 MDS (blank to skip) (): If you want to build with other BlackBerry SDK versions edit: C:/Ruby192/lib/ruby/gems/1.9.1/gems/rhodes-2.2.6/rhobuild.yml C:\Users\Thomas>
And Rhodes is set up!
To make a new application, the only thing we need to do is to extend the rhodes framework.
So first we can generate a simple "hello world" like application with one line.
From the command prompt, enter "rhodes app myapp" (changing "myapp" by whatever you want).
It will create the application template :
[thomas@myhost rhodes]$ rhodes app myapp Generating with app generator: [ADDED] myapp/rhoconfig.txt [ADDED] myapp/build.yml [ADDED] myapp/app/application.rb [ADDED] myapp/app/index.erb [ADDED] myapp/app/index.bb.erb [ADDED] myapp/app/layout.erb [ADDED] myapp/app/loading.html [ADDED] myapp/Rakefile [ADDED] myapp/app/loading.png [ADDED] myapp/app/helpers [ADDED] myapp/icon [ADDED] myapp/app/Settings [ADDED] myapp/public
Move to that folder (cd myapp) and you can directly try the application by typing "rake run:android"
The first time you run "rake run:android" you will have to choose a virtual device.
Just press enter to let rhodes create a new one and set it up.
Once you've done that, your first application will start in an Android Emulated window.
Building your own application
Hello World is nice, but we want a real application.
As I said in the introduction, we will write a simple Atom feed parser that can display all the entries of an Atom feed in a list and allow the user to click (well, tap!) on an entry title to see its content.
The Atom feed I am taking as example is the following one: http://www.sdm.keio.ac.jp/en/atom.xml
First, we need to create the model of our application.
We will store the entries in a “Feed” model, and each “feed” will have a title, a date, a link, a content and a language.
So we just generate the model automatically with rhodes:
[thomas@myhost myapp]$ rhodes model Feed title,date,link,content,lang Generating with model generator: [ADDED] app/Feed/index.erb [ADDED] app/Feed/edit.erb [ADDED] app/Feed/new.erb [ADDED] app/Feed/show.erb [ADDED] app/Feed/index.bb.erb [ADDED] app/Feed/edit.bb.erb [ADDED] app/Feed/new.bb.erb [ADDED] app/Feed/show.bb.erb [ADDED] app/Feed/feed_controller.rb [ADDED] app/Feed/feed.rb [ADDED] app/test/feed_spec.rb
It generated automatically some files for you.
It basically allows you to create new feeds, edit them, and delete them from the application.
You can have a look to the generated files to understand how Rhodes works.
In our case, we do not need to be able to add, edit et delete manually the entries so I deleted the “edit” and “new” templates (.erb) and removed the edit/update/create/delete methodes from the controller (feed_controller.erb).
What we want is to populate the database from the entries in the XML file.
So we need a Ruby XML parser. And of course there are plenty of them!
Rhodes supports the popular ReXML and also has its own implementation based on ReXML (but lighter) named RhoXML. Unfortunately RhoXML doesn’t support CDATA and there are CDATA in my feed so we will have to use ReXML.
To add ReXML support, simply add the “rexml” and “set” extensions to the build.yml file at the root of your application:
extensions: ["json", "rexml", "set"]
When we start the application, we want to list all the entries of the feed.
So we want to call the “index” of the “Feed”.
To do so, we just change the rhoconfig.txt file (root of the app) as follows:
# Startup page for your application start_path = '/app/Feed'
And what we want to do when we start the application is to list the feeds, so let’s do so by editing the index method in the feed_controller.rb as follows:
def index @feeds = Feed.find(:all) if @feeds.empty? then self.update else render :action => :index, :back => :exit end end
If we already loaded the feeds, we just display the list.
If there are no feeds, we update them.
You can see the full "update" method at the end of this post.
I just show you the most important part here, the part that loads the elements of the Atom feed into our @feeds variable:
require 'rexml/document' #@@get_result contains the XML text (as a string) doc = REXML::Document.new(@@get_result) REXML::XPath.each(doc,"//feed/entry/") do |e| Feed.create(:title => e.elements['title'].text, :link => e.elements['link'].attributes['href'], :date => e.elements['published'], :content => e.elements['content'].texts().at(1), :lang => e.elements['content'].attributes['xml:lang']) end
We also want to be able to "refresh" the entries because when we restart the application, if you noticed the beginning of the index method, if there are some entries in the database, we just display them directly.
However the database is not destroyed when we stop the application so the entries will be directly displayed without connecting to the internet.
We can add a simple "refresh" method that empty the database and update the entries from the Atom feed:
def refresh Feed.delete_all redirect :action => :update end
Then, when the user tap on a title form the index list, we want to display the content of the feed.
The "show" method has already been implemented for us and we don't need to change it:
def show @feed= Feed.find(@params['id']) if @feed render :action => :show else redirect :action => :index end end
The Views (index, show)
Finally, we only need to change the automatically generated views to display the information we want!
Let see the two most important views: index and show.
The index.erb has a button on the top to manually refresh the entries and a list of all the entries (showing their title):
<% @feeds.each do |feed| %>
- <%= feed.title %><% end %>
The show.erb shows the title, the date, and the content:
<h1><%= @feed.title %></h1>
- <%= @feed.title %>
- <%= @feed.date %><%= @feed.content %>
And... that's it!
I added some controls, the multi-language feature and the final application was done!
In addition to allow you to quickly build mobile applications, Rhodes also supports native powerful APIs of the smartphones.
It is also really cross-platform as you can deploy your application to the 5 top mobile devices (iPhone, Android, Windows Phone, BlackBerry and Symbian).
Ruby is a very user-friendly programming language that is pleasant to use.
The MVC and Database Abstraction layers inherited from Rails make the code easier to maintain.
IDEs that work with Ruby/Rails also work has a charm with Rhodes.
You can find some screenshots of the quickly built application here:
You can download the complete code of the application used as an example in this tutorial here: sdmnews.zip.
From your Android device, you can install the application by clicking on the following APK link: sdmnews.apk
You need to allow unknown sources to install this quickly built application (Settings > Applications > Unknown sources) as I do not publish it to the market (yet?).
If you have any comment or question about mobile software development, feel free to comment this post!