Use jQuery Mobile to Build a Native Android News Reader App: Part 3

Use jQuery Mobile to Build a Native Android News Reader App: Part 3

Tutorial Details
  • Technology: jQuery + Android SDK
  • Difficulty: Advanced
  • Estimated Completion Time: 1 Hour
This entry is part 3 of 3 in the series Use jQuery Mobile to Build a Native Android App

In Part 1 of this tutorial series, we introduced our sample application, described the page flow, and discussed how to construct the pages in the application via jQuery Mobile. In Part 2, we completed the implementation of our web application. In this final part, we will migrate the web application into a native Android application.


Converting Into A Native Android Application

The web application completed in Part 2 will now be converted into a native Android application. The discussion below applies to Android OS 2.2 & 2.3.

The Android application will use index.html as its UI component. We will write an android.app.Activity class to define the integration point between index.html and the native application. We will also write an android.webkit.WebViewClient class to make sure that the News Detail page is displayed inside the original android.webkit.WebView instance where the News application is launched.

Changes In index.html

We will update the NEWS_URI variable as follows:

var NEWS_URI = 'http://rss.news.yahoo.com/rss/';

We do not need bridge.php in the native Android application to forward AJAX calls to Yahoo! News. This is because the same-origin restriction does not apply here. When packaged as part of the native application, the index.html file is not downloaded from a web server. As such, it can make AJAX calls to remote URLs.

In addition, we add the following function:

var EMPTY = '';
...
function changeLocation(varURI){
  showProgress();
  $.get(EMPTY,function(data){
    window.location = varURI;
  });
}

The changeLocation() function will be called from the android.webkit.WebViewClient, which will be shown momentarily. The purpose of the function is to show the progress page during transition from the News page to the News Detail page.

  • The first step in changeLocation() is to display the progress page.
  • Remember that the jQuery get() function is a specialized jQuery ajax() function. We call get() passing to it an empty URL and a callback handler, that sets the window.location variable to the input argument. The input argument is the URL in the <a href='...'> attribute enclosed within an a tag for a news item, as discussed in Part 2, “Going To The News Detail Page From The News Page”. When the URL loads, the progress page is replaced with contents from that URL.
  • As we point out below, the function changeLocation() is not an essential part of migrating the web application into a native one. It is only needed to display a progress page when transitioning from the News page to the News Detail page in the native application.
  • A progress page is not needed in the web application when transitioning from the News page to the News Detail page. This is because during the transition the web browser itself displays a progress indicator to the user. For example, in Android, both the native and Dolphin browsers display a spinning wheel and a progress bar in the navigation toolbar. In iOS, the Safari browser displays a similar progress indicator.

The Activity Class

The initial portion of our Activity class, named NewsActivity is shown below:

package com.news;
import android.app.Activity;
import android.webkit.WebView;
import android.os.Bundle;
...
public class NewsActivity extends Activity {
	WebView mWebView;
  public void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.main);
    mWebView = (WebView) findViewById(R.id.webview);
    mWebView.setWebViewClient(new NewsClient());
    mWebView.getSettings().setJavaScriptEnabled(true);
    mWebView.getSettings().setDomStorageEnabled(true);
    mWebView.loadUrl("android_asset/www/index.html");
  }
  ...
}
  • In the onCreate() method, we first call the default implementation from the super class and then invoke setContentView() to load the layout file for this Activity. The input argument to setContentView() is R.layout.main which is a reference to main.xml in the res/layout folder.
  • We get a handle to the WebView via findViewById(R.id.webview). We set a custom WebViewClient on the WebView, named NewsClient (to be reviewed soon). Then, we configure the WebView to allow JavaScript execution and the DOM storage API (the latter is necessary to use HTML5 localStorage).
  • Finally, we ask the WebView to load the index.html page that has the UI code.

On the News Detail page, pressing the back button of the device will take the user back to the Categories page. To be assured of that, we first need to handle the onKeyDown event in our NewsActivity. This is shown below:

 public class NewsActivity extends Activity {
	WebView mWebView;
  public void onCreate(Bundle savedInstanceState) {
    ...
  }
  public boolean onKeyDown(int keyCode, KeyEvent event) {
    if ((keyCode == KeyEvent.KEYCODE_BACK) && mWebView.canGoBack()) {
      mWebView.goBack();
      return true;
    }
    return super.onKeyDown(keyCode, event);
  }
  ...
}
 

If the key event corresponds to the back button of the device and the WebView has history to go back to, we then ask the WebView to go back a single step in its history. In the News Detail page, this will correspond to index.html. When history goes one step back, the Categories page will be displayed following the steps described in Part 2, “Application Startup”.

Lastly, let us look at the custom WebViewClient which is implemented as an inner class of NewsActivity.

 public class NewsActivity extends Activity {
	WebView mWebView;
  public void onCreate(Bundle savedInstanceState) {
    ...
	mWebView.setWebViewClient(new NewsClient());
	...
  }
  public boolean onKeyDown(int keyCode, KeyEvent event) {
    ...
  }
  private class NewsClient extends WebViewClient {
    public boolean shouldOverrideUrlLoading(WebView view, String url) {
      view.loadUrl("javascript:changeLocation('" + url + "')");
      return true;
    }
  }
...
}
 

The only operation we override from the parent class is shouldOverrideUrlLoading() where we instruct the WebView to call the JavaScript function changeLocation() in index.html.

  • Had we not defined a custom WebViewClient, the News Detail page would be displayed in a separate browser application, outside the News application. Therefore, defining a custom WebViewClient is essential to display the News Detail page as part of the News application (i.e. in the same WebView that hosts the index.html).
  • We could have written shouldOverrideUrlLoading() in a more simplified manner, as follows:
    public boolean shouldOverrideUrlLoading(WebView view, String url)
    {
        view.loadUrl(url);
        return true;
    }
    

    That would be sufficient to display the News Detail page in the same WebView that hosts index.html. However, the transition from the News page to the News Detail page would not include showing the progress page.

Having reviewed the Activity class, let us look at other components of our application.

AndroidManifest.xml

<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
  package="com.news" android:versionCode="1" android:versionName="1.0">
    <application android:icon="@drawable/icon" android:label="@string/app_name">
      <activity android:name=".NewsActivity" android:configChanges="orientation|keyboardHidden"
        android:label="@string/app_name">
          <intent-filter>
            <action android:name="android.intent.action.MAIN" />
            <category android:name="android.intent.category.LAUNCHER" />
          </intent-filter>
      </activity>
    </application>
    <uses-permission android:name="android.permission.INTERNET" />
</manifest>

For a general discussion on the AndroidManifest.xml file refer to the official reference. In that file, there are two particular items worthy of commenting on.

  • As described in the android.app.Activity documentation, by default, a configuration change, including a change in orientation or keyboard accessibility, results in the current activity being destroyed. To prevent the default behavior, we configure our application by specifying the configuration changes that will be handled by the application itself. This is defined in the configChanges attribute where orientation corresponds to orientation change and keyboardHidden corresponds to a keyboard accessibility change (e.g. a user lays open the device keyboard). We are configuring the application so that if any of those changes occur, the current activity is not destroyed.
  • The element <uses-permission android:name="android.permission.INTERNET" /> allows the application to access the Internet.

strings.xml

<?xml version="1.0" encoding="utf-8"?>
<resources>
  <string name="app_name">News</string>
</resources>

This file defines the constant named app_name which is used to identify the News application. The value of that attribute is displayed in various places in our Android device, as shown below. From left to right: under the application launch icon, the application title bar, Settings – Manage applications.

Application name

Figure 11. How the application name is displayed in Android.

Integrating The HTML-based UI With android.app.Activity

We implement the UI in our native Android application using index.html and the supporting JavaScript and css libraries. An integration point between index.html and the custom android.app.Activity class is the following line:

  mWebView.loadUrl("android_asset/www/index.html");

In addition, observe in “The Activity Class” that we enable JavaScript and DOMStorage in the android.webkit.WebView object as index.html needs to run JavaScript and access HTML5 localStorage.

  mWebView.getSettings().setJavaScriptEnabled(true);
  mWebView.getSettings().setDomStorageEnabled(true);

Finally, in the AndroidManifest.xml we allow Internet connections from our application via:

<uses-permission android:name="android.permission.INTERNET" />

Screen Images of the Android Application

The previously shown Figures 1 – 4 in Part 1 of this series are the screen images of the native Android application.


Application Launch Icon

To create the launch icon for the News application, we followed the icon design guidelines for Android applications. In that resource, various templates in Adobe PSD format are available for download. We downloaded icon_templates-v2.0.zip and extracted Launcher-icon-template.psd. In that file, we selected two templates to create our launch icon:

icon 1 icon 2

We placed those templates in two separate layers in Adobe Photoshop and added a graphical text, News, on an additional layer at the top to compose the launch icon. Per the guideline, we created three versions of the icon for low, medium and high density screens with 36 x 36, 48 x 48, and 72 x 72 pixel sizes, respectively. Each of those icons is named icon.png and they are placed in the Android project folders according to the following table:

Folder nameFile namePixel size
res\drawable-ldpiicon.png 36 x 36
res\drawable-mdpiicon.png 48 x 48
res\drawable-hdpiicon.png 72 x 72

As an example, this is the 36 x 36 launch icon:

icon ldpi


Native Android Application Development Environment

As part of this tutorial, we provided the necessary project files to import the native Android News application into Eclipse development environment. The project prerequisites are:

The project has been successfully tested against both Android platform 2.2 API level 8 and platform 2.3 API level 9.

Importing The Project

Before importing the project into your Eclipse environment, make sure that Eclipse ADT plugin points to the correct location of Android SDK in your local system. To check this, in the Eclipse menu go to Window -> Preferences -> Android. The SDK Location window must be set to the location of the Android SDK. Once set up correctly, you should see something similar to the image below:

Preferences

Figure 12. Eclipse Preferences.

The project files are provided in an archive file named news.zip. To import the project in the Eclipse menu, go to File -> Import and then in the file import wizard select General -> Existing Projects into Workspace (see below).

Import

Figure 13. Project Import.

On the next page of the wizard, choose the Select archive file radio button and browse to where news.zip is located in your file system. The Projects window will be automatically populated where the News project is already selected. This is shown below. Press the Finish button to complete the import.

Project File Selection

Figure 14. Project File Selection.

Eclipse will build the application automatically after import. Now, you should see the News project in the project explorer, as shown below:

Project Explorer

Figure 15. Project Explorer.

For building/debugging your project, you can choose between Android OS 2.3 and 2.2 platforms as the build target. To do this, select the News project in the project explorer and from the right-click menu choose Properties. On the left hand side listing of properties, select Android as the property. The available build targets are displayed on the right, as shown below:

Android Build Target

Figure 16. Android Build Target.

File Listing

A listing of files in the project is given below.

Project Contents

Figure 17. Project Contents.

We have already discussed some of those files. Below is a quick review/recap:

  • The src folder contains the source code for the NewsActivity class.
  • The gen folder contains the files automatically generated by Eclipse ADT.
  • The assets\www folder and its subfolders contain all the files needed for the UI, including index.html; assets\www\css-js has the css and JavaScript files used by index.html. In particular:
    • jquery-1.4.4.min.js, jquery.mobile-1.0a2.min.js, jquery.mobile-1.0a2.min.css are the jQuery Mobile framework libraries.
    • jquery.ba-dotimeout.js is the jquery-dotimeout-plugin library.
    • jquery.dst.js is the DST.js plugin library.
    • assets\www\css-js\images\icons-18-white.png is an image file referenced by the jQuery Mobile framework libraries.
  • assets\www\img\wait.gif is the spinning icon used in progress page.
  • The res\drawable* folders store the launch icons, as discussed in the “Application Launch Icon” section of this tutorial.
  • The res\layout\main.xml file is the Android XML layout file. Since the UI in our application is defined in index.html using jQuery Mobile framework, this file is very simple and needs no further explanation.
  • We have already reviewed res\values\strings.xml and AndroidManifest.xml.
  • The file default.properties defines the build target and is part of news.zip. It will be overwritten by Eclipse ADT depending on your selection of the build target.

Conclusions

In addition to developing cross-platform mobile web applications, the jQuery Mobile framework can be used to implement native Android applications. In this tutorial series, we developed a web application using jQuery Mobile and then migrated it into a native Android application with only slight modifications. The main idea is to use the android.webkit.WebView object as a container to run the html file of the web application and the jQuery Mobile JavaScript code it contains. Some closing remarks are given below.

  • When packaged as part of a native Android application, an html page running in android.webkit.WebView is not subjected to same-origin restrictions when making AJAX calls.
  • The jquery-dotimeout-plugin and the DST.js plugin, although originally developed for the jQuery framework, perform well for jQuery Mobile. There are a vast amount of plugins written for jQuery and, although case-by-case analysis is needed, those might be readily available for jQuery Mobile. This is an immense asset for this new framework!
  • We tested the web application with an Android OS 2.2 phone and an iPod Touch iOS 4.1 & 4.2. The native Android application was tested with Android OS 2.2 & 2.3 emulators and an Android OS 2.2 phone. In all cases, the look and feel and functional attributes were very similar.
  • In the Android platform, there are known techniques to establish JavaScript-to-Java and Java-to-JavaScript method calls. In fact, we demonstrated how to call back a jQuery Mobile JavaScript function from Java code in our application. It is possible that with a reasonable amount of effort, one could develop jQuery Mobile plugins to access native Android APIs. This indicates further opportunities for the jQuery Mobile framework to develop native Android applications.
Series Navigation«Use jQuery Mobile to Build a Native Android News Reader App: Part 2

Note: Want to add some source code? Type <pre><code> before it and </code></pre> after it. Find out more
  • Alex

    Hey guys, how can i add this to my android phone as native app?
    which is the archive i must to put in my phone to run properly? i cant see .apk archive. thanks

    • http://tutopod.com/ Arif

      You have to build it first under IDE like eclipse. Once you get your project running perfectly on emulator, the apk will appear.

  • http://www.homeofandroid.com David

    I do have same question with alex, im a totally nubie here :D

  • Konur Unyelioglu
    Author

    You don’t even need an apk file to install the application. In your device, Applications menu, check the box for Unknown sources. Also, in Application menu, Development, check the USB debugging box. Follow the instructions in the tutorial to set up the project in Eclipse. Once the project correctly builds, hook up your device to your PC with the USB cable, select the project in Eclipse and from right click menu Run As -> Android application. It will deploy the app in your device.

  • http://www.kecskefeszek.hu Gabriel Grey

    Hi there,
    This is an excellent tutorial! I did it but I have a problem. When I want to use my RSS I click to “get” button it is just loading loading..
    here is my rss:
    http://www.kecskefeszek.hu/poenlada
    http://www.kecskefeszek.hu/_viccek/rss
    and it is working with video or mp3?
    Thanks for your help.
    Gabor

    • Konur Unyelioglu
      Author

      In original code, notice that the category selections are hardcoded with values like business, world, topstories etc. Those exactly match values in category elements supplied by Yahoo rss feeds. If you intend to modify the code to customize according to your own rss, the first thing you need to do is change those values according to the values in category elements in your own rss. Problem is, based on my quick inspection, the category elements do not have a uniform (constant) value in your rss. In Yahoo rss feeds, all category elements have the same value for a specific category and the tutorial code is written based on that particular logic.

      If you would like to further investigate this, run the tutorial code in web application mode and look at the temporary file in the web folder which has a copy of the rss feed from Yahoo. You can compare it to your own rss to figure out any structural differences.

  • Wikiboo

    I’ve downloaded source code and opened index.html from news-web-code and when I select category nothing happens, just animation keeps loading.

    Why does it not work for me?

    • Konur Unyelioglu
      Author

      Have you deployed bridge.php and is it working? In the web server folder where bridge.php and index.html are deployed, you should see a file named tmpFile.txt that has the rss response coming from Yahoo! News for the last selected category. If that file is missing I would think that the php file is not operational.

  • Wikiboo

    There is no tmpFile.txt, how to fix it?

    • Konur Unyelioglu
      Author

      You need to make sure that php file is functioning correctly. In your local web server, let us assume bridge.php are accessible under http://localhost/somefolder/bridge.php. Open your browser and try test URLs such as:http://localhost/somefolder/bridge.php?fwd=http://rss.news.yahoo.com/rss/topstories or http://localhost/somefolder/bridge.php?fwd=http://rss.news.yahoo.com/rss/business. In each case the browser should display an RSS feed and tmpFile.txt should be created with text representation of the RSS feed.

      If not working, check if your web server is set up correctly to run PHP files. Look at server error logs etc. Also if you are running your localhost behind a firewall, the php file may fail to access to outside Yahoo! News URLs.

      Good luck.

      • Kiran

        Hi,

        Nice tutorial. I am trying to test your demo code. But am getting the below error when using bridge.php. So when I access –

        I see the following error –

        This page contains the following errors:

        error on line 2 at column 1: Extra content at the end of the document
        Below is a rendering of the page up to the first error.

        Please comment. I know I have php configured on the web server correctly.

        Thanks.

      • Kiran

        Never mind my previous comment/question. It was a directory permission issue and It’s resolved now. Thanks.

  • Konur Unyelioglu
    Author

    Where are you exactly stuck at? The easiest is to start from the web application because you can debug more easily. When you set up the web project, do you see the news categories in selection?

  • Russ

    First of all, GREAT series of articles. I am learning Android and have latched onto your tutorials as a way to speed along the process. I am working in Eclipse with the Android plugin. I have gone directly to part three of your tutorials. The application builds but nothing is happening through emmulator–error message comes up.

    Any suggestions would be appreciated.

  • Russ

    For those that come behind me……….

    The URL is wrong in the tutorial and correct in the src code.

    mWebView.loadUrl(“file:///android_asset/www/index.html”);

    • http://www.agustianra.co.cc Agustian Romy Ariansyah

      i’m still confuse with this:

      mWebView.loadUrl(“file:///android_asset/www/index.html”);

      on figure 17 above… to access index.html, it’s must from folder “assets/www/index.html”

      why it’s call with “android_asset” <<< where it's from?

      NB: Sorry my english, i'm Indonesian…

  • Konur Unyelioglu
    Author

    Hi Russ, Thanks for pointing out the error.

    • kirit

      hello sir i want to download your code. i am used Windows XP OS and when i run your code to emulator that time give only blank display just only Add button. and when i select category and press Get Category button i give the only processing and processing only.
      so please help me. how to get perfect output your code.

    • Kirit

      Hello sir please give me answer how to solve my problem? i wan’t to ask u question sir please help. i studding in phone gap so u can solve the my problem.

  • http://tuanbach.wordpress.com Tuan

    Hi,

    The post is really interesting. Thanks to share your skills guys!! :)

    However as a “native Android developer” I just want to define the term used here: “Converting Into A Native Android Application”

    The title is very buzzing for a android developer as me because I was thinking that you found a way to compile and convert JS/Zeb files to Java codes… which is not the case here.

    So I will say to be exact that you are actually creating a simple web browser to browse directly your web app on android.

    By understanding this situation, I will advise you guys to develop this kind of App to congregate (just as flash apps do with Kongregate, available now on the Market) all your web apps on one “browser App”.

    So in this way you just have to create one Apk and get updated applications list directly from the net.

    Hope it make sense for you…

    Cheers guys!

  • http://oscar.solisdatacom.com/ Rick Ramirez

    I have tried averything and the code just spins it’s wheels in loading the rss…

    Please help

    • Haura

      I got the same problem as you. Have it been solved ?

  • Jason

    Hi,

    What if I want to load another URL like index2.html from the index.html.

    I tried doing the same but if I do that then i think it loads a URL like:

    file:///android_asset/www/index.html#index2.html.. And all the jQuery and Css are not loaded..

    Can you please help me with this.

    Sample : Observe

    Thanks,
    jason

  • Bogdan Mogosanu

    I’ve tried to install News.apk on a HTC Sensation – Android 2.3.4 and didnt worked. Application manager simply throw me the “Application not installed” error. The News.apk has 76kb size….Its correct?

    On the emulator works fine (with Android 2.3.1)….

    • Bogdan Mogosanu

      UPDATE: Ive installed the .apk from bin directory (generated by Emulator). Everything its ok, but the application did not resize on the full resolution.

  • WWWillem

    This looks very promising, but unfortunately it doesn’t work. Could it be that Yahoo changed???

    I downloaded the sources, extracted the zip and then pointed my browser (tried multiple FFs and Safari) at …/news-web-code/index.html.

    Thought that would keep things simple.

    First page only shows “Categories” and an “Add” button. Next page let me “Select a Category”, and I press “Get Category”.

    Result is a page “Processing…” with a spinning wheel. Nothing happens after that.

    Willem

  • fauzi

    hi,
    nice tutorial,
    i am trying test your tutorial and run http://localhost/news/bridge.php?fwd=http://rss.news.yahoo.com/rss/business

    i have a problem,
    the following error –

    This page contains the following errors:

    error on line 2 at column 1: Extra content at the end of the document

    Below is a rendering of the page up to the first error.

    please help me, I have a homework :)

    thank’s for help.

  • darkarchon

    Can you specify how to make a native App for iOS with jQuery Mobile?

  • http://seo seo

    Simply want to say your article is as astounding. The clearness in your post is simply nice and i can assume you are an expert on this subject. Well with your permission allow me to grab your feed to keep up to date with forthcoming post. Thanks a million and please carry on the rewarding work.

  • http://twitter.com/91_pavan Pavan

    Really good tutorial . Worked perfectly fine when i ran this application on my emulator but then i ran this application on my phone . The delete button is not working . If i click on delete , its opening the contents page . Please help . Is it because i’m running it on a android 2.2 device? Thanks.

  • http://twitter.com/91_pavan Pavan

    Very nice tutorial . However , from past few days i’m not able to go to the news page when i click on a news image . It says , 611 error . The webpage your looking for is unavailable . Please help . Urgent .

  • http://www.webspeaks.in Arvind Bhardwaj

    Excellent writeup.
    Thanks for such a nice tutorial.

  • Bernd

    Nice! Thank you! But do you have a clue, why sometimes the screen is just blank, after starting the app?

  • Will Smith

    Hi

    Like Bernd stated why is it that sometimes when you go into the app the screen is blank, I can go in once select a couple categories, select one, read it, then back out of the app then come back in and it is completely blank. This is the full downloaded app, any suggestions.

    Will

  • JCarlos

    Hi,
    a very good tutorial!!!
    Anyway, i have some problem, i have follow the tutorial and i have a mini-page to try the jquery. When I view it in the emulator in eclipse and directly opening with a web browser it works fine, but when i download to any android phone or tablet the css and style is not loading (i suposse) because appears the content without the styles.
    Have you any idea what is the problem?

    Thanks in advance.

  • Thom

    For people having the “extra content at the end of the document error” here’s a fix.

    in index.html, replace
    var NEWS_URI = ‘bridge.php?fwd=http://rss.news.yahoo.com/rss/’;
    with
    var NEWS_URI = ‘bridge.php?fwd=http://news.yahoo.com/rss/’;

    This will ask yahoo to get an xml feed.
    It worked for me.

  • Jack

    Hi I am having problems with the processing page, it is just stuck there.. I have followed everything from part 1 till here.. Do I need to do something else?

  • Nick

    Have you made the source code for this available?