Android Development Android Development Prerequisites

The Android development environment must be set up before starting development. See the Android Setup page for instruction on how to install and configure the Oracle SE JDK, the Eclipse IDE, the Android SDK, and the Eclipse ADT plugin. Instructions for setting up Android Virtual Devices are in Android Setup - Android Virtual Devices. This Android development used Java SE6. See Java SE Version 6 - API Specifications. Also see the Android APIs by version.

HelloAndroid | XML | Screen Layouts | Activities | Activity Creation | Intents | Intent Extras | Activity State | | Event Listeners | Spinners | List Views | Menus | WebViews | Custom Views

First Android Program Hello Android!

Create Android Project and Package:

  1. In the Package Explorer view of Eclipse, right-click and select New -> Project -> Android Application Project.

  2. Enter:
    1. Application Name (e.g. HelloAndroid)
    2. Project Name (e.g. HelloAndroid)
    3. Package Name (e.g. net.kcshadow.helloandroid) and select finish.
    4. I am using API 8 as the Minimum Required SDK and API 17 at the Target and Compile With SDKs.
    5. I selected "Holo Light with Dark Action Bar" for the Theme.

  3. On the Configure Project screen, these items were selected:
    1. Create custom launcher icon
    2. Create activity
    3. Create Project in Work Space (C:/Users/Kevin/workspace/HelloAndroid)

  4. On the Configure Launcher Icon screen I accepted the defaults.

  5. On the Create Activity screens I chose "Blank Activity" and a Navigation Type of "None".

  6. The Android project, package, and default set of source files is now set up".

Note, in the src directory of the project a file called "MainActivity.java" was created as:

  package net.kcshadow.helloandroid;
  import android.os.Bundle; 
  import android.app.Activity; 
  import android.view.Menu;
  
  public class MainActivity extends Activity { 
  
     @Override 
     protected 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.activity_main, menu);
     return true;
     } 
  } 

In the res, values directory of the project, a file called "strings.xml" was created. Edit the "hello_world" string to have a value of "Hello Kevins Android!".

Run Program using Emulator

To run the program using Eclipse ADT emulator:

  1. Select the project in the Package Explorer window and chose: Run -> Run Configurations. You can choose Debug Configurations if you wish to debug the application.

  2. Select the "HelloAndroid" project and the desired Android Virtual Device (AVD) target. See Android Virtual Device Setup for instructions on setting up an Android emulator.
Note: You may also run and debug on a physical device if it is attached to the computer and the device is in Developer mode.

Install Android Application on Physical Device

To install and run app on a real device:

  1. Turn on Android device.

  2. Connect the Android device to the development computer using a USB Cable.

  3. Enable USB debugging on Android device.
    • Note: On Android 4.0 and newer USB debugging is under Settings -> Developer Options.
    • Note2: On Android 4.2 and newer, Developer Options is hidden by default. To make it available, go to Settings -> About and tap the Build Number seven times. Return to previous screen to now find the Developer Options.

  4. In Eclipse, select the project and make sure none of the Android simulators (AVDs) are selected.

  5. From the tool bar, select Run -> Run as -> Android Device -> OK. Eclipse should install the application to the Android device and start the app.
Android XML Files Android Application: Program Code and Resources

Android uses a combination of program code and resource data (stored in XML files) to define applications. Application behaviors, layout, and resources can be declared in XML files.


Android Manifest File: AndroidManifest.xml

A file named AndroidManifest.xml must be included in the root directory of every Android project. The file contains essential information about the project to the Android operating system. Android uses the information in this file to


Android User Interface Resources: activity_main.xml

Android can use either program code or XML resource files for declaring and managing the user interface. Typically the user interface components are declared with XML files and program code is used to interact with the components. This approach separates the application's presentation from the code that controls its behavior. This separation allows multiple GUIs to be developed for different device screens with only one code base required for an application.

The Eclipse ADT plugin has a Graphical Layout tool for creating the user interface and underlying XML files. In the project's res/layout folder is an activity_main.xml file. In the Graphical Layout tool you can drag and drop a GUI component, such as a button, on to the screen form. You can then see the XML code has been generated in the activity_main.xml file for the button:


    <Button
        android:id="@+id/button1"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_alignParentLeft="true"
        android:layout_alignParentTop="true"
        android:layout_marginLeft="54dp"
        android:layout_marginTop="41dp"
        android:text="Button" />
         

In addition, Eclipse's Hierarchy Viewer tool allows you to change the components properties and see the resulting changes in the Graphical Layout emulator.

Each GUI layout XML file must contain exactly one root element, which must be a View or a ViewGroup. Additional elements can be defined inside the root element to build a view hierarchy. When compiled each XML layout file defines a View resource, as shown in the R.java file below:

        
/* AUTO-GENERATED FILE.  DO NOT MODIFY.
 *
 * This class was automatically generated by the
 * aapt tool from the resource data it found.  It
 * should not be modified by hand.
 */

package com.example.android1;

public final class R {
  public static final class layout {
        public static final int activity_main=0x7f030000;
}

The view resource should be specified in the callback function of the setContentView method in the onCreate object of the main activity code (MainActivity.java), as shown:


	@Override
	protected void onCreate(Bundle savedInstanceState) {
		super.onCreate(savedInstanceState);
		setContentView(R.layout.activity_main);
	}     
   
Content XML Files: strings.xml

It is good programming practice to specify the application's data content in XML resource files. String values are stored in the res/layout folder in the strings.xml file as shown below. Note when you use the Graphical Layout tool to create a GUI component, the content value may be hard coded. This can be converted to a string resource thru these menu options: (Refactor, Android, Extract Android String).

<?xml version="1.0" encoding="utf-8"?>
<resources> <string name="app_name">android1</string> <string name="hello_world">Hello world!</string> <string name="menu_settings">Settings</string> <string name="button">Button</string> </resources>

The data contents can be edited directly in the XML files (sometimes more reliable) or through the use of the Resources editor. For example you can edit the XML files to add bold <b> and italics<i> Note: you can leave the AVD emulator running between changes. You do not have to restart the AVD after each change.

Attributes

Every object has its own variety of XML attributes. An attribute that is common among the objects is the ID attribute. Below is an ID attribute for a button defined in the activity_main.xml file.

android:id="@+id/button1"

The @ symbol signals the XML parser that the remainder of the string should be identified as an XML resource. The + symbol indicates it is a new ID resource that has not been declared before. When compiled, the attribute in the XML file will be translated into a number, as shown in this line from the R.java file below. When using a Relative Layout, IDs are important because the location of the GUI components are specified in relationship to other GUI components, which are referenced by IDs.

public static final int button1=0x7f090000;

Screen Layouts Frame, Linear, Table, Relative

Android has layout classes that help position the GUI components on a screen. Layouts do not display anything, but they contain and arrange the GUI components in desired positions. Four common layout classes are:

1. FrameLayout
FrameLayout treats the entire screen as one space that can be filled with a single object. All the components are drawn at the upper-left corner of the screen. Subsequent components will overlay earlier components. Below two buttons were put into a FrameLayout; only the second button shows in the running application.


    <FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
        android:layout_width="fill_parent"
        android:layout_height="fill_parent" >

        <Button
            android:id="@+id/button1"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:text="Button1" />

        <Button
            android:id="@+id/button2"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:text="Button2" />

    </FrameLayout>

Frame Layout
 

2. LinearLayout
LinearLayout aligns all the components in either a horizontal or vertical direction. LinearLayout recognize margins, gravity, and weights.

Vertical LinearLayout is like a stack of pancakes.
In vertical LinearLayout the components can be stretched vertically by adding weight and positioned horizontally by adding gravity.


    <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
        android:layout_width="fill_parent"
        android:layout_height="fill_parent"
        android:orientation="vertical" >

        <Button
            android:id="@+id/button1"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:layout_weight="1"
            android:text="Button1" />

        <Button
            android:id="@+id/button2"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:layout_gravity="right"
            android:text="Button2" />

        <Button
            android:id="@+id/button3"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:text="Button3" />

    </LinearLayout>
    
img4
LinearLayout - Vertical

Weight(1,0,0)
Gravity(u,right,1)


Horizontal LinearLayout is like slicing bread.

In Horizontal LinearLayout the components can be stretched horizontally by adding weight and positioned vertically by adding gravity.


    <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
        android:layout_width="fill_parent"
        android:layout_height="fill_parent"
        android:orientation="horizontal" >

        <Button
            android:id="@+id/button1"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:layout_weight="1"
            android:text="Button1" />

        <Button
            android:id="@+id/button2"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:layout_gravity="right"
            android:text="Button2" />

        <Button
            android:id="@+id/button3"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:text="Button3" />

    </LinearLayout>
    
img3

LinearLayout - Horizontal

Weight(1,0,0)
Gravity(u,bottom,u)


3. TableLayout
TableLayout positions the components into rows and columns. Each table cell can contain a GUI component or another layout class.
          
 
    <TableLayout xmlns:android="http://schemas.android.com/apk/res/android"
        android:layout_width="fill_parent"
        android:layout_height="fill_parent" >

        <TableRow
            android:id="@+id/tableRow1"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content">

            <Button
                android:id="@+id/button1"
                android:layout_width="wrap_content"
                android:layout_height="wrap_content"
                android:layout_weight="1"
                android:text="Button1" />
            
            <Button
                android:id="@+id/button4"
                android:layout_width="wrap_content"
                android:layout_height="wrap_content"
                android:text="Button4" />
                    
        </TableRow>

        <TableRow
            android:id="@+id/tableRow2"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content" >

            <Button
                android:id="@+id/button2"
                android:layout_width="wrap_content"
                android:layout_height="wrap_content"
                android:layout_weight="1"
                android:text="Button2" />

        </TableRow>

        <TableRow
            android:id="@+id/tableRow3"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content" >

            <Button
                android:id="@+id/button3"
                android:layout_width="wrap_content"
                android:layout_height="wrap_content"
                android:layout_weight="0"
                android:text="Button3" />

        </TableRow>

    </TableLayout>   

img5

TableLayout

Weight(1,1,0,0)
Gravity(u,u,u,u)


4. RelativeLayout
RelativeLayout positions components in relationship to the parent view or other components (specified by ID). Positioning attributes include: alignParentTop, alignParentLeft, alignLeft, below, ...


    <RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
        android:layout_width="fill_parent"
        android:layout_height="fill_parent" >

        <Button
            android:id="@+id/button1"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:layout_alignParentLeft="true"
            android:layout_alignParentTop="true"
            android:layout_marginLeft="14dp"
            android:layout_marginTop="22dp"
            android:text="Button1" />

        <Button
            android:id="@+id/button2"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:layout_alignLeft="@+id/button1"
            android:layout_below="@+id/button1"
            android:layout_marginTop="19dp"
            android:text="Button2" />

        <Button
            android:id="@+id/button3"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:layout_alignParentRight="true"
            android:layout_alignTop="@+id/button1"
            android:layout_marginRight="58dp"
            android:layout_marginTop="20dp"
            android:text="Button3" />

        <Button
            android:id="@+id/button4"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:layout_alignRight="@+id/button3"
            android:layout_below="@+id/button2"
            android:layout_marginRight="30dp"
            android:layout_marginTop="119dp"
            android:text="Button4" />

    </RelativeLayout>

img6

RelativeLayout


Android Activities Creation, Life Cycles, Intents, Saving State

An Android Activity is a process with a screen for user interaction. Unlike traditional applications, each activity is independent of the other activities. Activities can not directly call the methods of another activity. Instead an activity will send an Intent to the Android system. For Implicit Intents, the startActivity() method is invoked and the registered activity for that intent is started. IntentFilters specify (in AndroidManifest.xml) the type of Intents for which an activity can respond. For Explicit Intents the exact components which should be called by the Android system are defined. Data can not be passed between activities in the traditional manner (like through parameters), but require special mechanisms , such as Intent Extras, for sharing "bundles" of data.

Applications can contain multiple activities, but one activity is designated as the main activity which launches the application. When a new activity starts, the previous activity is pushed onto the "back stack". When an activity is preempted by a new activity, the previous activity is notified of the reason and is given an opportunity to take appropriate action. Such as preserve its state, release resources, etc.

When a new activity is created it MUST be defined in the manifest in order for it to me accessible by Android. An activity can also define Intent Filters which declares how other applications can use it. Each activity is a subclass of the Activity class and must implement an onCreate() method. An activity can be started with either the startActivity() or startActivityForResult() methods. An activity is ended by calling its finish() method.

An activity basically has three states:

  1. Resumed - Activity in foreground and has focus.
  2. Paused - Still visible, but another activity is in foreground and has focus.
  3. Stopped - Still in memory, but no longer visible. Another activity is in foreground and has focus. The stopped activity can be killed by Android if it is in need of memory.

Various callback methods are used as an activity transitions among the different states, such as: onCreate(), onStart(), onResume(), onPause(), onStop(), onDestroy().

  1. The entire lifetime happens between the first call to onCreate() and the final call of onDestroy().
  2. The visible lifetime happens between a call to onStart() until a corresponding call to onStop().
  3. The foreground lifetime happens between a call to onResume() until a corresponding call to onPause().
  4. onPause() is typically used to commit changes to data and otherwise prepare to stop user interaction.
  5. All activities must implement onCreate() which will perform the initial setup.

The entire lifecycle of an activity is defined by the following methods. Any of these methods can be overridden to do the desired work when an activity changes state:

public class Activity extends ApplicationContext {

protected void onCreate(Bundle savedInstanceState);

protected void onStart();

protected void onRestart();

protected void onResume();

protected void onPause();

protected void onStop();

protected void onDestroy();
}

Activity Creation Steps to Create an Activity

To create a new activity:

  1. In the navigator, click on the application namespace (e.g. src=net.kcshadow).

  2. Right click, new, class. Populate name (eg scheduleActivity), change Super Class to 'Activity' and press the finish button to create the new activity. Inside the newly created java file hit ctrl-shift-o to pull in the missing imports.

  3. Inside the activity class, add an 'onCreate' method to the activity. Eclipse can assist with the code (ctrl-space).
    
    	@Override
    	protected void onCreate(Bundle savedInstanceState) {
    		super.onCreate(savedInstanceState);
    	}
  4. At the bottom of the onCreate method, add code to set the context view, such as:
    
    setContentView(R.layout.schedule);
    
    
  5. Add the activity to the Manifest:
    • Open the AndroidManifest.xml file.
    • Go to the Application tab.
    • Select Add in the application nodes.
    • Select "Create a new element at the top level, in Application". Select 'Activity', hit OK (Do not populate name yet).
    • Go to Attributes for Activity and populate name (eg. scheduleActivity). Save Manifest
    • Check the new activity is listed in the AndroidManifest.xml file.
6. To define a new activity to be launched by Android system: Intents Implicit and Explicit

Intents allow the application to move between different activities and to start services. Android activities do not directly call each other. Instead they send an Intent to the Android operating system which determines which process should be started. There are two types of intents:

  1. Implicit Intent - does not specify a component to be run. Instead they provide enough information for the system to determine which of the available components is the best to run for the intent.

  2. Explicit Intent - does specify a component to be run.

If the activity has data to be shared, instead of using a traditional method like parameter passing, the data must be put in a bundle to be included with the Intent as an Intent Extra.

Intent Extras Sharing Data between Activities

Instead of activities directly calling each other, they send an Intent to the Android system. If the activity has data to be shared, instead of using a traditional method like parameter passing, they store the data in a bundle that is included with the Intent. Intent Extras is the name of this mechanism for including data along with an Intent. Intent Extras consist of data bundles accessed by the putExtra() and getExtra() methods. The data is defined in key-value pairs. Below is an example of how to code intent extras to share data between activities:

  1. Create an explicit intent for the Dosage activity with extra data put into a bundle.
    
    
    Intent launchDosageActivity = new Intent(this, dosageActivity.class); launchDosageActivity.putExtra("dosageTime", time); launchDosageActivity.putExtra("dosageName", name); launchDosageActivity.putExtra("dosageStrength", strength); startActivity(launchDosageActivity);
  2. Get the Extra data from the bundle and assign to screen fields.

    
       public void onCreate(Bundle savedInstanceState) {
          super.onCreate(savedInstanceState);
          setContentView(R.layout.dosage);
    
          // Get Extra Data from Bundle
          Bundle extras = getIntent().getExtras();
          if (extras != null) {
             dosageTime = extras.getString("dosageTime");
             TextView dosageTimeTV = (TextView) findViewById(R.id.dosageTimeTV);
             dosageTimeTV.setText(dosageTime);
    
             dosageName = extras.getString("dosageName");
             TextView dosageNameTV = (TextView) findViewById(R.id.dosageNameTV);
             dosageNameTV.setText(dosageName);
    
             dosageStrength = extras.getString("dosageStrength");
             TextView dosageStrengthTV = (TextView) findViewById(R.id.dosageStrengthTV);
             dosageStrengthTV.setText(dosageStrength);
          }
    
Saving and Restoring Activity State onSaveInstanceState, onRestoreInstanceState

Android will destroy activities when certain device configurations change, such a screen orientation. When the screen orientation changes, Android destroys the running activity and recreates it. Android calls the onSaveInstanceState() before it destroys an activity. The method stores the state information in a data bundle to be used if the user should navigate back to the activity. Android is then able to recreate the activity and it would not be evident to the user that the activity was ever destroyed. Android automatically saves and restores the state data that is inherently part of a view. However, it is sometimes necessary to override the onSaveInstanceState() and onRestoreInstanceState() to save additional state data, as shown below:

  1. Store screen data by putting it into a data bundle.

    // ----------------------------------
    // Save Instance State Data
    // ----------------------------------
    @Override
    protected void onSaveInstanceState(Bundle outState) {
    super.onSaveInstanceState(outState);
    //Log.i(getClass().getSimpleName(), "onSaveInstanceState");

    // Put values into bundle
    medDoctorET = (EditText) findViewById(R.id.medDoctorET);
    outState.putString("doctor", medDoctorET.getText().toString());

    medNameET = (EditText) findViewById(R.id.medNameET);
    outState.putString("name", medNameET.getText().toString());

    medStrengthET = (EditText) findViewById(R.id.medStrengthET);
    outState.putString("strength", medStrengthET.getText().toString());

    medStartDateET = (EditText) findViewById(R.id.medStartDateET);
    outState.putString("startDate", medStartDateET.getText().toString());

    medStartTimeSP = (Spinner) findViewById(R.id.medStartTimeSP);
    ArrayAdapter medStartTimeAdap = (ArrayAdapter) medStartTimeSP.getAdapter();
    outState.putInt("startTimePosition", medStartTimeAdap.getPosition(medStartTimeSP.getSelectedItem().toString()));

    medFrequencySP = (Spinner) findViewById(R.id.medFrequencySP);
    ArrayAdapter medFrequencyAdap = (ArrayAdapter) medFrequencySP.getAdapter();
    outState.putInt("frequencyPosition", medFrequencyAdap.getPosition(medFrequencySP.getSelectedItem().toString()));

    medIntervalSP = (Spinner) findViewById(R.id.medIntervalSP);
    ArrayAdapter medIntervalAdap = (ArrayAdapter) medIntervalSP.getAdapter();
    outState.putInt("intervalPosition", medIntervalAdap.getPosition(medIntervalSP.getSelectedItem().toString()));
    }
  2. Restore screen date by getting it from the bundle created onSaveInstanceState() in #1:
        
    // ----------------------------------
    // Restore Instance State Data
    // ----------------------------------
       @Override
       protected void onRestoreInstanceState(Bundle savedInstanceState) {
           super.onRestoreInstanceState(savedInstanceState);
      
           // Restore values from bundle
           if( savedInstanceState != null ) { 
    
              medDoctorET    = (EditText) findViewById(R.id.medDoctorET);
              medDoctorET.setText(savedInstanceState.getString("doctor"));
              medNameET = (EditText) findViewById(R.id.medNameET);
              medNameET.setText(savedInstanceState.getString("name"));
      
              medStrengthET = (EditText) findViewById(R.id.medStrengthET);
              medStrengthET.setText(savedInstanceState.getString("strength"));
      
              medStartDateET = (EditText) findViewById(R.id.medStartDateET);
              medStartDateET.setText(savedInstanceState.getString("startDate"));
      
              medStartTimeSP = (Spinner) findViewById(R.id.medStartTimeSP);
              medStartTimeSP.setSelection(savedInstanceState.getInt("startTimePosition"));
     
              medFrequencySP = (Spinner) findViewById(R.id.medFrequencySP);
              medFrequencySP.setSelection(savedInstanceState.getInt("frequencyPosition"));
     
              medIntervalSP = (Spinner) findViewById(R.id.medIntervalSP);
              medIntervalSP.setSelection(savedInstanceState.getInt("intervalPosition"));
          } 
      }
Shared Preferences Data Persistence
Shared Preferences is a way Android can store a small amount of data that is private to the application. The shared preferences data will persist even after the application ends. The SharedPreferences class allows persistent storage of key-value pairs of primitive data types (boolean, float, int, long, string).
  1. Shared preferences data is typically written during the Pause phase of the activity life lifecycle by:
    • Call edit() to get a shared preferences editor.
    • Add values to the editor with methods such as putString and putInt.
    • Commit the added values with commit().

    // ------------------------------------------
    // onPause - Put data in shared preferences.
    // ------------------------------------------
    @Override
    protected void onPause() {
    super.onPause();

    // Get a SharedPreferences file
    SharedPreferences prefState = getSharedPreferences(PREFS_NAME, MODE_PRIVATE);
    // Get a SharedPreferences editor
    SharedPreferences.Editor editor = prefState.edit();

    // Load the editor with data in screen fields
    medNameET = (EditText) findViewById(R.id.medNameET); editor.putString(getPackageName() + ".name", medNameET.getText().toString());

    medDoctorET = (EditText) findViewById(R.id.medDoctorET); editor.putString(getPackageName() + ".doctor", medDoctorET.getText().toString());
    medStrengthET = (EditText) findViewById(R.id.medStrengthET);
    editor.putString(getPackageName() + ".strength", medStrengthET.getText().toString());

    medStartDateET = (EditText) findViewById(R.id.medStartDateET);
    editor.putString(getPackageName() + ".startDate", medStartDateET.getText().toString());

    medStartTimeSP = (Spinner) findViewById(R.id.medStartTimeSP);
    ArrayAdapter medStartTimeAdap = (ArrayAdapter) medStartTimeSP.getAdapter(); editor.putInt(getPackageName() + ".startTime", medStartTimeAdap.getPosition(medStartTimeSP.getSelectedItem().toString()));

    medFrequencySP = (Spinner) findViewById(R.id.medFrequencySP);
    ArrayAdapter medFrequencyAdap = (ArrayAdapter) medFrequencySP.getAdapter(); editor.putInt(getPackageName() + ".frequency", medFrequencyAdap.getPosition(medFrequencySP.getSelectedItem().toString()));

    medIntervalSP = (Spinner) findViewById(R.id.medIntervalSP);
    ArrayAdapter medIntervalAdap = (ArrayAdapter) medIntervalSP.getAdapter(); editor.putInt(getPackageName() + ".interval", medIntervalAdap.getPosition(medIntervalSP.getSelectedItem().toString()));

    // Commit the editor additions
    editor.commit();
    }
  2. Shared Preferences data is usually retrieved during the Resume or Create phase of the activity life lifecycle with methods such as getString and getInt.

       // -------------------------------------------------------   
       // onCreate - Restore screen data from shared preferences.
       // -------------------------------------------------------     
       @Override
       protected void onCreate(Bundle savedInstanceState) {
          super.onCreate(savedInstanceState);
          setContentView(R.layout.edit_med);
    
          // Restore the screen data from SharedPreferences
          SharedPreferences prefState = getSharedPreferences(PREFS_NAME, MODE_PRIVATE);
          
          medNameET    = (EditText) findViewById(R.id.medNameET);
          medNameET.setText(prefState.getString(getPackageName() + ".name", ""));
    
          medDoctorET    = (EditText) findViewById(R.id.medDoctorET);
          medDoctorET.setText(prefState.getString(getPackageName() + ".doctor", ""));
          
          medStrengthET = (EditText) findViewById(R.id.medStrengthET);
          medStrengthET.setText(prefState.getString(getPackageName() + ".strength", ""));
          
          medStartDateET = (EditText) findViewById(R.id.medStartDateET);
          medStartDateET.setText(prefState.getString(getPackageName() + ".startDate", ""));
          
          medStartTimeSP = (Spinner) findViewById(R.id.medStartTimeSP);
          medStartTimeSP.setSelection(prefState.getInt(getPackageName() + ".startTime", 0));
          
          medFrequencySP = (Spinner) findViewById(R.id.medFrequencySP);
          medFrequencySP.setSelection(prefState.getInt(getPackageName() + ".frequency", 0));
          
          medIntervalSP = (Spinner) findViewById(R.id.medIntervalSP);
          medIntervalSP.setSelection(prefState.getInt(getPackageName() + ".interval", 0));
    

Event Listeners OnClickListener, findViewById, setOnClickListener

The controls involved with the event listeners must be assigned IDs. These are set in the layout XML files with the id command, such as:


   android:id="@+id/medSaveButton"
     

Then in the xxxActivity.java file, inside the onCreate method, get a reference to the control(s):


	@Override
	protected void onCreate(Bundle savedInstanceState) {
		super.onCreate(savedInstanceState);
		setContentView(R.layout.edit_med);

		// Get reference to the Save button
		Button medSaveButton = (Button)findViewById(R.id.medSaveButton);
		medSaveButton.setOnClickListener(medSaveButtonListener);							
	}
Also in the xxxActivity.java file, create the listener as an anonymous method:


	   // Create medSaveButton listener with anonymous method
	   private OnClickListener medSaveButtonListener = new OnClickListener() {
		
		@Override
		public void onClick(View v) {
			EditText medNameET = (EditText)findViewById(R.id.medNameET);
		}
	   };

Spinners a.k.a Drop Down Lists

Spinners are the Android name for Drop Down Lists(DDL). Spinners are data input controls which allows a quick way to select one value from a set of values. Below are code segments used in creating a spinner:

1. xxxxlayout.xml, add Spinner control to screen layout:

   <Spinner
        android:id="@+id/medTimeSP"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:prompt="@string/time_prompt" />

2. strings.xml, add data set from possible selections in spinner:

    <string name="time_prompt">Select a Time</string>
    <string-array name="time_array">
       <item>12:00 am</item>
       <item> 1:00 am</item>
    </string-array>

3. xxxxactivity.java, add code to define spinner and assign a listener in onCreate method:

   // Spinner
   Spinner medTimeSpinner = (Spinner) findViewById(R.id.medTimeSP);
   ArrayAdapter<CharSequence> medStartTimeAdapter = ArrayAdapter.createFromResource(
      this, R.array.time_array, android.R.layout.simple_spinner_item);
   medStartTimeAdapter.setDropDownViewResource(
      android.R.layout.simple_spinner_dropdown_item);
   medTimeSpinner.setAdapter(medStartTimeAdapter);

   // Add listener
   medTimeSpinner.setOnItemSelectedListener(new medStartTimeSpinnerListener());

4. xxxxactivity.java, add code to override OnItemSelected class with onItemSelected() method for spinner listener:

   class medStartTimeSpinnerListener implements Spinner.OnItemSelectedListener
   {
     public void onItemSelected(AdapterView<?> parent, View v, int position, long id) {
        Toast.makeText(parent.getContext(),"Selected: " +
           parent.getItemAtPosition(position).toString(), Toast.LENGTH_LONG).show();
     }
        
     @Override
     public void onNothingSelected(AdapterView<?> parent) {
        // Nothing	
     }
   }
List Views Activity, List Activity, Adapters

List views are activities that display items in a vertical scrolling list. The list items are automatically inserted in to the list using an Adapter. The adapter pulls content from a source such as an array or a database query. List views can be customized to fit various needs. List views can be created by overriding the Activity class with a new class. List views can also be created by overriding the Activity class with the predefined ListActivity class. ListActivity provides shortcut methods to simplify coding. The code below overrides the Activity class with ListActivity to create a list view with an Exit button. It also overrides getView to set the field colors in the list view.

1. main.xml, screen layout containing the listview and button:

  <?xml version="1.0" encoding="utf-8"?>
  <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:orientation="vertical"
    android:layout_width="match_parent"
    android:layout_height="match_parent">

    <ListView 
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_weight="1" 
        android:id="@android:id/list"></ListView>
    
    <!-- Exit Button -->
    <Button
        android:id="@+id/mainExitButton"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:text="@string/exit" />
    
  </LinearLayout>

2. rowlayout.xml, screen layout for one row in the list view:

  <RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="wrap_content"
    android:layout_height="match_parent"
    android:layout_gravity="right"
    android:gravity="right"
    android:orientation="vertical" >
    
        <!-- Dosage Time -->
        <TextView
            android:id="@+id/time"
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:layout_marginBottom="5dip"
            android:layout_marginLeft="5dip"
            android:gravity="left"
            android:text="@string/time"
            android:textSize="16sp" />

        <!-- Dosage Status -->
        <TextView
            android:id="@+id/status"
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:layout_marginBottom="5dip"
            android:layout_marginRight="5dip"            
            android:text="@string/status"
            android:gravity="right"            
            android:textSize="16sp" />
                
        <!-- Dosage Name -->
        <TextView
            android:id="@+id/name"
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:layout_below="@id/time"
            android:layout_marginLeft="5dip"
            android:gravity="left"
            android:text="@string/name"
            android:textSize="16sp" />
                
        <!-- Dosage Strength -->
        <TextView
            android:id="@+id/strength"
            android:layout_width="match_parent"
            android:layout_height="wrap_content"            
            android:layout_marginRight="5dip"                        
            android:layout_alignParentLeft="true"
            android:layout_below="@+id/time"
            android:gravity="right"
            android:text="@string/strength"
            android:textSize="16sp" />
            
  </RelativeLayout>   

3. xxxxActivity, override with ListActivity class to create list view:


  package net.kcshadow.medmonitor;

  public class TodayActivity extends ListActivity {
final String SCHEDULE_FILE = "schedule.txt";
ArrayList<String> schedRecords = new ArrayList<String>(); public void onCreate(Bundle icicle) { super.onCreate(icicle); // Title Bar Update setTitle(" Medicine Monitor"); // Get current date. Date date = new Date(); String currentDate = new SimpleDateFormat("yyyyMMdd").format(date); // Define array list of hash maps. ArrayList<HashMap<String, String>> adapterList = new ArrayList<HashMap<String, String>>(); // Read the schedule file and move to adapter for screen display. try { FileInputStream fIn = openFileInput(SCHEDULE_FILE); Scanner inStream = new Scanner(fIn); String readString while (inStream.hasNextLine()) { readString = inStream.nextLine(); schedRecords.add(readString); String[] parts = readString.split(","); if (parts[1].trim().equals(currentDate)) { HashMap<String, String> map = new HashMap<String, String>(); map.put("hours", parts[0].trim()); map.put("name", parts[2].trim()); map.put("strength", parts[3].trim()); map.put("time", parts[4].trim()); map.put("status", parts[5].trim()); adapterList.add(map); } } fIn.close(); } catch (IOException ioe) { ioe.printStackTrace(); } // Create Simple Adapter and load with schedule records. SimpleAdapter mSchedule = new SimpleAdapter(this, adapterList, R.layout.rowlayout, new String[] { "name", "strength", "time", "status" }, new int[] { R.id.name, R.id.strength, R.id.time, R.id.status }) {
// Override getView to change field colors in listview. @Override public View getView(int position, View convertView, ViewGroup parent) { View view = super.getView(position, convertView, parent); TextView tv = (TextView) view.findViewById(R.id.status); String dosageStatus = tv.getText().toString(); if (dosageStatus.equals("Not Taken")) { tv.setTextColor(Color.RED); } else if (dosageStatus.equals("Skipped")) { tv.setTextColor(Color.BLUE); } else { tv.setTextColor(Color.BLACK); } return view; } }; setListAdapter(mSchedule); setContentView(R.layout.main); // Set Listener for Exit Button Button mainExitButton = (Button) findViewById(R.id.mainExitButton); mainExitButton.setOnClickListener(mainExitButtonListener); } // Define Listener for the Exit Button private OnClickListener mainExitButtonListener = new OnClickListener() { @Override public void onClick(View v) { TodayActivity.this.finish(); } }; @Override protected void onListItemClick(ListView l, View v, int position, long id) { super.onListItemClick(l, v, position, id); // Get values from adapter HashMap result = (HashMap) l.getAdapter().getItem(position); String time = result.get("time").toString(); String name = result.get("name").toString(); String strength = result.get("strength").toString(); Intent launchDosageActivity = new Intent(this, dosageActivity.class); launchDosageActivity.putExtra("dosageTime", time); launchDosageActivity.putExtra("dosageName", name); launchDosageActivity.putExtra("dosageStrength", strength); startActivity(launchDosageActivity); } }

Menus Context Menus, Options Menus, Sub Menus

Menus can be defined in either an XML file or in the application code. The Android Developers website recommends defining menus in XML files. Android supports three types of menus:

  1. Options Menu (Action Bar) - contains menu items for an application, which appears when the user touches the MENU button.

    An options menu is where actions that have a global impact should be placed. Such as: Search, Settings, About, etc.

    In API 10 or lower the option menu appears at the bottom of the screen when the user presses the Menu button. In API 11 and higher the options menu is available in the action bar. The action bar is a dedicated area at the top that usually persists throughout the application.

    The option menu supports 1 to 6 options. If more than 6 options are needed, then the 6th option button is used as a "More" option that calls an option sub menu (see Sub Menu below).

  2. Context Menu - is a floating list of menu items that appears when a long-press is performed on an element.

    Context Menus provide actions relating to the selected content. Context menus do not support item shortcuts or icons.

  3. Sub Menu - is a nested menu that can be added to any type of menu (Options or Context).

    Unlike context menus, sub menus can can be invoked by any event, just a long-press. Sub menus do not support item icons or nested sub menus.

The following code creates on Option Menu defined in an XML file:

  1. In the /res/menu folder, create an xml file (options_menu.xml) for the options menu:
    
    options_menu.xml<?xml version="1.0" encoding="utf-8"?>
    <menu xmlns:android="http://schemas.android.com/apk/res/android" >
      <item android:id="@+id/AboutMenuItem" android:title="About"></item>
      <item android:id="@+id/HelpMenuItem" android:title="Help"></item>
    </menu>
    

  2. In xxxxActivity.java, include code to inflate the menu (MenuInflater):
    
    // Inflate XML menu with MenuInflater
    @Override
    public boolean onCreateOptionsMenu(Menu menu) {
      MenuInflater menuInflater = getMenuInflater();
      menuInflater.inflate(R.menu.options_menu, menu);
      return true;
    } 
    
  3. In xxxxActivity.java, include code to handle the menu selection:
    
    // Handle menu item selection
    @Override
    public boolean onOptionsItemSelected(MenuItem item) {
    
      switch (item.getItemId()) {
        case R.id.AboutMenuItem:
          Intent launchAboutActivity = new Intent(this, aboutActivity.class);
          startActivity(launchAboutActivity);
          break;
        case R.id.HelpMenuItem:
          Intent launchHelpActivity = new Intent(this, helpActivity.class);
          startActivity(launchHelpActivity);
          break;
        default:
          break;
      }
      return super.onOptionsItemSelected(item);
    }  
    
WebViews Display HTML with WebKit

The WebView class will display web pages (HTML). WebView uses the WebKit rendering engine and can optionally include methods for many of the usual capabilities of a web browser. If the WebView class is used to access the Internet, you must add the INTERNET permissions to the Android Manifest file. However if you want to access the Internet, it is probably better to invoke a web browser application with a URL intent, as shown below:


Uri uri = Uri.parse("http://www.kcshadow.net"); 
Intent intent = new Intent(Intent.ACTION_VIEW, uri); 
startActivity(intent);        
  
Using WebView for Help Screen

A common use of the WebView class is to display local HTML in the application, such as in a Help screen. Below is example code for doing this:

  1. Create an xml file (help.xml) using a WebView for the help screen:
    
    <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:orientation="vertical"
        android:weightSum="60" >
            
        <!-- Page Title -->
        <LinearLayout
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:layout_gravity="center_horizontal"
            android:background="@color/gray"
            android:orientation="horizontal" >
    
           <TextView
               android:id="@+id/textView1"
               android:layout_width="match_parent"
               android:layout_height="match_parent"
               android:gravity="center"
               android:layout_weight="2"
               android:text="@string/help"
               android:textSize="20sp" />
        </LinearLayout>
    
        <!-- Horizontal Line -->
        <LinearLayout
            android:layout_width="match_parent"
            android:layout_height="2dip"
            android:layout_marginBottom="10dip"
            android:background="@android:color/black" />
    
        <!-- WebView -->
       <LinearLayout 
                android:id="@+id/ll1"
                android:layout_width="fill_parent"
                android:layout_height="wrap_content"
                android:orientation="vertical">
           <WebView
               android:id="@+id/helpWebView"
               android:layout_width="fill_parent"
               android:layout_height="fill_parent"
               android:layout_weight="3" />
       </LinearLayout>
    
        <!-- Exit Button -->
        <RelativeLayout
            android:layout_width="match_parent"
            android:layout_height="wrap_content"        
            android:layout_gravity="bottom" >
    
           <LinearLayout
              android:layout_width="match_parent"
              android:layout_height="wrap_content"
              android:layout_alignParentBottom="true"
              android:orientation="horizontal" >
            
            <Button
                android:id="@+id/helpExitButton"
                android:layout_width="wrap_content"
                android:layout_height="wrap_content"
                android:layout_weight="1"
                android:text="@string/exit"  />        
           </LinearLayout>
        </RelativeLayout>
    </LinearLayout>
    

  2. In helpActivity.java, include code to create and load the WebView object:
    
     public class helpActivity extends BaseMenu {
    
       private WebView webView;
       
       @Override
       protected void onCreate(Bundle savedInstanceState) {
          super.onCreate(savedInstanceState);
    
          setContentView(R.layout.help);
    
          // Load help file from assets directory
          webView = (WebView) findViewById(R.id.helpWebView);
          webView.loadUrl("file:///android_asset/help.html");
       };
    }
    
    
  3. In help.html, (assets directory) include HTML code for help screen:
    
    <!doctype html>
    <html>
    <head>
    </head>
    <body>
      <p> Medicine Monitor is designed to aid in the administration of a medicine schedule.
          Making a medicine entry causes the creation of the corresponding schedule entries.
          Each day's schedule entries are displayed in a listview where the entries can be
          selected and updated. The administration of the medicine dosage is recorded along 
          with a subjective assessment of the patients wellness.    
      </p>
      <oil>
         <li>runDate.txt - contains the application last run date.</li>
         <li>medicine.txt - contains the medicine information.</li>
         <li>schedule.txt - contains the daily medicine schedule.</li>
      </ol>    
    </body>
    </html>
Custom Views Creating Views Programmatically and Combining Views

The Android API has a large set of View classes for displaying various types of data. However sometimes the application has needs that are not met by the built-in views In those cases a custom view can be created by overriding one of the existing Views classes or by overriding the View class itself. Views draw themselves in the onDraw() method. A Canvas object is created as a drawing area for graphics methods (drawLine, drawPoint, drawText, etc.).

Custom views can be created in layout files (XML) or programmatically. Below is an example of creating two views programmatically and joining them together in one activity. One view contains a canvas and the other view contains an exit button.

  1. In historyActivity.java, create the two views and combine them together:
    
    public class historyActivity extends BaseMenu {   
    
       @Override
       protected void onCreate(Bundle savedInstanceState) {
          super.onCreate(savedInstanceState);
          
          // View containing Exit Button      
          View myButtonView = new historyView(this).createView(this);
          
          // View containing Drawing Canvas
          View historyCanvasView = new historyView(this);
        
          // Join two views together
          RelativeLayout relativeLayout = new RelativeLayout(this);  
          RelativeLayout.LayoutParams lp = new RelativeLayout.LayoutParams(     
          RelativeLayout.LayoutParams.WRAP_CONTENT, 
          RelativeLayout.LayoutParams.WRAP_CONTENT);      
          relativeLayout.addView(myButtonView,lp);    
          lp.addRule(RelativeLayout.ALIGN_PARENT_BOTTOM, RelativeLayout.TRUE);
          relativeLayout.addView(historyCanvasView,lp);
          
          // Show combined views
          setContentView(relativeLayout);
                
          // Set Listener for Exit Button
          Button historyExitButton = (Button) findViewById(1);
          historyExitButton.setOnClickListener(historyExitButtonListener);      
       }
    
       // Define Listener for the Exit Button
       private OnClickListener historyExitButtonListener = new OnClickListener() {
    
          @Override
          public void onClick(View v) {
             historyActivity.this.finish();
          }
       };   
    }
           
  2. In historyView.java, override the View class to create a custom view with a drawing canvas. Also define the exit button view with createView() method. Code onDraw method using device independent units with graphics commands:
    
    public class historyView extends View {
       
       final String SCHEDULE_FILE = "schedule.txt";
       
       private Paint paint;
       private int xMax;
       private int xStart = 30;
       private int yMax;
       private int yStart = 200;
       
       public historyView(Context context) {
          super(context);
          paint = new Paint(Paint.ANTI_ALIAS_FLAG);
       }
    
       @Override
       protected void onDraw(Canvas canvas) {
          
          // Values initializations for graph data
          int[] wellness  = {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0};
          int[] medicine1 = {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0};
          int[] medicine2 = {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0};
    
          String medicine1Name = "";
          String medicine2Name = "";
          
          // Get current date.
          Date date = new Date();
          String currentDate = new SimpleDateFormat("yyyyMMdd").format(date);
          String displayDate = new SimpleDateFormat("EEE, MMM d, ''yy").format(date);
    
          // Read the schedule file and move to adapter for screen display.
          try {
             
             // Get context since this is a custom view.
             Context context = this.getContext();
             
             FileInputStream fIn = context.openFileInput(SCHEDULE_FILE);
             Scanner inStream = new Scanner(fIn);
             String readString;
    
             // Loop thru medicine schedule records
             int count=0;
             while (inStream.hasNextLine()) {
                readString = inStream.nextLine();
                //schedRecords.add(readString);
    
                String[] parts = readString.split(",");
                if (parts[1].trim().equals(currentDate)) {
                   count++;
    
                   // Get two medicine names
                   if (medicine1Name.equals("")) {
                      medicine1Name = parts[2].trim();
                   }
                   if ((!medicine1Name.equals(""))
                        && (medicine2Name.equals(""))
                        && (!parts[2].trim().equals(medicine1Name))) {
                      medicine2Name = parts[2].trim();
                   }
                   
                   // Record Wellness and Taken Times of Medicine 1
                   if (parts[2].trim().equals(medicine1Name)) { 
                      wellness[Integer.parseInt(parts[0].trim())] = Integer.parseInt(parts[6].trim().substring(0,1));                     
                      if (parts[5].trim().equals("Taken")) {               
                         medicine1[Integer.parseInt(parts[0].trim())] = 1;
                      }
                   }
                   
                   // Record Wellness and Taken Times of Medicine 2
                   if (parts[2].trim().equals(medicine2Name)) {
                      if (Integer.parseInt(parts[6].trim().substring(0,1)) < wellness[Integer.parseInt(parts[0].trim())]) {
                         wellness[Integer.parseInt(parts[0].trim())] = Integer.parseInt(parts[6].trim().substring(0,1));
                      }
                      if (parts[5].trim().equals("Taken")) {
                         medicine2[Integer.parseInt(parts[0].trim())] = 1;
                      }
                   }               
                }
             }
             fIn.close();
    
          } catch (IOException ioe) {
             ioe.printStackTrace();
          }
                
          // Draw Chart Border Lines
          paint.setColor(Color.rgb(0,0,0));
          paint.setStyle(Paint.Style.STROKE);
          paint.setStrokeWidth(3);      
          canvas.drawLine(xStart, 0, xStart, yMax-yStart, paint);
          canvas.drawLine(xStart, yMax-yStart, xMax, yMax-yStart, paint);
    
          // Plot Point Markers on Hozizontal Axis
          paint.setColor(Color.rgb(0,0,0));
          paint.setStrokeWidth(5);  
          int xUnit = ((xMax-10)/24)-1;
          for (int x=xStart+xUnit; x<xMax-10; x+=xUnit) {
             canvas.drawPoint(x, yMax-203, paint);
          }     
          
          // Plot Point Markers on Vertical Axis
          paint.setColor(Color.rgb(0,0,0));
          paint.setStrokeWidth(5);      
          int yUnit = ((yMax-yStart)/9)-1; 
          for (int y=yMax-yStart-yUnit; y<0; y-=yUnit) {
             canvas.drawPoint(33, y, paint);
          }     
                
          // Draw Day Text on Horizontal Axis
          paint.setStrokeWidth(1);      
          paint.setStyle(Paint.Style.FILL);
          paint.setTextSize(10);
          canvas.drawText("M", xStart+xUnit-5, yMax-180, paint);  
          int time;
          for (int i=1; i<24; i++) {
            time = i;
            if (time > 12) { time -=12; }
            canvas.drawText(Integer.toString(time), i*xUnit+xUnit-5+xStart, yMax-180, paint);
          }
          
          // Draw Wellness Text on Vertical Axis
          paint.setStrokeWidth(1);      
          paint.setStyle(Paint.Style.FILL);
          paint.setTextSize(15);
          canvas.drawText("9", 10, 18, paint);
          paint.setTextSize(12);
          canvas.drawText("W", 9,  200, paint);
          canvas.drawText("e", 10, 220, paint);
          canvas.drawText("l", 11, 240, paint);
          canvas.drawText("l", 11, 260, paint);
          canvas.drawText("n", 10, 280, paint);
          canvas.drawText("e", 10, 300, paint);
          canvas.drawText("s", 10, 320, paint);
          canvas.drawText("s", 10, 340, paint);
          paint.setTextSize(15);
          canvas.drawText("1", 10, yMax-yStart-yUnit+5, paint);
                
          // Draw Text for Chart Title
          paint.setColor(Color.rgb(0,0,0));
          paint.setStyle(Paint.Style.FILL);
          paint.setTextSize(15);
          canvas.drawText("Time", xStart+xMax/2-30, yMax-155, paint);
    
          // Draw Text for Chart Title
          paint.setColor(Color.rgb(0,0,0));
          paint.setStyle(Paint.Style.FILL);
          paint.setTextSize(20);
          canvas.drawText("Today's Medicine", xStart+xMax/2-100, yMax-100, paint);
                
          // Draw Medicine Legend
          paint.setTextSize(10);
          paint.setStrokeWidth(10);
          
          // Medicine 1
          paint.setColor(Color.rgb(0,0,0));
          canvas.drawText(medicine1Name, 35, yMax-130, paint);
          paint.setColor(Color.BLUE);
          canvas.drawRect(5, yMax-130, 25, yMax-139, paint);
    
          // Plot Medicine1 Points
          paint.setColor(Color.BLUE);
          paint.setStrokeWidth(5);      
          int d=0;      
          for (int x=xStart+xUnit; x<xMax-10; x+=xUnit) {  
             if (medicine1[d++]==1) {
                canvas.drawPoint(x, yMax-yStart-yUnit/4, paint);
             }
          }
          
          // Medicine 2
          paint.setColor(Color.rgb(0,0,0));
          canvas.drawText(medicine2Name, 35, yMax-110, paint);
          paint.setColor(Color.RED);      
          canvas.drawRect(5, yMax-110, 25, yMax-119, paint);
          
          // Plot Medicine2 Points
          paint.setColor(Color.RED);
          paint.setStrokeWidth(5);      
          d=0;      
          for (int x=xStart+xUnit; x<xMax-10; x+=xUnit) {  
             if (medicine2[d++]==1) {
                canvas.drawPoint(x, yMax-yStart-yUnit/2, paint);
             }
          }
                
          // Interaction
          paint.setColor(Color.rgb(0,0,0));      
          canvas.drawText("Interaction", 35, yMax-90, paint);
          paint.setColor(Color.GREEN);
          canvas.drawRect(5, yMax-90, 25, yMax-99, paint);
                
          // Plot Interaction Points
          paint.setColor(Color.GREEN);
          paint.setStrokeWidth(5);      
          d=0;      
          for (int x=xStart+xUnit; x<xMax-10; x+=xUnit) {   
             if (wellness[d] > 0) {
                canvas.drawPoint(x, yMax-yStart-wellness[d]*yUnit, paint);
             }
             d++;
          }
          
          // Draw Interaction Line
          paint.setStrokeWidth(2);       
          d = 0;
          int lastX = 0;
          int lastY = 0;
          for (int x=xStart+xUnit; x<xMax-xUnit; x+=xUnit) {
             if (d < 23){
                if (wellness[d] > 0) { 
                   lastX = xStart+xUnit+xUnit*d;
                   lastY = yMax-yStart-wellness[d]*yUnit;
                }      
                if (wellness[d+1] > 0) {
                   canvas.drawLine(lastX, lastY, 
                                   xStart+xUnit*(d+2), yMax-yStart-wellness[d+1]*yUnit, paint);               
                }
             }
            d++;
          }       
       }
       
       @Override
       public void onSizeChanged(int w, int h, int oldW, int oldH) {
          xMax = w;
          yMax= h;
       }
      
       // Create Exit Button view
       public View createView(historyActivity historyActivity){
          RelativeLayout relativeLayout = new RelativeLayout(historyActivity);
          Button exitButton = new Button(historyActivity);
          exitButton.setId(1);
          exitButton.setText("Exit");
              
          RelativeLayout.LayoutParams lp = new RelativeLayout.LayoutParams(     
          RelativeLayout.LayoutParams.MATCH_PARENT, 
          RelativeLayout.LayoutParams.WRAP_CONTENT);          
          lp.addRule(RelativeLayout.ALIGN_PARENT_BOTTOM, RelativeLayout.TRUE);   
              
          relativeLayout.addView(exitButton,lp);
          return relativeLayout;
      }   
    }
    
    

Top | HelloAndroid | XML | Screen Layouts | Activities | Activity Creation | Intents | Intent Extras | Activity State | Event Listeners | Spinners | List Views | Menus | WebViews | Custom Views