In A Simple First App we created our first simple app. Let's now build a somewhat more sophisticated Android project. We shall put two buttons on the screen, and then have the buttons load particular web addresses into new screens when they are pressed. This is more advanced than our first simple project because now we must manage more than one button on the screen, and because in the Simple First App project we displayed a webpage using the default web browser built into the system, but in this project we shall display the content of web addresses in a basic browser that we shall create and manage ourselves programatically using the Android WebView class.
Although all of these steps are fairly rudimentary, completing them will already teach us a lot about how to build Android applications. In this one example we shall gain experience in how to
  • Create an Eclipse project
  • Use Eclipse to debug and correct errors
  • Define string and color resources in external files
  • Lay out a basic user interface in XML
  • Add a click listener and associated event handling to the interface
  • Use an Intent to launch a new Activity
  • Add new Java and XML files to a project
  • Use the manifest file
  • Leverage Android lifecycle management for multitasking
  • Use and control objects of the WebView class
  • Compile and test an Android application on an emulator or device
In short, when we finish this project we will have already touched on many basics of Android development. So let's get started!

Creating the Project in Eclipse

Following the general procedure in Creating a New Project, open Eclipse and click File > New > Project. Then Select Android > Android Application Project, and click Next. Fill out the resulting window as in the following figure,



(except that you should substitute your namespace for com.lightcone in the package name and in what follows).


Namespaces are explained further in Creating a New Project. Our choices above indicate that we are choosing to build against Android 4.4 (API level 19), but that we intend to write the program so that it will run under Android versions as early as 2.2 (API level 8). Of course this is just a declaration of intention at this point. We shall have to take care to use only code that is compatible with Android 2.2, and confirm with testing when we are finished that it will indeed run under Android versions from 2.2 to 4.4.)

Click Next and on the subsequent screens keep the default values as in the example in Creating an Android Project and continue to click Next; finally click Finish on the last screen. A project WebViewDemo should now appear in the left panel of the Eclipse interface, as in the figure below. If the project is not open, click the right triangle to open it, and then click successive right triangles to open WebViewDemo/src/<YourNamespace>/webviewdemo. There should be a single file, MainActivity.java showing in the Package Explorer panel. If it is not already open, double click it to open the file in the Eclipse editing window:


We see that Eclipse has generated automatically a stub for the MainActivity class:
    package <YourNamespace>.webviewdemo;

    import android.app.Activity;
    import android.os.Bundle;
    import android.view.Menu;

    public class MainActivity extends Activity {

        /** Called when the activity is first created. */
        @Override
        public void onCreate(Bundle savedInstanceState) {
            super.onCreate(savedInstanceState);
            setContentView(R.layout.activity_main);
        }

        @Override
        public boolean onCreateOptionsMenu(Menu menu) {
            // Inflate the menu; this adds items to the 
            // action bar if it is present.
            getMenuInflater().inflate(R.menu.main, menu);
            return true;
        }
    }
This is a short segment of code, but it already does a lot. We (through our loyal sidekick Eclipse) have now:
  • Inserted some imports with class definitions that will be required.

  • Subclassed (extended) the Android class Activity so that our new class MainActivity inherits all of its properties and methods.

  • Overriden (replaced) the onCreate() method that was inherited from Activity with our own custom definition of the method, which begins by invoking onCreate of the superclass but then adds more (with still more to be added later).


    The @Override is an annotation used to mark methods that override a method declaration in a superclass. Its use is optional but compilers produce an error if a method annotated with @Override does not actually override a method in a superclass, so it provides a useful automatic consistency check.


  • Retrieved the Bundle savedInstanceState, which contains initialization information, including the information saved by Android if our app has already been running and is being brought back to the foreground. This complex task is handled automatically by Android; a Bundle is a way to store "bundles" of information as name-value pairs. A more extensive discussion of how this is done in Android may be found in the project Lifecycle Methods and in the general discussion under Application Lifecycles.

  • Invoked the setContentView(R.layout.activity_main) method that MainActivity inherits from Activity to "inflate" (instantiate from the XML) the UI (User Interface) view associated with the file res/layout/activity_main.xml---the stub of which was created automatically when the project was created)---that defines the layout of our app's initial screen. The integer R.layout.activity_main is Android's ID for the resource that will be supplied from res/layout/activity_main.xml at compile time.

  • Invoked the onCreateOptionsMenu (Menu menu) method that MainActivity inherits from Activity to initialize the contents of the Activity's standard options menu. Menu items will be placed in menu, which is an object of type Menu. You can add items to this menu and handle clicks on your additions. This method will instantiate from the XML the menu view associated with the file res/menu/main.xml, which is referenced from Android by the integer R.menu.main at compile time.
Before proceeding, if the import commands at the top of this file are folded up in the Eclipse code listing, click the + sign to their left to expand them.

Adding OnClickListener

Let us now modify this stub so that it can do some useful things. First, since we are going to add button widgets to the page for which we will need to listen for and process click events, we have the class implement the OnClickListener interface by modifying the first line defining the class to read
   public class MainActivity extends Activity implements OnClickListener { 
The Eclipse display of the file should now look like the following figure


Notice that now in Eclipse
  1. there is a small red x to the left of line 6, indicating an error, and that

  2. in that line OnClickListener is underlined with a wavy red line, indicating that it is the source of the error (we are assuming that Project > Build Automatically is checked so that Eclipse attempts to build as we make changes).
If we hover the mouse over the red x we get the popup message "OnClickListener cannot be resolved to a type", and if we hover over the wavy red underline we get a number of suggested possible quick fixes for the problem, as illustrated in the following figure.


Since OnClickListener is an Android interface, the most likely problem is just that we have not imported the appropriate Android classes and indeed the first two options for quick fixes indicate that we should import android.view.View or android.content.DialogInterface. We can insert one of these import statements manually, but Eclipse will do it for us: clicking on the second choice, we see that Eclipse automatically inserts a new import statement
   import android.view.View.OnClickListener;
(If the import statements are folded up, click the + beside them to expand them.) There is still a red x, but now
  1. it is MainActivity that is underlined by a wavy red line, and

  2. if we hover over the red x we see the popup message "The type MainActivity must implement the inherited abstract method View.OnClickListener.onClick(View)".
If we then hover over MainActivity we get the following popup window.


If we select the quick fix "Add unimplemented methods" and select File > Save (ctrl-S), Eclipse will fix it for us by adding a stub for the method and a required import. Now our code reads
    package <YourNamespace>.webviewdemo;
    import android.app.Activity;
    import android.os.Bundle;
    import android.view.View;
    import android.view.View.OnClickListener;

    public class MainActivity extends Activity implements OnClickListener {

        /** Called when the activity is first created. */
        @Override
        public void onCreate(Bundle savedInstanceState) {
            super.onCreate(savedInstanceState);
            setContentView(R.layout.activity_main);
        }

        @Override
        public boolean onCreateOptionsMenu(Menu menu) {
            // Inflate the menu; this adds items to the 
            // action bar if it is present.
            getMenuInflater().inflate(R.menu.main, menu);
            return true;
        }

        @Override
        public void onClick(View v) {
            // TODO Auto-generated method stub
        }
    }
where the added code is indicated in red. This should compile with no error messages because a stub for the method onClick(View v) has been inserted (with a "TODO" comment, indicating that this is just a stub satisfying the formal requirements for the interface, but we still must add the code appropriate to our goals).

An interface in Java is a reference type similar to, but not the same as, a class. An interface cannot contain any method bodies, only constants, nested types, and method signatures (methods without bodies). An interface cannot be instantiated; it can only be
  • implemented (by classes), or

  • extended (by other interfaces).
An abstract method is one that is declared without an implementation (with the expectation that the implementation will be supplied by something else). If a class contains abstract methods, it itself must be declared abstract. All methods of an interface are implicitly abstract.

When a class implements an interface, it must provide a method body for each of the methods declared in the interface, or the class must be declared abstract. Notice that these were the two quick-fix options suggested above by Eclipse:
  1. add the unimplemented method onClick(View v), or

  2. declare the class MainActivity abstract
for the error introduced when we implemented the OnClickListener interface.


Eclipse Is Only a Faithful Servant

Obviously Eclipse has been very helpful in laying out the basic initial structure of our class, but it has only done what a good programmer would have done by a manual analysis.
  1. When we added "implements OnClickListener" it was necessary to import the Android classes defining this interface, and since an interface in Java generally requires that certain methods be implemented (even if only as stubs), we had to add those required methods.

  2. In this case, if we had consulted the Android documentation by going to the Android developer docs and putting "OnClickListener" in the search field we would have gotten two options:
    • android.view.View.OnClickListener

    • android.content.DialogInterface.OnClickListener

  3. Choosing the first we get documentation for the interface View.OnClickListener. So we must import android.view.View.OnClickListener.

  4. Furthermore, we find on the same page that this interface has the single method public abstract void onClick (View v).

  5. Thus, by the general rules for Java interfaces, we must provide an implementation of this method if we employ the interface View.OnClickListener (or we must declare the class abstract).
All that Eclipse has done is carry out this sequence of programmer deductions rather automatically.

Layout of the User Interface

Now we wish to
  1. lay out a page containing some button widgets,

  2. define event handlers for the buttons, and

  3. implement some actions when the buttons are clicked.
First let's define some string and color resources that we will need. Open in the left panel res/values and double-click on the file strings.xml to open it (if the file text is not displayed, click the strings.xml tab at the bottom). Edit the file to read
    <?xml version="1.0" encoding="utf-8"?>
    <resources>
        <string name="app_name">WebViewDemo</string>
        <string name="action_settings">Settings</string>
        <string name="button1_label">Mojito Recipe</string>
        <string name="button2_label">NOAA Tropical Satellite</string>
    </resources>
and save the strings.xml file. Now create a new file under res/values called colors.xml:
  1. Right-click on values and select New > Android XML File.

  2. In the resulting window, set (many of these will already be set)

    • Project to WebViewDemo,

    • File to colors.xml,

    • Resource Type to Values, and

    • Root Element to Resources

  3. Click Finish.
This will create a new file in the left panel under res/values called colors.xml. Double-click to open and edit it to read as follows:
    <?xml version="1.0" encoding="utf-8"?>
    <resources>
        <color name="background">#ffe6d6bd</color>
    </resources>
Save the colors.xml file.

In Android, 32-bit colors with alpha-opacity are specified by a sequence #AARRGGBB where
  • AA is a hexadecimal (hex) number defining the alpha-opacity,

  • RR is a hex number defining the amount of red,

  • GG is a hex number defining the amount of green, and

  • BB is a hex number defining the amount of blue.
The hex numbers range from 00 to ff (that is, 0-255 decimal), with 00 meaning no contribution for the component and ff meaning full contribution. For example, opaque black would be specified by #ff000000 (full opacity, but no RGB colors). It is also possible to define
  • 24-bit color (#RRGGBB),

  • 16-bit color with alpha-opacity (#ARGB),

  • and 12-bit color (#RGB).
Finally, the Color class has a few colors predefined as static constants (for example, Color.MAGENTA or Color.TRANSPARENT).


You can also create these XML and Java files manually using a text editor by navigating to the appropriate directories in the directory tree of your workspace on your disk that corresponds to the project tree in Eclipse. Be very careful with editing XML however, as it requires exact syntax and form or it will generate an error message when you try to compile. For example, any whitespace before the first XML line may generate an error message.

We are now ready to lay out the opening screen of our app. Open res > layout and double-click on activity_main.xml to open it. Edit it to read
     <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
         android:orientation="vertical"
         android:layout_width="fill_parent"
         android:layout_height="fill_parent"
         android:background="@color/background"
         android:padding="30dip" >

         <TextView  
         android:layout_width="wrap_content" 
         android:layout_height="wrap_content" 
         android:text="@string/app_name"
         android:layout_gravity="center"
         android:layout_marginBottom="25dip"
         android:textSize="24.5sp" />

         <Button
         android:id="@+id/button1"
         android:layout_width="fill_parent"
         android:layout_height="wrap_content"
         android:text="@string/button1_label"
         android:textSize="18sp" />
         
         <Button
         android:id="@+id/button2"
         android:layout_width="fill_parent"
         android:layout_height="wrap_content"
         android:text="@string/button2_label"
         android:textSize="18sp" />

      </LinearLayout>
Save the file when you have completed the changes. In this file
  • The LinearLayout parent element has an orientation="vertical" attribute, so it will lay out its children (a TextView and two Buttons ) vertically.

  • The wrap_content attributes attempt to wrap children into a minimal space while the fill_parent attributes attempt to fill the parent container with the children. It is strongly advised to specify layout height and width in terms of these constants rather than in absolute terms, since then Android can adapt the display to devices with different screen sizes.

  • The "@" constructions refer to variables defined in the resource files. Thus, @string/var1 refers to the variable var1 in the file strings.xml and @color/var2 refers to the variable var2 in the file colors.xml.

  • The android:id="@+id/label1 constructions define labels for elements that we will reference from the Java code.

  • The attribute background specifies a background color, the attribute layout_gravity defines preferred positioning, and padding and marginBottom define padding and margins, respectively.
The units for sizes and distances used in this layout are discussed in the following box, and a more complete discussion of XML attributes may be found in the Android Layout document. A comprehensive list of XML attributes in Android may be found at R.attr.

Notice the size units dip, sp in these layout elements. Generally in Android layout sizes can be specified in
  • pixels (px),

  • millimeters (mm),

  • inches (in),

  • points (pt), which are equal to 1/72 of an inch,

  • density-independent pixels (dp or dip), or

  • scale-independent pixels (sp).
It is good practice to use sp for font sizes and dip for other user interface sizes rather than absolute units like inches or pixels, since then your interface will scale better on different devices with different screen resolutions.

We now should have an opening screen laid out that will display two buttons. Execute the program on an emulator or a phone or tablet:
  1. Right-click on WebViewDemo in the left panel.

  2. Select Run As > Android Application.

  3. Launch and/or choose an appropriate emulator, or choose a connected device, if prompted to do so. If you use an emulator, try initially the android4.3 emulator configured in Configuring an AVD .
For example, the following prompt asks to choose between the android4.3 emulator and a Galaxy Nexus phone attached to the computer by USB


Choose and click OK. You should see on the emulator or device a screen like that shown below (which is a screenshot from a Galaxy Nexus phone),


where the strings displayed as titles and button labels were those defined in strings.xml, and the background color was defined in colors.xml.

Using Intents to Launch New Activities

This is now a user interface with a label and two buttons, but it doesn't do anything except that the buttons may change color momentarily to indicate that they have been clicked by the mouse on the emulator (or pressed by a finger on an actual device). Now we shall add event handlers to cause actions to be taken when the buttons are clicked. When each button is clicked, we wish to launch a new screen (that will replace the original screen) on which we are going to do something. As we discussed in Android User Interfaces the standard way to do that is to launch an intent, with the corresponding screen defined by a new Java class. Let's first create the basic stub for the new class, leaving some details to be filled in later, and then define the event handlers that open the new screen.
Right click on src/<YourNamespace>.webviewdemo and select New > Class. On the resulting screen, fill in the blanks as in the following figure and click Finish.


This should create a new file Webscreen.java under src. Edit this file so that it has the content
    package <YourNamespace>.webviewdemo;
    
    import android.app.Activity;
    import android.os.Bundle;
    import android.webkit.WebView;
    import android.util.Log;
    
    public class Webscreen extends Activity {

        public static final String URL = "";

        /** Called when the activity is first created. */
        @Override
        public void onCreate(Bundle savedInstanceState) {
            super.onCreate(savedInstanceState);
            setContentView(R.layout.webscreen);
        }
    }
(We've added several imports and defined a String variable URL that we will need shortly.) If you save this file
  1. There will be a red x on the setContentView line, with a wavy red line under R.layout.webscreen.

  2. Hovering over these with the mouse will indicate that the error is associated with a missing R.layout.webscreen source.

  3. The R. notation indicates that this is a resource that Java expects Android to supply at compile time.

  4. The full notation R.layout.webscreen indicates that it expects this resource to reside in a file res/layout/webscreen.xml, which of course has not been created yet.

At compilation, each XML resource file is compiled into a View resource.
  • The resource is loaded by calling setContentView(int layoutResID) from the Activity.onCreate() callback, which is called by the Android framework at launch of the app; see the lifecycle diagram in Application Lifecycles.

  • The reference layoutResID to your layout resource is passed as an argument to setContentView in the form R.layout.layout_file_name, where layout_file_name is the name of the file (without extension) that you have placed in res/layout containing the layout specification.
For a more extensive discussion, see the Android Layout document.

So we fix this problem by adding a file webscreen.xml that will define the layout of the new screen:
  1. Right-click on res/layout and select New > Android XML File.

  2. On the resulting screen choose a file name webscreen.xml, a resource type of Layout, and a LinearLayout for the XML root element.
Click Finish and edit the resulting file (webscreen.xml under res/layout) so that it reads
    <?xml version="1.0" encoding="utf-8"?>
        <LinearLayout
            xmlns:android="http://schemas.android.com/apk/res/android"
            android:orientation="vertical"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content">
        </LinearLayout>
If you save this you should now find that the error indicated for Webscreen.java has disappeared because now the resource webscreen.xml (which is supplied as R.layout.webscreen by Android at compilation) is defined.

Event Handlers

Now we add event listeners and edit the onClick method of MainActivity.java to add the corresponding event handlers so that the file MainActivity.java reads
    package <YourNamespace>.webviewdemo;
    import android.app.Activity;
    import android.content.Intent;
    import android.os.Bundle;
    import android.view.View;
    import android.view.View.OnClickListener;
    
    public class MainActivity extends Activity implements OnClickListener {
        /** Called when the activity is first created. */
        @Override
        public void onCreate(Bundle savedInstanceState) {
            super.onCreate(savedInstanceState);
            setContentView(R.layout.activity_main);

            // Add Click listeners for all buttons
            View firstButton = findViewById(R.id.button1);
            firstButton.setOnClickListener(this);
            View secondButton = findViewById(R.id.button2);
            secondButton.setOnClickListener(this);

        }

        @Override
        public boolean onCreateOptionsMenu(Menu menu) {
            // Inflate the menu; this adds items to the 
            // action bar if it is present.
            getMenuInflater().inflate(R.menu.main, menu);
            return true;
        }
    
        // Process the button click events
        @Override

        public void onClick(View v) {
            switch(v.getId()){
                case R.id.button1:
                    Intent j = new Intent(this, Webscreen.class);
                    j.putExtra(<YourNamespace>.webviewdemo.Webscreen.URL, 
                        "http://eagle.phys.utk.edu/guidry/recipes/mojito.html");
                    startActivity(j);
                break;
                
                case R.id.button2:
                    Intent k = new Intent(this, Webscreen.class);
                    k.putExtra(<YourNamespace>.webviewdemo.Webscreen.URL, 
                        "http://www.ssd.noaa.gov/goes/east/tatl/vis-l.jpg");
                    startActivity(k);
                break;      
            }
  
        }
    }
where the added and modified lines are indicated in red. A number of important things are happening in this compact segment of code:
  • The Views corresponding to the two buttons are sorted out by using the findViewById method of Activity so that ClickListeners can be assigned to them.

  • The arguments R.id.mywidget are references to the id values assigned to widgets in the XML layout files using the @+id construction. For example, in the above code R.id.button1 references the Button with attribute android:id="@+id/button1" in the layout file for the initial screen activity_main.xml.

  • The View v argument of the onClick(View v) callback allows the button that was pressed to be determined by the switch statement on v.getId().

  • When the correct button has been identified, a new Intent is instantiated corresponding to the new class (Webscreen) to be launched and the corresponding activity is initiated using the startActivity(Intent i) method that Activity inherits from Context.


    Context is an abstract class implemented at Android system level that provides an interface to global information about an application environment. One common use of Context is to broadcast and receive Intents and launch Activities.


  • The putExtra method of Intent passes values of variables from the launching class to the class launched by the intent, as described in the following box.
The putExtra method of the Intent class is a way to pass variables to the class that will be launched by the intent. In this case the value of a string corresponding to a web address (the first argument of putExtra) is communicated by assigning its value to a string variable defined in the class launched by the intent (the second argument), but variables of other types may be passed in this way also. See the various overloaded versions of putExtra(String name, Bundle value) documented under the class Intent. Note that the variable name in the putExtra arguments must have a package prefix (e.g., <YourNamespace>.myClass rather than myClass).

This should now compile, but if we launch it on the emulator or device and press one of the buttons we get an error popup:


Checking the logcat file (see The Purr of the Logcat) we find the source of the problem immediately:
      06-12 22:57:11.302 I/ActivityManager(59):Starting activity:Intent { cmp=com.lightcone.webviewdemo/.Webscreen (has extras)}
      06-12 22:57:11.302 D/AndroidRuntime(399):Shutting down VM
      06-12 22:57:11.302 W/dalvikvm(399): threadid=1:thread exiting with uncaught exception (group=0x4001d800)
      06-12 22:57:11.342 E/AndroidRuntime(399):FATAL EXCEPTION: main
      06-12 22:57:11.342 E/AndroidRuntime(399):android.content.ActivityNotFoundException: Unable to find explicit activity class
      {com.lightcone.webviewdemo/com.lightcone.webviewdemo.Webscreen}; 
      have you declared this activity in your AndroidManifest.xml?
This is because Android requires that all activities must be declared in the AndroidManifest.xml file. To fix it,
  1. open AndroidManifest.xml (select the .xml tab at the bottom if the XML code is not displayed) and

  2. add an appropriate <activity></activity> tag within the <application></application> tag
so that the manifest file now reads
   <?xml version="1.0" encoding="utf-8"?>
   <manifest xmlns:android="http://schemas.android.com/apk/res/android"
      package="<YourNamespace>.webviewdemo"
      android:versionCode="1"
      android:versionName="1.0" >
      <uses-sdk
         android:minSdkVersion="8"
         android:targetSdkVersion="18" />
      <application
         android:allowBackup="true"
         android:icon="@drawable/ic_launcher"
         android:label="@string/app_name"
         android:theme="@style/AppTheme" >
         <activity
               android:name="<YourNamespace>.webviewdemo.MainActivity"
               android:label="@string/app_name" >
               <intent-filter>
                  <action android:name="android.intent.action.MAIN" />
                  <category android:name="android.intent.category.LAUNCHER" />
               </intent-filter>
         </activity>
         <activity android:name=".Webscreen" android:label="Web"> </activity>
      </application>
   </manifest>
where the added line is highlighted in red. If we execute in the emulator, clicking on the first button loads a new blank screen, hitting the return button on the phone keyboard returns us to the first screen, and clicking on the second button again loads a new blank screen. Now we just need to add content to these blank screens.

Adding WebViews

First, let's check that the variables are being passed by the putExtra command to the new activities launched with the intent. Edit the file Webscreen.java so that it reads
    package <YourNamespace>.webviewdemo;
    import android.app.Activity;
    import android.os.Bundle;
    import android.webkit.WebView;
    import android.util.Log;

    public class Webscreen extends Activity {
            
        public static final String URL = "";
        private static final String TAG = "Class Webscreen";
        
        /** Called when the activity is first created. */
        @Override
        public void onCreate(Bundle savedInstanceState) {
            super.onCreate(savedInstanceState);
            setContentView(R.layout.webscreen);   
            String turl = getIntent().getStringExtra(URL);
            Log.i(TAG, "Recipe url = "+turl);     
        }
    }
The getIntent().getStringExtra(URL) now assigns the string variable passed using putExtra, and the Log.i allows us to check whether the variable is being passed correctly.

The method getIntent() of the Activity class returns the Intent that started the activity. The method getStringExtra(String) of the Intent class takes a String argument corresponding to a variable passed to the Intent using putExtra() and returns its String value. Thus the net effect of the chained expression
    String turl = getIntent().getStringExtra(URL);
is to use the getIntent() method of Webscreen (which it inherits from its superclass Activity) to return the Intent that launched Webscreen, and then to use the getStringExtra method of that Intent to return the String corresponding to the variable URL that was passed to the Intent using the Intent method putExtra(), and finally assign it to the local String variable turl.

Executing the app in the emulator after these changes and clicking the two buttons successively we find in the logcat output
      06-12 23:40:19.131 I/ActivityManager(59):Starting activity: Intent { cmp=com.lightcone.webviewdemo/.Webscreen (has extras)}
      06-12 23:40:19.231 I/WebscreenClass(501): URL=http://eagle.phys.utk.edu/guidry/recipes/mojito.html
      06-12 23:40:19.521 I/ActivityManager(59): Displayed activity com.lightcone.webviewdemo/.Webscreen: 354 ms (total 354 ms)
      06-12 23:40:22.071 W/KeyCharacterMap(501): No keyboard for id 0
      06-12 23:40:22.071 W/KeyCharacterMap(501): Using default keymap: /system/usr/keychars/qwerty.kcm.bin
      06-12 23:40:23.361 I/ActivityManager(59): Starting activity: Intent{ cmp=com.lightcone.webviewdemo/.Webscreen (has extras)}
      06-12 23:40:23.441 I/WebscreenClass(501): URL=http://www.ssd.noaa.gov/goes/east/tatl/vis-l.jpg
Thus, the web addresses are indeed being passed to the Webscreen instance. Now finally, let us embed a WebView in the screen generated by the Webscreen object so that we can display these web addresses as web pages. Add code to Webscreen.java so that it reads
    package <YourNamespace>.webviewdemo;
    import android.app.Activity;
    import android.os.Bundle;
    import android.webkit.WebView;
    import android.util.Log;

    public class Webscreen extends Activity {
            
        public static final String URL = "";
        private static final String TAG = "WebscreenClass";
        
        /** Called when the activity is first created. */
        @Override
        public void onCreate(Bundle savedInstanceState) {
            super.onCreate(savedInstanceState);
            setContentView(R.layout.webscreen);
            
            String turl = getIntent().getStringExtra(URL);
            Log.i(TAG, " URL = "+turl);
            
            WebView webview = new WebView(this);
            setContentView(webview);
    
            // Simplest usage: No exception thrown for page-load error
            webview.loadUrl(turl);  

        }
    }
This should compile, but when we try to execute in the emulator we find that the buttons attempt to load webpages but we get error messages in both cases that the webpage is not available. There could be many reasons (like the network being down) for such messages but in this case the explanation is quite basic: we have not yet done one final thing that is required for an Android application that tries to access the internet. It must be given explicit permission to do so, and this is done by adding to the AndroidManifest.xml file a permission line (which must be within the manifest tag)
    <uses-permission android:name="android.permission.INTERNET" />
So that the AndroidManifest.xml file now reads
   <?xml version="1.0" encoding="utf-8"?>
   <manifest xmlns:android="http://schemas.android.com/apk/res/android"
      package="<YourNamespace>.webviewdemo"
      android:versionCode="1"
      android:versionName="1.0" >
      <uses-sdk
         android:minSdkVersion="8"
         android:targetSdkVersion="18" />
      <application
         android:allowBackup="true"
         android:icon="@drawable/ic_launcher"
         android:label="@string/app_name"
         android:theme="@style/AppTheme" >
         <activity
               android:name="<YourNamespace>.webviewdemo.MainActivity"
               android:label="@string/app_name" >
               <intent-filter>
                  <action android:name="android.intent.action.MAIN" />
                  <category android:name="android.intent.category.LAUNCHER" />
               </intent-filter>
         </activity>
         <activity android:name=".Webscreen" android:label="Web"> </activity>
      </application>
      <uses-permission android:name="android.permission.INTERNET" />
   </manifest>
Now if we execute in the emulator or on a device we obtain the left figure below when we click on the first button and the right figure below when we click on the second button (these are screen shots from a Galaxy Nexus phone running Android 4.2).


So our application is indeed loading and displaying---under our complete programming control---arbitrary webpages using an extension of the WebView class.

Each time you have run WebViewDemo on an emulator or device, the project has been installed on that emulator or device (through the .apk file). If you look in the apps folder of the device or the emulator, there should now be an icon labeled WebViewDemo, and you can launch the app by pressing that icon.




By default, when a project is created in Eclipse a file called ic_launcher.png that corresponds to a stock Android image (see the icon for WebView Demo in the above figure) is placed in all res/drawable directories corresponding to images to be used for devices of different screen resolution: (res/drawable-hdpi, res/drawable-ldpi, res/drawable-mdpi, res/drawable-xhdpi, and res/drawable-xxhdpi), and a line

    <application
       android:allowBackup="true"
       android:icon="@drawable/ic_launcher"
       android:label="@string/app_name"
       android:theme="@style/AppTheme" >
is inserted in the AndroidManifest.xml file for the project. This causes the project to use the image in the ic_launcher.png file as the app icon. You can customize your app by placing your own icon file in the res/drawable directory and changing the android:icon tag in the manifest file shown above to point to the new image. The icon file must be in .png, .jpg, or .gif format, with .png preferred, and only lower-case letters, numbers, and the symbols _ and . may appear in the file name.

NOTE: In older versions of Android the default name of the app icon was icon.png. You can check the default name in the version in which you are developing by looking at the content of the res/drawable-hdpi directory or at the Manifest file in Eclipse.

Use of a customized launcher icon (and other icons used in your app) is optional for development but you will certainly want to do this if you release your app for others to use. There are some tricks of the trade associated with effective icon design for small screens. If you decide to make a custom icon, consult the Android icon design guidelines in the Iconography document for guidance.


The complete project for the application described above is archived at the link WebViewDemo. Instructions for installing it in Eclipse may be found in Packages for All Projects.

Source: http://eagle.phys.utk.edu/guidry/android/webviewdemo.html

Post a Comment

 
Top