You are on page 1of 67

Android Project Appointment and Location Management App

Abstract The aim of this project is to develop an Android app for mobiles. With the help of Eclipse, it demonstrates the basic elements of an Android app and additional features that make it a real app, including regularly used widgets, techniques of communications between activities, SQLite database, Google Map for Android and so on. This report presents a design of the project with class diagram and app prototype, and instructions to run and use the app. The main executable codes of the project are attached at the end of the report so as to give a deeper look into the project.

Key Words mobile software; Android app; Google Map; appointment management; location management

1 Introduction to the App


App Name: MemoPal Features: The app allows the following: Manage appointments, meetings and other interested events Locate position of event address in Google map Pick an address from Google map for the event. Specification: The app can deal with any area, but has to include particular features as follows: The app must store data in a local SQLite database It must contain an input screen where the user has to enter data Must include a list (with an underlying SELECT) Must do INSERT, UPDATE, SELECT, DELETE on the database Must have at least 1 list screen, 1 input screen, 1 extra screen (e.g. splash, or help). Use at least two Android features not covered in class. The purpose of this is to demonstrate your proficiency at using the API to discover new features, which you can then implement because you should have built up enough general familiarity with Android to be able to do this. Examples of features might be using new widgets on your screen (e.g. menus on your screen, tabs), multi-row lists, linking to camera, linking to network, animated images, location services, preferences, dialogs, etc. Picking features that make your app look and feel more usable is always a good start.

2 Class Diagram
The interactions and parameter passing between activities are showed in the class diagram below. It shows how each module of the app communicates with each other.
EventDetailActivity MapLocationActivity

finish()

finish()

address

row_id

finish() row_id & flag = 0

WelcomeActivity finish()

EventListActivity

finish()

EditEventActivity

finish()

row_id

MapAddressActivity

row_id & flag = 0

finish() row_id & address flag = 1

finish() eventValues & row_id = -1 finish() HelpActivity flag = 0 finish() CreateEventActivity finish() eventValues & flag = 1

Figure 1 Class Diagram of MemoPal Project

3 App Prototype
The app prototypes of the main modules are as follows. 3.1 Welcome View Display a welcome page to show main features of the project.

Figure 2 Welcome View

3.2 Help View Show help instructions for new users.

Figure 3 Help View

3.3 Create/Edit Appointment View Display an edit page for users to create or edit details of an appointment, with input fields, Google Map button, time pickers and Save/Cancel buttons.

Figure 4 Create/Edit Appointment View

3.4 View/Pick Location View Mark appointment location with a pin marker on Google Map, and enable users to pick a new location for the appointment by long click the screen.

Figure 5 View/Pick Location View

3.5 Appointment List View Display appointments that a user created.

Figure 6 Appointment List View

3.6 Appointment Details View Display appointment details, including event time, date, start time, end time, location and description for the events. Users can view the location on Google Map by clicking the map button, edit details by clicking Edit button or go back to appointment list by clicking home button.

Figure 7 Appointment Details View

3.7 Options Menu View Display an options menu when an appointment is long clicked. Users are allowed to edit or delete selected appointment.

Figure 8 Options Menu View

3.8 Context Menu View Display a context menu when the main menu button on the handset is clicked. Users are allowed to create a new appointment, get help instructions or exit the app.

Figure 9 Context Menu View

4 Additional Features
During the development of the app, I explored a lot in Java APIs, Android Developers APIs and Google Map APIs. The main additional features I applied in the app are listed below: Google Map: displays Google MapView, displays marker in the position interested, and uses Geocoder to convert between address and GeoPoint DatePicker and TimePicker: a friendly and easy way for users to enter date and time Calendar: applies Calendar to get system date and time and to convert the format of date and time OptionsMenu: displays a menu with three options when MENU key is clicked ContextMenu: displays a popup menu with two options when item is long clicked Bundle and Intent: passes and gets data between two activities, such as int, string, long, ArrayList<String> and so on

5 How to Run the App


There are two ways to run this app, either to run it in an Eclipse emulator, or to run it in an Android mobile phone. In Eclipse: Import the project in Eclipse Launch Google APIs 2.1 (API level 7) emulator Run the project as Android Application

In Android mobile phone: Find bin file in the project file Find *.apk in the bin file Install the *.apk in a mobile phone Click the app logo in the mobile handset to run it

6 How to Use the App


Follow the steps below and get started to use the app: When the app runs successfully, a front screen is displayed to briefly introduce what the app does. Touch anywhere on the screen to go to the event list page. The event list page is empty if the app runs for the first time. Click MENU key on the mobile to get a menu that contains three options: Create, Help and Exit. Clicked Create to create your new event, Help to get tips about how to use this app, and Exit to exit the app. While creating an event, click Map icon to view Google map, where you can click to view address toast and long press to pick the address for your event location. Save your event. Now you can see the event you just created on your screen. Long click the event, you will see a menu popped up on your screen, with two options: Edit and Delete. While editing your event, you can click the Map icon to do the same thing as mentioned in creating event. Click the event to view the details of it. Note the Map icon in the details page. Click it and it will display you a Google map, with your event location located in the centre of map.

7 Executable Code
The main codes of the project include three parts: AndroidManifest.xml file *.java files *.xml files The main codes are attached below. 7.1 Part I: AndroidManifest.xml file AndroidManifest.xml <?xml version="1.0" encoding="utf-8"?> <manifest xmlns:android="http://schemas.android.com/apk/res/android" package="ie.dit.student.chen.wenchong" android:versionCode="1" android:versionName="1.0" > <uses-sdk android:minSdkVersion="7" />

<uses-permission android:name="android.permission.ACCESS_COARSE_LOCATION"/> <uses-permission android:name="android.permission.ACCESS_FINE_LOCATION"/> <uses-permission android:name="android.permission.INTERNET"/> <application android:icon="@drawable/ic_launcher" android:label="@string/app_name" > <uses-library android:name="com.google.android.maps" /> <activity android:name=".WelcomeActivity" 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=".EventListActivity" android:label="@string/app_name" > </activity> <activity android:name=".CreateEventActivity" android:label="@string/app_name" > </activity> <activity android:name=".EventDetailActivity" android:label="@string/app_name" > </activity> <activity android:name=".EditEventActivity" android:label="@string/app_name" > </activity> <activity android:name=".HelpActivity" android:label="@string/app_name" > </activity>

<activity android:name=".MapAddressActivity" android:label="@string/app_name" > </activity> <activity android:name=".MapLocationActivity" android:label="@string/app_name" > </activity> </application> </manifest> 7.2 Part II: *.java files EventListActivity.java /** * EventListActivity.java * * redirected from WelcomeActivity when screen touched * * display event list with memo logo, event name and location * click event item to view details of that event, redirecting to EventDetailActivity * long click event item to make options from a popup menu: * - Edit, redirecting to EditEventActivity to edit selected event * - Delete, deleting selected event * click menu to make options from the menu: * - Create, redirecting to CreateEventActivity to create new event * - Help, redirecting to HelpActivity to get tips of how to use this app * - Exit, finish this activity and exit this app * * this activity will only be finished when Exit is performed * */ package ie.dit.student.chen.wenchong; import import import import import import import android.app.ListActivity; android.content.Intent; android.database.Cursor; android.os.Bundle; android.view.ContextMenu; android.view.LayoutInflater; android.view.Menu;

import import import import import import import import

android.view.MenuItem; android.view.View; android.view.ViewGroup; android.view.ContextMenu.ContextMenuInfo; android.widget.AdapterView; android.widget.ListView; android.widget.SimpleCursorAdapter; android.widget.TextView;

public class EventListActivity extends ListActivity { // variables to interact with SQLite DB private EventDBManager myDBManager; private Cursor myCursor; private MyCursorAdapter curAdapter; // variables to project data from DB to ListView private String[] events = {"event_title", "location"}; private int[] to = new int[]{R.id.event_title_row, R.id.location_row}; // menu items private int createItem = Menu.FIRST; private int helpItem = Menu.FIRST + 1; private int exitItem = Menu.FIRST + 2; // long click menu items private int editItem = Menu.FIRST + 3; private int deleteItem = Menu.FIRST + 4; /** Called when the activity is first created. */ @Override public void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.event_list); myDBManager = new EventDBManager(this); // register long click menu listener getListView().setOnCreateContextMenuListener(this); // method to get all events to be displayed in a list getAllEvents();

// end of onCreate()

// actions to be taken when it goes back to this app after interuption public void onResume() { super.onResume(); // get all events to be displayed in a list getAllEvents(); } /** * SELECT: get all events to be displayed in a list */ private void getAllEvents() { // open database myDBManager.open(); myCursor = myDBManager.getAllEvents(); // set SimpleCursorAdapter to project data from DB to ListView curAdapter = new MyCursorAdapter(); this.setListAdapter(curAdapter); // close database myDBManager.close(); } // list items on click actions protected void onListItemClick(ListView l, View v, int position, long id) { super.onListItemClick(l, v, position, id); // get row_id of the event clicked myCursor = (Cursor)curAdapter.getItem(position); long rowId myCursor.getLong(myCursor.getColumnIndex(EventDBManager.KEY_ROWID)); // create bundle to store row_id = rowId Bundle bundle = new Bundle(); bundle.putLong("row_id", rowId); // pass row_id to EventDetailActivity by intent

Intent intent = new Intent(); intent.putExtras(bundle); intent.setClass(EventListActivity.this, EventDetailActivity.class); startActivity(intent); } // create menu that contains three options: Create, Help and Exit public boolean onCreateOptionsMenu(Menu menu) { super.onCreateOptionsMenu(menu); menu.add(0, createItem, 1, "Create"); menu.add(0, helpItem, 2, "Help"); menu.add(0, exitItem, 3, "Exit"); return true; } // menu items onSelected actions public boolean onOptionsItemSelected(MenuItem item) { // create new event if (item.getItemId() == createItem) { // create bundle to store flag to indentify which activity passes the parameters Bundle bundle = new Bundle(); /** * flag = 0 to identify parameters from EventListActivity * flag = 1 to identify parameters from MapAddressActivity */ bundle.putInt("flag", 0); // pass flag to CreateEventActivity by intent Intent intent = new Intent(); intent.putExtras(bundle); intent.setClass(EventListActivity.this, CreateEventActivity.class); startActivity(intent); } // help tip option else if (item.getItemId() == helpItem) { // redirect to HelpActivity frame Intent intent = new Intent(EventListActivity.this, HelpActivity.class);

startActivity(intent); } // exit app option else if (item.getItemId() == exitItem) { // exit the app MemoPal finish(); } return true; } // create long click popup menu, two options: Edit or Delete event public void onCreateContextMenu(ContextMenu menu, View view, ContextMenuInfo menuInfo) { // for getting information of clicked item AdapterView.AdapterContextMenuInfo info; try { // assign information of selected item to info info = (AdapterView.AdapterContextMenuInfo)menuInfo; } catch (ClassCastException e) { return; } // get selected list item info as a Cursor Cursor selectedCursor = (Cursor) getListAdapter().getItem(info.position); if (selectedCursor == null) { return; } // set event name to be header title menu.setHeaderTitle(selectedCursor.getString(EventDBManager.TITLE_COLUMN)); // add two options in the popup menu: Edit and Delete menu.add(1, editItem, 1, "Edit"); menu.add(1, deleteItem, 2, "Delete");

} // long click menu on click actions @Override public boolean onContextItemSelected(MenuItem item) { // for getting information of clicked item AdapterView.AdapterContextMenuInfo info; try { // assign information of selected item to info info = (AdapterView.AdapterContextMenuInfo)item.getMenuInfo(); } catch (ClassCastException e) { return false; } // edit selected event if (item.getItemId() == editItem) { // create bundle to store row id = info.id Bundle bundle = new Bundle(); bundle.putLong("row_id", info.id); /** * flag = 0 to identify parameters from EventListActivity/EventDetailActivity * flag = 1 to identify parameters from MapAddressActivity */ bundle.putInt("flag", 0); // pass row id to EditEventActivity by intent Intent intent = new Intent(); intent.putExtras(bundle); intent.setClass(EventListActivity.this, EditEventActivity.class); startActivity(intent); return true; } // delete selected record else if (item.getItemId() == deleteItem) { // open DB

myDBManager.open(); /** * DELETE: delete record where _id = info.id */ myDBManager.deleteEvent(info.id); // myDBManager.close() is invoked in getAllEvents(), so don't need to close DB here getAllEvents(); return true; } return false; } /** * inner class to project data from DB to ListView * and inflate view to reduce resource consumption */ public class MyCursorAdapter extends SimpleCursorAdapter { // constructor public MyCursorAdapter() { super(EventListActivity.this, R.layout.list_row, myCursor, events, to); } // inflate view and get convertView public View getView(int position, View convertView, ViewGroup parent) { View list_row = convertView; // if convertView is null, inflate list_row if (list_row == null) { LayoutInflater inflater = getLayoutInflater(); list_row = inflater.inflate(R.layout.list_row, parent, false); } // get current cursor that contains current event details Cursor currentCursor = (Cursor)getItem(position);

// get the TextView for the row event title, and set it to the current value TextView eventTitle (TextView)list_row.findViewById(R.id.event_title_row); eventTitle.setText(currentCursor.getString(EventDBManager.TITLE_COLUMN)); // get the TextView for the row event location, and set it to the current value TextView location = (TextView)list_row.findViewById(R.id.location_row); location.setText(currentCursor.getString(EventDBManager.LOCATION_COLUMN)); return list_row; } } } // end of getView()

// end of inner class MyCursorAdapter

EventDetailActivity.java /** * EventDetailActivity.java * * redirected from EventListActivity by clicking an event item on the screen * * - view event details * - can locate event position on Google map by clicking map icon, redirecting to MapLocationActivity * - can Edit event, redirecting to EditEventActivity, when this activity will be finished * - click Home to go back to EventListActivity, when this activity will be finished * */ package ie.dit.student.chen.wenchong; import import import import import import import import android.app.Activity; android.content.Intent; android.database.Cursor; android.os.Bundle; android.view.View; android.widget.Button; android.widget.ImageView; android.widget.TextView;

public class EventDetailActivity extends Activity implements View.OnClickListener

{ // for selecting event details by row_id private EventDBManager myDBManager; private Cursor myCursor; // parameter passed from EventListActivity private long rowId; // parameter to be passed to MapLocationActivity to locate position private String address; // widgets for displaying event details private TextView eventTitle; private TextView eventDate; private TextView startTime; private TextView endTime; private ImageView mapView; private TextView location; private TextView description; private Button editBtn; private Button homeBtn; /** Called when the activity is first created. */ @Override public void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.event_detail); myDBManager = new EventDBManager(this); /** * get view and register listeners */ editBtn = (Button)findViewById(R.id.edit_button); editBtn.setOnClickListener(this); homeBtn = (Button)findViewById(R.id.home_button); homeBtn.setOnClickListener(this); mapView = (ImageView)findViewById(R.id.map_img_view); mapView.setOnClickListener(this); eventTitle = (TextView)findViewById(R.id.evt_title);

location = (TextView)findViewById(R.id.evt_location); description = (TextView)findViewById(R.id.evt_desc); eventDate = (TextView)findViewById(R.id.evt_date); startTime = (TextView)findViewById(R.id.evt_start_time); endTime = (TextView)findViewById(R.id.evt_end_time); // get intent data row_id from EventListActivity Bundle bundle = this.getIntent().getExtras(); rowId = bundle.getLong("row_id"); // display details of selected event displaySelectedEvent(); } // end of onCreate

// display selected record details public void displaySelectedEvent() { // open DB myDBManager.open(); /** * SELECT: get record by rowId */ myCursor = myDBManager.getEvent(rowId); myCursor.moveToFirst(); // when time end with "00", only "0" is displayed, so need to check time format String stTime = myCursor.getString(EventDBManager.START_TIME_COLUMN); String[] start_time = myCursor.getString(EventDBManager.START_TIME_COLUMN).split(":"); if (start_time[1].length() == 1) { // make sure time displayed correctly when ending with "00" stTime = start_time[0] + ":00"; } // when time end with "00", only "0" is displayed, so need to check time format String enTime = myCursor.getString(EventDBManager.END_TIME_COLUMN); String[] end_time = myCursor.getString(EventDBManager.END_TIME_COLUMN).split(":"); if (end_time[1].length() == 1) { // make sure time displayed correctly when ending with "00"

enTime = end_time[0] + ":00"; } // display record column values eventTitle.setText(myCursor.getString(EventDBManager.TITLE_COLUMN)); location.setText(myCursor.getString(EventDBManager.LOCATION_COLUMN)); description.setText(myCursor.getString(EventDBManager.DESCRIPTION_COLUMN)); eventDate.setText(myCursor.getString(EventDBManager.DATE_COLUMN)); startTime.setText(stTime); endTime.setText(enTime); // get address to locate its position in Google map address = myCursor.getString(EventDBManager.LOCATION_COLUMN); // close DB myDBManager.close(); }

// onClick actions: Edit, Home and click Map icon public void onClick(View v) { // Edit button, finish this activity and redirect to EditEventActivity to edit event if (v == editBtn) { // create bundle to store row_id = rowId and flag = 0 Bundle bundle = new Bundle(); bundle.putLong("row_id", rowId); /** * flag = 0 to identify parameters from EventListActivity/EventDetailActivity * flag = 1 to identify parameters from MapAddressActivity */ bundle.putInt("flag", 0); // pass row_id and flag to EditEventActivity by intent Intent intent = new Intent(); intent.putExtras(bundle); intent.setClass(EventDetailActivity.this, EditEventActivity.class); startActivity(intent); finish();

// end of editBtn action

// finish this activity, and go back to EventListActivity if (v == homeBtn) { finish(); } // locate event position in Google map, with address passed into MapLocationActivity // don't finish this activity for it needs to go back to this activity when map is closed if (v == mapView) { // create bundle to store address Bundle bundle = new Bundle(); bundle.putString("address", address); // pass address to MapLocationActivity by intent to locate position in memo Intent intent = new Intent(); intent.putExtras(bundle); intent.setClass(EventDetailActivity.this, MapLocationActivity.class); startActivity(intent); } } } // end of mapView

// end of onClick()

// end of class EditEventAcitvity

EditEventActivity.java /** * EditEventActivity.java * * redirected from EventListActivity/EventDetail to edit events * * - can view Google map by clicking map icon, redirecting to MapAddressActivity * and pick an address from Google map * - can Save changes to event and go back to EventListActivity, when the activity will be finished * - can Clear all texts in EditText * - can Cancel to go back to EventListActivity, when the activity will be finished * */

package ie.dit.student.chen.wenchong; import java.util.Calendar; import import import import import import import import import import import android.app.Activity; android.content.Intent; android.database.Cursor; android.os.Bundle; android.view.View; android.widget.Button; android.widget.DatePicker; android.widget.DatePicker.OnDateChangedListener; android.widget.EditText; android.widget.ImageView; android.widget.TimePicker;

public class EditEventActivity extends Activity implements View.OnClickListener { // for selecting data from DB and updating record into DB private EventDBManager myDBManager; private Cursor myCursor; // parameters from EventListActivity/EventDetailActivity/MapAddressActivity private long rowId; private int flag; private String address; // for passing parameters to MapAddressActivity private Bundle bundle; // widgets for edting event private EditText eventTitle; private DatePicker eventDate; private TimePicker startTime; private TimePicker endTime; private EditText location; private ImageView mapView; private EditText description; private Button saveBtn; private Button clearBtn; private Button cancelBtn; // Calendar and other time and date variables to convert format private Calendar calendar;

private int private int private int private int private int private int private int

year; month; day; startHour; startMinute; endHour; endMinute;

/** Called when the activity is first created. */ @Override public void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.edit_event); myDBManager = new EventDBManager(this); /** * get view and register listeners */ saveBtn = (Button)findViewById(R.id.save_button); saveBtn.setOnClickListener(this); clearBtn = (Button)findViewById(R.id.clear_button); clearBtn.setOnClickListener(this); cancelBtn = (Button)findViewById(R.id.cancel_button); cancelBtn.setOnClickListener(this); mapView = (ImageView)findViewById(R.id.map_img_view2); mapView.setOnClickListener(this); eventTitle = (EditText)findViewById(R.id.event_title); location = (EditText)findViewById(R.id.location); description = (EditText)findViewById(R.id.description); eventDate = (DatePicker)findViewById(R.id.event_date); startTime = (TimePicker)findViewById(R.id.start_time); startTime.setIs24HourView(true); // set 24 hour format endTime = (TimePicker)findViewById(R.id.end_time); endTime.setIs24HourView(true); // set 24 hour format

// initialize calendar calendar = Calendar.getInstance(); // assign system date and time as default for DatePicker and TimePicker year = calendar.get(Calendar.YEAR); month = calendar.get(Calendar.MONTH); day = calendar.get(Calendar.DAY_OF_MONTH); startHour = calendar.get(Calendar.HOUR_OF_DAY); startMinute = calendar.get(Calendar.MINUTE); endHour = startHour; // set end hour one hour later than start hour endMinute = startMinute; // set listener to handle changes in DatePicker eventDate.init(year, month, day, new OnDateChangedListener() { public void onDateChanged(DatePicker view, int year, int monthOfYear, int dayOfMonth) { eventDate.updateDate(year, monthOfYear, dayOfMonth); } }); // set listener to handle changes in DatePicker below /** * warning: when initialize startTime, error occurred using setCurrentHour() * use another way below instead */ //startTime.setCurrentHour(calendar.get(Calendar.HOUR_OF_DAY)); //startTime.setCurrentMinute(calendar.get(Calendar.MINUTE)); startTime.setOnTimeChangedListener(new TimePicker.OnTimeChangedListener() { public void onTimeChanged(TimePicker view, int hourOfDay, int minute) { //startTime.setCurrentHour(hourOfDay); //startTime.setCurrentMinute(minute); EditEventActivity.this.startHour = hourOfDay; EditEventActivity.this.startMinute = minute; } }); // set listener to handle changes in TimePicker endTime.setOnTimeChangedListener(new TimePicker.OnTimeChangedListener() { public void onTimeChanged(TimePicker view, int hourOfDay, int minute)

{ EditEventActivity.this.endHour = hourOfDay; EditEventActivity.this.endMinute = minute; } }); // get intent data from EventListActivity/EventDetailActivity/MapViewActivity bundle = this.getIntent().getExtras(); rowId = bundle.getLong("row_id"); flag = bundle.getInt("flag"); // display details of selected event displaySelectedEvent(); } // end of onCreate

// display selected record details public void displaySelectedEvent() { // open DB myDBManager.open(); /** * SELECT: get record by rowId */ myCursor = myDBManager.getEvent(rowId); myCursor.moveToFirst(); // display record column values eventTitle.setText(myCursor.getString(EventDBManager.TITLE_COLUMN)); description.setText(myCursor.getString(EventDBManager.DESCRIPTION_COLUMN)); /** * flag = 0 to identify parameters from EventListActivity/EventDetailActivity * flag = 1 to identify parameters from MapAddressActivity */ if (flag == 0) { location.setText(myCursor.getString(EventDBManager.LOCATION_COLUMN)); } else if (flag == 1) {

// get address from Google map address = bundle.getString("address"); location.setText(address); } // convert date and update eventDate, and display it in DatePicker String myDate = myCursor.getString(EventDBManager.DATE_COLUMN); String[] date = myDate.split("-"); eventDate.updateDate(Integer.parseInt(date[2]), // year Integer.parseInt(date[0]) - 1, // month (starts from 0) Integer.parseInt(date[1])); // day of month // convert time and update startTime and endTime, and display them in TimePicker String myTime; String[] time; // startTime myTime = myCursor.getString(EventDBManager.START_TIME_COLUMN); time = myTime.split(":"); startTime.setCurrentHour(Integer.parseInt(time[0])); startTime.setCurrentMinute(Integer.parseInt(time[1])); // endTime myTime = myCursor.getString(EventDBManager.END_TIME_COLUMN); time = myTime.split(":"); endTime.setCurrentHour(Integer.parseInt(time[0])); endTime.setCurrentMinute(Integer.parseInt(time[1])); // close DB myDBManager.close(); } // onClick actions: Save, Clear, Cancel and click Map icon public void onClick(View v) { // save event details by inserting them into DB if (v == saveBtn) { // open database myDBManager.open(); // for event date String month = String.valueOf(eventDate.getMonth() + 1); String day = String.valueOf(eventDate.getDayOfMonth()); String year = String.valueOf(eventDate.getYear());

// for start time String strHour = Integer.toString(startHour); String strMinute = Integer.toString(startMinute); // for end time String edHour = Integer.toString(endHour); String edMinute = Integer.toString(endMinute); // for column values String evtTitle = eventTitle.getText().toString(); String evtDate = month + "-" + day + "-" + year; String strTime = strHour + ":" + strMinute; String edTime = edHour + ":" + edMinute; String lction = location.getText().toString(); String destion = description.getText().toString(); /** * UPDATE: update a record */ myDBManager.updateEvent(rowId, evtTitle, evtDate, strTime, edTime, lction, destion); // close database myDBManager.close(); finish(); } // end of saveBtn action

// clear all texts in all EditTexts if (v == clearBtn) { eventTitle.setText(""); location.setText(""); description.setText(""); } // cancel create new event action, finish this activity, go back to EventListActivity if (v == cancelBtn) { finish(); }

// view Google map, with event details and flag passed into MapAddressActivity if (v == mapView) { // create bundle to store row_id = rowId Bundle bundle = new Bundle(); /** * both CreateEventActivity and EditEventActivity make use of MapAddressActivity * in a similar way, to get address from Google map * * to decide which activity uses MapAddressActivity, * assign row_id = -1 to identify parameters passed from CreateEventActivity, and * assign row_id = the rowId of the event the user selected to identify EditEventActivity */ bundle.putLong("row_id", rowId); // pass row_id to MapViewActivity by intent Intent intent = new Intent(); intent.putExtras(bundle); intent.setClass(EditEventActivity.this, MapAddressActivity.class); startActivity(intent); finish(); } } } // end of mapView

// end of onClick()

// end of class EditEventAcitvity

CreateEventActivity.java /** * CreateEventActivity.java * * redirected from EventListActivity to create events * * - can view Google map by clicking map icon, redirecting to MapAddressActivity * and pick an address from Google map * - can Save new event and go back to EventListActivity, when this activity will be finished * - can Clear all texts in EditText

* - can Cancel to go back to EventListActivity, when this activity will be finished * */ package ie.dit.student.chen.wenchong; import java.util.ArrayList; import java.util.Calendar; import import import import import import import import import import android.app.Activity; android.content.Intent; android.os.Bundle; android.view.View; android.widget.Button; android.widget.DatePicker; android.widget.DatePicker.OnDateChangedListener; android.widget.EditText; android.widget.ImageView; android.widget.TimePicker;

public class CreateEventActivity extends Activity implements View.OnClickListener { // for inserting new record into DB private EventDBManager myDBManager; // parameters from EventListActivity/MapAddressActivity private ArrayList<String> eventValues = new ArrayList<String>(); private int flag; // widgets for creating new event private EditText eventTitle; private DatePicker eventDate; private TimePicker startTime; private TimePicker endTime; private EditText location; private ImageView mapView; private EditText description; private Button saveBtn; private Button clearBtn; private Button cancelBtn; // Calendar and other time and date variables to convert format private Calendar calendar; private int year;

private int private int private int private int private int private int

month; day; startHour; startMinute; endHour; endMinute;

/** Called when the activity is first created. */ @Override public void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.edit_event); myDBManager = new EventDBManager(this); /** * get view and register listeners */ saveBtn = (Button)findViewById(R.id.save_button); saveBtn.setOnClickListener(this); clearBtn = (Button)findViewById(R.id.clear_button); clearBtn.setOnClickListener(this); cancelBtn = (Button)findViewById(R.id.cancel_button); cancelBtn.setOnClickListener(this); mapView = (ImageView)findViewById(R.id.map_img_view2); mapView.setOnClickListener(this); eventTitle = (EditText)findViewById(R.id.event_title); location = (EditText)findViewById(R.id.location); description = (EditText)findViewById(R.id.description); eventDate = (DatePicker)findViewById(R.id.event_date); startTime = (TimePicker)findViewById(R.id.start_time); startTime.setIs24HourView(true); // set 24 hour format endTime = (TimePicker)findViewById(R.id.end_time); endTime.setIs24HourView(true); // set 24 hour format // initialize calendar

calendar = Calendar.getInstance(); // assign system date and time as default for DatePicker and TimePicker year = calendar.get(Calendar.YEAR); month = calendar.get(Calendar.MONTH); day = calendar.get(Calendar.DAY_OF_MONTH); startHour = calendar.get(Calendar.HOUR_OF_DAY); startMinute = calendar.get(Calendar.MINUTE); endHour = startHour; endMinute = startMinute; // set listener to handle changes in DatePicker eventDate.init(year, month, day, new OnDateChangedListener() { public void onDateChanged(DatePicker view, int year, int monthOfYear, int dayOfMonth) { eventDate.updateDate(year, monthOfYear, dayOfMonth); } }); // set listener to handle changes in DatePicker below /** * warning: when initialize startTime, error occurred using setCurrentHour() * use another way below instead */ //startTime.setCurrentHour(calendar.get(Calendar.HOUR_OF_DAY)); //startTime.setCurrentMinute(calendar.get(Calendar.MINUTE)); startTime.setOnTimeChangedListener(new TimePicker.OnTimeChangedListener() { public void onTimeChanged(TimePicker view, int hourOfDay, int minute) { //startTime.setCurrentHour(hourOfDay); //startTime.setCurrentMinute(minute); CreateEventActivity.this.startHour = hourOfDay; CreateEventActivity.this.startMinute = minute; } }); // set listener to handle changes in TimePicker endTime.setOnTimeChangedListener(new TimePicker.OnTimeChangedListener() { public void onTimeChanged(TimePicker view, int hourOfDay, int minute) {

CreateEventActivity.this.endHour = hourOfDay; CreateEventActivity.this.endMinute = minute; } }); // get intent data from MapAddressActivity/EventListActivity Bundle bundle = this.getIntent().getExtras(); flag = bundle.getInt("flag"); /** * flag = 0 to identify parameters from EventListActivity * flag = 1 to identify parameters from MapAddressActivity */ if (flag == 1) { /* * - if parameters from MapAddressActivity, get eventValues from it * and display event details with address picked from Google map in it * * - eventValues is passed to MapAddressActivity so that event details * entered by user can be displayed again when it redirects back from * MapAddressActivity * * - eventValues passed from MapAddressActivity contains address picked * from Google map apart from the original eventValues */ eventValues = bundle.getStringArrayList("event_column_values"); displayDetails(); } } // end of if()

// end of onCreate

// display event details entered before viewing Google map and address from Google map private void displayDetails() { eventTitle.setText(eventValues.get(0)); eventDate.updateDate(Integer.parseInt(eventValues.get(1)), // year Integer.parseInt(eventValues.get(2)), // month Integer.parseInt(eventValues.get(3))); // day of month startTime.setCurrentHour(Integer.parseInt(eventValues.get(4))); startTime.setCurrentMinute(Integer.parseInt(eventValues.get(5))); endTime.setCurrentHour(Integer.parseInt(eventValues.get(6)));

endTime.setCurrentMinute(Integer.parseInt(eventValues.get(7))); description.setText(eventValues.get(8)); location.setText(eventValues.get(9)); // from Google map } // onClick actions: Save, Clear, Cancel and click Map icon public void onClick(View v) { // save event details by inserting them into DB if (v == saveBtn) { // open database myDBManager.open(); // for event date String month = String.valueOf(eventDate.getMonth() + 1); String day = String.valueOf(eventDate.getDayOfMonth()); String year = String.valueOf(eventDate.getYear()); // for start time String strHour = Integer.toString(startHour); String strMinute = Integer.toString(startMinute); // for end time String edHour = Integer.toString(endHour); String edMinute = Integer.toString(endMinute); // for column values String evtTitle = eventTitle.getText().toString(); String evtDate = month + "-" + day + "-" + year; String strTime = strHour + ":" + strMinute; String edTime = edHour + ":" + edMinute; String lction = location.getText().toString(); String destion = description.getText().toString(); /** * INSERT: insert a new record */ myDBManager.insertEvent(evtTitle, evtDate, strTime, edTime, lction, destion); // close database myDBManager.close(); finish();

// end of saveBtn action

// clear all texts in all EditTexts if (v == clearBtn) { eventTitle.setText(""); location.setText(""); description.setText(""); } // cancel create new event action, finish this activity, go back to EventListActivity if (v == cancelBtn) { finish(); } // view Google map, with event details and flag passed into MapAddressActivity if (v == mapView) { // for event date String month = String.valueOf(eventDate.getMonth()); String day = String.valueOf(eventDate.getDayOfMonth()); String year = String.valueOf(eventDate.getYear()); // for start time String strHour = Integer.toString(startHour); String strMinute = Integer.toString(startMinute); // for end time String edHour = Integer.toString(endHour); String edMinute = Integer.toString(endMinute); // add event details to eventValues eventValues.add(eventTitle.getText().toString()); eventValues.add(year); eventValues.add(month); eventValues.add(day); eventValues.add(strHour); eventValues.add(strMinute); eventValues.add(edHour); eventValues.add(edMinute); eventValues.add(description.getText().toString());

// create bundle to store row_id = -1, and eventValues Bundle bundle = new Bundle(); bundle.putStringArrayList("event_column_values", eventValues); /** * both CreateEventActivity and EditEventActivity make use of MapAddressActivity * in a similar way, to get address from Google map * * to decide which activity uses MapAddressActivity, * assign row_id = -1 to identify parameters passed from CreateEventActivity, and * assign row_id = the rowId of the event the user selected to ident ify EditEventActivity */ bundle.putLong("row_id", -1); // pass row_id and event details to MapAddressActivity by intent Intent intent = new Intent(); intent.putExtras(bundle); intent.setClass(CreateEventActivity.this, MapAddressActivity.class); startActivity(intent); finish(); } } } // end of mapView

// end of onClick()

// end of class EditEventAcitvity

EventDBManager.java /** * EventDBManager.java * * manage SQLite DB with SQLiteDatabase and SQLiteOpenHelper: * - create DB and table * - open DB * - select all records * - select record by _id * - insert record * - update record * - delete record * - close DB

* */ package ie.dit.student.chen.wenchong; import import import import import import android.content.ContentValues; android.content.Context; android.database.Cursor; android.database.SQLException; android.database.sqlite.SQLiteDatabase; android.database.sqlite.SQLiteOpenHelper;

public class EventDBManager { /** * member fields */ // table column names public static final String KEY_ROWID = "_id"; public static final String KEY_EVENT_TITLE = "event_title"; public static final String KEY_EVENT_DATE = "event_date"; public static final String KEY_START_TIME = "start_time"; public static final String KEY_END_TIME = "end_time"; public static final String KEY_LOCATION = "location"; public static final String KEY_DESCRIPTION = "description"; // column indexes public static final int _ID_COLUMN = 0; public static final int TITLE_COLUMN = 1; public static final int DATE_COLUMN = 2; public static final int START_TIME_COLUMN = 3; public static final int END_TIME_COLUMN = 4; public static final int LOCATION_COLUMN = 5; public static final int DESCRIPTION_COLUMN = 6; // database name, version, and table name private static final String DATABASE_NAME = "Events.db"; private static final String DATABASE_TABLE = "Event"; private static final int DATABASE_VERSION = 1; // query to create Event table private static final String DATABASE_CREATE = "create table Event (" +

"_id integer primary key autoincrement, " + "event_title text not null, " + "event_date text, " + "start_time text, " + "end_time text, " + "location text, " + "description text);"; private final Context context; private DatabaseHelper DBHelper; private SQLiteDatabase db; // constructor public EventDBManager(Context ctx) { // initialize SQLiteOpenHelper this.context = ctx; DBHelper = new DatabaseHelper(context); } /** * inner class DatabaseHelper that creates DB and updates DB structure */ private static class DatabaseHelper extends SQLiteOpenHelper { // constructor DatabaseHelper(Context context) { super(context, DATABASE_NAME, null, DATABASE_VERSION); } @Override // create DB public void onCreate(SQLiteDatabase db) { db.execSQL(DATABASE_CREATE); } @Override // update DB structure public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) { // whatever is to be changed on dB structure

} // end of inner class DatabaseHelper

/** * methods below */ // open DB as writable public EventDBManager open() throws SQLException { db = DBHelper.getWritableDatabase(); return this; } // close DB public void close() { DBHelper.close(); } // insert a new event record public long insertEvent(String event_title, String event_date, String start_time, String end_time, String location, String description) { // create ContentValues to insert a record ContentValues initialValues = new ContentValues(); // insert data initialValues.put(KEY_EVENT_TITLE, event_title); initialValues.put(KEY_EVENT_DATE, event_date); initialValues.put(KEY_START_TIME, start_time); initialValues.put(KEY_END_TIME, end_time); initialValues.put(KEY_LOCATION, location); initialValues.put(KEY_DESCRIPTION, description); return db.insert(DATABASE_TABLE, null, initialValues); } // end of insertEvent()

// delete a event record by _id public boolean deleteEvent(long rowId) { return db.delete(DATABASE_TABLE, KEY_ROWID + "=" + rowId, null) > 0; }

// select all records from DB public Cursor getAllEvents() { return db.query(DATABASE_TABLE, new String[] { KEY_ROWID, KEY_EVENT_TITLE, KEY_EVENT_DATE, KEY_START_TIME, KEY_END_TIME, KEY_LOCATION, KEY_DESCRIPTION, }, null, null, null, null, null); } // end of getAllEvents() // select a record by _id public Cursor getEvent(long rowId) throws SQLException { Cursor mCursor =db.query(true, DATABASE_TABLE, new String[] { KEY_ROWID, KEY_EVENT_TITLE, KEY_EVENT_DATE, KEY_START_TIME, KEY_END_TIME, KEY_LOCATION, KEY_DESCRIPTION, }, KEY_ROWID + "=" + rowId, null, null, null, null, null); if (mCursor != null) { mCursor.moveToFirst();

} return mCursor; } // end of getEvent()

// update a record public boolean updateEvent(long rowId, String event_title, String event_date, String start_time, String end_time, String location, String description) { // create ContentValues to update a record ContentValues args = new ContentValues(); // put column values into DB args.put(KEY_EVENT_TITLE, event_title); args.put(KEY_EVENT_DATE, event_date); args.put(KEY_START_TIME, start_time); args.put(KEY_END_TIME, end_time); args.put(KEY_LOCATION, location); args.put(KEY_DESCRIPTION, description); return db.update(DATABASE_TABLE, args, KEY_ROWID + "=" + rowId, null) > 0; } } // end of updateEvent()

// end of class EventDBManager

MapLocationActivity.java /** * MapLocationActivity.java * * redirected from EventDetailActivity * * - display Googel map with default centre the address passed in * - click BACK key to redirect back to EventDetailActivity, * when this activity will be finished * */ package ie.dit.student.chen.wenchong; import java.io.IOException;

import java.util.List; import java.util.Locale; import import import import import import import import import import import import import com.google.android.maps.GeoPoint; com.google.android.maps.MapActivity; com.google.android.maps.MapController; com.google.android.maps.MapView; android.graphics.Bitmap; android.graphics.BitmapFactory; android.graphics.Canvas; android.graphics.Point; android.location.Address; android.location.Geocoder; android.os.Bundle; android.view.MotionEvent; android.widget.Toast;

public class MapLocationActivity extends MapActivity { // for making use of Google map and managing location private MapView mapView; private MapController mapController; private MapOverlay mapOverlay; private GeoPoint geoPoint; // parameter passed from EventDetailActivity to locate position of event address private String myAddress; /** Called when the activity is first created. */ @Override public void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.map_view); // get address from EventDetailActivity Bundle bundle = this.getIntent().getExtras(); myAddress = bundle.getString("address"); // get MapView mapView = (MapView)findViewById(R.id.map_view); // get map controller

mapController = mapView.getController(); // set the location of the address passed in as default centre location mapController.setCenter(getLocationPoint()); mapController.setZoom(17); mapView.setBuiltInZoomControls(true); // get GeoPoint of the address passed in geoPoint = getLocationPoint(); // add a location marker mapOverlay = new MapOverlay(); mapView.getOverlays().add(mapOverlay); } @Override protected boolean isRouteDisplayed() { return false; } // convert the format of GeoPoint private GeoPoint getPoint(double lat, double lon) { // 1E6 = 1000000.0 return (new GeoPoint((int)(lat * 1E6), (int)(lon * 1E6))); } // get GeoPoint from address name passed in private GeoPoint getLocationPoint() { // Geocoder manages the transformation of address and GeoPoint Geocoder geoCoder = new Geocoder(this, Locale.getDefault()); // if address does not exist, use default location: DIT Kevin St GeoPoint newPoint = getPoint(53.33745906192509, -6.267592906951904); try { // convert address passed in to the format of Address List List<Address> address = geoCoder.getFromLocationName(myAddress, 2); if (address.size() > 0) {

// if address list not null, get its GeoPoint newPoint = new GeoPoint( (int) (address.get(0).getLatitude() * 1E6), (int) (address.get(0).getLongitude() * 1E6)); } } catch (IOException ex) { ex.printStackTrace(); } return newPoint; } // inner class MapOverlay private class MapOverlay extends com.google.android.maps.Overlay { // draw marker in the location public boolean draw(Canvas canvas, MapView mapView, boolean shadow, long when) { super.draw(canvas, mapView, shadow); // translate GeoPoint to screen coordinate Point screenPoint = new Point(); mapView.getProjection().toPixels(geoPoint, screenPoint); // add location marker to the current location Bitmap bmp = BitmapFactory.decodeResource(getResources(), R.drawable.marker); // screenPoint.y - 41 to make sure the pin will point to the right location // 41 pixel is the height of maker.png canvas.drawBitmap(bmp, screenPoint.x, screenPoint.y - 41, null); return true; } // end of draw()

// public boolean onTouchEvent(MotionEvent me, MapView mapView) { // if finger leaves screen, toast address to the screen if (me.getAction() == MotionEvent.ACTION_UP)

{ // translate screen coordinate to GeoPoint GeoPoint newPoint = mapView.getProjection().fromP ixels((int)me.getX(), (int)me.getY()); // define Geocoder Geocoder geoCoder Locale.getDefault());

new

Geocoder(getBaseContext(),

// address where the screen is touched String addr = ""; try { // get address from GeoPoint List<Address> address = geoCoder.getFromLocation( newPoint.getLatitudeE6() / 1E6, newPoint.getLongitudeE6() / 1E6, 1); addr = ""; if (address.size() > 0) { // if address list not null, append it to addr for (int i = 0; i < address.get(0).getMaxAddressLineIndex(); i++) { addr += address.get(0).getAddressLine(i) + "\n"; } } // toast address to the screen Toast.makeText(getBaseContext(), Toast.LENGTH_SHORT).show(); } // end of try{} catch (IOException ex) { ex.printStackTrace(); } return true; } // end of if() else

addr,

{ return false; } } } } // end of onTouchEvent()

// end of inner class MapOverlay

// end of class MapViewActivity

MapAddressActivity.java /** * MapAddressActivity.java * * redirected from EditEventActivity/CreateEventActivity * * - display Googel map with default centre DIT Kevin St * - touch screen to toast address * - long press screen to get address for EditEventActivity/CreateEventActivity, * when this actvity will be finished, and * redirect back to EditEventActivity/CreateEventActivity * */ package ie.dit.student.chen.wenchong; import import import import import import import import import import import import import import import import java.io.IOException; java.util.ArrayList; java.util.List; java.util.Locale; com.google.android.maps.GeoPoint; com.google.android.maps.MapActivity; com.google.android.maps.MapController; com.google.android.maps.MapView; android.content.Intent; android.graphics.Bitmap; android.graphics.BitmapFactory; android.graphics.Canvas; android.graphics.Point; android.location.Address; android.location.Geocoder; android.os.Bundle;

import android.view.MotionEvent; import android.widget.Toast; public class MapAddressActivity extends MapActivity { // for making use of Google map and managing location private MapView mapView; private MapController mapController; private MapOverlay mapOverlay; private GeoPoint geoPoint; // parameter passed from EditEventActivity/CreateEventActivity private long rowId; // parameter passed from CreateEventActivity private ArrayList<String> eventValues = new ArrayList<String>(); /** Called when the activity is first created. */ @Override public void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.map_view); // get MapView mapView = (MapView)findViewById(R.id.map_view); // get map controller mapController = mapView.getController(); // set default centre location: DIT, Lower Kevin Street, Dublin, Ireland mapController.setCenter(getPoint(53.33745906192509, -6.267592906951904)); mapController.setZoom(17); mapView.setBuiltInZoomControls(true); // get current GeoPoint geoPoint = getPoint(53.33745906192509, -6.267592906951904); // add a location marker mapOverlay = new MapOverlay(); mapView.getOverlays().add(mapOverlay); // get row_id from EditEventActivity/CreateEventActivity Bundle bundle = this.getIntent().getExtras(); rowId = bundle.getLong("row_id");

/** * both CreateEventActivity and EditEventActivity make use of MapAddressActivity * in a similar way, to get address from Google map * * to decide which activity uses MapAddressActivity, * assign row_id = -1 to identify parameters passed from CreateEventActivity, and * assign row_id = the rowId of the event the user selected to identify EditEventActivity */ if (rowId == -1) { // get event details if parameters passed from CreateEventActivity eventValues = bundle.getStringArrayList("event_column_values"); } } // end of onCreate()

@Override protected boolean isRouteDisplayed() { return false; } // convert the format of GeoPoint private GeoPoint getPoint(double lat, double lon) { // 1E6 = 1000000.0 return (new GeoPoint((int)(lat * 1E6), (int)(lon * 1E6))); } // inner class MapOverlay private class MapOverlay extends com.google.android.maps.Overlay { // draw marker in the location public boolean draw(Canvas canvas, MapView mapView, boolean shadow, long when) { super.draw(canvas, mapView, shadow); // translate GeoPoint to screen coordinate Point screenPoint = new Point(); mapView.getProjection().toPixels(geoPoint, screenPoint);

// add location marker to the current location Bitmap bmp = BitmapFactory.decodeResource(getResources(), R.drawable.marker); // screenPoint.y - 41 to make sure the pin will point to the right location // 41 pixel is the height of maker.png canvas.drawBitmap(bmp, screenPoint.x, screenPoint.y - 41, null); return true; } // end of draw()

// public boolean onTouchEvent(MotionEvent me, MapView mapView) { // if finger leaves screen, check whether it is a long press or short press motion event if (me.getAction() == MotionEvent.ACTION_UP) { // translate screen coordinate to GeoPoint GeoPoint newPoint = mapView.getProjection().fromP ixels((int)me.getX(), (int)me.getY()); // define Geocoder Geocoder geoCoder Locale.getDefault());

new

Geocoder(getBaseContext(),

// address where the screen is touched String addr = ""; try { // get address from GeoPoint List<Address> address = geoCoder.getFromLocation( newPoint.getLatitudeE6() / 1E6, newPoint.getLongitudeE6() / 1E6, 1); addr = ""; if (address.size() > 0) { // if address list not null, append it to addr for (int i = 0; i < address.get(0).getMaxAddressLineIndex(); i++)

{ addr += address.get(0).getAddressLine(i) + "\n"; } } // if address of where clicked does not exist, set defaul address if (addr.equals("")) { addr = "18 Lower Kevin St" + "\n" + "Rathmines" + "\n" + "Dublin 2" + "\n" + "Dublin" + "\n" + "Ireland"; } } // end of try{} catch (IOException ex) { ex.printStackTrace(); } // calculate time the screen is pressed long time = me.getEventTime() - me.getDownTime(); // long click, pass address to fill in location EditEventActivity/CreateEventActivity if (time > 1200) { // create bundle to store row_id, address and flag Bundle bundle = new Bundle(); /** * flag = 0 to identify parameters EventListActivity/EventDetailActivity * flag = 1 to identify parameters from MapAddressActivity */ bundle.putInt("flag", 1); // create Intent Intent intent = new Intent(); /** * both CreateEventActivity and EditEventActivity make use of MapAddressActivity field in

from

* in a similar way, to get address from Google map * * to decide which activity uses MapAddressActivity, * assign row_id = -1 to identify parameters passed from CreateEventActivity, and * assign row_id = the rowId of the event the user selected to identify EditEventActivity */ if (rowId != -1) { // from EditEventActivity bundle.putString("address", addr); bundle.putLong("row_id", rowId); // pass row_id, address and flag to EditEventActivity by intent intent.putExtras(bundle); intent.setClass(MapAddressActivity.this, EditEventActivity.class); } else if (rowId == -1) { // from CreateEventActivity // pass eventValues back to CreateEventActivity with address encapsulated in it eventValues.add(addr); bundle.putStringArrayList("event_column_values", eventValues); // pass event details with address from Google map to CreateEventActivity by intent intent.putExtras(bundle); intent.setClass(MapAddressActivity.this, CreateEventActivity.class); } startActivity(intent); finish(); } // end of if()

// else it is short click, toast address to the screen

else { Toast.makeText(getBaseContext(), Toast.LENGTH_SHORT).show(); } return true; } else { return false; } } } } // end of onTouchEvent() // end of if() addr,

// end of inner class MapOverlay

// end of class MapViewActivity

WelcomeActivity.java /** * WelcomeActivity.java * * welcome page to show app name and * main functionalities: * - manage memos * - make use of Google map * * touch the screen to redirect to EventListActivity * and this activity will be finished * */ package ie.dit.student.chen.wenchong; import import import import android.app.Activity; android.content.Intent; android.os.Bundle; android.view.MotionEvent;

public class WelcomeActivity extends Activity

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

// when screen touched, go to event list page public boolean onTouchEvent(MotionEvent me) { if (me.getAction() == MotionEvent.ACTION_DOWN) { // start EventListActivity Intent intent = new Intent(WelcomeActivity.this, EventListActivity.class); startActivity(intent); // finish WelcomeActivity, don't need to go back to this activity finish(); } return true; } } // end of onTouchEvent()

// end of class WelcomeAcitvity

HelpActivity.java /** * HelpActivity.java * * redirected from EventListActivity by selecting Help item in menu * * provides five help tips * * finished when redirected back to EventListActivity * */ package ie.dit.student.chen.wenchong; import android.app.Activity;

import android.os.Bundle; import android.view.View; import android.widget.Button; public class HelpActivity extends Activity { // button that redirects back to EventListActivity private Button backBtn; /** Called when the activity is first created. */ @Override public void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.help); backBtn = (Button)findViewById(R.id.back_button); backBtn.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View v) { // finish this activity to reduce resource consumption // can always start this activity from help menu in EventListActivity finish(); } }); // end of onCreate

} }

// end of class HelpAcitvity

7.3 Part III: *.xml files welcome.xml <?xml version="1.0" encoding="utf-8"?> <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" android:layout_width="fill_parent" android:layout_height="wrap_content" android:orientation="vertical" > <!-- app name --> <TableRow android:layout_width="fill_parent"

android:layout_height="wrap_content" > <TextView android:layout_width="fill_parent" android:layout_height="wrap_content" android:text="@string/welcome_text" android:textSize="30dip" /> </TableRow> <!-- black gap separator 1 --> <ImageView android:id="@+id/image_separator1" android:layout_width="fill_parent" android:layout_height="wrap_content" android:src="@drawable/separator" /> <!-- functionality 1: manage events --> <TableRow android:layout_width="fill_parent" android:layout_height="wrap_content" > <ImageView android:id="@+id/img_1" android:layout_width="wrap_content" android:layout_height="wrap_content" android:src="@drawable/memo_logo" /> <TextView android:layout_width="fill_parent" android:layout_height="wrap_content" android:text="@string/welcome_memo" android:textAppearance="?android:attr/textAppearanceMedium" /> </TableRow> <!-- black gap separator 1 --> <ImageView android:id="@+id/image_separator2" android:layout_width="fill_parent" android:layout_height="wrap_content" android:src="@drawable/separator" /> <!-- functionality 2: Google map --> <TableRow android:layout_width="fill_parent" android:layout_height="wrap_content" > <ImageView android:id="@+id/img_2"

android:layout_width="wrap_content" android:layout_height="wrap_content" android:src="@drawable/map_logo2" /> <TextView android:layout_width="fill_parent" android:layout_height="wrap_content" android:text="@string/welcome_map" android:textAppearance="?android:attr/textAppearanceMedium" /> </TableRow> </LinearLayout> help.xml <?xml version="1.0" encoding="utf-8" ?> <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" android:layout_width="fill_parent" android:layout_height="wrap_content" android:orientation="vertical" > <!-- Help tips --> <TableRow android:layout_width="fill_parent" android:layout_height="wrap_content" > <TextView android:layout_width="fill_parent" android:layout_height="wrap_content" android:text="@string/help_text" android:textSize="30dip" /> </TableRow> <!-- tip 1 --> <TableRow android:layout_width="fill_parent" android:layout_height="wrap_content" > <ImageView android:id="@+id/tip_img_view1" android:layout_width="wrap_content" android:layout_height="wrap_content" android:src="@drawable/tip" /> <TextView android:layout_width="fill_parent" android:layout_height="wrap_content" android:text="@string/tip_text_1"

android:textAppearance="?android:attr/textAppearanceMedium" android:textColor="@color/grey" /> </TableRow> <!-- tip 2 --> <TableRow android:layout_width="fill_parent" android:layout_height="wrap_content" > <ImageView android:id="@+id/tip_img_view2" android:layout_width="wrap_content" android:layout_height="wrap_content" android:src="@drawable/tip" /> <TextView android:layout_width="fill_parent" android:layout_height="wrap_content" android:text="@string/tip_text_2" android:textAppearance="?android:attr/textAppearanceMedium" android:textColor="@color/grey" /> </TableRow> <!-- tip 3 --> <TableRow android:layout_width="fill_parent" android:layout_height="wrap_content" > <ImageView android:id="@+id/tip_img_view3" android:layout_width="wrap_content" android:layout_height="wrap_content" android:src="@drawable/tip" /> <TextView android:layout_width="fill_parent" android:layout_height="wrap_content" android:text="@string/tip_text_3" android:textAppearance="?android:attr/textAppearanceMedium" android:textColor="@color/grey" /> </TableRow> <!-- tip 4 --> <TableRow android:layout_width="fill_parent" android:layout_height="wrap_content" > <ImageView android:id="@+id/tip_img_view4"

android:layout_width="wrap_content" android:layout_height="wrap_content" android:src="@drawable/tip" /> <TextView android:layout_width="fill_parent" android:layout_height="wrap_content" android:text="@string/tip_text_4" android:textAppearance="?android:attr/textAppearanceMedium" android:textColor="@color/grey" /> </TableRow> <!-- tip 5 --> <TableRow android:layout_width="fill_parent" android:layout_height="wrap_content" > <ImageView android:id="@+id/tip_img_view5" android:layout_width="wrap_content" android:layout_height="wrap_content" android:src="@drawable/tip" /> <TextView android:layout_width="fill_parent" android:layout_height="wrap_content" android:text="@string/tip_text_5" android:textAppearance="?android:attr/textAppearanceMedium" android:textColor="@color/grey" /> </TableRow> <!-- button for going back to home screen --> <Button android:id="@+id/back_button" android:layout_width="wrap_content" android:layout_height="wrap_content" android:text="@string/back_button_text" /> </LinearLayout> event_list.xml <?xml version="1.0" encoding="utf-8" ?> <ListView xmlns:android="http://schemas.android.com/apk/res/android" android:layout_width="fill_parent" android:layout_height="fill_parent" android:cacheColorHint="#00000000"

android:id="@android:id/list" > </ListView> list_row.xml <?xml version="1.0" encoding="utf-8" ?> <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" android:layout_width="fill_parent" android:layout_height="wrap_content" android:orientation="vertical" > <!-- MemoPal logo and event title --> <TableRow android:layout_width="fill_parent" android:layout_height="wrap_content" > <ImageView android:id="@+id/logo_view" android:layout_width="wrap_content" android:layout_height="wrap_content" android:src="@drawable/memo_logo" /> <TextView android:id="@+id/event_title_row" android:layout_width="fill_parent" android:layout_height="wrap_content" android:textAppearance="?android:attr/textAppearanceLarge" /> </TableRow> <!-- event location --> <TextView android:id="@+id/location_row" android:layout_width="fill_parent" android:layout_height="wrap_content" /> </LinearLayout> edit_event.xml <?xml version="1.0" encoding="utf-8" ?> <ScrollView xmlns:android="http://schemas.android.com/apk/res/android" android:layout_width="fill_parent" android:layout_height="fill_parent" android:orientation="vertical" >

<TableLayout xmlns:android="http://schemas.android.com/apk/res/android" android:layout_width="fill_parent" android:layout_height="wrap_content" android:stretchColumns="0" > <!-- event title --> <TextView android:id="@+id/event_text" android:layout_width="wrap_content" android:layout_height="wrap_content" android:text="@string/event_title_text" android:textAppearance="?android:attr/textAppearanceLarge" /> <EditText android:id="@+id/event_title" android:layout_width="fill_parent" android:layout_height="wrap_content" />

<!-- separator 1: location --> <TextView android:id="@+id/separator1" android:layout_width="fill_parent" android:layout_height="0.8dp" android:background="@color/separator_color" /> <!-- separator 1 --> <TextView android:id="@+id/location_text" android:layout_width="wrap_content" android:layout_height="wrap_content" android:text="@string/location_text" android:textAppearance="?android:attr/textAppearanceLarge" /> <TableRow android:layout_width="fill_parent" android:layout_height="wrap_content" > <ImageView android:id="@+id/map_img_view2" android:layout_width="wrap_content" android:layout_height="wrap_content" android:src="@drawable/map_logo" /> <EditText

android:id="@+id/location" android:layout_width="fill_parent" android:layout_height="wrap_content" android:inputType="textPostalAddress" android:text="@string/location_tip" /> </TableRow>

<!-- separator 2: date --> <TextView android:id="@+id/separator2" android:layout_width="fill_parent" android:layout_height="0.8dp" android:background="@color/separator_color" /> <!-- separator 2 --> <TextView android:id="@+id/event_date_text" android:layout_width="wrap_content" android:layout_height="wrap_content" android:text="@string/event_date_text" android:textAppearance="?android:attr/textAppearanceLarge" /> <DatePicker android:id="@+id/event_date" android:layout_width="fill_parent" android:layout_height="wrap_content" />

<!-- separator 3: start time --> <TextView android:id="@+id/separator3" android:layout_width="fill_parent" android:layout_height="0.8dp" android:background="@color/separator_color" /> <!-- separator 3 --> <TextView android:id="@+id/start_time_text" android:layout_width="wrap_content" android:layout_height="wrap_content" android:text="@string/start_time_text"

android:textAppearance="?android:attr/textAppearanceLarge" /> <TimePicker android:id="@+id/start_time" android:layout_width="wrap_content" android:layout_height="wrap_content" />

<!-- separator 4: end time --> <TextView android:id="@+id/separator4" android:layout_width="fill_parent" android:layout_height="0.8dp" android:background="@color/separator_color" /> <!-- separator 4 --> <TextView android:id="@+id/end_time_text" android:layout_width="wrap_content" android:layout_height="wrap_content" android:text="@string/end_time_text" android:textAppearance="?android:attr/textAppearanceLarge" /> <TimePicker android:id="@+id/end_time" android:layout_width="wrap_content" android:layout_height="wrap_content" />

<!-- separator 5: description --> <TextView android:id="@+id/separator5" android:layout_width="fill_parent" android:layout_height="0.8dp" android:background="@color/separator_color" /> <!-- separator 5 --> <TextView android:id="@+id/description_text" android:layout_width="wrap_content" android:layout_height="wrap_content" android:text="@string/description_text"

android:textAppearance="?android:attr/textAppearanceLarge" /> <EditText android:id="@+id/description" android:layout_width="fill_parent" android:layout_height="wrap_content" />

<!-- separator 6: buttons --> <TextView android:id="@+id/separator6" android:layout_width="fill_parent" android:layout_height="0.8dp" android:background="@color/separator_color" /> <!-- separator 6 --> <Button android:id="@+id/save_button" android:layout_width="fill_parent" android:layout_height="wrap_content" android:text="@string/save_button_text" /> <Button android:id="@+id/clear_button" android:layout_width="fill_parent" android:layout_height="wrap_content" android:text="@string/clear_button_text" /> <Button android:id="@+id/cancel_button" android:layout_width="fill_parent" android:layout_height="wrap_content" android:text="@string/cancel_button_text" /> </TableLayout> </ScrollView> event_detail.xml <?xml version="1.0" encoding="utf-8" ?> <ScrollView xmlns:android="http://schemas.android.com/apk/res/android" android:layout_width="fill_parent" android:layout_height="fill_parent"

android:orientation="vertical" > <TableLayout xmlns:android="http://schemas.android.com/apk/res/android" android:layout_width="fill_parent" android:layout_height="wrap_content" android:stretchColumns="0" > <!-- event title --> <TextView android:layout_width="wrap_content" android:layout_height="wrap_content" android:text="@string/event_title_text" android:textAppearance="?android:attr/textAppearanceLarge" android:textColor="@color/grey" />" <TextView android:id="@+id/evt_title" android:layout_width="wrap_content" android:layout_height="wrap_content" android:textAppearance="?android:attr/textAppearanceMedium" />

<!-- separator 1: date --> <TextView android:layout_width="fill_parent" android:layout_height="0.8dp" android:background="@color/separator_color" /> <!-- separator 1 --> <TextView android:layout_width="wrap_content" android:layout_height="wrap_content" android:text="@string/event_date_text" android:textAppearance="?android:attr/textAppearanceLarge" android:textColor="@color/grey" /> <TextView android:id="@+id/evt_date" android:layout_width="wrap_content" android:layout_height="wrap_content" android:textAppearance="?android:attr/textAppearanceMedium" />

<!-- separator 2: start time --> <TextView android:layout_width="fill_parent" android:layout_height="0.8dp" android:background="@color/separator_color" /> <!-- separator 2 --> <TextView android:layout_width="wrap_content" android:layout_height="wrap_content" android:text="@string/start_time_text" android:textAppearance="?android:attr/textAppearanceLarge" android:textColor="@color/grey" /> <TextView android:id="@+id/evt_start_time" android:layout_width="wrap_content" android:layout_height="wrap_content" android:textAppearance="?android:attr/textAppearanceMedium" />

<!-- separator 3: end time --> <TextView android:layout_width="fill_parent" android:layout_height="0.8dp" android:background="@color/separator_color" /> <!-- separator 3 --> <TextView android:layout_width="wrap_content" android:layout_height="wrap_content" android:text="@string/end_time_text" android:textAppearance="?android:attr/textAppearanceLarge" android:textColor="@color/grey" /> <TextView android:id="@+id/evt_end_time" android:layout_width="wrap_content" android:layout_height="wrap_content" android:textAppearance="?android:attr/textAppearanceMedium" />

<!-- separator 4: location --> <TextView android:layout_width="fill_parent" android:layout_height="0.8dp" android:background="@color/separator_color" /> <!-- separator 4 --> <TextView android:layout_width="wrap_content" android:layout_height="wrap_content" android:text="@string/location_text" android:textAppearance="?android:attr/textAppearanceLarge" android:textColor="@color/grey" /> <TableRow android:layout_width="fill_parent" android:layout_height="wrap_content" > <TextView android:id="@+id/evt_location" android:layout_width="wrap_content" android:layout_height="wrap_content" android:textAppearance="?android:attr/textAppearanceMedium" /> <ImageView android:id="@+id/map_img_view" android:layout_width="wrap_content" android:layout_height="wrap_content" android:src="@drawable/map_logo3" /> </TableRow>

<!-- separator 5: description --> <TextView android:layout_width="fill_parent" android:layout_height="0.8dp" android:background="@color/separator_color" /> <!-- separator 5 --> <TextView android:layout_width="wrap_content" android:layout_height="wrap_content" android:text="@string/description_text" android:textAppearance="?android:attr/textAppearanceLarge"

android:textColor="@color/grey" /> <TextView android:id="@+id/evt_desc" android:layout_width="wrap_content" android:layout_height="wrap_content" android:textAppearance="?android:attr/textAppearanceMedium" />

<!-- separator 6: buttons --> <TextView android:layout_width="fill_parent" android:layout_height="0.8dp" android:background="@color/separator_color" /> <!-- separator 6 --> <Button android:id="@+id/edit_button" android:layout_width="fill_parent" android:layout_height="wrap_content" android:text="@string/edit_button_text" /> <Button android:id="@+id/home_button" android:layout_width="fill_parent" android:layout_height="wrap_content" android:text="@string/home_button_text" /> </TableLayout> </ScrollView> map_view.xml <?xml version="1.0" encoding="utf-8" ?> <RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android" android:layout_width="fill_parent" android:layout_height="fill_parent" > <!-- Google map view --> <com.google.android.maps.MapView android:id="@+id/map_view" android:layout_width="fill_parent" android:layout_height="fill_parent"

android:state_enabled="true" android:clickable="true" android:apiKey="0-txY3oq88UmohH7Gbz-BjkxoC0joaXbBVvuW2w" /> </RelativeLayout> strings.xml <?xml version="1.0" encoding="utf-8" ?> <resources> <string name="app_name">MemoPal</string> <string name="welcome_text">MemoPal App</string> <string name="welcome_memo" >Manage your appointments, meetings, important dates and any other interested events</string> <string name="welcome_map" >Locate position of the address in your memo in Google map or pick an address from Google map for your memo</string> <string <string <string <string <string <string <string <string <string <string <string name="event_title_text" >Event</string> name="event_date_text">Date</string> name="start_time_text">Start Time</string> name="end_time_text">End Time</string> name="location_text" >Location</string> name="location_tip">Enter or click map to find address</string> name="description_text" >Description</string> name="image" >Image</string> name="save_button_text" >Save</string> name="clear_button_text" >Clear All</string> name="cancel_button_text" >Cancel</string>

<string name="help_text">Help</string> <string name="tip_text_1">Click MENU to create events or exit MemoPal</string> <string name="tip_text_2">Long click item to edit or delete it</string> <string name="tip_text_3" >Click map icon in EDIT page to pick an address from Google map</string> <string name="tip_text_4">Click item to view details</string> <string name="tip_text_5" >Click map icon in DETAIL page to locate your memo address in Google map</string> <string name="back_button_text">Back to Home</string> <string name="edit_button_text">Edit</string> <string name="home_button_text">Home</string> </resources>

colors.xml <?xml version="1.0" encoding="utf-8" ?> <resources> <color name="separator_color">#FFFFFF</color> <color name="white" >#000000</color> <color name="grey" >#888888</color> </resources>