July 21, 2014

SharedPreferences and SQLite Storage

Storing data across multiple application sessions is important. To enable the application to persist data , there are many options available but here we going to discuss just two methods. SharedPreferences is used to store small pieces of key-value pairs while the SQLite database is used to persist complex data. Let's first see how to store and access data from SharedPreferences.

SharedPreferences:

Remember that the sharedPreferences is retrieved with the current activity as the name when calling getPreferences(MODE_PRIVATE);. You could also save preferences with custom name by fetching sharedPreferences as follows. 
    getSharedPreferences('GeoPref', mode);
If a SharedPreference named GeoPref is not present then a new one is created and returned.

Storing data
1. Get reference to SharedPreference from an activity using the following code. 
     final SharedPreferences prefs = getPreferences(MODE_PRIVATE);
This will call the getSharedPreferences('currentActivityName', mode) method of the context object.
2. Store key, value into the map using the following code
    SharedPreferences.Editor editor = prefs.edit();
    editor.putInt("HIGH_SCORE", val);
    editor.commit();

Read data
Just call prefs.getInt("HIGH_SCORE", -2). If such a key is not present then the passed -2 is returned. 

SharedPreferencesFragment

This class is useful for presenting a list view of needed preferences to be saved for an application. It is very useful when showing, editing by displaying a dialog and saving multiple settings for an application with just few lines of code.

1. Load the fragment just like a normal fragment by defining it in xml or by calling it dynamically
    setContentView(R.layout.user_prefs_fragment);
The user_prefs_fragment xml is shown below.
Note that you can reference an inner class in xml using the symbol '$'

2. Load the preference and register the change listener for setting the initial value of uname as shown below
The xml from which the items to be loaded on to the fragment is defined in R.xml.user_prefs as shown below
The above file helps to display a dialog box to accept changes when a particular key-value is edited. This is what makes SharedFragment so easy to view and edit existing preferences.

Initially there is no value set for the uname key . So the changeListener is called back by invoking onSharedPreferenceChanged as shown below.

July 14, 2014

Multimedia - Playing Audio

Audio manager is used to play sounds in an activity. Different ways of using the audiomanager is shown below,


Following are the steps to play sound effects.
1. Get reference to the AudioManager
mAudioManager = (AudioManager) getSystemService(AUDIO_SERVICE)
2. Create a SoundPool
    mSoundPool = new SoundPool(1, AudioManager.STREAM_MUSIC, 0);
3. Load the sound
mSoundId = mSoundPool.load(this, R.raw.slow_whoop_bubble_pop, 1);
4. Housekeeping for soundmanager
5. Play the sound
mSoundPool.play(mSoundId, leftVolume, rightVolume, priority, loop, rate);

Using Fragments

Fragments were added to Android 3.0 to better support user interfaces for devices with 
large screens, such as tablets. Every fragment needs a host activity and a single fragment can span across multiple activities. The fragment by itself has several life-cycle methods as shown below,

There are two ways to load a fragment into an activity
1)Declare it statically using the using the Activity's layout file 
2)Add it programmatically using the FragmentManager

Static Fragment:

Define the fragments to be hosted in the current activity using the activity layout file as shown below,
Now when the activity is loaded. The corresponding fragments are attached and the life-cycle methods  of both fragments are invoked. Once the fragments are loaded as defined statistically in the above xml, the view of fragment is loaded in onCreateView(). 

TitlesFragment is the one which inherits the ListFragment class and thereby all list related actions such as setting the Single choice mode can be done in the onActivityCreated() as shown below.
Another point to note here is that a ListSelectionListener interface is defined here which needs to be implemented in the hosting activity. This is done typically in any fragment scenario because the hosting activity has reference to both the fragments and can control the data shown in a fragment different from the fragment from which the selection was done. The activity typically acts like the Orchestra conductor by implementing the ListSelectionListener's onListSelection() method as shown below,
The TitleFragment's onListItemClick hook method call this onListSelection method as shown below
Thus the corresponding details of the clicked title  is displayed in the textview of the DetailsFragment.

Dynamic Fragment:

Here the activity xml does not define the fragments instead only defines the views which are going to be loaded for the corresponding fragments. So we have to programmatically call the fragments to be hosted in the current activity.

In the activity's onCreate method load the fragments using the fragmentManager as shown below,
In the static fragment example, both fragments were loaded at the same time. Here first the title is loaded and the second fragment is loaded and the entire activity layout is adjusted via a addOnBackChangedListener callback method.
Rest of the fragment implementation is similar to the static example. Examples were referred from Dr.Adam Porter's lectures.

July 03, 2014

Comparable & Comparator API

Total order
A total order is a binary relation ≤ that satisfies:
・Antisymmetry: if v ≤ w and w ≤ v, then v = w.
・Transitivity: if v ≤ w and w ≤ x, then v ≤ x.
・Totality: either v ≤ w or w ≤ v or both.
Ex.
・Standard order for natural and real numbers.
・Chronological order for dates or times.
・Alphabetical order for strings.

 Note that the <= operator for double is not a total order. Double.NaN <= Double.NaN is false.

Comparable API
Implement compareTo() so that v.compareTo(w)
・Is a total order.
・Returns a negative integer, zero, or positive integer
if v is less than, equal to, or greater than w, respectively.
・Throws an exception if incompatible types (or either is null).

Tips:
To sort an Array, use the Arrays.sort().
To sort an ArrayList, use the Collections.sort().

Natural Sorting of numbers:

Output: 1,2,3,5,7,10,16,23,46

Incorrect sorting of cars:
Let us consider taking a car class with the data members as shown below.


Here the client tries to sort an array consisting of three cars. But do you see the problem?

Yes. This cannot be sorted by Java because we haven't told it what is the order to be followed and which data member should be considered to be sorted. This is why we implement the comparable interface. The output of above as expected would be.

Correct Sorting of Cars:
Shown below is the class diagram:

Here the Car class now implements the comparable Interface and defines the total order in compareTo() method.
Output: Mazda,Honda,Toyota

Correct Sorting of Cars with different properties:
You do not have to implement Comparable but you have to create static members of type Comparator which overrides the method compare(). Below is shown the class diagram.
Code:
package george.comparablesWithComparator;

import java.util.Comparator;

public class Car{

private String make;
private String model;
private int cost;
public String getMake() {
return make;
}
public void setMake(String make) {
this.make = make;
}
public String getModel() {
return model;
}
public void setModel(String model) {
this.model = model;
}
public int getCost() {
return cost;
}
public void setCost(int cost) {
this.cost = cost;
}
public static Comparator carCostComparator = new Comparator() {

@Override
public int compare(Car c1, Car c2) {
if(c1.cost < c2.cost)
return -1;
else if(c1.cost > c2.cost)
return 1;
else
return 0;
}
};
public static Comparator carModelComparator = new Comparator() {

@Override
public int compare(Car c1, Car c2) {
if(c1.model.compareTo(c2.model) < 0)
return -1;
else if(c1.model.compareTo(c2.model) > 0)
return 1;
else
return 0;
}
};
public static Comparator carMakeComparator = new Comparator() {

@Override
public int compare(Car c1, Car c2) {
if(c1.make.compareTo(c2.make) < 0)
return -1;
else if(c1.make.compareTo(c2.make) > 0)
return 1;
else
return 0;
}
};
}


package george.comparablesWithComparator;

import java.util.Arrays;

public class ClassClient {

/**
* @param args
*/
public static void main(String[] args) {
Car car1 = new Car();
Car car2 = new Car();
Car car3 = new Car();
car1.setCost(1000);
car1.setMake("Honda");
car1.setModel("City");
car2.setCost(120);
car2.setMake("Mazda");
car2.setModel("ZX-1");
car3.setCost(90888);
car3.setMake("Toyota");
car3.setModel("Qualis");
Car[] carArray = {car1, car2, car3};
System.out.print("Sorting by Make: ");
Arrays.sort(carArray,Car.carMakeComparator);
for(Car c : carArray)
{
System.out.print(c.getMake() + ",");
}
System.out.println();
System.out.print("Sorting by Model: ");
Arrays.sort(carArray,Car.carModelComparator);
for(Car c : carArray)
{
System.out.print(c.getModel() + ",");
}
System.out.println();
System.out.print("Sorting by Cost: ");
Arrays.sort(carArray,Car.carCostComparator);
for(Car c : carArray)
{
System.out.print(c.getCost() + ",");
}
}

}


July 02, 2014

The crux of Java collections - Stack, Queue & Bags

Collections is one of the most important standard library available in Java. It allows developers to take the power of generics and Iterator and develop code which expects less input from the user and allows good reusability. All references are from Dr.Sidgewich codebase. Collections can be implemented using linked list or array.

Here I am going show my implementation of Queue using basic re-sizing array, implements Iterable interface and is generic. Below is shown the class diagram. This can be easily ported into stack and bags using simple logic changes.

Code:

package george.queue;

import java.util.Iterator;

public class VariableCapacityQueue implements Iterable {
private E[] s;
private int N = 0;

public VariableCapacityQueue() {
s = (E[]) new Object[1];
}

public boolean isEmpty() {
return N == 0;
}

public void enqueue(E item) {
if (N == s.length)
resize(2 * s.length);
s[N++] = item;
System.out.println("array size is "+s.length);
// array size increament verified
}

public E dequeue() {
// return s[--N];//just moves the pointer but not the element//So
// modifying code
E temp = s[0];
s[0] = null;
moveElements(s.length);
N--;
// The above two steps prevents loitering
if (N > 0 && N == s.length / 4)// otherwise will terminate at -1 itself
resize(s.length / 2);
System.out.println("array size is " + s.length);
return temp;
}

private void resize(int capacity) {
E[] copy = (E[]) new Object[capacity];
for (int i = 0; i < N; i++)
copy[i] = s[i];
s = copy;
}

private void moveElements(int capacity) {
E[] copy = (E[]) new Object[capacity];
for (int i = 1; i < N; i++)
// first element in queue removed so n reduced by 1
copy[i - 1] = s[i];
s = copy;
}

public class ListIterator implements Iterator {
private int i = 0;

public boolean hasNext() {
return i < N;
}

public void remove() {
}

public E next() {
return s[i++];
}
}

public Iterator iterator() {
return new ListIterator();
}


}


Performance:

Order of Growth:
Running time is worst when compared to Linked List implementation because of moveElements() method being called each time something is dequeued.  Thus dequeue operation has a order of growth  O(N^2). Enqueue operation consumes in the order of O(N) for elements of size N. Any suggestion to improve dequeue implementation is welcome.

Memory:
The memory consumption will be almost similar to the one shown below. Expect for the fact that we are using generics so the 8N + 24 for String  will be xN + 24 depending upon the datatype used for storing in the array. Similarly padding will change accordingly.