In the first part of the tutorial, you have been guided through the coding of a complete Ruby on Rails backend that can be used to register and login users through a JSON API.
In the second part then, you’ll learn how to code an Android native app that will consume that API. This tutorial doesn’t want to start from scratch about Android development, so I advice you to take a look at this series of tutorials from mobile.tutsplus.com that will guide you during the first steps of setting up the Eclipse environment.
Once you have Eclipse up and running with everything you need, we can start coding our app.
App creation and setup
Open up Eclipse and navigate the menus to create a new Android application: "File > New > Other ... > Android Application Project"
Choose the Application/Project/Package names appropriately and select these SDKs:
Build SDK: Android 4.1 (API 16)
Minimum required SDK: API 8 Android 2.2 (Froyo)
We target the latest Android version and we support devices down to Froyo.
Choose if you want to create a Launcher Icon or not and create a blank activity and call it HomeActivity.
HomeActivity
Dummy Tasks controller
In order to implement the JSON authentication, I wanted to first test the api client on our Android app. To do so I added a “fake” tasks controller that renders an arbitrary JSON response. I leave you the actual work to implement something more “real” and dynamic.
Don’t forget to add the route under the API::V1 namespace.
The HomeActivity will be the core of our simple app, it retrieves the tasks saved on the Rails backend and show them as a list.
To read the JSON from the application, without interrupting the UI thread, we will use an helper (with some additional classes) written by Tony Lukasavage (savagelook.com) called UrlJsonAsyncTask.
To add this nice set of tools, just download the package from Github (github.com/tonylukasavage/com.savagelook.android) and drag and drop the unzipped “com” directory and its content into the Package Explorer in Eclipse. If you did it right, a com.savagelook.android new package will appear under the “src” directory.
In the following snippet of code I will show you the code I added to the HomeActivity that Eclipse automatically wrote when we created our app.
In order to access our local Rails server from the Android Emulator, we need to use the 10.0.2.2 IP address that the Emulator maps to the localhost on our machine. Keep in mind to change this constant to the actual address (and port) you will use in production.
The onCreate() method, after the usual initialization, calls the loadTasksFromAPI() where we create and initialize the GetTasksTask (I know …) that extends the UrlJsonAsyncTask class.
The important thing to understand about this useful helper is that we need to override the onPostExecute() method, telling how to use the JSON we hopefully received from the backend.
In this case we just extract the tasks array and setup the adapter with the list of task’s titles found.
It’s important to add the permission to use the internet connection in the Manifest: without it our app couldn’t reach the API, even on our localhost machine and running the emulator.
The HomeActivity layout (GingerBread 2.3 left and Jelly Bean 4.1 right)
Bonus: Menus
I wanted to add a “Refresh” action to our activity so I added these two methods (the first should be already there at the creation) to setup the menu/actionbar and respond to clicks on their items.
A default file called res/menu/activity_home.xml should be found, edit it accordantly to the above code with the right id and strings.
Clicking on refresh should now retrieve the tasks list again.
WelcomeActivity
Before adding the functionality to authorize the access to our tasks to an authenticated user, we want to prompt him to register or login.
To do so, we will change the HomeActivity to check if the user already obtained an authorization token from our Rails backend.
We’ll do it by adding another override method onResume():
As you can see, we moved the loadTasksFromAPI() call from the onCreate() method to the newly added one.
The mPreferences variable has been added and we will use the SharedPreferences class to store our login informations later on. More information about this interface can be found here: developer.android.com/guide/topics/data/data-storage.html#pref
What we are going to do now with this code, is to check whether or not there’s an auth_token set for our user. If it’s present, just load the tasks; if not launch the WelcomeActivity.
To add a new activity, click on the menu "File > New > Other ... > Android activity" and select a blank one and call it "WelcomeActivity".
This activity will be really simple, just presenting a message and two buttons: Register and Login.
Inside the onCreate() method we simply set the layout and add two onClickListener to the buttons: to start the RegisterActivity from the Register button and to start the LoginActivity from the Login button.
I also added another override - onBackPressed() - because I want to consider this activity as the “main” one until the user has been logged in. So whenever he or she wants to exit our app without having registered/signed in, he or she will be sent back to the Home screen of the phone without going back to the HomeActivity. In other words, he or she won’t see the HomeActivity until logged in: the WelcomeActivity will be considered as the actual main activity.
Here’s the simple layout for our WelcomeActivity:
Don’t forget to add the needed strings to the res/values/strings.xml file.
Finally, register the new activity in the AndroidManifest.xml file:
I added the android:noHistory attribute because I don’t want to allow the user to return to this activity once he or she successfully logged in.
The WelcomeActivity layout (GingerBread 2.3 left and Jelly Bean 4.1 right)
LoginActivity
Right now the app won’t start because we didn’t create the LoginActivity and RegisterActivity yet. Let’s proceed with the usual method we already covered for the WelcomeActivity.
Once we have the LoginActivity file created, let’s start with the layout file:
As you can see we added two EditText fields and a Button to a ScrollView, in order to allow the controls to show no matter what the screen size/rotation.
Let’s now put a good use of this interface. Open the LoginActivity.java file and add these variables and methods.
If you recall the activity_login.xml layout file, we added an android:onClick attribute to the Button, with a login value. This is the method login() we have to add to our Activity that will be called when the user click on the button.
The method just collect the values from the two EditText fields and save the user’s email and password into our two variables, mUserEmail and mUserPassword.
We then check if they are not empty strings and alert the users if they are, prompting him or her to provide all the information to login in.
If everything seems ok, we create a new LoginTask to execute the actual authentication with our Rails backend.
The LoginTask is another class we extend from UrlJsonAsyncTask just like we did in the HomeActivity to load the tasks from the API.
This time, though, we will override not only the onPostExecute() method but also the ` doInBackground()` one.
We have to do this because the standard implementation doesn’t allow us to post data to the JSON API, but it’s really easy to do otherwise.
Add this new class inside the LoginActivity class.
The code should be easy to follow. The important things are that we have to setup the params for our HTTP POST request, adding the user’s email and password and setting the correct headers.
The method then tries to contact the request’s url (our API) and if everything goes ok, return to the onPostExecute() method the results.
If the user exists and the password is correct, the auth_token will be returned from the API with the success info. We then proceed to save it in the SharedPreferences and launch the HomeActivity again, closing this one and showing a simple Toast.
Before switching to the RegisterActivity class, don’t forget to add this new activity to the application’s manifest.
The android:noHistory attribute is added for the same reasons we did it for the WelcomeActivity.
The LoginActivity layout (GingerBread 2.3 left and Jelly Bean 4.1 right)
RegisterActivity
Our app is almost completed (for the sake of this tutorial!) and what’s left is adding the possibility for our potential users to register themselves directly on the app itself.
Create now (if you didn’t do it before) a new Activity with the usual method and call it RegisterActivity
The layout file is again a ScrollView, containing our EditText fields for the user’s information: email, username, password and password confirmation.
The implementation of the RegisterActivity class is really similar to what we did for the login.
The registerNewAccount() method is called whenever the user click on the register button. We then collect the data from the EditText fields and check if they are empty or not and also if the password and its confirmation are the same.
We then proceed to send all the information about the new user to the API, using again a custom implementation of the `
UrlJsonAsyncTask` class.
We need now to add the RegisterTask class implementation just like we did for the login. The details are really similar and maybe we can consider a refactor of the code to avoid some un-necessary repetitions. But I leave this chore to you.
The code should be clear at this point and speak for itself.
Almost there, just remember to add the activity to the manifest and we are done!
The RegisterActivity layout (GingerBread 2.3 left and Jelly Bean 4.1 right)
Use the authentication
In order to use all the efforts we made until now, we need to edit just a line of code in our HomeActivity code. We have to pass the auth_token we set in the SharedPreferences after a successful login or registration and append it to the request url to the API.
The Android app is now complete and it can be extended to be a fully capable application that consumes every data you want to provide via your API.
The very last thing to do is to uncomment the before_filter :authenticate_user! in the TasksController inside the Rails application. Without that filter every data is available without an authentication; with it an user can access to the data only with a proper authentication token.
Bonus: ActionBarSherlock
Before concluding this long tutorial, I want to add just a little bonus that will enhance the user’s experience of the app for the users that have not the latest and shiniest Android handset.
ActionBarSherlock is an extension of the support library designed to facilitate the use of the action bar design pattern across all versions of Android with a single API.
The library will automatically use the native action bar when appropriate or will automatically wrap a custom implementation around your layouts. This allows you to easily develop an application with an action bar for every version of Android from 2.x and up.
Download and extract the actionbarsherlock files from the site and add the library to the current workspace in Eclipse: "File > New > Other ... > Android Project from Existing Code"
Navigate the ActionBarSherlock directory and select the “library” dir. Ignore the warning/error that may arise and right-click on the new project and select "Refactor > Rename" and rename the project “ABS 4.0” (or whatever you like).
Right-click on the AuthExample project and select "Properties": click on the "Android" section and add the just added ABS library in the "Library" sub-section.
Eclipse should now give you an error like this:
The problem can be solved by deleting the android-support-v4.jar in the "libs" directory of our projects: browsing the Package Explorer, right-click on it and select "delete".
Updating the existing code
To use all the nice features that ABS provides, we need to alter some code, starting from changing the parent class of our Activities. Instead of extending the android.app.Activity, we need to extend the SherlockActivity like so:
Do the same for all the other activities and remember to remove the old imports of import android.app.Activity;.
In the HomeActivity there will be some problems with the code that manage the creation of the Menu. The fix is quick and consists in changing the method called to get the menu inflater - getMenuInflater() - with getSupportMenuInflater() provided by the SherlockActivity class.
Finally, change the default theme for the application in the AndroidManifest.xml file.
You can choose the default dark one or Theme.Sherlock.Light and Theme.Sherlock.Light.DarkActionBar. For more information, check out the official documentation at actionbarsherlock.com/theming
The final results: GingerBread with the Sherlock Holo theme
Conclusion
That’s all! It was a wild ride, spanning a lot of topics and languages. I hope you enjoyed and if you have anything to ask or critics to make, let me know at luca.tironi@gmail.com.
I hope the information provided with this tutorial could be the basis for your wonderful applications. I tried to write it as the tutorial I wished I had when I started addressing these topics in coding my apps.