Archive

Mobile technology

1. Introduction

In the last ten years over 250,000 mobile applications have been developed, and this statement is based on a paper by Wasserman [1] dating back to 2010. Meanwhile, the number of users, mobile devices, applications and developers has only grown. As a result, having at least some knowledge of mobile development has become an attractive skill for a software developer in general.

In this article we will try to give a brief introduction to mobile development and the processes that it involves. Similarly to previous projects we will include a requirement analysis of the given problem description and an analysis of the user interface. If you wish to learn how to create an Android app without all the rest, you can also simply follow Google’s tutorial here (link to website).

The technology we will use to implement the final product is Android. Reasons for chosing Android are among other that Android is Java-based, meaning that we can refer to previous posts, but also that Android actually the market leader in mobile operating systems (OS) [3]. Android also has a strong portal integration making it easier for developers to publish applications on their portal, i.e., the Google Play Store. Android is also more open than for instance Apple’s iOS or Microsoft’s Windows Phone [4].

1.1 Learning objectives

Some of the learning objectives for this post are as follows:

  • Familiarization with mobile development using Android;
  • Introducing user interface design techniques;
  • Introducing a structured approach for mobile application development;
  • Implementation of a user interface and application back-end in Android;
  • Basic data persistence;

1.2 Problem description

A friend of yours has recently bought an Android phone. He likes writing songs, but as song ideas don’t always pop up when there is a piece of paper around to write them down, he would like to use his phone to write down his musings. He asked you if you could create such an application for him.

The application was to be very simple: one needed to be able to create a new note, browse and search for past notes and finally delete and edit old ones. Additional constraints are that the app should be very easy to use and should work regardless of network connectivity.

2. Mobile development

2.1 The mobile landscape

A characteristic of mobile development is the fragmentation in the mobile landscape. As the technology only emerged relatively recently, a relatively large number of competitors have tried to dominate the market. Charland et al. [2] identify no less than nine technologies that are to be learned before one can cover most of the mobile platforms out there. More recently however, Google’s Android, Apple’s iOS and Microsoft’s Windows Phone and up have emerged as the front runners in this competition [2, 3]. Although this suggests development of native applications can be reduced to development for two to three technologies, the cost of developing and maintaining applications in these technologies would still create a considerable overhead.

In their paper, Charland et al. [2] investigate the success and future of cross-platform technologies to counter this heterogeneity. Still, although web-based mobile application are an interesting alternative, native technologies are likely to boast greater performance levels at the cost of development time to cover as many platforms as possible.

2.2 Mobile sofware engineering

In a paper by Wasserman [1] some of the aspects of software engineering for mobile application development are analyzed. He identifies user experience as especially critical for the success of mobile applications [1]. In [2] a distinction is made between aspects of user experience that can be controlled, i.e., the ‘implementation’, and those that must be understood but cannot be controlled, i.e., the context. The implementation refers to performance, integration with platform features (such as specific sensors) and design. The context includes hardware and platform specifics, UI conventions and the environment in which the application is used.

One of the key issues for user experience in mobile development is the design of user interfaces. The screen is relatively small and may differ greatly depending on the device. The mobile user interface is based upon widgets, touch, physical motion and virtual and physical keyboards, in contrast to the traditional desktop style [1]. In section 4 we will study this topic in greater detail.

Reliability, security and quality have to be taken in consideration, just like for traditional applications. In the case of mobile development, special care should be taken with issues related to for example connectivity loss and battery life [1].

3. Software design

As in previous posts we will use standard specifications to model the requirements of our application: use cases and a domain model. The resulting document can be found here (link to pdf).

4. User interface design

There is a variety of techniques to design user interfaces. In this post we will use techniques to model the flow of the user interface (screen transition diagram), and sketches of the visual elements (paper prototypes or mockups). These paper prototypes will then be used in user evaluations.

4.1 Application flow

To visualize the idea and flow of an application, one can use a story board. A story board is a sequence of drawings depicting a specific usage of the application. In some cases designers interpret story boards as a very high-level concept where the actors are drawn and the details of user interface are neglected, illustrating mainly the usage of the application in a specific context [7]. Alternatively, others may use very detailed drawings, focusing on the screens themselves [8].

To model the flow of the application, we can use the use cases and/or scenarios from our requirements analysis as input. Each transition between two screens is triggered by a specific action or event, for example clicking a button, swiping over a screen element, reaching the deadline of a timer, et cetera [9].

4.2 User interface design

4.2.1 Paper prototyping

Paper prototyping is defined as “a variation of usability testing where representative users perform realistic tasks by interacting with a paper version of the interface that is manipulated by a person ‘playing computer’, who doesn’t explain how the interface is intended to work” [6]. It is a technique for designing, testing, and refining user interfaces [5], and is closely related to usability testing [6]. In the last decade it has become a regularly applied technique in major businesses such as IBM, Digital, Honeywell, and Microsoft among others [5].

In [11] a number of benefits are associated with paper prototyping:

  • Potential usability problems can be detected at a very early stage in the design process before any code has been written.
  • Paper prototyping promotes communication between designers and users.
  • Paper prototypes can be created and refined relatively easily, allowing for rapid design iterations.
  • Only minimal resources and materials are required.
Making a paper prototype

To start, we will need a number of materials to create the physical paper prototype. Typical materials are blank paper for drawing prototype pieces, some kind of fixed background upon which other paper prototype elements are placed, pens for hand-drawing the prototype, and scissors for cutting out certain pieces, making popups and so on [5]. Feel free to come up with additional materials that can be used to facilitate the simulation of a real interface. An important remark though, is that the paper prototype is usually bigger than the actual interface, and does not have to look very artistic or realistic, as long as it conveys the main ideas of the design [5].

For mobile applications the “background” can be constructed as follows. Start with drawing the casing and screen of a common mobile device on a sheet of paper. Next, make two incisions at the bottom and top of the screen. When creating a new interface for your prototype, cut of the edges so that you can slide the screen through the incisions, replacing the default white screen of your paper “casing”.

Simulating the interaction

According to Snyder pretty much anything can be simulated, using a little imagination. It is still hard to simulate complex or subtle interaction. A number of examples taken from [5] are listed here:

  • Tooltips/mouseovers: Tell the users that some visual elements have a tooltip associated with them, and that they can ask if they wish to know what it says for a particular item;
  • Beeps: Simply say “beep” whenever the computer would, for example, when the user clicks outside a modal dialog box;
  • Drag and drop: Ask users to specify what they’re dragging and where they’re dropping it. The Computer then describes the visual changes that occur during this process;
  • Right mouse menus: Ask users to say when they are clicking the right mouse button. If they do, display the menu.

Note that some interactions such as drag and drop, and right mouse clicks often not come to mind of the test subject when using a paper prototype. Also, some interactions such as scrolling are not always incorporated in the paper prototype, but tested in a later stage of the interface design [5].

4.3 Improving the design

Prototypes are not just a technique for the analysis of an idea for application, but can serve as input for a method to iteratively improve the user interface. When we want to improve a user interface, we are generally talking about usability. In the ISO standard ISO 9241-11, usability is defined as “the extent to which a product can be used by specified users to achieve specified goals with effectiveness, efficiency and satisfaction in a specified context of use” [12].

Usability should not be considered a one-dimensional property of a user interface. Nielsen identifies several characteristics of usability in applications [13]:

  • Learnability : if the system is easy to learn, the user can get started quickly;
  • Efficiency : if the system is efficient to use, it will be possible to complete more work in less time;
  • Error rate and severity : if the system should be robust and minimize faults;
  • Memorability : once the system is learned, acquired skills should not be forgotten easily;
  • Satisfaction : the system should be pleasant to use.

According to these characteristics, objectives for the usability of an application can be determined, tested and improved over a series of iterations. The sum of incremental changes should converge to the optimal user interface. There is a variety of evaluation techniques, including usability engineering, expert (heuristic) evaluation and using questionnaires. Different evaluation techniques have different strengths and focus on different aspects of human-computer interaction [15,16,17].

To produce sound test results, it is imperative that the objectives of each iteration are clearly defined, how and by who they will be tested. To produce relevant test results, the number of subjects should be high enough. Nielsen proposes to use a minimum of 5 test users per iteration [14].

NOTE : We urge the reader to consult some of the referenced articles. In this text we have often been very brief to avoid losing focus of the exercise itself.

4.4 Result

The resulting diagrams and prototypes are listed here (link to pdf). We included two iterations in the document, but it should be clear that for larger applications more (paper as well as digital) prototypes and evaluations are likely to be needed to obtain adequate results.

5. Implementation

5.1 Getting started with Android

Google’s developer pages provide very good documentation for Android. Before we can return to the actual implementation, you might need to install some software first, so if you didn’t already, follow Google’s tutorial here (link to website) to set up the development environment. If you have an Android device click here (link to website) to see how you can configure the project to run on the device. If you don’t, you can set up a virtual device, as decribed here (link to website).

Figure 1 shows how to create a new Android application project. The general Android project structure is described here (link to website). How to run and build a project can be found here (link to website).


Figure 1 : Creating a new Android application project.

5.2 Model

I suggest we start with what we already learned from a previous post, which is how to create Java classes. In this case our model is as simple as it can get. We only need one class, namely the MyNote class as we named it in our project. Objects from this class are used to pass between the back-end and front-end of the application, between screen transitions, corresponding to moving from one Android Activity implementation to another.

A note has a title and a body, i.e., the actual text of the note. As a note is mapped on some table in the database it also has an id once it has been persisted, as well as a timestamp for when the note was first created. Setters for these fields have checks to verify whether or not the input is valid. The implementation for the MyNote class is (partially) shown in Listing 1.

public class MyNote implements Parcelable {

	private String title;
	private String text;
	private long id;
	private Timestamp timeCreated;
	
	public MyNote(String title, String text, long id, Timestamp timeCreated) throws NullPointerException, IllegalArgumentException {
		this(title, text);
		this.setID(id);
		this.setTimeCreated(timeCreated);
	}
	
	public final void setTitle(String title) throws NullPointerException, IllegalArgumentException {
		if (title == null) throw new NullPointerException("MyNote.title resolved as NULL.");
		if (title.length() == 0) throw new IllegalArgumentException("No empty MyNote.title allowed.");
		this.title = title;
	}
	
	public final void setText(String text) throws NullPointerException, IllegalArgumentException {
		if (text == null) throw new NullPointerException("MyNote.text resolved as NULL.");
		if (text.length() == 0) throw new IllegalArgumentException("No empty MyNote.text allowed.");
		this.text = text;
	}
	
	final void setTimeCreated(Timestamp timeCreated) {
		if (timeCreated == null) throw new NullPointerException("MyNote.timeCreated resolved as NULL.");
		this.timeCreated = timeCreated;
	}
	
	final void setTimeCreated(String timeCreated) {
		this.setTimeCreated(Timestamp.valueOf(timeCreated));
	}
	
	final void setID(long id) {
		this.id = id;
	}
	
	public String getTitle() {
		return title;
	}
	
	public String getText() {
		return text;
	}
	
	public long getID() {
		return id;
	}
	
	public Timestamp getTimeCreated() {
		return timeCreated;
	}
	
	@Override
	public String toString() {
		return this.getTitle();
	}
	
	@Override
	public boolean equals(Object o) {
		if (o == null) return false;
		if (! (o instanceof MyNote)) return false;
		MyNote m = (MyNote) o;
		if (m.getID() != this.getID()) return false;
		return true;
	}
	
	@Override
	public int hashCode() {
		return super.hashCode();
	}
}

In order to pass objects of this class between Android Activities, the MyNote class implements the Parcelable interface. As can be seen in Listing 2, a Parcelable class requires a constructor that takes a Parcel and constructs an object from it, a method implementation to create a Parcel from an object and finally a public static final field, CREATOR, which has the responsibility for the creation of a MyNote object from a Parcel.

public static final Parcelable.Creator<MyNote> CREATOR = new Parcelable.Creator<MyNote>() {

	@Override
	public MyNote createFromParcel(Parcel source) {
		return new MyNote(source);
	}

	@Override
	public MyNote[] newArray(int size) {
		return new MyNote[size];
	}
};

public MyNote(Parcel parcel) {
	this(parcel.readString(), parcel.readString(), parcel.readLong(), parcel.readString());
}

@Override
public int describeContents() {
	return 0;
}

@Override
public void writeToParcel(Parcel dest, int flags) {
	dest.writeString(this.getTitle());
	dest.writeString(this.getText());
	dest.writeLong(this.getID());
	dest.writeString(this.getTimeCreated().toString());
}

5.3 Activities

5.3.1 MainActivity

Classes that extend the Activity class (cf. listing 3) are used to form a link between the visual elements described by layout XML files (cf. listing 4) and the rest of the Java code. Create a new Activity subclass is similar to creating a normal Java class, but instead of one, two files will be generated: the Activity subclass under the src folder, and a layout file under the res > layout folder in your project.

We provided comments to clarify some of the code in listing 3.

public class MainActivity extends Activity {
	
	private static String TAG = "mynotes";
	private IPersistency persistency;	
    private ListView listview;
    private ArrayAdapter<MyNote> adapter;
    private EditText inputSearch;
    private List<MyNote> mynotes = new ArrayList<MyNote>();

	@Override
	protected void onCreate(Bundle savedInstanceState) {
		// (auto-generated) bind the activity to the layout file
		super.onCreate(savedInstanceState);
		setContentView(R.layout.activity_main);
		
		// Create a connection to the database
		this.persistency = new MyNotePersistency(this);
		
		// retrieve all (in the future this can be optimized with paging for example) notes :
		try {
			mynotes = persistency.selectAll();
		} catch (PersistencyException pe) {
			Log.e(TAG, pe.getLocalizedMessage());
		} finally {
			persistency.closeTransaction();
		}
		
		// retrieve the listview in the layout file
		// instantiate the adapter with given layout (id) and the list of notes
		// add the adapter to the listview
		// add an action that will be performed when an item is clicked
		listview = (ListView) findViewById(R.id.listView1);
		adapter = new ArrayAdapter<MyNote>(this, android.R.layout.simple_list_item_1, mynotes);
		listview.setAdapter(adapter);
		listview.setOnItemClickListener(new OnItemClickListenerImplementation());
		
		// find the search field
		// add an event listener that will filter the list with the given input
		inputSearch = (EditText) findViewById(R.id.inputSearch);
		inputSearch.addTextChangedListener(new EditTextWatcher());
	}
	
	@Override
	public boolean onCreateOptionsMenu(Menu menu) {
		getMenuInflater().inflate(R.menu.main, menu);
		return true;
	}

	public void createNewMyNote(View view) {
		// finish this activity
		finish();
		// start a new CreateNewMyNoteActivity Activity
        startActivity(new Intent(MainActivity.this, CreateNewMyNoteActivity.class));
	}
}
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:orientation="vertical"
    android:paddingBottom="@dimen/activity_vertical_margin"
    android:paddingLeft="@dimen/activity_horizontal_margin"
    android:paddingRight="@dimen/activity_horizontal_margin"
    android:paddingTop="@dimen/activity_vertical_margin"
    tools:context=".MainActivity" >

    <LinearLayout
        android:layout_width="match_parent"
        android:layout_height="wrap_content" >

        <EditText
            android:id="@+id/inputSearch"
            android:layout_width="0dp"
            android:layout_height="wrap_content"
            android:layout_weight="1"
            android:ems="10"
            android:hint="@string/search"
            android:inputType="textVisiblePassword" />

		<Button
            android:id="@+id/button1"
            style="?android:attr/buttonStyleSmall"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:text="@string/plus"
            android:onClick="createNewMyNote" />

    </LinearLayout>	

    <ListView
        android:id="@+id/listView1"
        android:layout_width="match_parent"
        android:layout_height="wrap_content" >
    </ListView>

</LinearLayout>
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:orientation="vertical" >
    
    <TextView android:id="@+id/my_note_title_view"
        android:layout_width="fill_parent"
        android:layout_height="wrap_content"
        android:padding="10dip"
        android:textStyle="bold"
        android:textIsSelectable="false"/> 

</LinearLayout>

In our main menu we have a button to create a new note. As you can see in the screen transition diagram, this action opens up a form where we can enter our note data. To go from one activity to another, we can create an Intent object where we provide the current context and the target Activity class. This can be seen in listing 3 in the createNewMyNote method. To link this method the button, we add the method name to the onClick event handler of the Button definition in the layout file, as can be seen in listing 4.

In listing 3, we programmatically bind an click event listener to each list item. The implementation for this event listener is provided in listing 6. Note that we add the MyNote object that was clicked by the user to the Intent object.

private class OnItemClickListenerImplementation implements OnItemClickListener {

	@Override
	public void onItemClick(AdapterView< ?> arg0, View arg1, int position, long id) {
		// create a bundle that can be added to the intent to pass it between Activity classes
		Bundle bundle = new Bundle();
		bundle.putParcelable("mynote", mynotes.get(position));
		Intent intent = new Intent(MainActivity.this, MyNoteActivity.class);
		// add the bundle to the intent
		intent.putExtras(bundle);
		
		finish();
		startActivity(intent);
	}
}

Finally listing 7 shows the implementation for the TextWatcher which will filter the list using the given character sequence.

private class EditTextWatcher implements TextWatcher {
	@Override
	public void onTextChanged(CharSequence cs, int arg1, int arg2, int arg3) {
		MainActivity.this.adapter.getFilter().filter(cs);   
	}
	
	@Override
	public void beforeTextChanged(CharSequence arg0, int arg1, int arg2, int arg3) {}
	
	@Override
	public void afterTextChanged(Editable arg0) {}
}

5.3.2 CreateNewMyNoteActivity

Listing 8 shows the (partial) implementation of the CreateNewMyNoteActivity class. We will zoom in on the implementation for the createMyNote operation. To avoid the user entering incomplete or wrong input, we added a check and an AlertDialog implementation to warn the user in such events. Providing meaningful feedback or avoiding bad behaviour is essential in creating a good user experience.

public class CreateNewMyNoteActivity extends Activity {
	
	public void createMyNote(View view) {
		
		EditText titleField = (EditText) findViewById(R.id.create_mynote_title);
		EditText textField = (EditText) findViewById(R.id.create_mynote_text);
		String title = titleField.getText().toString().trim();
		String text = textField.getText().toString().trim();
		
		if (title.isEmpty() || text.isEmpty()) {
			new AlertDialog.Builder(this).setTitle("Wrong input:")
				.setMessage("Please make sure both the title and text fields are filled in.")
				.setNeutralButton("Close", null).show();
		} else {
			try {
				persistency.insert(new MyNote(title, text));
			} catch (PersistencyException pe) {
				Log.e(TAG, pe.getLocalizedMessage());
			}
			finish();
	        startActivity(new Intent(this, MainActivity.class));
		}
	}
	
	// other methods and fields ...
}

5.3.3 MyNoteActivity

Our final Activity subclass is loaded when clicking an item in the list view. In this activity the user can edit or delete the note. As we saw before, when we created the Intent object to load this activity, we added a Bundle object to it, containing the (Parcelable) MyNote object. When this activity is then loaded, we have to unpack the Bundle object from the Intent object, as shown in the onCreate method in listing 9.

public class MyNoteActivity extends Activity {

	@Override
	protected void onCreate(Bundle savedInstanceState) {
		super.onCreate(savedInstanceState);
		setContentView(R.layout.activity_my_note);
		Bundle bundle = this.getIntent().getExtras();
		myNote = bundle.getParcelable("mynote");
		
		titleField = (EditText) findViewById(R.id.edit_mynote_title);
		textField = (EditText) findViewById(R.id.edit_mynote_text);
		titleField.setText(myNote.getTitle());
		textField.setText(myNote.getText());
		
		persistency = new MyNotePersistency(this);
	}
	
	public void deleteMyNote(View view) {
		new AlertDialog.Builder(this).setTitle("Warning")
			.setMessage("Are you sure you want to delete this note?")
			.setNegativeButton("Cancel", null)
			.setPositiveButton("Yes", new DialogInterface.OnClickListener() {
				
	            @Override
	            public void onClick(DialogInterface dialog, int which) {
	            	try {
	        			persistency.delete(myNote);
	        		} catch (PersistencyException pe) {
	        			Log.e(TAG, pe.getLocalizedMessage());
	        		}
	        		MyNoteActivity.this.finish();
	        		MyNoteActivity.this.startActivity(new Intent(MyNoteActivity.this, MainActivity.class));
	            }
	        })
			.show();
	}
	
	// other methods and fields ...
}

We also show the delete functionality here, as the rest of the implementation is fairly similar to those of the other activities. Listing 9 shows how we load another alert dialog and bind the execution of the delete operation to the “Yes” option in our dialog. If the other button is clicked, the dialog is closed and no further actions take place.

5.4 Data persistence

We want to store our notes somehow on our mobile device or on a remote website. There are a number of ways to achieve this, for example by adding a small database to the application, using local storage of the phone, or connecting to a remote web site and sending/fetching the data to/from it [18]. We opted to use a small SQLite database.

5.4.1 From digital prototype to final implementation

Since we decided to add this database implementation later in the development cycle, allowing us to create our digital prototypes faster, we added some flexibility to our design. We created an IPersistency interface (cf. listing 10) with a TestData implementation (cf. listing 11). Since the interface doesn’t change, but only its implementation class, we were able to implement our complete application without a database, but with the complete application flow already in place. When we finally implemented the database class, we only needed to change the private IPersistency persistency fields in our activities from a TestData object to a MyNotePersistency (see further).

public interface IPersistency {

	/**
	 * Inserts a new note into the database and returns the generated id for this entry.
	 * @param myNote the note to be persisted.
	 * @return the id of the persisted note.
	 */
	public long insert(MyNote myNote) throws PersistencyException;
	
	/**
	 * Updates the given note in the database.
	 * @param myNote
	 */
	public void update(MyNote myNote) throws PersistencyException;
	
	/**
	 * Deletes the given note in the database.
	 * @param myNote
	 */
	public void delete(MyNote myNote) throws PersistencyException;
	
	/**
	 * Select the note from the database with given id.
	 * @param comparator
	 * @return the note with given id.
	 */
	public MyNote select(long id) throws PersistencyException;
	
	/**
	 * Select all the notes from the database.
	 * @param comparator
	 * @return all the notes in the database.
	 */
	public List<MyNote> selectAll() throws PersistencyException;

	/**
	 * @return the number of records in the MyNote table.
	 */
	public int recordCount();

	/**
	 * Close the current transaction.
	 */
	public void closeTransaction();
}
public class TestData implements IPersistency {

	private static final String TAG = "TestData";
	private static long ID = 0;
	
	// Database contents :
	private final Map<Long, MyNote> myNotes = new HashMap<Long, MyNote>();
	
	private static IPersistency persistency;
	
	public static IPersistency getInstance() {
		if (TestData.persistency == null) TestData.persistency = new TestData();
		return TestData.persistency;
	}
	
	private TestData() {
		super();
		this.insert(new MyNote("Example MyNote 1", "This is an example note."));
		this.insert(new MyNote("Example MyNote 2", "This is an example note."));
		this.insert(new MyNote("Example MyNote 3", "This is an example note."));
		this.insert(new MyNote("Example MyNote 4", "This is an example note."));
	}

	@Override
	public long insert(MyNote myNote) {
		myNote.setID(++ID);
		myNote.setTimeCreated(Timestamp.valueOf("2014-06-03 14:23:00.000000000"));
		this.myNotes.put(myNote.getID(), myNote);
		return myNote.getID();
	}

	@Override
	public void update(MyNote myNote) {
		this.myNotes.put(myNote.getID(), myNote);
	}

	@Override
	public void delete(MyNote myNote) {
		this.myNotes.remove(myNote.getID());
	}

	@Override
	public MyNote select(long id) {
		return this.myNotes.get(id);
	}

	@Override
	public List<MyNote> selectAll() {
		return new ArrayList<MyNote>(myNotes.values());
	}

	@Override
	public int recordCount() {
		return this.myNotes.values().size();
	}

	@Override
	public void closeTransaction() {
		// not used.
	}
}

5.4.2 The actual database implementation

Listing 12 shows the implementation for the SQL query to create the mynote table. The ID should autoincrement, meaning that the database itself will determine the ID value. The title and text values can’t be NULL, meaning that they have to contain a meaningful value. The DATE_CREATED field will also be auto-generated by the database. As can be seen in listing 13, when inserting or updating a record, the updated fields of that record are only the title and body fields, set in the getContentValues method. Alternatively, when a record is selected from the database, the resulting Cursor object is then converted into a MyNote object in the setMyNote. Before each operation on the database, we always need call either the getWritableDatabase or getReadableDatabase method of the SQLiteOpenHelper super class.

CREATE TABLE mynote (
	ID				INTEGER	PRIMARY_KEY AUTOINCREMENT NOT NULL,
	TITLE			VARCHAR(256) NOT NULL,
	BODY			TEXT NOT NULL,
	DATE_CREATED	TIMESTAMP DEFAULT CURRENT_TIMESTAMP NOT NULL
);
public class MyNotePersistency extends SQLiteOpenHelper implements IPersistency {
	
	private static final String CREATE_TABLE_MYNOTE = "CREATE TABLE " + TABLE_NAME + " (" +
			ID 				+ " " + INTEGER		+ " " + PRIMARY_KEY + " " + AUTOINCREMENT + " " + NOT_NULL + ", " +
    		TITLE			+ " " + VARCHAR_256 + " " + NOT_NULL + ", " +
    		BODY			+ " " + TEXT 		+ " " + NOT_NULL + ", " +
    		DATE_CREATED	+ " " + TIMESTAMP 	+ " DEFAULT CURRENT_TIMESTAMP " + NOT_NULL +
    ");";
	
	public MyNotePersistency(Context context) {
		super(context, DB_NAME, null, 1);
	}

	@Override
	public long insert(MyNote record) throws PersistencyException {
		SQLiteDatabase db = this.getWritableDatabase();
        long id = db.insert(TABLE_NAME, null, getContentValues(record));
        return id;
	}

	@Override
	public void update(MyNote record) throws PersistencyException {
		SQLiteDatabase db = this.getWritableDatabase();
	    int rowsaffected = db.update(TABLE_NAME, getContentValues(record), ID + " = ?",
	            new String[] { String.valueOf(record.getID()) });
	}

	@Override
	public void delete(MyNote myNote) throws PersistencyException {
		SQLiteDatabase db = this.getWritableDatabase();
	    db.delete(TABLE_NAME, ID + " = ?", new String[] { String.valueOf(myNote.getID()) });
	}

	@Override
	public MyNote select(long id) throws PersistencyException {
		SQLiteDatabase db = this.getReadableDatabase();
	    Cursor cursor = db.query(TABLE_NAME, new String[] { ID }, ID + "=?", new String[] { String.valueOf(id) }, null, null, null, null);
        cursor.moveToFirst();
	    MyNote data = setMyNote(cursor);
        cursor.close();
	    return data;
	}

	@Override
	public List<MyNote> selectAll() throws PersistencyException {
		List<MyNote> list = new ArrayList<MyNote>();
        SQLiteDatabase db = this.getReadableDatabase();
        Cursor cursor = db.rawQuery("SELECT * FROM " + TABLE_NAME, null);

        if (cursor.moveToFirst()) {
            do {
                list.add(setMyNote(cursor));
            } while (cursor.moveToNext());
        }
    	cursor.close();
        return list;
	}
	
	@Override
	public int recordCount() {
	    SQLiteDatabase db = this.getReadableDatabase();
	    Cursor cursor = db.rawQuery("SELECT * FROM " + TABLE_NAME, null);
	    int count = cursor.getCount();
	    cursor.close();
	    return count;
	}
	
	@Override
	public void onCreate(SQLiteDatabase db) {
		db.execSQL(CREATE_TABLE_MYNOTE);
	}

	@Override
	public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) {
		db.execSQL("DROP TABLE IF EXISTS " + TABLE_NAME);
		db.execSQL(CREATE_TABLE_MYNOTE);
	}
	
	@Override
	public void closeTransaction() {
		this.close();
	}
	
	private ContentValues getContentValues(MyNote record) {
		ContentValues values = new ContentValues();
        values.put(TITLE, record.getTitle());
        values.put(BODY, record.getText());
        return values;
	}

	private MyNote setMyNote(Cursor cursor) {
		MyNote data = new MyNote();
        data.setID(cursor.getLong(0));
        data.setTitle(cursor.getString(1));
        data.setText(cursor.getString(2));
        data.setTimeCreated(cursor.getString(3));
        return data;
	}
	
	public void deleteDatabase(Context context) {
		context.deleteDatabase(DB_NAME);
	}
}

5.5 Result

On figure 2 you can see some screen shots from the resulting application, run on an mobile Android device.


Figure 2 : the MyNotes application on an Android device.

6. Final thoughts

We have seen how we can design a mobile application from start to finish. Although this was a fairly simple application, we hope that the concepts provided here can be used as a stepping stone for more advanced mobile development.

The full implementation of the application can be found on our GitHub page here (link to website).

References

[1] A.I. Wasserman, 2010, “Software Engineering Issues for Mobile Application Development”

[2] A. Charland and B. LeRoux, 2011, Mobile Development, Web vs. Native

[3] M. Butler, 2011, “Android: Changing the mobile landscape”

[4] A. Holzer and J. Ondrus, 2010, “Mobile application market: A developer’s perspective”

[5] C. Snyder, 2003, “Paper Prototyping: The Fast and Easy Way to Design and Refine User Interfaces (Interactive Technologies)”, Morgan Kaufmann, Pages: 408

[6] C. Snyder, 2003, “What is Paper Prototyping”, [Online] Available at: http://www.paperprototyping.com/what.html, [Accessed: 10 February 2013]

[7] E. Duval, 2014, “CHI sessie 2: brainstorming, personas and storyboards”, [Online] Available at: http://www.slideshare.net/erik.duval/20140224-chi-sessie2 [Accessed 4 June 2014]

[8] E. Duval, 2009, “Multimedia: storyboard”, [Online] Available at: http://www.slideshare.net/erik.duval/multimedia-storyboard [Accessed 4 June 2014]

[9] E. Duval, 2010, “Paper prototyping”, [Online] Available at: http://www.slideshare.net/erik.duval/paper-prototyping-3266200 [Accessed 4 June 2014]

[10] UsabilityFirst, 2013, Usability First – Usability Glossary – user profile | Usability First, [Online] Available at: http://www.usabilityfirst.com/glossary/user-profile/ [Accessed 14 February 2013]

[11] UsabilityNet, 2006, UsabilityNet: Paper prototyping methods, URL: http://www.usabilitynet.org/tools/prototyping.htm, [Online, Accessed: 10 February 2013]

[12] UsabilityNet, 2006, UsabilityNet: International Standards, [Online] Available at: http://www.usabilitynet.org/tools/r_international.htm#9241-11, [Online, Accessed 20 February 2013]

[13] Nielsen J., 1994, Usability Engineering, Morgan Kaufmann Publishers, ISBN 0-12-518406-9, Pages: 362

[14] Nielsen J., 2012, Why You Only Need to Test with 5 Users, [Online] Available at: http://www.nngroup.com/articles/why-you-only-need-to-test-with-5-users/, Accessed 20 February 2013

[15] Nielsen J., 2012, Thinking Aloud: The #1 Usability Tool, [Online] Available at: http://www.nngroup.com/articles/thinking-aloud-the-1-usability-tool/, Accessed 20 February 2013

[16] Nielsen J., 2012, How to Conduct a Heuristic Evaluation, [Online] Available at: http://www.nngroup.com/articles/how-to-conduct-a-heuristic-evaluation/, Accessed 20 February 2013

[17] Kirakowski J., 2000, Questionnaires in Usability Engineering, [Online] Available at: http://www.ucc.ie/hfrg/resources/qfaq1.html, Accessed 20 February 2013

[18] Google, 2014, “Storage Options | Android Developers”, [Online] Available at: http://developer.android.com/guide/topics/data/data-storage.html, Accessed 6 June 2014