LAB 7 [Shared Preferences and SQLite Database]

Main Points
==================================================================
Shared Preferences 

Write value to SharedPreferences 
SharedPreferences myPrefs = getSharedPreferences("PREF_COUNT",0);
      SharedPreferences.Editor myEditor = myPrefs.edit();
      myEditor.putInt("COUNT", count);
      myEditor.commit();

Read value from SharedPreferences 
SharedPreferences myPrefs = getSharedPreferences("PREF_COUNT",0);
       SharedPreferences.Editor myEditor = myPrefs.edit();
       int count = myPrefs.getInt("COUNT",0);


SQLite Database

CreateDatabase and create table statement
 SQLiteDatabase db;

   //#2 Place Create SQLite database code below
     try {
      db = SQLiteDatabase.openOrCreateDatabase("sdcard/mdb.db", null);
      db.beginTransaction();
      db.execSQL("create table if not exists tData (recID integer PRIMARY KEY autoincrement, pname text, score integer);");
      db.setTransactionSuccessful();
      db.endTransaction();
     }
      catch (Exception e) {
     Toast.makeText(DataStorage.this, e.getMessage(),Toast.LENGTH_LONG).show();  }



SQL insert statement
  try {
       db.beginTransaction();
       db.execSQL("insert into tData(pname,score) values('"+name+"','"+score+"');");
       db.setTransactionSuccessful();
       db.endTransaction();
       et.setText("");//clear editText
       score=100; //reset score to initial value of 100
         }
        catch (Exception e) {
   Toast.makeText(DataStorage.this, e.getMessage(),Toast.LENGTH_LONG).show();
             }  


SQL select statement

Cursor c1 = db.rawQuery("select * from tData", null);
   String s1, s2, sc="";
   while(c1.moveToNext())
   {
    s1=c1.getString(1);
    s2=c1.getString(2);
    sc+=s1+"\t"+s2+"\n";
   }

 tvDisplay.setText("Count from Preferences: ["+count+"]\nScoreboard\n"+sc);



================================================================== LAB 7: Mobile Device Application [Shared Preferences and SQLite Database]


Storing to Shared Preferences and SQLite Database
1.    Create a new Android Project called DataStorage with package mdad.lab7 and Activity name: DataStorage.

2.    Copy/replace activity_data_storage.xml file with the file downloaded from OLIVE.







3.    For external SD card file input/output, you need to add permissions in the AndroidManifest.xml  { Refer to Lab 6 Step 6 }
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />


4.    Copy and replace the DataStorage.java file with the one downloaded from OLIVE.


  
5.    In the DataStorage class, complete the missing codes after each of the comment headers:
//#1 Place btnDecCount (Decrease Count) code below
btnDecCount
= (Button)findViewById(R.id.btnDecCount);
btnDecCount.setOnClickListener(new View.OnClickListener(){
       public void onClick(View v){
       SharedPreferences myPrefs = getSharedPreferences("PREF_COUNT",0);
       SharedPreferences.Editor myEditor = myPrefs.edit();
       int count = myPrefs.getInt("COUNT",0);
       --count;
       DataStorage.this.btnDecCount.setText("Decrease Count ["+count+"]");
       myEditor.putInt("COUNT", count);

       myEditor.commit();
          } });




6.    Create SQLite database and database table (continue inside onCreate method):
//#2 Place Create SQLite database code below
try {
   db = SQLiteDatabase.openOrCreateDatabase("sdcard/mdb.db", null);
   db.beginTransaction();
db.execSQL("create table if not exists tData (recID integer PRIMARY KEY autoincrement, pname text, score integer);");
   db.setTransactionSuccessful();
   db.endTransaction();
}
   catch (Exception e) {
Toast.makeText(DataStorage.this, e.getMessage(),Toast.LENGTH_LONG).show();     }
    rnum=(int)(Math.random()*10); //random number from 1 to 10

 Log.d("rnum","rnum is "+rnum);




7.    Add the event handling for button btnPlay for the SQLITEDB tab (inside onCreate method):
//#3 Place btnPlay code below              
btnPlay.setOnClickListener(new View.OnClickListener() {
public void onClick(View arg0) {
       num = Integer.parseInt(et.getText().toString());
       if(num==rnum)
              {      et.setText("");
                     et.setHint("Bravo! "+ score  +"pts Enter Your Name");                              et.setInputType(InputType.TYPE_CLASS_TEXT) ;
                     btnEnterName.setEnabled(true); //Enable enter name btn
                     btnPlay.setEnabled(false);//Disable play btn
              }else{
et.setText("");
                     et.setHint("Try Again. dun give up.");
                     score-=10; //reduce score by 10 points
                     if(score==0) score=10;//lowest score is 10
                   }

 }               });



8.    Add the event handling for button btnEnterName for the SQLITEDB tab (inside onCreate method):
//#4 Place btnEnterName code below
    btnEnterName= (Button) findViewById(R.id.btnEnterName);
    btnEnterName.setOnClickListener(new View.OnClickListener() {                        
              public void onClick(View arg0) {
                     String name = et.getText().toString();                          
                     et.setText("");et.setHint("Guess the next number");
                     et.setInputType(InputType.TYPE_CLASS_NUMBER) ;
                     btnEnterName.setEnabled(false); //Disable enter name btn
                     btnPlay.setEnabled(true);//Enable play btn
                     rnum=(int)(Math.random()*10); //random number from 1 to 10
Log.d("rnum","rnum is "+rnum);
                     try {
                 db.beginTransaction();
       db.execSQL("insert into tData(pname,score) values('"+name+"','"+score+"');");
                 db.setTransactionSuccessful();
                 db.endTransaction();
                 et.setText("");//clear editText
                   }
                     catch (Exception e) {
       Toast.makeText(DataStorage.this, e.getMessage(),Toast.LENGTH_LONG).show();
                                           }          

                     }  });


9.    Test run the application for SQLITEDB tab.

You are expected to see the program stopped as shown below.




Look at the Logcat, it showed that there is a NullPointerException occurred at line 110 of DataStorage.java
    btnPlay.setOnClickListener(new View.OnClickListener() { //LINE 110
NullPointerException occurred when it returned a Null object
This is a very common mistake encountered by many students.
 Button  btnPlay  was declared but was NOT Instantiated (Created)          
public class DataStorage extends Activity {
       Button btnIncCount, btnDecCount, btnPlay, btnEnterName, btn5;
       SQLiteDatabase db;
    TextView tv;
    EditText et; //et is declared but not created yet so et is Null
       int num, rnum, score=100;
       protected void onCreate(Bundle savedInstanceState) {
              super.onCreate(savedInstanceState);
              setContentView(R.layout.activity_data_storage);

           et = (EditText) findViewById(R.id.etResult);
           btnEnterName = (Button) findViewById(R.id.btnEnterName);

        

Solution: Add one more line for to instantiate btnPlay  ,  as shown below:
protected void onCreate(Bundle savedInstanceState) {
              super.onCreate(savedInstanceState);
              setContentView(R.layout.activity_data_storage);

           et = (EditText) findViewById(R.id.etResult);
           btnEnterName = (Button) findViewById(R.id.btnEnterName);
    btnPlay = (Button) findViewById(R.id.btnEnterName);


10. Run the app and test the SHAREDPREF tab buttons.
Pressing each button will increase or
decrease the count value. Close and open the App. The last number is still saved in the sharedpreferenced value.


11. Run the app and test the SQLiteDB Tab






Mobile Device Application (Part 2)
Objective: Persistent Data Storage in Android mobile devices


Modify DataStorage program so that when the last button, btnShow, is pressed, the count value stored in Shared Preferences and the names & scores in SQLite Database must be read again and shown in the TextView of the DISPLAY tab as shown.



Fill in the blanks for marking

Declare a Button btnShow and TextView tvDisplay; as class variable

Then type these lines inside onCreate method of DataStorage.java


//In onCreate() method:

tvDisplay = (TextView)findViewById(R.id.tvDisplay);
btnShow = (Button) findViewById(R.id.btnShow);
btnShow.setOnClickListener(
              new View.OnClickListener() {
              public void onClick(View arg0) {
              try {
              SharedPreferences myPrefs = getSharedPreferences(_______________,0);

              int count = myPrefs.getInt("____________",0);

              Cursor c1 = db.rawQuery("_______________________", null);
                     String s1, s2, sc="";
                     while(c1.moveToNext())
                     {
                           s1=c1.getString(______________);
                           s2=c1.getString(______________);
                           sc+=s1+"\t"+s2+"\n";
                     }
       tvDisplay.setText("Count from Preferences: ["+count+"]\nScoreboard\n"+sc);

                     }
              catch (Exception e) {
       Toast.makeText(DataStorage.this, e.getMessage(), Toast.LENGTH_LONG).show();
                                   }
                     }
              });

                 




Lab7 Solution



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

    <uses-sdk
        android:minSdkVersion="18"
        android:targetSdkVersion="21" />
    <uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE"/>

    <application
        android:allowBackup="true"
        android:icon="@drawable/ic_launcher"
        android:label="@string/app_name"
        android:theme="@style/AppTheme" >
        <activity
            android:name="mdad.lab7.DataStorage"
            android:label="@string/app_name" >
            <intent-filter>
                <action android:name="android.intent.action.MAIN" />

                <category android:name="android.intent.category.LAUNCHER" />
            </intent-filter>
        </activity>
    </application>

</manifest>



activity_data_storage.xml
<TabHost xmlns:android="http://schemas.android.com/apk/res/android"
 android:id="@+id/DStabhost" android:layout_width="match_parent"
 android:layout_height="match_parent">
 <TabWidget android:id="@android:id/tabs"
  android:layout_width="match_parent" android:layout_height="60dp" />
 <FrameLayout android:id="@android:id/tabcontent"
  android:layout_width="match_parent" android:layout_height="wrap_content" android:paddingTop="60dp">
  <LinearLayout android:id="@+id/content1"
   android:orientation="vertical" android:layout_width="match_parent"
   android:layout_height="match_parent">
  
  <Button
      android:id="@+id/btnIncCount"
      android:layout_width="wrap_content"
      android:layout_height="wrap_content"
      android:text="Increase Count" >
</Button>

<Button
    android:id="@+id/btnDecCount"
    android:layout_width="wrap_content"
    android:layout_height="wrap_content"
    android:text="Decrease Count" >
</Button>
</LinearLayout>
  <LinearLayout android:id="@+id/content2"
   android:orientation="vertical" android:layout_width="match_parent"
   android:layout_height="match_parent">
<TextView android:id="@+id/etIntroTab2" android:layout_width="wrap_content" android:layout_height="wrap_content" android:text="Enter a number from 1 to 10 "></TextView>

   <EditText
       android:id="@+id/etResult"
       android:layout_width="match_parent"
       android:layout_height="wrap_content" >

            <requestFocus />
        </EditText>
      
  <Button
      android:id="@+id/btnPlay"
      android:layout_width="wrap_content"
      android:layout_height="wrap_content"
      android:text="Play " >
</Button>

<Button
    android:id="@+id/btnEnterName"
    android:layout_width="wrap_content"
    android:layout_height="wrap_content"
    android:text="Enter name " >
</Button>
</LinearLayout>

  <LinearLayout android:id="@+id/content3"
   android:orientation="vertical" android:layout_width="match_parent"
   android:layout_height="match_parent">

   <TextView
       android:id="@+id/etIntroTab3"
       android:layout_width="wrap_content"
       android:layout_height="wrap_content"
       android:text="Read data from SharedPreferences and SQLite" >
</TextView>
   <Button
       android:id="@+id/btnShow"
       android:layout_width="wrap_content"
       android:layout_height="wrap_content"
       android:text="Show " >
</Button>

<TextView
    android:id="@+id/tvDisplay"
    android:layout_width="wrap_content"
    android:layout_height="wrap_content"
    android:inputType="textMultiLine" >
</TextView>
</LinearLayout>


 </FrameLayout>
</TabHost>


DataStorage.java

package mdad.lab7;

import android.os.Bundle;
import android.app.Activity;
import android.content.SharedPreferences;
import android.database.Cursor;
import android.database.sqlite.SQLiteDatabase;
import android.text.InputType;
import android.util.Log;
import android.view.View;
import android.widget.Button;
import android.widget.EditText;
import android.widget.TabHost;
import android.widget.TabHost.TabSpec;
import android.widget.TextView;
import android.widget.Toast;

public class DataStorage extends Activity {
 Button btnIncCount, btnDecCount, btnPlay, btnEnterName, btnShow;
 SQLiteDatabase db;
 TextView tvDisplay;
    EditText et; //et is declared but not created yet so et is Null
 int num, rnum, score=100;
 protected void onCreate(Bundle savedInstanceState) {
  super.onCreate(savedInstanceState);
  setContentView(R.layout.activity_data_storage);

     et = (EditText) findViewById(R.id.etResult);
  btnEnterName = (Button) findViewById(R.id.btnEnterName);
  btnPlay = (Button) findViewById(R.id.btnPlay);
  tvDisplay = (TextView)findViewById(R.id.tvDisplay);
  //Initial conditions
     et.setInputType(InputType.TYPE_CLASS_NUMBER) ;
     btnEnterName.setEnabled(false);

  TabHost tabs =(TabHost) this.findViewById(R.id.DStabhost);
  tabs.setup();

  TabSpec ts1 = tabs.newTabSpec("SharedPreferences");
  ts1.setIndicator("SharedPref");
  ts1.setContent(R.id.content1);
  tabs.addTab(ts1);

  TabSpec ts2 = tabs.newTabSpec("SQLiteDatabase");
  ts2.setIndicator("SQLiteDB");
  ts2.setContent(R.id.content2);
  tabs.addTab(ts2);

  TabSpec ts3 = tabs.newTabSpec("DisplayAll");
  ts3.setIndicator("Display");
  ts3.setContent(R.id.content3);
  tabs.addTab(ts3);

  
  

tvDisplay = (TextView)findViewById(R.id.tvDisplay);
btnShow = (Button) findViewById(R.id.btnShow);
btnShow.setOnClickListener(
  new View.OnClickListener() {
  public void onClick(View arg0) {
  try {
  SharedPreferences myPrefs = getSharedPreferences("PREF_COUNT",0);
  int count = myPrefs.getInt("COUNT",0);

  Cursor c1 = db.rawQuery("select * from tData", null);
   String s1, s2, sc="";
   while(c1.moveToNext())
   {
    s1=c1.getString(1);
    s2=c1.getString(2);
    sc+=s1+"\t"+s2+"\n";
   }
 tvDisplay.setText("Count from Preferences: ["+count+"]\nScoreboard\n"+sc);

   }
  catch (Exception e) {
 Toast.makeText(DataStorage.this, e.getMessage(), Toast.LENGTH_LONG).show();
            }
   }
  });
     

  
  //btnIncCount (Increase Count)  code below
  btnIncCount = (Button)findViewById(R.id.btnIncCount);
     btnIncCount.setOnClickListener(new View.OnClickListener(){
     public void onClick(View v){
     SharedPreferences myPrefs = getSharedPreferences("PREF_COUNT",0);
   SharedPreferences.Editor myEditor = myPrefs.edit();
   int count = myPrefs.getInt("COUNT",0);
           ++count;
   DataStorage.this.btnIncCount.setText("Increase Count ["+count+"]");
    myEditor.putInt("COUNT", count);
    myEditor.commit();
                }
        });

   //#1 Place btnDecCount (Decrease Count) code below 
     btnDecCount = (Button)findViewById(R.id.btnDecCount);
     btnDecCount.setOnClickListener(new View.OnClickListener(){
      public void onClick(View v){
      SharedPreferences myPrefs = getSharedPreferences("PREF_COUNT",0);
      SharedPreferences.Editor myEditor = myPrefs.edit();
      int count = myPrefs.getInt("COUNT",0);
      --count;
      DataStorage.this.btnDecCount.setText("Decrease Count ["+count+"]");
      myEditor.putInt("COUNT", count);
      myEditor.commit();
           } }); 


       
       
    
       
   //#2 Place Create SQLite database code below
     try {
      db = SQLiteDatabase.openOrCreateDatabase("sdcard/mdb.db", null);
      db.beginTransaction();
      db.execSQL("create table if not exists tData (recID integer PRIMARY KEY autoincrement, pname text, score integer);");
      db.setTransactionSuccessful();
      db.endTransaction();
     }
      catch (Exception e) {
     Toast.makeText(DataStorage.this, e.getMessage(),Toast.LENGTH_LONG).show();  }
         rnum=(int)(Math.random()*10); //random number from 1 to 10
         Log.d("rnum","rnum is "+rnum);

 
       
       
    //#3 Place btnPlay code below     
      btnPlay.setOnClickListener(new View.OnClickListener() {
      public void onClick(View arg0) {
       num = Integer.parseInt(et.getText().toString());
       if(num==rnum)
        { 
         et.setText("");
         et.setHint("Bravo! "+ score  +"pts Enter Your Name");
         et.setInputType(InputType.TYPE_CLASS_TEXT) ;
         btnEnterName.setEnabled(true); //Enable enter name btn 
         btnPlay.setEnabled(false);//Disable play btn 
        }else{
      et.setText("");
         et.setHint("Try Again. dun give up.");
          Log.d("rnum","rnum is "+rnum);
          score-=10; //reduce score by 10 points
         if(score==0) score=10;//lowest score is 10
             }
           }
           });


     
    //#4 Place btnEnterName code below
      btnEnterName = (Button) findViewById(R.id.btnEnterName);
      btnEnterName.setOnClickListener(new View.OnClickListener() {    
    public void onClick(View arg0) {
       String name = et.getText().toString();
       
       et.setText("");et.setHint("Guess the next number");
       et.setInputType(InputType.TYPE_CLASS_NUMBER) ;
       btnEnterName.setEnabled(false); //Disable enter name btn
       btnPlay.setEnabled(true);//Enable play btn 
       rnum=(int)(Math.random()*10); //random number from 1 to 10
       Log.d("rnum","rnum is "+rnum);
       
        try {
       db.beginTransaction();
       db.execSQL("insert into tData(pname,score) values('"+name+"','"+score+"');");
       db.setTransactionSuccessful();
       db.endTransaction();
       et.setText("");//clear editText
       score=100; //reset score to initial value of 100
         }
        catch (Exception e) {
   Toast.makeText(DataStorage.this, e.getMessage(),Toast.LENGTH_LONG).show();
             }  
        }  });

 


 } //end of onCreate method
}// end of DataStorage class