Thursday, 1 September 2016

Custom listeners with interfaces

In my little experiments, I often find myself using custom dialogs to display information to the user or to get input. Therefore, I needed a way to create a callback method to detect what the user selected once the dialog has been dismissed. In order to do so, we can use interfaces to create custom listeners.

This will allow us to create callback functions for custom dialogs and set listener objects that, well listen to what the user selected and react accordingly. Very much how you set an click listener for buttons.

In this episode we are going to create a custom dialog and set a listener in order to follow the choices made by the user.

Let's first create a layout for our dialog:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:orientation="vertical" android:layout_width="match_parent"
    android:layout_height="match_parent">

    <TextView
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:textAppearance="?android:attr/textAppearanceLarge"
        android:text="Main text"
        android:id="@+id/custom_dialog_textview"
        android:layout_gravity="center_horizontal" />

    <LinearLayout
        android:orientation="horizontal"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:layout_gravity="center_horizontal">

        <Button
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:text="Confirm"
            android:layout_weight="0.5"
            android:id="@+id/custom_dialog_confirmbutton" />

        <Button
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:text="Cancel"
            android:layout_weight="0.5"
            android:id="@+id/custom_dialog_cancelbutton" />
    </LinearLayout>
</LinearLayout>

In your design window, will look like so:

We can now go on and create a class called CustomDialog, which will be responsible for spawning our dialog to the screen.


I will post the class code below:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
public class CustomDialog implements View.OnClickListener {

    ICustomDialogListener listener;

    Button confirmButton;
    Button cancelButton;
    TextView maintext;

    Dialog dialog;

    public enum ButtonResults
    {
        BUTTON_CONFIRM,
        BUTTON_CANCEL

    }

    public CustomDialog(Context c, String text,ICustomDialogListener listener)
    {

        this.listener = listener;

        dialog = new Dialog(c);

        dialog.setContentView(R.layout.custom_dialog_layout);
        dialog.setCancelable(false);

        WindowManager.LayoutParams lp = new WindowManager.LayoutParams();
        Window dialogWin = dialog.getWindow();

        lp.copyFrom(dialogWin.getAttributes());

        lp.width = WindowManager.LayoutParams.MATCH_PARENT;

        dialogWin.setAttributes(lp);

        maintext = (TextView) dialog.findViewById(R.id.custom_dialog_textview);
        maintext.setText(text);

        confirmButton = (Button)dialog.findViewById(R.id.custom_dialog_confirmbutton);
        cancelButton = (Button)dialog.findViewById(R.id.custom_dialog_cancelbutton);

    confirmButton.setOnClickListener(this);
        cancelButton.setOnClickListener(this);

        dialog.show();
    }

    @Override
    public void onClick(View v) {

        switch (v.getId())
        {

            case R.id.custom_dialog_confirmbutton:
                listener.OnDialog(ButtonResults.BUTTON_CONFIRM,dialog);
                break;

            case R.id.custom_dialog_cancelbutton:
                listener.OnDialog(ButtonResults.BUTTON_CANCEL,dialog);
                break;
        }
    }
}

The class itself is pretty simple. The dialog is created in the constructor (line 23) and we pass it in the custom layout we previously set up (line25). From line 28 to line 37 we simply tell the dialog window to extend its width as far as the parent view. I found that MATCH_PARENT doesn't work well when set in the xml file, so this is how you can achieve the same thing in Java.

As you can see, the constructor accepts a parameter of type ICustomDialogListener, which is an interface used to define a listener for this dialog. The object listener is then notified of the button(s) pressed by the user in the onClick method on line 50. To identify which button has been pressed, I used an enumeration. To notify the listener, we call the interface method OnDialog which accepts an enumeration type variable, which identifies the button, and the dialog itself.

Below is the interface ICustomDialogListener:


1
2
3
4
public interface ICustomDialogListener {

    void OnDialog(CustomDialog.ButtonResults result, Dialog dialog);
}

Simple and efficient.

The advantage to use interfaces is that we can implement this in every class which displays a dialog and requires a callback. We can also use it in an anonymous class.

Here's an example. In the MainActivity, I jusst create a dialog in the onCreate method, so the window will pop up immediately as soon as the app boots. You will see that, according to which button is pressed, an appropriate toast message will appear.

This is the code for the onCreate method in MainActivity:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
@Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        Toolbar toolbar = (Toolbar) findViewById(R.id.toolbar);
        setSupportActionBar(toolbar);

        CustomDialog dialog = new CustomDialog(MainActivity.this, "Hi", new ICustomDialogListener() {
            @Override
            public void OnDialog(CustomDialog.ButtonResults result, Dialog dialog) {

                switch (result)
                {
                    case BUTTON_CONFIRM:
                        Toast.makeText(MainActivity.this,"You pressed Confirm",Toast.LENGTH_SHORT).show();
                        break;

                    case BUTTON_CANCEL:
                        Toast.makeText(MainActivity.this,"You pressed Cancel",Toast.LENGTH_SHORT).show();
                        break;

                }

              
            }
        });

    }

Remember, the dialog will show because in the constructor of CustomDialog we call dialog.show() on line 46. If you omit that, nothing will show up.

As you can see, in the constructor call for the dialog, we create an anonymous class for the listener (line 8), so we can deal with the callback function straight in the onCreate method.

We could very much pass this, which will require the MainActivity to implement ICustomDialogInterface:

1
   CustomDialog dialog = new CustomDialog(MainActivity.this,"Hi",this);


 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
public class MainActivity extends AppCompatActivity implements ICustomDialogListener {

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        Toolbar toolbar = (Toolbar) findViewById(R.id.toolbar);
        setSupportActionBar(toolbar);

//Rest of the code

.........
........
.......
}

And you would have to implement the method OnDialog(...) required by the interfrace:


 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
   @Override
    public boolean onOptionsItemSelected(MenuItem item) {
        // Handle action bar item clicks here. The action bar will
        // automatically handle clicks on the Home/Up button, so long
        // as you specify a parent activity in AndroidManifest.xml.
        int id = item.getItemId();

        //noinspection SimplifiableIfStatement
        if (id == R.id.action_settings) {
            return true;
        }

        return super.onOptionsItemSelected(item);
    }

    @Override
    public void OnDialog(CustomDialog.ButtonResults result, Dialog dialog) {

        switch(result)
        {
            case BUTTON_CONFIRM:
                Toast.makeText(MainActivity.this,"You pressed Confirm",Toast.LENGTH_SHORT).show();
                break;

            case BUTTON_CANCEL:
                Toast.makeText(MainActivity.this,"You pressed Cancel",Toast.LENGTH_SHORT).show();
                break;

        }

    }

This works exactly like when you set a listener for a button or any other view.

Just as I did in the anonymous class earlier, I use a switch to deal with the result obtained.

Below, a gif will show the final result.



Notice how the dialog is not dismissed after pressing a button. That is because we simply did not tell it to. If you need the dialog to disappear after the user has chosen, add the line dialog.dismiss() in the switch and there you go.

Conclusion

Creating a good callback system is a good way to maintain the code readable and organized. Using interfaces gives us great flexibility as we can implement as many as we want in a single class, in case you would need many different listeners. Of course, this concept can be applied to different scenarios. Perhaps you will need a callback method for a GPS app which will callback when the user has reached a particular location or you could use this technique in a database class, to notify a ListView that the database has been edited and it need to update its views.

Finally, you can also set multiple listeners. Instead of having a single variable listener in the CustomDialog class, we could use a static ArrayList<ICustomDialogListener>. In the constructor we would. It needs to be static of course, as we do not want a new list for each dialog. We can then add new listeners any time the constructor is called and, when it's time to notify them, we simply iterate through the list itself calling the method OnDialog(..) for each of its elements.

Wednesday, 24 August 2016

Display records with a ListView and custom layout

This post is a follow up of the previous one. In this section, we are going to fetch records from the database and place them in a ListView.

A ListView is nothing but a container of views that are stacked on each other. Imagine something like your Facebook posts on your mobile phones.

We can create custom views for each item to place in the list, with all the components we need, like buttons, layouts, edit texts and so on.

In fact, the first thing I will show oyu is our list_adapter_item.xml, which contains all the information on how to display our items in the list:


 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:orientation="vertical" android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:background="#FACAAA">

    <TextView
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:textAppearance="?android:attr/textAppearanceLarge"
        android:text="Account title"
        android:id="@+id/textView8"
        android:layout_gravity="center_horizontal" />

    <TextView
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:textAppearance="?android:attr/textAppearanceLarge"
        android:id="@+id/list_adapter_item_title"
        android:layout_gravity="center_horizontal"
        android:text=".........."
        android:textStyle="bold|italic" />

    <TextView
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:textAppearance="?android:attr/textAppearanceLarge"
        android:text="Account login"
        android:id="@+id/textView9"
        android:layout_gravity="center_horizontal" />

    <TextView
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:textAppearance="?android:attr/textAppearanceLarge"
        android:text=".............."
        android:id="@+id/list_adapter_item_loginID"
        android:layout_gravity="center_horizontal"
        android:textStyle="bold|italic" />

    <TextView
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:textAppearance="?android:attr/textAppearanceLarge"
        android:text="Account password"
        android:id="@+id/textView5"
        android:layout_gravity="center_horizontal" />

    <TextView
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:textAppearance="?android:attr/textAppearanceLarge"
        android:text="..........."
        android:id="@+id/list_adapter_item_psw"
        android:layout_gravity="center_horizontal"
        android:textStyle="bold|italic" />

</LinearLayout>

You may now behold my amazing design skills:


This is what each view inside our ListView is going to be displayed.

Before we  go on and create our list adapter class, let's place the actual list on the display.

Simply go to your content_main.xml and drag in a ListView. After changing the colors to match the previous layout file, this is what you should see:


Although very simple, I will post the actual xml code:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools"
    xmlns:app="http://schemas.android.com/apk/res-auto" android:layout_width="match_parent"
    android:layout_height="match_parent" android:paddingLeft="@dimen/activity_horizontal_margin"
    android:paddingRight="@dimen/activity_horizontal_margin"
    android:paddingTop="@dimen/activity_vertical_margin"
    android:paddingBottom="@dimen/activity_vertical_margin"
    android:background="#FACAAA"
    app:layout_behavior="@string/appbar_scrolling_view_behavior"
    tools:showIn="@layout/activity_main" tools:context=".MainActivity">


    <ListView
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:id="@+id/listView"
        android:layout_gravity="top"
        android:layout_weight="1" />
</LinearLayout>

We can now go on and create a custom list adapter. When we use a ListView it is necessary to set a listAdapter, which is a class that contains all the settings regarding how to display the actual items, including which layout to use. You could use the default layouts that are available in the system but, since we are going to use our own, we will create our custom class.

This is it:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
public class MyListAdapter extends BaseAdapter {

    Context context;
    String[] titles;

    TextView title_text_view;
    TextView loginID_text_view;
    TextView psw_text_view;


    public MyListAdapter(Context context, String[] titles)
    {
        this.titles = titles;
        this.context = context;

       
    }
    @Override
    public int getCount() {
        return titles.length;
    }

    @Override
    public Object getItem(int position) {
        return titles[position];
    }

    @Override
    public long getItemId(int position) {
        return position;
    }

    @Override
    public View getView(final int position, View convertView, ViewGroup parent) {

        View view;

        Account a = PswDatabase.getInstance().getAccountByTitle(titles[position],false);

        LayoutInflater inflater= (LayoutInflater)context.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
        view = inflater.inflate(R.layout.list_adapter_item,null);

        title_text_view = (TextView) view.findViewById(R.id.list_adapter_item_title);
        loginID_text_view = (TextView) view.findViewById(R.id.list_adapter_item_loginID);
        psw_text_view = (TextView) view.findViewById(R.id.list_adapter_item_psw);

        title_text_view.setText(a.getTitle());
        loginID_text_view.setText(a.getId());
        psw_text_view.setText(a.getThePassword());

        return view;
    }
}

The class must extend BaseAdapter in order to be used for a ListView.

Most of the inherited methods are pretty self explanatory, but the real stuff happens in the getView function. Here is where the custom view for each item is created. On lines 40 and 41, we use the inflater object to inflate our custom layout in the previously created view. Once the view is ready, we can finally get all the references to our texview.

For each item we have an index, position, and we use that value to get each account object in the database by its title (line 38). We then assign their respective strings (title, login, password) to the textviews. This will run for as many views we need, which are going to be as many as the title array's elements.

At this point all we have to do in get the ListView reference and assign the adapter.

In the MainActivity, create a method called UpdateList() which is called in the onCreate. The method will do what its names suggests it would do, which is updating the listview.

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
    void UpdateList()
    {
        ListView listView;
        listView = (ListView)findViewById(R.id.listView);
        String[] titles = new String[PswDatabase.getInstance().getTitlesList().size()];
        titles = PswDatabase.getInstance().getTitlesList().toArray(titles);
    
        MyListAdapter adapter = new MyListAdapter(MainActivity.this,titles);
        listView.setAdapter(adapter);

    }

We firstly get our list view reference form the layout. We then get the list of titles from the database. the method used was not implemented in the previous post, and it is displayed below:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
 public List<String> getTitlesList()
    {
        List<String> titles = new ArrayList<String>();

        SQLiteDatabase db = getReadableDatabase();

        Cursor cursor = db.rawQuery("SELECT * FROM " + TABLE_NAME,null);

        if(cursor.moveToFirst())
        {
            do{

                String s = cursor.getString(1);
                titles.add(s);
            }while(cursor.moveToNext());
        }
        
        return titles;
    }

We should now ready to go. You should place a call to UpdateList every time the database is changed, so the list will be updated as well..

Imagine we had added 2 accounts in our database. Using our PswDatabase class we wrote last time, we would proceeed like this:

1
2
  Account a1 = new Account("Gmail account","myusername@gmail.com","mypassword");
  Account a2 = new Account("Youtube account","myyoutube username","myyoutubePassw0rd");

Once the list is updated, you should see this:


Conclusion

We should now have a working database with a ListView that displays the information to the user. This will conclude the topic. It wold be possible to add buttons to edit and delete each record. All you would have to do is to add the actual Button view in the layout, reference it in the MyListAdapter class, set an on click listener that calls the deleteAccountByTitle method in the database class. That simple.And of course, a better design would not hurt, but this is a good example on how to use a list view efficiently.

Friday, 19 August 2016

Database programming with SQLite

If you're like me, you probably have several different accounts for different things, you email, your paypal, your dropbox and so on. I often have to use different passwords as the password requirements differ from account to account. I decided to work on a simple app that allows me to store all the accounts logins and passwords and, in order to do so, I have to implement database programming.

This post is about SQL and the "lite" version we find on Android devices.

In my project, a created a class Account, which will create objects with the information we want to store.

The class is displayed below:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
public class Account {

    private String thePassword;

    private String title;

    private String id;

    public String getId() {
        return id;
    }

    public void setId(String id) {
        this.id = id;
    }

    public Account(String t, String id, String psw)
    {
        thePassword = psw;
        title = t;
        this.id = id;
    }

    public String getThePassword() {
        return thePassword;
    }

    public void setThePassword(String thePassword) {
        this.thePassword = thePassword;
    }

    public String getTitle() {
        return title;
    }

    public void setTitle(String title) {
        this.title = title;
    }
}

Nothing special at all, the class contains 3 String parameters for the information needed.

Now we can create our database helper class. The class itself is called PswDatabase, I will show you each method one by one.

Class declarataion and parameters

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
public class PswDatabase extends SQLiteOpenHelper {

    private static List<IDatabaseListener> databaseListeners;

    private static PswDatabase instance;

    private static final String DATABASE_NAME = "passwords_database";
    private static final String TABLE_NAME = "passwords_table";
    private static final int DATABASE_VERSION = 1;

    private final String COLUMN_ID = "id";
    private final String COLUMN_PSW_ID = "login";
    private final String COLUMN_PSW = "password";
    private final String COLUMN_TITLE = "title";
}

The class will extend SQLiteOpenHelper and these above are the parameters needed.
Since I have only one database and I wanted to be able to call it from anywhere in the project I made this class a singleton, which is why you see the instance object on line 3.

Constructor, getInstance, on create and on upgrade

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
 public PswDatabase(Context context) {
        super(context, DATABASE_NAME, null, DATABASE_VERSION);
    }

    public static synchronized PswDatabase getInstance()
    {
        if(instance==null) {
            databaseListeners = new ArrayList<IDatabaseListener>();
            instance = new PswDatabase(MainActivity.context);

        }

        return instance;
    }

    @Override
    public void onCreate(SQLiteDatabase db) {

        String CREATE_CONTACTS_TABLE = "CREATE TABLE " + TABLE_NAME + "("
                + COLUMN_ID + " INTEGER PRIMARY KEY AUTOINCREMENT," // cursror 0
                + COLUMN_TITLE + " TEXT,"                           // cursror 1
                + COLUMN_PSW_ID + " TEXT, "                          // cursror 2
                + COLUMN_PSW + " TEXT" + ")";                       // cursror 3

        db.execSQL(CREATE_CONTACTS_TABLE);
    }

    @Override
    public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) {

        db.execSQL("DROP TABLE IF EXISTS " + TABLE_NAME);
        onCreate(db);

    }

All these methods (except for getInstance) are automatically inherited from SQLiteOpenHelper and we must implement a body for them.

The constructor simply call the base class constructor, passing the name and version of the database.

The getInstance() method will check if the instance object has already been instantiated. If not, it will call the constructor in order to create the object, passing MainActivity.this as context (static parameter) and it will finally return the object itself.

In onCreate(...) we execute our first sql statement, which will need to create the table and set its columns along with their variable type stored. Finally, onUpgrade(...), which is usually called whenever the database needs upgrading. This is a very standard implementation of sql in Android and there is not much I can add to the already many tutorials out there. The best learning source is of course the Android dev website and its database programming tutorial.

Adding, deleting, updating records

Here is how we add a new account to our database. The method checks first to make sure there is no other account stored with the same title, as the application will not accept 2 entries with the same title parameter.

In case a record with the same title is found, the application will notify the user (via Toast) of the event and won't add any new row in the database.

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
 public boolean addAccount(Account a)
    {
        //Check for Title. Two accounts with matching titles are not allowed

        Account pass = getAccountByTitle(a.getTitle());

        if(pass!=null)
        {
            Toast.makeText(MainActivity.appContext,"Cannot duplicate titles",Toast.LENGTH_LONG).show();
            return false;
        }

        SQLiteDatabase db = getWritableDatabase();
        ContentValues cv = new ContentValues();

        cv.put(COLUMN_TITLE,a.getTitle());
        cv.put(COLUMN_PSW_ID,a.getId());
        cv.put(COLUMN_PSW, a.getThePassword());

        db.insert(TABLE_NAME, null, cv);
        db.close();

        
        
        return  true;
    }

Below, the method in charge of deleting records:

1
2
3
4
5
6
7
 public void deleteAccountByTitle(String t)
    {
        SQLiteDatabase db = getWritableDatabase();

        db.delete(TABLE_NAME,COLUMN_TITLE + " = ?",new String[]{t});        
        db.close();

    }

Throughout the application, all the records are identified by their title. The delete method of the database object will delete any entry in the table of name TABLE_NAME, where the title column (COLUMN_TITLE) is equal to the parameter passed vie the String array (String[]{t}). So, when we pass a title, the record associated with it will be removed from the database.

Replacing a record:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
 public void replaceAccount(String toReplacePasswordTitle, Account replaceWith)
    {
        SQLiteDatabase db = getWritableDatabase();

        ContentValues cv = new ContentValues();

        cv.put(COLUMN_TITLE,replaceWith.getTitle());
        cv.put(COLUMN_PSW_ID,replaceWith.getId());
        cv.put(COLUMN_PSW, replaceWith.getThePassword());

        db.update(TABLE_NAME, cv, COLUMN_TITLE + " = ?", new String[]{toReplacePasswordTitle});
        db.close();
        
    }

In a similar way, we select the record by its title and update its colums using the content values, just like we did when adding a new account.

Retrieving information

At last, a few methods to retrieve the information stored.

First, if we want to return a single Account object:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
 public Account getAccountByTitle(String t)
    {
        Account a;
        String q = "SELECT * FROM " + TABLE_NAME + " WHERE " + COLUMN_TITLE + "= ?";
        SQLiteDatabase db = getReadableDatabase();

        Cursor cursor = db.rawQuery(q,new String[]{t});

        if(cursor.moveToFirst())
        {
            do {
                a = new Account(cursor.getString(1),cursor.getString(2),cursor.getString(3));
                return a; //break the loop at first password found
            }while(cursor.moveToNext());

        }
        else {
            Toast.makeText(MainActivity.appContext,"Could not find the account with title -" + t + "-",Toast.LENGTH_LONG).show();
            return null;
        }

    }

We initially create an empty account object, a.

The sql string will select any record (SELECT *) from the table named TABLE_NAME ,where the coulm title (COLUMN_TITLE) is equal to the parameter t, passed in a String array on line 7.

this line will return a cursor, which is a pointer to a position in the database.

We move the cursor to its first position assuming it has found something according to the parameters passed to it. If it hasn't, we will notify the user that account (with title t) is not in the table.

If the cursor has found something, we instantiate a new Account object passing the values obtaint from the cursor while moving it from colum to column (cursor.getString(int columnIndex)). The first column (0) is the integer value COLUMN_ID, which we are not using. The second column is the title, then the password_id (which I should have called account_id really...) and finally the password. See the comments in the onCreate method of this class.

As soon as the object is instantiated, we can return it and interrupt the do-while loop.

One other thing we might need is to retrieve a list of all the accounts in the database. Here's how:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
public List<Account> getAccountList()
    {
        List<Account> list = new ArrayList<Account>();

        SQLiteDatabase db = getReadableDatabase();

        Cursor cursor = db.rawQuery("SELECT * FROM " + TABLE_NAME,null);

        if(cursor.moveToFirst())
        {
            do{

                Account account = new Account(cursor.getString(1),cursor.getString(2),cursor.getString(3));
                list.add(account);
            }while (cursor.moveToNext());

        }

        return  list;
    }

Again, we create a cursor which this time, however, has no conditions. It will select anything from the table. So, for every row starting from the first one available (cursor.moveToFirst()) we instantiate an Account object and add it to the list. when cursor.moveToNext() returns false, means that there are no more rows in the database, and the do-while loop will end so we can finally return the list.

Conclusion

This is a pretty standard implementation of database programming in Android. In the next post, I'm going to place all the records in a ListView so we can display them to the user.