Click here to Skip to main content
65,938 articles
CodeProject is changing. Read more.
Articles / Hosted-services / storage

Article 8 - Handling Input and Storage on Android

4.72/5 (12 votes)
9 Sep 2014CPOL22 min read 40.6K   2.2K  
This articles provides a brief description of different methods that Android platform can provide for a developer to save different data types with different storage methods like Shared Preferences, Internal Storage, External Storage, SQLite DB, and Web Services

Introduction

In this article, we will have a brief understanding of handling storage of different input types, and different storage options that you can apply on your android applications depending on your needs and application type, as well as accessing data through a web service which is the most apply method now. 

We will cover the following options :

  1. Storage Options
    1. Shared Preferences
      1. What it is?
      2. When should I use Shared Preferences?
      3. How to store data?
      4. How to retrieve data?
      5. How to delete Shared Preference Data?
      6. Example
      7. Tip
    2. Internal Storage
      1. What it is?
      2. When should I use Internal Storage?
      3. How to store data?
      4. How to retrieve data?
      5. How to delete Internal Storage Data?
      6. Example
      7. Tip
    3. External Storage
      1. What it is?
      2. When should I use External Storage?
      3. How to store data?
      4. How to retrieve data?
      5. How to delete External Storage Data?
    4. SQLite Database
      1. What it is?
      2. When should I use Shared Preferences?
      3. Example
        1. DB Model Classes
        2. DB Handler
        3. CRUD
          1. Create
          2. Read
          3. Read All
          4. Update
          5. Delete
        4. User Interaction with DB
  2. Web Service
    1. kSOAP 2
      1. Download kSOAP Library
      2. Include kSOAP Library Into Our Project
      3. Create a Response
      4. JSON Parsing

Background

If you are looking for a complete tutorial, Please refer to the following links 

Article 1   - Introduction to Android by Ranjan.D

Article 2   - Setting Up Your Android Development Environment by Peter Leow

Article 3   - Creating a Simple Hello World Android Project by Varavut

Article 4   - Android UI Layout and Controls by Peter Leow

Article 5   - Android User Interactivity and Sensors by Ranjan.D

​​Article 6   - Beginner’s Guide to Organizing/Accessing Android Resources by Grasshopper.iics

Article 7   - To be Updated Soon

Article 8   - To be Updated Soon

Article 9   - To be Updated Soon

Article 10 - To be Updated Soon

Article 11 - To be Updated Soon

Article 12 - To be Updated Soon

Downloads

Storage Options

In 99% of any android application, you will have to save users data somehow, that's why android provides different storage options and data management that developers can use to save these data and choosing which option to use depends on the developer needs and your application type.

1. Shared Preferences

1.1 - What it is?

Shared Preferences is an API from Android to store and retrieve small application data that are stored persistently which mean that data that you save in Shared Preferences will exist even if you close the application and data will be removed only by uninstalling the application from the device. Also, data saved in Shared Preferences are private to this application only and not accessible by anyway for any other application on the device.

You have to note that data are saved as Key/Value Pair.

Key/Value Pair: it's a known method to save data as a unique identifier and a value that is the data of the identifier or a link on the location of data such that your code looks like <Key, Value> => <"Website","CodeProject">, when you need to find a specific value , you will search by the key as ex: find(website) and it will display the value for this key.

1.2 - When should I use Shared Preferences?

If you need to save simple data for your application, the simplest and straight forward way is Shared Preferences. It's probably used to save simple data like integer,double, boolean, and short text. As Example, It's used to save application settings or user login info.

1.3 - How to store data?

First, you have to initialize a Shared Preference instance and use it to store your data as below

protected void onCreate(Bundle savedInstanceState) {
   super.onCreate(savedInstanceState);
   setContentView(R.layout.activity_main);
        
   SharedPreferences _SharedPref = getApplicationContext().getSharedPreferences("MyAppData", 0);
   Editor _SharedPrefEditor = _SharedPref.edit();
}

I created a Shared Preferences Instance called _SharedPref of File Name called MyAppData (this can be anything), and the 2nd parameter is set to 0 which means that these data are private for this application only (private mode). Then we created an Editor that we will use to store new values as we will see in the next lines.

Now, you can save the data using the created Editor as below

_SharedPrefEditor.putBoolean(key, value);
_SharedPrefEditor.putFloat(key, value);
_SharedPrefEditor.putInt(key, value);
_SharedPrefEditor.putLong(key, value);
_SharedPrefEditor.putString(key, value);
_SharedPrefEditor.putStringSet(arg0, arg1);
        
_SharedPrefEditor.commit(); //you have to commit to save your data

1.4 - How to retrieve data?

Same as storing data, you need to initialize an instance of shared preference and use it to retrieve data

SharedPreferences _SharedPref = getApplicationContext().getSharedPreferences("MyAppData", 0);

_SharedPref.getAll(); // to retrieve all data related to MyAppData SharedPreference File
_SharedPref.getBoolean(key, defValue); 
_SharedPref.getFloat(key, defValue);  
_SharedPref.getInt(key, defValue);    
_SharedPref.getLong(key, defValue);   
_SharedPref.getString(key, defValue);
_SharedPref.getStringSet(arg0, arg1);

1.5 - How to delete Shared Preference Data?

You can 2 options, you can delete a specific data or delete all data inside a Shared Preference

1. Delete specific item

SharedPreferences _SharedPref = getApplicationContext().getSharedPreferences("MyAppData", 0);
Editor _SharedPrefEditor = _SharedPref.edit();
        
_SharedPrefEditor.remove(key); //Set the key of the data you want to delete
_SharedPrefEditor.commit();

2. Delete All Data

SharedPreferences _SharedPref = getApplicationContext().getSharedPreferences("MyAppData", 0);
Editor _SharedPrefEditor = _SharedPref.edit();
        
_SharedPrefEditor.clear(); //This will clear all data inside MyAppData Shared Preference File
_SharedPrefEditor.commit();

1.6 - Example

I created an example to combine all the previous points that we discussed. The example is a simple login form where user have to login to move into next activity then he can logout or stay logged in.

1. I created my XML Layout that contains a title , email input text , password input text and login button.

Image 1

                               figure 1.1.6.1 - XML Layout

2. It's time to implement some code, i created a static user and trying to login with. If the data are valid then save UserID in Shared Preferences and go to Profile Page Or if already user is logged in then go directly to Profile Page

SharedPreferences _SharedPref = getApplicationContext()
                .getSharedPreferences("MyAppData", 0);
final Editor _SharedPrefEditor = _SharedPref.edit();

// Check if user already logged in
int UserKey = _SharedPref.getInt("UserKey", -1);
if (UserKey != -1) {
      Intent i = new Intent(MainActivity.this, Profile.class);
      startActivity(i);
}

// Linking XML to Code
final EditText txt_Email = (EditText) findViewById(R.id.Email);
final EditText txt_Password = (EditText) findViewById(R.id.Password);
Button btn_Login = (Button) findViewById(R.id.btnLogin);

btn_Login.setOnClickListener(new OnClickListener() {

      public void onClick(View arg0) {
          // TODO Auto-generated method stub
          int UserID = IsLogin(txt_Email.getText().toString(),
                        txt_Password.getText().toString());
          if (UserID != -1) {
               _SharedPrefEditor.putInt("UserKey", UserID);
               _SharedPrefEditor.commit();

               Intent i = new Intent(MainActivity.this, Profile.class);
               startActivity(i);

          } else {
               Toast msg = Toast.makeText(getApplicationContext(),
                            "Login Failed", Toast.LENGTH_LONG);
               msg.show();
          }
    }
});

3. Try to close and open the application and it should redirect you to profile page directly without the need to enter your email and password again unless you logged out and Use saved UserID inside Shared Preferences to load information about the user like User Name in our example

// Load Shared Preference
SharedPreferences _SharedPref = getApplicationContext()
                .getSharedPreferences("MyAppData", 0);
final Editor _SharedPrefEditor = _SharedPref.edit();
int UserKey = _SharedPref.getInt("UserKey", -1);
        
//If User is logged In and Display User Data
if (UserKey != -1) {
      if (User._CurrentUser.UserID == UserKey) {
            TextView txt_Name = (TextView) findViewById(R.id.txtUsername);
            txt_Name.setText(User._CurrentUser.Name);
      }
} else {
     // Go back to MainActivity Activity
     Intent i = new Intent(Profile.this, MainActivity.class);
     startActivity(i);
}

Image 2

                               figure 1.1.6.2 - Logged In Screen

4. Try to log out and open the application again 

//Logout Button
Button btn_Logout = (Button)findViewById(R.id.btnLogout);
btn_Logout.setOnClickListener(new OnClickListener() {
            
     @Override
     public void onClick(View arg0) {
          // TODO Auto-generated method stub
          _SharedPrefEditor.remove("UserKey");
          _SharedPrefEditor.commit();
                
         // Go back to MainActivity Activity
         Intent i = new Intent(Profile.this, MainActivity.class);
         startActivity(i);
     }
});

You can download the entire code from: Download SharedPreferences.zip 

1.7 - Tip

You can view your Shared Preference files, Edit, and Create new file using Eclipse IDE - DDMS 

1. Run Your Application on an Emulator

2. Select DDMS from Menu, then Select Your Emulator and choose File Explorer 

Image 3

                                                                                    figure 1.1.7.1 - DDMS Screen

3. You should see a similar figure, then select data->data

Image 4

                                                                                     figure 1.1.7.2 - File Explorer

4. Select the com.example.sharedpreferences (Your Project)

5. Here you see your Shared Preference File and you can edit/add/delete/import/export any file from the provided tools

Image 5

                                                                                     figure 1.1.7.3 - Controllers

2. Internal Storage

2.1 - What it is?

One of the Storage Options is Internal Storage. You can save your application data directly on the device's internal storage and these data are stored persistently which mean that data still exist even if you close the application and data will be removed only by uninstalling the application from the device. Also, data saved in device's internal storage are private to this application only and not accessible by anyway for any other application on the device.

2.2 - When should I use Internal Storage?

The amount of data in Internal Storage depends on the device, so don't try to save a large persistent file because it may crash your application if there isn;t enough space on device. Preferably, keep any data under 1M such as text files or xml files.

2.3 - How to store data?

First, You have to create a FileOutputStream Object that we will use to write our data in a file as BYTES, you have to open/ create a file and use .write() function to write your data as bytes and never forget to close the FileOutputStream as code below

FileOutputStream _FileOutput;
String FileName = "Note";
String FileInput = txt_EditNote.getText().toString();
try {
   //by default mode is private
   _FileOutput = openFileOutput(FileName, 0);
   _FileOutput.write(FileInput.getBytes());
   _FileOutput.close();

   Toast.makeText(getApplicationContext(),
             FileName + " saved", Toast.LENGTH_LONG).show();

} catch (FileNotFoundException e) {
     e.printStackTrace();
} catch (IOException e) {
     e.printStackTrace();
}

2.4 - How to retrieve data?

You need to create a StringBuffer to save each line you read from data into and Create a BufferReader Object to open file and read line by line and never forget to close the BufferReader as code below

StringBuffer stringBuffer = new StringBuffer();    
try {    
   BufferedReader inputReader = new BufferedReader(new InputStreamReader(  
        openFileInput(FileName)));  
   String inputString;                
   while ((inputString = inputReader.readLine()) != null) {  
            stringBuffer.append(inputString + "\n");  
   }  
                          
   inputReader.close();

} catch (IOException e) {  
      e.printStackTrace();  
}  

2.5 - How to delete Internal Storage Data?

This is a very easy step, all you need just the file name you want to delete and the filedir

File dir = getFilesDir(); //Use this as FileDir for Internal Storage
File file = new File(dir, "filename");
file.delete();

2.6 - Example

I would like to provide an example that will combine all the above points for better explanation. In this example, we will create a note and save it into our device's internal storage then display all notes and show its content.

1. I created my XML Layout that contains a title , note input text , save button, and load all button.

Image 6

                               figure 1.2.6.1 - XML Layout

2. As shown, we need to add an input and save it into a file in internal storage. I intiliazed a string for FileName and an FileOutputStream as discussed above to save our data as bytes in a file called Note

final String FileName = "Note";
// On Save Click
btn_Save.setOnClickListener(new OnClickListener() {

     @Override
     public void onClick(View arg0) {
         // TODO Auto-generated method stub
         FileOutputStream _FileOutput;
         String FileInput = txt_EditNote.getText().toString();
         try {
             //by default mode is private
             _FileOutput = openFileOutput(FileName, 0);
             _FileOutput.write(FileInput.getBytes());
             _FileOutput.close();

             Toast.makeText(getApplicationContext(),
                            FileName + " saved", Toast.LENGTH_LONG).show();

          } catch (FileNotFoundException e) {
                    e.printStackTrace();
          } catch (IOException e) {
                    e.printStackTrace();
          }
    }
});

Image 7

                               figure 1.2.6.2 - Test Application #1

3. I created another Activity to load all my files of this application and only this app since files are private and can't access them from another app. On Creation of this activity, I load all files as below

SavedDataInInternalStorage = getApplicationContext().fileList();
ArrayAdapter<String> adapter = new ArrayAdapter<String>(this,
          android.R.layout.simple_list_item_1, SavedDataInInternalStorage);

_List.setAdapter(adapter);

Image 8

                               figure 1.2.6.3 - Display All Notes

4. On Click of any item of List View, it displays the content of that file as decribed below 

_List.setOnItemClickListener(new OnItemClickListener() {

     @Override
     public void onItemClick(AdapterView<?> arg0, View arg1, int arg2,
                    long arg3) {
         // TODO Auto-generated method stub
         String FileName = ((TextView) arg1).getText().toString();
         StringBuffer stringBuffer = new StringBuffer();
         try {
            BufferedReader inputReader = new BufferedReader(
                            new InputStreamReader(openFileInput(FileName)));
            String inputString;
            while ((inputString = inputReader.readLine()) != null) {
                stringBuffer.append(inputString + "\n");
            }

            inputReader.close();
          } catch (IOException e) {
             e.printStackTrace();
          }

           Toast.makeText(getApplicationContext(),
                        stringBuffer.toString(), Toast.LENGTH_LONG).show();
     }
});

Image 9

                               figure 1.2.6.4 - Display single note info 

You can download the entire code from: Download InternalStorage.zip

2.7 - Tip

1. Detect Internal Storage Space

Maybe, You may need to know Internal Sotrage Space and decide where to save your data on internal or external storage, that's why i think it's important to know the available space on device before saving your data.

You can find this as code below ( Credits goes to: Link )

public static String getAvailableInternalMemorySize() {
        File path = Environment.getDataDirectory();
        StatFs stat = new StatFs(path.getPath());
        long blockSize = stat.getBlockSize();
        long availableBlocks = stat.getAvailableBlocks();
        return formatSize(availableBlocks * blockSize);
}
    
public static String formatSize(long size) {
  String suffix = null;

  if (size >= 1024) {
     suffix = "KB";
     size /= 1024;
     if (size >= 1024) {
           suffix = "MB";
           size /= 1024;
     }
  }

  StringBuilder resultBuffer = new StringBuilder(Long.toString(size));

  int commaOffset = resultBuffer.length() - 3;
        while (commaOffset > 0) {
            resultBuffer.insert(commaOffset, ',');
            commaOffset -= 3;
        }

   if (suffix != null)
       resultBuffer.append(suffix);
   
   return resultBuffer.toString();
}

2. Edit/Remove Internal Storage Files using Eclipse IDE - DDMS

1. Run Your Application on an Emulator

2. Select DDMS from Menu, then Select Your Emulator and choose File Explorer 

Image 10

                                                                                              figure 1.2.7.1 - DDMS

3. You should see a similar figure, then select data->data

Image 11

                                                                                             figure 1.2.7.2 - File Explorer                 

4. Select the com.example.internalstorage (Your Project)

5. Here you see your Internal Storage Files and you can edit/add/delete/import/export any file from the provided tools

Image 12

                                                                                 figure 1.2.7.3 - Display all files through DDMS

3. External Storage

3.1 - What it is?

One of the Storage Options is External Storage. You can save your application data directly on the device's external storage and these data are world-readable and can be modified/transfered on a computer. Also, data saved in device's external storage can be unavailable if user mounts or removed the external media.

3.2 - When should I use External Storage?

You should use External Storage whenever you need to save large files such as audio files or any large file that won't kill your application and can be retrieved by user again multiple of times, or if you want your files to be shared through different application like statistics files.

3.3 - How to store data?

Before storing data in an external media, you have to give permission to your application for such operation by allowing write to external media in manifest file.

<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
    package="com.example.externalstorage"
    android:versionCode="1"
    android:versionName="1.0" >

    <uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />

Now, your application is ready to store data in an external media in one of these directories

  1. Music
  2. Pictures
  3. Ringtones
  4. Movies
  5. Alarms
  6. Notifications
  7. Downloads

How to access one of these files?

  1. Environment.getExternalStoragePublicDirectory(Environment.DIRECTORY_MUSIC, FileName);
  2. Environment.getExternalStoragePublicDirectory(Environment.DIRECTORY_PICTURES, FileName);
  3. Environment.getExternalStoragePublicDirectory(Environment.DIRECTORY_RINGTONES, FileName);
  4. Environment.getExternalStoragePublicDirectory(Environment.DIRECTORY_MOVIES, FileName);
  5. Environment.getExternalStoragePublicDirectory(Environment.DIRECTORY_ALARMS, FileName);
  6. Environment.getExternalStoragePublicDirectory(Environment.DIRECTORY_NOTIFICATIONS, FileName);
  7. Environment.getExternalStoragePublicDirectory(Environment.DIRECTORY_DOWNLOADS, FileName);

You need to create file and save it wherever of the above files to save it into as example below

FileOutputStream _FileOutput;
String FileInput = txt_EditNote.getText().toString();
try {
  // by default mode is private
  File myFile = new File(Environment.getExternalStoragePublicDirectory(
                                Environment.DIRECTORY_DOWNLOADS), FileName);
  myFile.createNewFile();
                     
  _FileOutput = new FileOutputStream(myFile); 
  _FileOutput.write(FileInput.getBytes());
  _FileOutput.close();

  Toast.makeText(getApplicationContext(),
                            FileName + " saved", Toast.LENGTH_LONG).show();

} catch (FileNotFoundException e) {
    e.printStackTrace();
} catch (IOException e) {
    e.printStackTrace();
}

3.4 - How to retrieve data?

In order to retrieve any data or file from External Storage, you have to access the file and read its data. As example i will try to load an image saved inside DIRECTORY_PICTURES and decode it to bitmap image

File file = new File(Environment.getExternalStoragePublicDirectory(
                      Environment.DIRECTORY_PICTURES, FileName);
FileInputStream InputFileStream = new FileInputStream(file);
Bitmap bitmap = BitmapFactory.decodeStream(InputFileStream);
InputFileStream.close();

3.5 - How to delete External Storage Data?

In order to delete external storage data, you have to reference to a specific file and simply apply delete function for this file as described 

File file = new File(Environment.getExternalStorageDirectory()
            .getAbsolutePath(), FileName);
file.delete();

4. SQLite Database

4.1 - What it is?

SQLite is an Open Source database. It supports standard relational database feasure like SQL Syntax and Views. SQLite is a very light weight DB that can be used in any mobile platforms.

For more information about SQLite : http://www.sqlite.org

Download SQLite Studio : http://sqlitestudio.pl/

4.2 - When should I use SQLite DB?

It doesn't have a specific case, you can use it whenever you need to save user data like fetching data from an external API but what if user is not connect to an internet then you can fetch the same data from database on offline mode or saving user search criteria to use it as default whenever user tries to search.

4.3 - Example

I think the best way to get into breif description of SQLite is to move directly into an example.

Our example is as follows : we have a set of cars and its description as well as its model as given in the following DB Diagram

Image 13

                                                             figure 1.4.3.1 - Database Model

1. Create Model Classes

1. We need to build our Model Classes - Create your first class model CarModel. Always Create 3 constructors  and set private variables in your class

  1. Empty Constructor 
  2. Constructor with all fields as parameters WITH ID
  3. Constructor with all fields  as parameters WITHOUT ID
public class CarModel {

   //Set Private Variables
    int _CarID;
    int _CarModelID;
    String _CarName;
    String _Description;
    String _Color;
    double _Price;
    
    // Empty constructor
    public CarModel(){
         
    }

     // constructor
     public CarModel(int CarID, int CarModelID, String CarName, String Description, String Color, double Price){
        this._CarID = CarID;
        this._CarModelID = CarModelID;
        this._CarName = CarName;
        this._Description = Description;
        this._Color = Color;
        this._Price = Price;
    }
     
   // constructor
   public CarModel(int CarModelID, String CarName, String Description, String Color, double Price){
        this._CarModelID = CarModelID;
        this._CarName = CarName;
        this._Description = Description;
        this._Color = Color;
        this._Price = Price;
    }
}

2. We need to create our getters/setter for all DB columns as follows

// getting CarID
public int getCarID(){
   return this._CarID;
}
     
// setting CarID
public void setCarID(int Carid){
   this._CarID = Carid;
}
     
// getting CarModelID
public int getCarModelID(){
   return this._CarModelID;
}
     
// setting CarModelID
public void setCarModelID(int CarModelID){
   this._CarModelID = CarModelID;
}
    
// getting Car Name
public String getCarName(){
   return this._CarName;
}
     
// setting Car Name
public void setCarName(String CarName){
   this._CarName = CarName;
}
     
// getting Description
public String getDescription(){
   return this._Description;
}
     
// setting Description
public void setDescription(String Description){
   this._Description = Description;
}
    
// getting Color
public String getColor(){
   return this._Color;
}
     
// setting Color
public void setColor(String Color){
   this._Color = Color;
}
    
// getting Price
public double getPrice(){
   return this._Price;
}
     
// setting Price
public void setPrice(double Price){
   this._Price = Price;
}

3. Do the above 2 steps for Model Class CarModelModel

public class CarModelModel {
    //Set Private Variables
    int _ModelID;
    String _ModelName;
    
 // Empty constructor
    public CarModelModel(){
         
    }
    // constructor
    public CarModelModel(int ModelID, String ModelName){
        this._ModelID = ModelID;
        this._ModelName = ModelName;
    }
     
    // constructor
    public CarModelModel(String ModelName){
        this._ModelName = ModelName;
    }
    
 // getting ModelID
    public int getModelID(){
        return this._ModelID;
    }
     
    // setting ModelID
    public void setModelID(int ModelID){
        this._ModelID = ModelID;
    }
     
    // getting ModelName
    public String getModelName(){
        return this._ModelName;
    }
     
    // setting ModelName
    public void setModelName(String ModelName){
        this._ModelName = ModelName;
    }
}

2. Create DB Handler Class

1. Create DB Handler Class DBHandler then extends SQLiteOpenHelper  and Add Unimplemented methods

public class DBHandler extends SQLiteOpenHelper {

    public DBHandler(Context context) {
        super(context, DB_NAME, null, DB_VERSION);
    }

    @Override
    public void onCreate(SQLiteDatabase db) {
        // TODO Auto-generated method stub
        
    }

    @Override
    public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) {
        // TODO Auto-generated method stub
        
    }
}

2. You will get an errors unless we add some static data like DB_NAME, DB_VERSION, Tables, Columns

//DB Inst
public static final int DB_VERSION = 1;
public static final String DB_NAME = "CarDB";
    
//DB Tables
public static final String TableCar = "car";
public static final String TableCarModel = "model";
    
//Columns as their Name in DB
public static final String Car_ID = "CarID";
public static final String Car_ModelID = "CarModelID";
public static final String Car_Name = "CarName";
public static final String Car_Description = "Description";
public static final String Car_Color = "Color";
public static final String Car_Price = "Price";
    
public static final String Model_ID = "ModelID";
public static final String Model_Name = "ModelName";

3. We have to implement OnCreate function that will create table for us for the first time, Create a string that will create the table as SQL Syntax

String CREATE_CAR_TABLE = "CREATE TABLE " + TableCar + "("
         + Car_ID + " INTEGER PRIMARY KEY," 
         + Car_ModelID + " INTEGER," + Car_Name + " TEXT,"
         + Car_Description + " TEXT," + Car_Color + " TEXT,"
         + Car_Price + " double" + " )";

db.execSQL(CREATE_CAR_TABLE);

4. Do the same for Model Table

String CREATE_MODEL_TABLE = "CREATE TABLE " + TableCarModel + "("
         + Model_ID + " INTEGER PRIMARY KEY," 
         + Model_Name + " TEXT" + ")";

db.execSQL(CREATE_MODEL_TABLE);

5. What OnUpgrade does? Simply, it always you to re-create DB table in case of any changes like column name or type or added constrains

//Drop Tables
db.execSQL("DROP TABLE IF EXISTS " + TableCar);
db.execSQL("DROP TABLE IF EXISTS " + TableCarModel);
        
// Add tables again
onCreate(db);

3. Create Tables ViewModel to hold their CRUD (Created/ Read/ Updated/ Delete)

1. Create a new class CarViewModel that will hold CRUD operations for this table and Add these methods

public class CarViewModel {
   
    // Database fields
    private SQLiteDatabase database;
    private DBHandler dbHelper;
    private String[] CarTableColumns = { DBHandler.Car_ID,
            DBHandler.Car_ModelID, DBHandler.Car_Name,
            DBHandler.Car_Description, DBHandler.Car_Color,
            DBHandler.Car_Price};

    public CarViewModel(Context context) {
        dbHelper = new DBHandler(context);
    }

    public void open() throws SQLException {
        database = dbHelper.getWritableDatabase();
    }

    public void close() {
        dbHelper.close();
    }

    // Adding Car
    public void addCar(CarModel car) {}

    // Get Specific Car By ID
    public CarModel getCar(int id) {}

    // Get All Cars
    public List<CarModel> getAllCars() {}

    // Updating Car
    public int updateCar(CarModel car) {}

    // Deleting Car
    public void deleteCar(CarModel car) {}
}

3.1. CRUD - Add Car

We need to create a ContentValues that will hold all our columns values and save this ContentValue inside the db as follows

// Adding Car
public void addCar(CarModel car) 
{
   ContentValues values = new ContentValues();
   values.put(DBHandler.Car_ModelID, car._CarModelID);
   values.put(DBHandler.Car_Name, car._CarName);
   values.put(DBHandler.Car_Description, car._Description);
   values.put(DBHandler.Car_Color, car._Color);
   values.put(DBHandler.Car_Price, car._Price);
        
   // Inserting Row
   database.insert(DBHandler.TableCar, null, values);
   database.close(); // Closing database connection
}

3.2. CRUD - Read A Car Value By ID

To Read a record from the DB, we need to create something called cursor that will handle our query and navigate between returned records using this record. In the following code, we trying to read a car with its ID and returning a set of columns specified in the new String[] of Table determinded by DBHandler.TableCar and depends on Car_ID as specified

Cursor cursor = database.query(DBHandler.TableCar, new String[] { DBHandler.Car_ID,
         DBHandler.Car_ModelID, DBHandler.Car_Name, DBHandler.Car_Description,
         DBHandler.Car_Color, DBHandler.Car_Price}, DBHandler.Car_ID + "=?",
         new String[] { String.valueOf(id) }, null, null, null, null);

What are these nulls? They represent some SQL Features like group by, having, order by

Image 14

                                                               figure 1.4.3.2 - SQL Features Supported by Android

And whole code for retrieving an item from DB is as follows

// Get Specific Car By ID
public CarModel getCar(int id) {
        Cursor cursor = database.query(DBHandler.TableCar, new String[] { DBHandler.Car_ID,
                DBHandler.Car_ModelID, DBHandler.Car_Name, DBHandler.Car_Description,
                DBHandler.Car_Color, DBHandler.Car_Price}, DBHandler.Car_ID + "=?",
                new String[] { String.valueOf(id) }, null, null, null, null);
        if (cursor != null)
            cursor.moveToFirst();
 
        CarModel Car = new CarModel(Integer.parseInt(cursor.getString(0)),
                Integer.parseInt(cursor.getString(1)), cursor.getString(2),
                cursor.getString(3), cursor.getString(4),
                Double.parseDouble(cursor.getString(5)));
        
        // return Car
        return Car;
}

3.3. CRUD - Read All Cars

It's the same as Load By ID but here we set the selection to null since we are not looking for a specific value of a column

// Get All Cars
public List<CarModel> getAllCars() {
        List<CarModel> Cars = new ArrayList<CarModel>();

        Cursor cursor = database.query(DBHandler.TableCar,
            CarTableColumns, null, null, null, null, null);

        cursor.moveToFirst();
        while (!cursor.isAfterLast()) {
          CarModel Car = new CarModel(Integer.parseInt(cursor.getString(0)),
                    Integer.parseInt(cursor.getString(1)), cursor.getString(2),
                    cursor.getString(3), cursor.getString(4),
                    Double.parseDouble(cursor.getString(5)));
          Cars.add(Car);
          cursor.moveToNext();
        }
        // make sure to close the cursor
        cursor.close();
        return Cars;
}

3.4. CRUD - Update A Car

Here we have to update columns of existing record in database, by specifying the new values of the record then update db using its ID

// Updating Car
public int updateCar(CarModel car) {
        ContentValues values = new ContentValues();
        values.put(DBHandler.Car_ModelID, car.getCarModelID());
        values.put(DBHandler.Car_Name, car.getCarName());
        values.put(DBHandler.Car_Description, car.getDescription());
        values.put(DBHandler.Car_Color, car.getColor());
        values.put(DBHandler.Car_Price, car.getPrice());
 
        // updating a row
        return database.update(DBHandler.TableCar, values, DBHandler.Car_ID + " = ?",
                new String[] { String.valueOf(car.getCarID()) });
}

3.5. CRUD - Delete A Car

It's one of the easiest query you can do in SQL. Just use delete to remove a specific record from the db

// Deleting Car
public void deleteCar(CarModel car) {
        long id = car.getCarID();
        database.delete(DBHandler.TableCar, DBHandler.Car_ID
            + " = " + id, null);
}

Now, we need to implement the above steps again for our Model class. I'll skip this part since it's the same and code is available.

4. Create User Interaction with DB

I created my 1st screen that consists of some buttons that will apply the above CRUD operations

Image 15

                               figure 1.4.3.3 - XML Layout

1. Add New Car

As we see in the following code, i created a save button and onClick we need to create an instance of our CarViewModel to call addCar function and create another object of car that will be saved with its data.

I created a car object called _Car with CarModel : 1, Name : Aveo, Description : I Love Aveo, Color : Red, Price : 100

Then another object of CarViewModel and pass our context as parameter in the constructor then call addCar function

btn_Save.setOnClickListener(new OnClickListener() {
            
   @Override
   public void onClick(View arg0) {
       // TODO Auto-generated method stub
       CarViewModel = new CarViewModel(getApplicationContext());
       CarViewModel.open();
                
       // save the new comment to the database
       CarModel _Car = new CarModel(1, "Aveo", "I Love Aveo", "Red", 100);
       CarViewModel.addCar(_Car);
                
       Toast.makeText(getApplicationContext(), "Added New Car", Toast.LENGTH_LONG).show();
   }
});

Image 16

                figure 1.4.3.4 - Insert

2. Load All Cars

Our next button is Load All Cars screen that will display all our saved cars in the database.

btn_LoadACar.setOnClickListener(new OnClickListener() {
            
    @Override
    public void onClick(View v) {
         // TODO Auto-generated method stub
         CarViewModel = new CarViewModel(getApplicationContext());
         CarViewModel.open();
                
         List<CarModel> _List;
         _List = CarViewModel.getAllCars();
                
         Toast.makeText(getApplicationContext(), _List.get(0)._CarName, Toast.LENGTH_LONG).show();
    }
});

Image 17

                figure 1.4.3.5 - Retrieve All

3. Load A Car 

It's the same steps as loading all cars but we have to provide Car_ID in order to load a specific car but it applies the same idea as the previous points. Here we use our ready function getCar(Id) to load a car with specific Car_ID and then displays its name and price

btn_LoadACar.setOnClickListener(new OnClickListener() {
            
    @Override
    public void onClick(View v) {
        // TODO Auto-generated method stub
        CarViewModel = new CarViewModel(getApplicationContext());
        CarViewModel.open();
                
        CarModel Car = CarViewModel.getCar(1);
                
         Toast.makeText(getApplicationContext(), Car._CarName + " " + Car._Price, Toast.LENGTH_LONG).show();
    }
});

Image 18

                figure 1.4.3.6 - Retrieve by ID

4. Update A Car

Coming to update method that you will need to use it alot. I decided to update the price of the Car that we just loaded in the previous point of ID = 1 and set the price to 200 instead of 100 

Image 19

                figure 1.4.3.7 - Update

5. Delete A Car 

Our last method we need to test is deleting an object from our application db. First, we need to load the object we have to delete same as loading a car using getCar(Id) then passing this object of CarModel to our function deleteCar(object Car) as below

btn_DeletCar.setOnClickListener(new OnClickListener() {
            
    @Override
    public void onClick(View v) {
        // TODO Auto-generated method stub
        CarViewModel = new CarViewModel(getApplicationContext());
        CarViewModel.open();
                
        CarModel Car = CarViewModel.getCar(1);           
        CarViewModel.deleteCar(Car);
                
        Toast.makeText(getApplicationContext(), "Deleted Car", Toast.LENGTH_LONG).show();
    }
});

You can download the entire code from: Download SQLite.zip

Web Service

1. kSOAP 2

kSOAP is one of the famous library to consume web service in android applications. It's a lightweight and efficient library and it's open source and saves alot of time to reach what you need from using web service. As well as it's easy to install in your application as we will see in the next steps.

1.1. Download kSOAP Library

Our first step we need to do is to download kSOAP Library to add it into your lib folder in our project.

kSOAP Project Page : kSOAP Page or you can download the library we will use directly from : kSOAP 2 V 3.1.1

1.2. Include kSOAP Library Into Our Project

We created a new project called kSOAP that will hold our example. First, we need to add an internet access to our application inside manifest file.

1. Open your application Manifest file and add a permission of internet access

<manifest xmlns:android="http://schemas.android.com/apk/res/android"
    package="com.example.ksoap"
    android:versionCode="1"
    android:versionName="1.0" >

    <uses-permission android:name="android.permission.INTERNET"/>

2. Now, it's time to add the kSOAP Library into our project. Right-Click on your project-> Properties

Image 20

                         figure 2.1.2.1 - Properties Windows

3. From the left bar, select Java Build Path -> Libraries

Image 21

                                                                                       figure 2.1.2.2 - Libraries

4. Choose External Jars from the right panel then navigate to the downloaded kSOAP Library that you have downloaded

Image 22

                                                                                                 figure 2.1.2.3 - Adding kSOAP Library

5. Click Ok  BUT WE ARE NOT DONE after some work and tries to run your application you will get an error saying "java.lang.NoClassDefFoundError" because there is one step left to do

6. We need to add our .jar file inside Lib Folder of our project

Image 23

figure 2.1.2.4 - Libs Folder

7. Drag and Drop your jar file inside Lib Folder and Select Copy Files

8. Now We are done of adding the library to our project.

1.3. Create a Response

To send a request using kSOAP, we need to create an HTTP request using HttpTransportSE, but before we create our HTTP request, we need to know some points.

I'll be using W3schools Web Service to retrieve data from : W3schools Web Service

1. From any service we will use, we need to extract some information about it like webservice namespace and SOAP ActionName. Open the above link-> click on service description

Image 24

                                                                     figure 2.1.3.1 - Temp Converter Website

2. You should see something like this image and you can extract the namespace and soap action names after scrolling down as in the image with the underlines parts

Image 25

                                                                    figure 2.1.3.2 - Temp Converter Service Description

3. It's time to add these variables to the project. In MainActivity, onCreate() function simply add these variables

private static final String NAMESPACE = "http://www.w3schools.com/webservices/";
private static final String URL = "http://www.w3schools.com/webservices/tempconvert.asmx?wsdl";
private static final String SOAP_ACTION = "http://www.w3schools.com/webservices/FahrenheitToCelsius";
private static final String METHOD_NAME = "FahrenheitToCelsius";

4. We need to create our request using these variables. First we have to create a SOAP Object and Assign all parameters we have to send and include the SOAP Object to OutputSOAPObject. 

String SoapResult = null;
                    
SoapObject SOAPRequest = new SoapObject(NAMESPACE, METHOD_NAME);
//Add Parameter
SOAPRequest.addProperty("Fahrenheit", "100.0");
                    
SoapSerializationEnvelope envelope = new SoapSerializationEnvelope(
                            SoapEnvelope.VER11);
envelope.setOutputSoapObject(SOAPRequest);
envelope.dotNet = true;

How did i know the parameter name? - Simply open the webservice you are willing to call and you can determine all the parameters it needs

Image 26

                   figure 2.1.3.3 - FahrenheitToCelsius Web Method Info

5. Let's call the web service using HTTP request, simply assign the SoapSerilizationEnvelope to the HTTP request and it will support all the rest, then display the result inside a TextView

HttpTransportSE ht = new HttpTransportSE(URL);
ht.call(SOAP_ACTION, envelope);
                    
// Get the SoapResult from the envelope body.
if (envelope.bodyIn instanceof SoapFault) {
      SoapResult = ((SoapFault) envelope.bodyIn).faultstring;
} else {
      SoapObject resultsRequestSOAP = (SoapObject) envelope.bodyIn;
      SoapResult = resultsRequestSOAP.getProperty(0).toString();
}
                    
final String str = SoapResult;

runOnUiThread(new Runnable() {
  public void run() {
      txt_Input.setText(str);
  }
});

6. AGAIN WE ARE NOT DONE. If we simply add the above code inside our main thread,the application will crash because we idle our main thread waiting for the responce from web service that's why we need to apply the code inside another thread inherited from main thread. To achieve this, we need to create a new thread 

Thread SOAPThread = new Thread() {
     @Override
     public void run() {
     } 
};

SOAPThread.start();

Image 27

                                                         figure 2.1.3.4 - Temp Converter Example Test

You can download the entire code from: Download kSOAP.zip

1.4. JSON Parser

What if we use a web service that returns multiple columns, not just a single value that's why we use JSON Parser to parse and loop through our json input and return all columns we need to retrieve from the json.

So, JSON Parser means extracting what we need from this string. How we can obtain that? - It's easy we just need to use JSONObject to retrieve data from by parsing the json tree.

Consider the following json input

{
"User":
   {
      "Name":"Ahmed Alaa ElDin",
      "Title":"Software Engineer",
      "Company":"Enozom Software Company",
      "Copyrights" : "CodeProject"
   }
}

and we need to extract these data, each in a separate variable 

JSONObject DataReader;
try {
   //Hold Input String "Data" inside JSONObject 
   DataReader = new JSONObject(Data);

   //Read an object inside Data that might contain multiple objects , and here is called User
   JSONObject User  = DataReader.getJSONObject("User");

   //Hold Columns inside variables as below
   String Name = User.getString("Name");
   String Title = User.getString("Title");
   String Company = User.getString("Company");
   String Copyright = User.getString("Copyrights");
   
   //Set Data on the screen
   txt_Name.setText("Name : " + Name);
   txt_Name.setText("Name : " + Name);
   txt_Title.setText("Title : " + Title);
   txt_Company.setText("Company : " + Company);
   txt_Copyrights.setText("Copyrights : " + Copyright);
} catch (JSONException e) {
            // TODO Auto-generated catch block
}

Image 28

You can download the entire code from: Download JSONParser.zip

Points of Interest

I suggest to investigate more about another web service which is called Android Restful WebService. It's another method used to fetch/save data using a Webservice.

History

1. Article Release - 10/09/2014

2. Update # 1 : Added JSON Parser - 13/09/2014

License

This article, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)