How to Develop Android Apps Using Ruby
Like many other language created for the web, Ruby is going mobile. Read on to learn how to use RubyMotion to create mobile apps written in Ruby.
Join the DZone community and get the full member experience.
Join For FreeThe way mobile apps are developed has dramatically changed over the past decade. Mobile apps were built using native technologies like Android and iOS and then came mobile frameworks like Titanium and PhoneGap that allowed JavaScript developers to build hybrid mobile apps with a sustained framework limitation. Ever Since RubyMotion was released, Ruby developers have been building cross-platform native apps for iOS, Android, and OS X using the Ruby language alone, without any framework limitations.
An important skill to have when creating Android applications is to have an understanding of Java programming, the required Java packages, and the Android SDK. Learning this narrow set of skills could be challenging for someone new, and the Ruby language has a solution for Ruby developers or someone new wanting to learn the Ruby language in the form of RubyMotion.
What is RubyMotion? It's a Ruby language implementation that is compiled to run on iOS, OS X, and Android supported devices with a unified runtime approach and optimized binary support using an ahead-of-time static compiler. RubyMotion also includes testing tools, interactive debugging support optimized and designed for embedded device constraints that can quickly be learned by Ruby developers.
RubyMotion is considered a combination of runtimes since it is tightly integrated with Android runtime and uses the command-line interface (CLI) to develop Android apps interactively. This article will make developing Android apps easier for Ruby developers, and make Android developers more productive. This article will take you through RubyMotion by developing an Android app that links movie names to Wikipedia; let’s call it Moviepedia.
Let’s start with the installation part first.
Installation and Setup
RubyMotion comes in multiple flavors ranging from hobbyist to professional and picks the package that is right for you to get started. I will use the starter package for simplicity, download the RubyMotion Installer, and follow the steps below. First, double-click the RubyMotion Installer.
Agree to the End User License Agreement and enter the license key sent to your email address during the installation and the installer will resume the installation process as shown in the screen below
Look for the successful install confirmation before you close out the installer.
IF at any point you run into trouble, RubyMotion support is available on @RubyMotion’s Twitter account. Additional help and resources are available in case any assistance is needed from the RubyMotion community.
To verify that RubyMotion is successfully installed on your machine, run the following command:
$ motion --version 5.9
If at any time you want to upgrade to a newer version:
$ motion update
Installing Java
The RubyMotion build system requires the Java compiler to be installed; follow these steps if you don’t have one installed. To verify Java is installed successfully, run the following command:
$ java -version
Java(TM) SE Runtime Environment (build 9.0.4+11)
Java HotSpot(TM) 64-Bit Server VM (build 9.0.4+11, mixed mode)
Install Android Environment
A single line command is used to set up the Android environment using the android-setup
command. This will download both the Android SDK and Android NDK under the ~/.rubymotion-android
directory and select the SDK version of your choice or pick the latest one if you are not sure.
$ motion android-setup
You should see an output similar to the screen below during the SDK installation
The Android SDK (Software Development Kit) provides a selection of tools to build Android applications which require Java to be installed as a pre-requisite. The Android SDK ecosystem contains the following for mobile app creation:
- Build-tools
- Platform-tools
- Android Debug Bridge (ADB)
- Android Emulator
The Android NDK (Native Development Kit) provides tools for Android devices to integrate with the Android SDK compilation tool.
Now that we have the Android SDK and Android NDK installed, let’s start creating our new RubyMotion app, Moviepedia
Project Creation: Moviepedia
Similar to Rails, RubyMotion works through the command line for app creation. Open up the terminal and navigate to the folder of your choice to start creating the app using the motion create
command. The motion create
command, by default, creates iOS application templates and explicitly calls out Android keywords that will create an Android application with the application name specified, which in our case is Moviepedia.
$ motion create --template=android Moviepedia
After successfullly running these commands, you should see a creation action similar to the below screenshot:
Navigate to Moviepedia project directory using the cd Moviepedia from the current directory and let’s understand the files created.
- Moviepedia/app directory: app directory contains all the ruby code with a *.rb file extension
- Moviepedia/app/main_activity.rb file: This file contains the fundamental lifecycle callback methods. Rubymotion creates onCreate() method which gets fired when the system initially creates the activity and check the visual lifecycle of android app activity below to understand the further steps after onCreate callback gets initiated
- Moviepedia/spec directory: spec directory includes automated tests that are automatically generated and rake spec command will run all .*rb files included inside the spec directory.
- Moviepedia/.gitignore file: gitignore file is used by Git repository system to ignore file tracking on the files mentioned
- Moviepedia/Gemfile: Gemfile lists all the gem dependencies that are needed for our application to run sourced from https://rubygems.com . Rubymotion defaults rake gem to run our application
- Moviepedia/Rakefile: Rakefile contains the application name, SDK, NDK, device location which is run by a rake command.
Install dependencies
Since Rubymotion apps contain a Gemfile, all the required application dependencies mentioned in the Gemfile should be installed before running or building the app. Run the bundle command to install the Gemfile dependencies
$ bundle install
Using rake 12.3.1
Using bundler 1.16.0.pre.3
Bundle complete! 1 Gemfile dependency, 2 gems now installed.
Use `bundle info [gemname]` to see where a bundled gem is installed.
Running a gemfile will create a Gemfile.lock which contains a snapshot of all the gem(s) along with their associated dependency versions.
Build the App
The rakefile is the first file loaded by RubyMotion when the app builds initially with all the application properties and load configurations included. Check the default Rakefile with the application name mentioned in the App.Setup section.
#- * -coding: utf - 8 - * -
$: .unshift("/Library/RubyMotion/lib")
require 'motion/project/template/android'
begin
require 'bundler'
Bundler.require
rescue LoadError
end
Motion::Project::App.setup do |app | #Use `rake config' to see complete project settings.
app.name = 'Moviepedia'
end
Let’s fire up the terminal to understand the rake options. The rake config specifies the application defaults and is self-explanatory and customizable as needed.
$ rake config
api_version : "27"
application_class : nil
archs : ["armv7"]
assets_dirs : ["./assets"]
build_dir : "./build"
features : []
files : ["./app/main_activity.rb", "./app/movies.rb"]
icon : nil
logs_components : ["com/yourcompany/moviepedia:I", "AndroidRuntime:E", "chromium:E", "dalvikvm:E", "Bundle:E", "art:E"]
main_activity : "MainActivity"
main_dex_list : nil
manifest : {"xmlns:android"=>"http://schemas.android.com/apk/res/android", "package"=>#<Proc:0x007fa61a16d358@/Library/RubyMotion/lib/motion/project/template/android/config.rb:146 (lambda)>, "android:versionCode"=>#<Proc:0x007fa61a16d2e0@/Library/RubyMotion/lib/motion/project/template/android/config.rb:148 (lambda)>, "android:versionName"=>#<Proc:0x007fa61a16d218@/Library/RubyMotion/lib/motion/project/template/android/config.rb:149 (lambda)>}
motiondir : "/Library/RubyMotion"
multidex : false
name : "Moviepedia"
ndk_path : "/Users/.rubymotion-android/ndk"
optional_features : []
package : "com.yourcompany.moviepedia"
permissions : []
resources_dirs : ["./resources"]
sdk_path : "/Users/.rubymotion-android/sdk"
services : []
specs_dir : "./spec"
sub_activities : []
support_libraries : []
target_api_version : "27"
theme : "@android:style/Theme.Material.Light"
version_code : "1"
version_name : "1.0"
You can specify the rake configuration if you want to modify and not stick to the defaults explicitly. Check some config examples changes below to provide custom values as configuration settings.
app.api_version = '26' # Will change the api version to 26 from 27
app.sdk_path = '/.rubymotion-android/sdk' #SDK path change
app.version_name = '2.0' # Change the version name
app.main_activity = 'NewActivity' #Point main activity to non Mainactivity
app.sub_activities ='SubActivity' #Include all other files that are needed for app to run
Run the rake
command for the app to check if the app compiles, builds, and runs successfully on an emulator or device. To run the application on a device use the device
command.
$ rake device
For your application to run successfully on a device, make sure your device settings have permissions provided for the application to run on a device successfully. If you are not sure about the device settings, please follow the instructions below to setup the device.
- Navigate to the Settings in your Android Device.
- Scroll down to find System settings (for Google Pixel) or the About Phone section (for all other devices) to open a new screen.
- Scroll down to find the Build Number item and tap 7 times to enable developer mode.
- Go back one level or to the previous screen to find the Developer Options and tap on it.
- Look out for the USB Debugging section and approve your device's request to authorize the Mac/Windows machine used for development.
Now the rake device
command should start the app. To understand more about the rake capabilities, you can run the various rake commands. Specifying the app to run on an emulator or a device will need additional settings needed, for the case of simplicity let’s run the application using RubyMotion’s default emulator.
$ rake -T
rake build # Create an application package file (.apk)
rake clean # Clear local build objects
rake clean:all # Clean all build objects
rake config # Show project config
rake ctags # Generate ctags
rake default # Same as 'rake emulator'
rake device # Build the app then run it in the device
rake device:install # Install the app in the device
rake device:start # Start the app's main intent in the device
rake emulator # Build the app then run it in the emulator
rake emulator:install # Install the app in the emulator
rake emulator:start # Start the app's main intent in the emulator
rake release # Create an application package file (.apk) for release (Google Play)
rake spec # Same as 'spec:emulator'
rake spec:device # Run the test/spec suite on the device
rake spec:emulator # Run the test/spec suite on the emulator
The Android SDK comes with an emulator that can be configured via the command line or Android Studio (if this is your choice of IDE).
Configure Android Emulator Using the Command Line
Follow the steps below to create an Android Emulator or Virtual Device (AVD):
- Launch the Android command line tool from the terminal, as in ./android which is present inside SDK folder.
- Click the 'Create' button.
- Select the option for ABI (x86) and target API and provide a unique name to identify the emulator.
- Run the emulator to check for a successful run.
Configure Android Emulator Using Android Studio
Follow the steps below to create an Android Emulator or Virtual Device (AVD) using Android Studio.
- Open the Android Studio application and navigate to the Tools menu to run the AVD Manager option.
- Click on the Create Virtual Device button to create a new virtual device configurtion.
- Select the hardware that suits your needs by size and resolution (I picked Pixel 2 XL) and click Next.
- Select the system image, API Level targets, and download the release if it's not downloaded already.
- Provide a unique name, orientation, and Advanced settings to complete the setup.
- Click on Finish and run the emulator.
To run the application on an emulator use the emulator
command.
$ rake emulator
Running the rake emulator will compile, create, and auto sign the apk file and open the apk file in an emulator.
Now we have a clearer understanding on RubyMotion, Rakefile, and, of course, our application is off to a great start with an unbeaten run on an Android emulator. Let’s keep the application rolling.
Movie List Creation
RubyMotion did the heavy lifting by generating the needed skeleton for our application. Now, let’s spice up the application by adding a list of movies and linking them to the Wikipedia page.
Create a new file app/movies.rb with Movies class to add an array of movie names.
class Movies
end
Ruby provides a shortcut to list an array of strings with a %w
literal instead of using a traditional array presentation with comma separated double-quoted strings. As an example, the traditional way of writing an array would look like:
movie_names = [“Shrek”, “Frozen”, “Toy Story”, “Finding Nemo”, “Despicable Me”, “Inside Out”]
The movie_names
array can be rewritten using the %w
literal:
movie_names =
%w(
Shrek
Frozen
Toy\ Story
Finding\ Nemo
Despicable\ Me
Inside\ Out
)
Now, let’s change the shape of the Movies class by adding a list of movies inside the names
method.
class Movies
def self.names
##Moviews name list
%w(
Shrek
Frozen
Toy\Story
FInding\Nemo
Despicable\Me
Inside\Out
Wall-E
Zootopia
Brave
Moana
Tangled
Coco
Ice\Age
Aladdin
Rango
Cars
Finding\Dory
Coraline
Ratatouille
The\Incredible
Monsters,\Inc.
Kung\Fu\Panda
Up
Wolf\Children
Ponyo
)
end
end
We have the Movie list ready, so let’s create a adapter to access the Movie names from the MainActivity.
Android::Widget::ArrayAdapter.new(self, Android::R::Layout::Simple_list_item_1, Movies.names)
To access and display the Movie list names, the onCreate
lifecycle needs to call the list adapter from the onCreate
state.
list = Android::Widget::ListView.new(self)
list.adapter = Android::Widget::ArrayAdapter.new(self, Android::R::Layout::Simple_list_item_1, Movies.names)
Loading the movie names on the initial app load works well with ListView
and ArrayAdapter
using AndroidLayout
to choose a list item layout. Now let’s add the click listener event to identify the movie name the user clicked on.
selected_movie = Movies.names[position]
puts "Click event triggered for the movie -> #{selected_movie}"
Passing the parent, view, and position to ItemclickListener
will identify the selected movie position and to any intent activity after the click event is triggered. The intent is a message passed between activities, services, broadcast receivers, and content providers, in other words, it is similar to the parameters passed on to an API call asynchronously. In our application, this will make a call to Wikipedia and pass the movie name asynchronously.
intent = Android::Content::Intent.new
Use Android::Context::Intent
to create a new intent which can be pointed to a subActivity; let’s name the subactivity wikipediaActivity
. Let’s create a new file called wikipedia_activity.rb
.
class WikipediaActivity < Android::App::Activity
end
Specify the file name under the sub_activities
section before moving further along inside the rake file
app.sub_activities += %w(WikipediaActivity)
Every Activity created should have an onCreate
state similar to the main activity and our goal here is to make the SelectedMovie
data pass to the onCreate
method and load the Wikipedia link.
movie = self.intent.getStringExtra(SelectedMovie)
wiki_link = "https://en.wikipedia.org/wiki/#{movie}"
puts "Loading #{wiki_link}"
We have the wiki link with the movie name embedded at the end of the link, and in order for our activity to access the internet and load webpages, Android provides a WebView
as part of Andorid::Webkit
. Add the permission to the rake file specifying the permissions of rake config.
app.permissions = 'android.permission.INTERNET'
Permission is granted to access the webpage, so let’s write logic to load Wikipedia.
webview = Android::Webkit::WebView.new(self)
webview.webViewClient = Android::Webkit::WebViewClient.new
webview.loadUrl wiki_link
self.contentView = webview
Here’s how the onCreate
state flow for the wikipedia_activity.rb file should look:
def onCreate(savedInstanceState)
super
movie = self.intent.getStringExtra(SelectedMovie)
wiki_link = "https://en.wikipedia.org/wiki/#{movie}"
webview = Android::Webkit::WebView.new(self)
webview.webViewClient = Android::Webkit::WebViewClient.new
webview.loadUrl wiki_link
self.contentView = webview
end
Accessing the Wikipedia activity from the Main Activity to tie the Movie name link to load the Wikipedia URL is the final step in the process. We'll use the intent mechanism explained above.
intent = Android::Content::Intent.new(self, WikipediaActivity)
intent.putExtra(WikipediaActivity::SelectedMovie, selected_movie)
startActivity(intent)
Let’s rewrite the MainActivity
class to have more readability and structure.
class MainActivity < Android::App::Activity
def onCreate(savedInstanceState)
super
list = Android::Widget::ListView.new(self)
list.adapter = Android::Widget::ArrayAdapter.new(self, Android::R::Layout::Simple_list_item_1, Movies.names)
list.onItemClickListener = self
list.onItemClickListener = self
self.contentView = list
end
def onItemClick(parent, view, position, id)
selected_movie = Movies.names[position]
intent = Android::Content::Intent.new(self, WikipediaActivity)
intent.putExtra(WikipediaActivity::SelectedMovie, selected_movie)
startActivity(intent)
end
end
Here’s the link to the working app on GitHub.
Wrapping Up
In this article, we learned RubyMotion by building a Moviepedia app with some Android SDK calls using the power of the Ruby language and the Rake build language. We could have built the app using Android native app or Phone Gap hybrid development; however, once you have a good understanding of Ruby and it’s simplicity to build web apps, RubyMotion feels like an extension to your learning with no or little learning curve.
If you want to dive deeper into RubyMotion Development, check out “RubyMotion Android Development” to understand and see if RubyMotion is right for your Mobile Development needs. Rubymotion might not be a perfect option if you are worried about Memory management or Debugging capabilities. On the brighter side, the Ruby Open community is pretty good in addressing the concerns, thanks to the open source world.
Further Reading
- RubyMotion Android Development Guide, RubyMotion’s official Android Developer documentation.
- Android Studio IDE, Android’s official IDE for mobile app development.
- Understand Android SDK, Android’s SDK for beginner understanding.
- RubyMotion Support, Community support forums and support ticket.
Opinions expressed by DZone contributors are their own.
Comments