ANDROID TUTORIAL FINAL PART: AFRICAN HAIRSTYLE APP

complete android project
In this new tutorial we will start off from where we stop in the part 5 of this tutorial series. If you have not read the part 5 or other previous parts, I will suggest you do that first by clicking on this link – Android tutorial on African Hairstyle app.

Although I have received few messages from our readers urging me to find time to finish this tutorial so I promise I will and now we are on it again. If you have forgotten what you learnt before, spare some time out and revise all the previous tutorials before starting with this part.

A recap of what we have done so far. We have starting with the development of our app after introductory lessons on android and how to create a new android project. In the last tutorial we went ahead to create our intro page for our app.

In today’s tutorial we will create the quiz page and continue with how to setup SQLITE database which will hold all the data our app will make use of.

Let’s first talk about our database structure. We are going to have three fields

  1. Hairstyle name
  2. Hairstyle description
  3. Hairstyle image

Please note that we can also choose to use a data structure like Arraylist to store this information. We will use SQLITE database and this will afford us the opportunity to learn how to working with a database in android development.

We will also eemphasizetwo different ways I use when I am working with data driven application in android.

The first one is by using the inbuilt SQLITE command to create and manipulate your application database. The second option is to use external SQLITE database management software to create your database visually and then use another third party library in your application to manage your database file.

I will go with the second option but before then I will brief demonstrate how you can accomplish the same task if you want to use the first option.

Android SDK comes pre-package with SQLITE. This affords easy usage without the necessary need for drivers or database connectors. You can easily create a database with a call to this method openOrCreateDatabase. It accepts parameters as shown below.

SQLiteDatabse mydatabase = openOrCreateDatabase("String path, SQLiteDatabase.CursorFactory factory, int flags);

The openOrCreateDatabase method can be used to open an existing database or simple create a new one. The instance of the created database object can now be used to create table, insert and manipulate the content of the tables. SQLITE database class has a method called – execSQL. This method as the name implies is used to execute SQLITE query.

A simple example of how this method can be used is shown below.

Cursor resultSet  =  mydatbase.rawQuery("Select * from mytable",null);

The select query execution returns a cursor object. The cursor class has many methods that can be used to manipulate a cursor object. A simple example is also shown below.

String tableColumn = resultSet.getString(1);

Before we round up with this brief description on how to use SQLITE in android I will like to emphasize that android has provided SQLiteOpenHelper class. This class is used to manage database and all operation the database runs. It automatically manages the creation and updating of the database. To use this class for database management, you will simple create a subclass of SQLiteOpenHelper as shown in the example below.

public class FileHelper extends SQLiteOpenHelper {  

   public FileHelper(){
      super(context,DATABASE_NAME,null,1);

   }

   public void onCreate(SQLiteDatabase db) {}

   public void onUpgrade(SQLiteDatabase database, int oldVersion, int newVersion) {}

}

Now let’s head back to the second option we will use to create our database. I will use SQLITE Expert database manager software to create my own database outside of my project.

There are many open source SQLITE database manager you can download and use (example). If you find it difficult to get one, you can simply download my database file on the link below.

 

Third party Library

There is one important thing we will discuss now. It is about third party libraries in android. Third party library is a collection of different classes that help to solve a particle problem better or that is not supported. In other to manage our created database we are going to use a third party library called android-sqlite-asset-helper. You can search for it on google or you can simply download the jar file here.

To add android-sqlite-asset-helper jar file in our project, we have to follow the steps below.

  1. Right click on your project folder
  2. In the pop-up window that appear, click on properties
  3. Click on the Java build path
  4. Click on the Libraries tab
  5. Click on add external Jar
  6. Find the path to the jar file and upload
  7. Click on order and export tab
  8. Tick the checkbox on left side of the jar file
  9. Finally, click the ok button and now the jar file has been added in our project and we can make use of it.

To separate all the database files in our application files from other files, we will create a new package to hold our database files. Right click on your project src folder; place your mouse cursor on new and in the fly out menu; click on package. Give your package a name. Refer to our project tutorial to refresh your mind on package naming conversion.

Once you are done it is time for use to start creating classes that will help us manage our database.

 One more thing to do

Create a new folder called database inside the assets folder. Then place your database file inside this folder. This is where our android-sqlite-asset-helper class will look for our database file. It is not there our application will crash. Remember to zip the database file once you drop it on its folder.

Create a new class called DatabaseConnection.java in your database package. Copy and paste the code shown below to the file

import android.content.Context;
import com.readystatesoftware.sqliteasset.SQLiteAssetHelper; 

public class DatabaseConnection extends SQLiteAssetHelper{  
          private static final String DATABASE_NAME = "braids";
          private static final int DATABASE_VERSION = 1;           

          public DatabaseConnection(Context context) {
              super(context, DATABASE_NAME, null, DATABASE_VERSION);
            }
}

In the code snippet above, you will see that we have extended from SQLiteAssetHelper class. The two class variables represent our database name and version.

The next step is to create a new class called Database.java. The code below will live in this file. Copy and paste it in the file.

import android.content.Context;
import android.database.sqlite.SQLiteDatabase;

public class Database {

            private static DatabaseConnection mAdapter;
            private static SQLiteDatabase db;

             /**
             * @param context application context
             * @return database instance
             */

            public static SQLiteDatabase getDb(Context context){
                 mAdapter = new DatabaseConnection(context);
                 db = mAdapter.getWritableDatabase();        
                 return db;
            }
}

In the code above, we are using the database adapter we created in DatabaseConnection class to return a static instance of our database object. This might not be the best way to handle this because of memory leak so if you have a better idea you can drop it in the comment section.

Now that we have our database instance, we will move on to create a new class called DatabaseBack.java. This class will contain all the queries we will use in this application.

Copy and paste the following code in the file.

import java.util.ArrayList;
import java.util.List;
import com.toscanyacademy.africanbraids.BraidObject;
import android.content.Context;
import android.database.Cursor;
import android.database.sqlite.SQLiteDatabase;

public class DatabaseBackend extends Database{
    private static Context context;       
    private static SQLiteDatabase db;
    private static final String DATABASE_TABLE = "braid";
    private static DatabaseBackend instance = null;

     private DatabaseBackend() {}

     public static DatabaseBackend getInstance() {
        if (instance == null) {
             instance = new DatabaseBackend();
        }
        return instance;
    }    
   /**
     * initialization method for database
     * @param context application context
     */
    public void init(Context contexts){
       context = contexts;
       db = getDb(context);
    }

    public List<BraidObject> getAllBraids(){
      List<BraidObject> braidList = new ArrayList<BraidObject>();
      String sql = "select * from " + DATABASE_TABLE;
      Cursor cursor = db.rawQuery(sql, null);        
      if(cursor.moveToFirst()){
      do{
          String braidImageId = cursor.getString(cursor.getColumnIndexOrThrow("imageid"));
          String braidName = cursor.getString(cursor.getColumnIndexOrThrow("name"));
          String braidDescription = cursor.getString(cursor.getColumnIndexOrThrow("description"));
          braidList.add(new BraidObject(braidName, braidDescription, braidImageId));
     }while(cursor.moveToNext());
     }
     cursor.close();
     return questionList;                
     }
}

In the above code, DatabaseBackend class extends our Database class. We use a singleton pattern to create a single instance of our database object. Whenever there is a database call, our database manager will first check if there is an existing instance of our database object if not it will create a new database object.

The getAllBraids() method is used to return all the data we have in the database about our hairstyle. This data wraps inside a BraidObject object which is store in an Arraylist.

So when this function is executed we will have all our data retrieved from the database and store in an Arraylist. That is basically what we need for our database classes. If it is still confusing to you, you can use our comment box to ask questions.

The BraidObject class is a domain class that is used to wrap a single hairstyle row in our database. Create a class called BraidObject.java. Copy and paste the code below to this file

public class BraidObject {
    private String name;
    private String description;
    private String imageId;

    public BraidObject(String name, String description, String imageId) {
      super();
      this.name = name;
      this.description = description;
      this.imageId = imageId;
    }
     /**
     * @return the description
     */
    public String getName() {
        return name;
    }

    /**
    * @param description the description to set
     */
    public void setName(String name) {
       this.name = name;
    }
    /**
     * @return the description
    */
    public String getDescription() {
      return description;
    }

    /**
    * @param description the description to set
    */
    public void setDescription(String description) {
      this.description = description;
    }
    /**
    * @return the imageId
    */
    public String getImageId() {
        return imageId;
    }

    /**
    * @param imageId the imageId to set
    */
     public void setImageId(String imageId) {
        this.imageId = imageId;
     }
}

There is nothing special in this class. It is a bunch of setters and getters use for setting and getting individual values of hairstyle.

We will head over to the final activity page that will hold all the data we have retrieved from our database. We are going to create a new activity page. You should call this file BraidsActivity.java. Once you are done, open the activity_braids.xml and copy and paste the code below.

<RelativeLayout 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:background="@drawable/bg">

<ScrollView
        android:id="@+id/scrollView1"
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:scrollbars="none">

<RelativeLayout
    android:layout_width="match_parent"
    android:paddingBottom="60dp"
    android:layout_height="wrap_content">

     <LinearLayout   
        android:id="@+id/newlayout"
        android:layout_width="fill_parent"
        android:layout_height="wrap_content"
        android:layout_centerHorizontal="true"
        android:layout_alignParentTop="true"
        android:background="#f6f7bd"
        android:padding="10dp"
        android:gravity="center">

     <TextView
        android:id="@+id/braid_title"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:textSize="20sp"
        android:textStyle="bold"
        android:textColor="@color/black"
        android:text="@string/title_activity_braids"/>       

    </LinearLayout>

    <ImageView
       android:id="@+id/braids"
       android:layout_width="wrap_content"
       android:layout_height="wrap_content"
       android:layout_below="@+id/newlayout"
       android:layout_centerHorizontal="true"
       android:layout_marginTop="10dp"
       android:contentDescription="@string/app_name"
       android:src="@drawable/rain" />

    <TextView
        android:id="@+id/braid_info"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_alignParentLeft="true"
        android:layout_below="@+id/braids"
        android:layout_marginTop="10dp"
        android:layout_marginLeft="10dp"
        android:layout_marginRight="10dp"
        android:textColor="@color/white"
        android:textSize="15sp"
        android:text="@string/braid_text" />

    <Button
        android:id="@+id/previous_button"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_below="@+id/braid_info"
        android:layout_alignParentLeft="true"
        android:layout_marginLeft="10dp"
        android:layout_marginTop="20dp"
        android:textColor="@color/black"
        android:background="@drawable/button"
        android:text="@string/next_button" />

    <Button
        android:id="@+id/next_button"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_alignParentBottom="true"
        android:layout_alignParentRight="true"
        android:layout_marginRight="10dp"
        android:textColor="@color/black"
        android:background="@drawable/button"
        android:text="@string/previous_button" />
</RelativeLayout>

</ScrollView>      

</RelativeLayout>

The xml file might look intimidating but we will break it down gradually. What we have done is to create a linearlayout inside our scroll view to hold the name of the selected hairstyle.

We have also created the following view controls

  1. ImageView that holds the hairstyle image
  2. TextView that holds the description of the hairstyle
  3. Two Button view for previous and next hairstyle

All the string content of these views should be copy and pasted in the string.xml file located in the resource folder. The string xml are shown below.

<string name="start_button">Start</string>
    <string name="title_activity_braids">African Braids</string>
    <string name="braid_text">It is a long established fact that a reader will be distracted by the readable content of a page when looking at its layout. The point of using Lorem Ipsum is that it has a more-or-less normal distribution of letters, as opposed to using Content here, content here</string>
    <string name="previous_button">Previous</string>
    <string name="next_button">Next</string>
    <string name="title_activity_button">ButtonActivity</string>

Now that we are done with the layout file, we will move over to our BraidsActivity.java file to implement our code. Just like we did in the previous file, the code for this file is shown below. Copy and paste it on your BraidsActivity.java file.

import java.util.List;
import com.toscanyacademy.africanbraids.database.DatabaseBackend;
import android.support.v7.app.ActionBarActivity;
import android.support.v4.app.Fragment;
import android.content.pm.ActivityInfo;
import android.os.Bundle;
import android.view.LayoutInflater;
import android.view.Menu;
import android.view.MenuItem;
import android.view.View;
import android.view.ViewGroup;
import android.view.Window;
import android.view.WindowManager;
import android.view.View.OnClickListener;
import android.widget.Button;
import android.widget.ImageView;
import android.widget.TextView;

public class BraidsActivity extends ActionBarActivity {     
    private static ImageView braids;
    private static TextView braid_name;
    private static TextView braid_info;
    private static Button previous_button;
    private static Button next_button;
    private static int sizeofList;
    private static int listPointer;
    private static List<BraidObject> allBraids;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        requestWindowFeature(Window.FEATURE_NO_TITLE);
        this.getWindow().setFlags(WindowManager.LayoutParams.FLAG_FULLSCREEN,
WindowManager.LayoutParams.FLAG_FULLSCREEN);
        setContentView(R.layout.activity_braids);
        setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_PORTRAIT);

        listPointer = 0;

        // intialized the database object
        DatabaseBackend.getInstance().init(this);
        braids = (ImageView)findViewById(R.id.braids);                           

        braid_info = (TextView)findViewById(R.id.braid_info);
        braid_name = (TextView)findViewById(R.id.braid_title);
        previous_button = (Button)findViewById(R.id.previous_button);
        next_button = (Button)findViewById(R.id.next_button);

        //get all list data in the database
        allBraids = DatabaseBackend.getInstance().getAllBraids();

        if(allBraids != null){
            sizeofList= allBraids.size();
        }
        BraidObject mBraid = allBraids.get(listPointer);
        String braidName = mBraid.getName();
        String braidDescription = mBraid.getDescription();

        String braidImage = mBraid.getImageId();
        int imageId = convertNameToResourceId(braidImage);

         // set all the view components
         braids.setImageResource(imageId);  
         braid_name.setText(braidName);
         braid_info.setText(braidDescription);
         previous_button.setOnClickListener(new OnClickListener(){

         @Override
         public void onClick(View view) {
         // TODO Auto-generated method stub
         if(listPointer <= 0){
            listPointer = 0;
        }
        else{
            listPointer--;
        }
        BraidObject mBraid = allBraids.get(listPointer);
        String braidName = mBraid.getName();
        String braidDescription = mBraid.getDescription();
        String braidImage = mBraid.getImageId();
        int imageId = convertNameToResourceId(braidImage);

        // set all the view components
        braids.setImageResource(imageId);  
        braid_name.setText(braidName);
        braid_info.setText(braidDescription);                                                    }
     });
         next_button.setOnClickListener(new OnClickListener(){
            @Override
            public void onClick(View view) {
               // TODO Auto-generated method stub
               if(listPointer >= sizeofList - 1){
                  listPointer = sizeofList - 1;
               }
               else{
                  listPointer++;
               }
            BraidObject mBraid = allBraids.get(listPointer);
            String braidName = mBraid.getName();
            String braidDescription = mBraid.getDescription();
            String braidImage = mBraid.getImageId();
            int imageId = convertNameToResourceId(braidImage);
            // set all the view components
            braids.setImageResource(imageId);  
            braid_name.setText(braidName);
            braid_info.setText(braidDescription);           
         }
       });
     }

    @Override
    public boolean onCreateOptionsMenu(Menu menu) {

      // Inflate the menu; this adds items to the action bar if it is present.
      getMenuInflater().inflate(R.menu.braids, menu);
      return true;
    }

    @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();
     if (id == R.id.action_settings) {
         return true;
     }
     return super.onOptionsItemSelected(item);
   }
   private int convertNameToResourceId(String imageName){
      int resID = getResources().getIdentifier(imageName, "drawable", getPackageName());
      return resID;
   }
}

Please don’t freak out by asking yourself what is going on here. We will go through the code step by step.

The first thing to do is to get the instance of our view controls. This is done by using the activity class method findViewById. Subsequently, we instantiate our database class and call the getAllBraids() method which will return all our data from the database and store it in an Arraylist

We declare a class variable called listPointer and assign an initial value of 0 to it. The listPointer is used as an indication of the Arraylist index will are currently working on. Since Arraylist index starts from 0, we initialized it to 0.

We attached a click event listener to our previous and next button view controls. So when the next button is click, it will increment the value of listPointer by 1 otherwise if previous button is click we will decrement listPointer value by 1

We use the listPointer to get an instance of a BraidObject object and our get methods will retrieve the object values and assigned it to their respective view controls.

I know by now the whole thing is beginning to make more sense to you. You are free to ask questions when you are in doubt.

There is no better time to run your application than now. If everything works out good for you, you will have a working application in your device.

The code for this project is free to use. You can adopt it and use it to do whatever you like.

Remember, we are updating our website everyday will fresh and well detailed tutorials on android development and mobile game development. Please remember to subscribe to be among the first that will get all our exclusive information.

OTHER INTERESTING POSTS:

Add a Comment