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/';
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;
- });
- }
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 jQueryajax()
function. We callget()
passing to it an empty URL and a callback handler, that sets thewindow.location
variable to the input argument. The input argument is the URL in the<a href='...'>
attribute enclosed within ana
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 ourActivity
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 invokesetContentView()
to load the layout file for this Activity. The input argument tosetContentView()
isR.layout.main
which is a reference tomain.xml
in theres/layout
folder. - We get a handle to the
WebView
viafindViewById(R.id.webview)
. We set a customWebViewClient
on theWebView
, namedNewsClient
(to be reviewed soon). Then, we configure theWebView
to allow JavaScript execution and the DOM storage API (the latter is necessary to use HTML5localStorage
). - Finally, we ask the
WebView
to load theindex.html
page that has the UI code.
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);
- }
- ...
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;
- }
- }
- ...
- }
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 customWebViewClient
is essential to display the News Detail page as part of the News application (i.e. in the sameWebView
that hosts theindex.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;
- }
WebView
that hostsindex.html
. However, the transition from the News page to the News Detail page would not include showing the progress page.
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>
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 theconfigChanges
attribute whereorientation
corresponds to orientation change andkeyboardHidden
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>
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.
No comments:
Post a Comment