![Page 1: Android Fundamentals Mobile Application Development Selected Topics – CPIT 490 21-Sep-15](https://reader030.vdocuments.net/reader030/viewer/2022033106/56649e695503460f94b6576a/html5/thumbnails/1.jpg)
Android Fundamentals
Mobile Application Development
Selected Topics – CPIT 490
Apr 19, 2023
![Page 2: Android Fundamentals Mobile Application Development Selected Topics – CPIT 490 21-Sep-15](https://reader030.vdocuments.net/reader030/viewer/2022033106/56649e695503460f94b6576a/html5/thumbnails/2.jpg)
2
Data Storage Data Storage
Shared Preferences (a lightweight mechanism) Data Files SQLite Content Provider
Saving Data Your options (most complex apps use all)
Shared Preferences (just to store name-value pair like name, DOB, etc) Bundles Local files (to store ad-hoc data like RSS feed, note-taking, etc); External
storage (if you need to share data with other applications) Local database (SQLite) Remote database
Saving data is obviously essential
![Page 3: Android Fundamentals Mobile Application Development Selected Topics – CPIT 490 21-Sep-15](https://reader030.vdocuments.net/reader030/viewer/2022033106/56649e695503460f94b6576a/html5/thumbnails/3.jpg)
3
Saving UI State
Activity should save its user interface state each time it moves to the background Required due to OS killing processes Even if you think your app will be in the foreground all the
time, you need to do this, because of.... Phone calls Other apps The nature of mobile use
![Page 4: Android Fundamentals Mobile Application Development Selected Topics – CPIT 490 21-Sep-15](https://reader030.vdocuments.net/reader030/viewer/2022033106/56649e695503460f94b6576a/html5/thumbnails/4.jpg)
4
Shared Preferences Simple, lightweight key/value pair (or name/value pair NVP) mechanism Support primitive types: Boolean, string, float, long and integer Stored as XML in the protected application directory on main memory
(/data/data/<package name>/shared_prefs/<package name>_preferences.xml)
Shared among application components running in the same application context
//Getting Context example public class MyActivity extends Activity { public void method() { Context actContext = this; // since Activity extends Context Context appContext = getApplicationContext(); Context vwContext =
((Button)findViewById(R.id.btn_id)).getContext(); } }
![Page 5: Android Fundamentals Mobile Application Development Selected Topics – CPIT 490 21-Sep-15](https://reader030.vdocuments.net/reader030/viewer/2022033106/56649e695503460f94b6576a/html5/thumbnails/5.jpg)
5
DDMS – File Explorer http://developer.android.com/guide/developing/debugging/ddms.html (Window > Open Perspective > Other... > DDMS)
![Page 6: Android Fundamentals Mobile Application Development Selected Topics – CPIT 490 21-Sep-15](https://reader030.vdocuments.net/reader030/viewer/2022033106/56649e695503460f94b6576a/html5/thumbnails/6.jpg)
6
Creating and Sharing Prefs
public static String MY_PREFS = "<package_name>_preferences";
int mode = Activity.MODE_PRIVATE; SharedPreferences mySharedPreferences = getSharedPreferences(MY_PREFS, mode); SharedPreferences.Editor editor = mySharedPreferences.edit();
// Store new primitive types in the shared preferences object. editor.putBoolean("isTrue", true); editor.putFloat("lastFloat", 1f); editor.putInt("wholeNumber", 2); editor.putLong("aNumber", 3l); editor.putString("textEntryValue", "Not Empty"); // Commit the changes. editor.commit();
![Page 7: Android Fundamentals Mobile Application Development Selected Topics – CPIT 490 21-Sep-15](https://reader030.vdocuments.net/reader030/viewer/2022033106/56649e695503460f94b6576a/html5/thumbnails/7.jpg)
7
Retrieving Prefs
public static String MY_PREFS = "MY_PREFS"; public void loadPreferences() { // Get the stored preferences int mode = Activity.MODE_PRIVATE; SharedPreferences mySharedPreferences =
getSharedPreferences(MY_PREFS, mode);
// Retrieve the saved values. boolean isTrue = mySharedPreferences.getBoolean("isTrue", false); float lastFloat = mySharedPreferences.getFloat("lastFloat", 0f); int wholeNumber = mySharedPreferences.getInt("wholeNumber", 1); long aNumber = mySharedPreferences.getLong("aNumber", 0); String stringPreference =
mySharedPreferences.getString("textEntryValue", ""); }
![Page 8: Android Fundamentals Mobile Application Development Selected Topics – CPIT 490 21-Sep-15](https://reader030.vdocuments.net/reader030/viewer/2022033106/56649e695503460f94b6576a/html5/thumbnails/8.jpg)
8
Preference Activity System-style preference screens
Familiar Can merge settings from other apps (e.g., system settings such as
location)
3 parts Preference Screen Layout (XML) Extension of PreferenceActivity onSharedPreferenceChangeListener
![Page 9: Android Fundamentals Mobile Application Development Selected Topics – CPIT 490 21-Sep-15](https://reader030.vdocuments.net/reader030/viewer/2022033106/56649e695503460f94b6576a/html5/thumbnails/9.jpg)
9
Shared Preferences Create an xml file to indicate what to store<PreferenceScreen
xmlns:android=”http://schemas.android.com/apk/res/android”><PreferenceCategory android:title=”Category 1”> Provide the key for different preferences<CheckBoxPreference … android:key=”checkboxPref” /> Create an activity that extends the PreferenceActivity base class, and then call
the addPreferencesFromResource() method to load the XML file containing the preferences: addPreferencesFromResource(R.xml.myapppreferences);
The MODE_PRIVATE constant indicates that the preference file can only be opened by the application that created it
Use getString() method to retrieve string preferences and use putString() method to update string preferences
Change the default preference (net.learn2develop.<packagename>_preferences.xml> using PreferenceManager prefMgr =
getPreferenceManager(); prefMgr.setSharedPreferencesName(“appPreferences”);
![Page 10: Android Fundamentals Mobile Application Development Selected Topics – CPIT 490 21-Sep-15](https://reader030.vdocuments.net/reader030/viewer/2022033106/56649e695503460f94b6576a/html5/thumbnails/10.jpg)
10
Preference Activity XML <?xml version="1.0" encoding="utf-8"?> <PreferenceScreen
xmlns:android="http://schemas.android.com/apk/res/android"> <PreferenceCategory android:title="My Preference Category"/>
<CheckBoxPreference android:key="PREF_CHECK_BOX" android:title="Check Box Preference" android:summary="Check Box Preference Description" android:defaultValue="true" /> </PreferenceCategory> </PreferenceScreen>
![Page 11: Android Fundamentals Mobile Application Development Selected Topics – CPIT 490 21-Sep-15](https://reader030.vdocuments.net/reader030/viewer/2022033106/56649e695503460f94b6576a/html5/thumbnails/11.jpg)
11
Preference Activity Options
CheckBoxPreference EditTextPreference ListPreference RingtonePreference
![Page 12: Android Fundamentals Mobile Application Development Selected Topics – CPIT 490 21-Sep-15](https://reader030.vdocuments.net/reader030/viewer/2022033106/56649e695503460f94b6576a/html5/thumbnails/12.jpg)
12
Preference Activity
Public class MyPreferenceActivity extends PreferenceActivity { @Override Public void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); addPreferencesFromResource(R.xml.preferences); } } In manifest... <activity android:name=“.MyPreferenceActivity” android:label=“My Preferences”> To start...
Intent I = new Intent(this, MyPreferenceActivity.class); startActivityForResult(i, SHOW_PREFERENCES);
![Page 13: Android Fundamentals Mobile Application Development Selected Topics – CPIT 490 21-Sep-15](https://reader030.vdocuments.net/reader030/viewer/2022033106/56649e695503460f94b6576a/html5/thumbnails/13.jpg)
13
Using Prefs from Pref. Activity Recorded shared prefs are stored in Application Context. Therefore, available
to any component: Activities Services BroadcastReceiver
Context context = getApplicationContext(); SharedPreferences prefs = PreferenceManager.getDefaultSharedPreferences(context); // then Retrieve values using get<type> method
![Page 14: Android Fundamentals Mobile Application Development Selected Topics – CPIT 490 21-Sep-15](https://reader030.vdocuments.net/reader030/viewer/2022033106/56649e695503460f94b6576a/html5/thumbnails/14.jpg)
14
Prefs change listeners Run some code whenever a Shared Preference value is added, removed,
modified Useful for Activities or Services that use SP framework to set application
preferences
![Page 15: Android Fundamentals Mobile Application Development Selected Topics – CPIT 490 21-Sep-15](https://reader030.vdocuments.net/reader030/viewer/2022033106/56649e695503460f94b6576a/html5/thumbnails/15.jpg)
15
SP change listeners
public class MyActivity extends Activity implements OnSharedPreferenceChangeListener { @Override public void onCreate(Bundle SavedInstanceState) { // Register this OnSharedPreferenceChangeListener Context context = getApplicationContext(); SharedPreferences prefs = PreferenceManager.getDefaultSharedPreferences(context); prefs.registerOnSharedPreferenceChangeListener(this); }
public void onSharedPreferenceChanged(SharedPreferences prefs, String key) { // TODO Check the shared preference and key parameters // and change UI or behavior as appropriate. } }
![Page 16: Android Fundamentals Mobile Application Development Selected Topics – CPIT 490 21-Sep-15](https://reader030.vdocuments.net/reader030/viewer/2022033106/56649e695503460f94b6576a/html5/thumbnails/16.jpg)
16
Shared Preferences – Summary Lightweight key-value pair storage General framework that allows you to save and retrieve persistent key-value pairs of
primitive data types. Use it to save any primitive data: booleans, floats, ints, longs, and strings. Persist amongst user sessions getSharedPreferences() – Use this if you need multiple preferences files identified by
name where you specify with the first parameter getPreferences() – Use this if you need only one preferences file for your Activity.
Since this will be the only preferences file for your Activity, you don’t supply a name Get a SharedPreferences.Editor
Call edit() Add values with methods (put<type>()) Commit new values with commit()
Use SharedPreferences methods (get<type>()) to grab the values from your preferences Example: getBoolean(key, defaultvalue);
![Page 17: Android Fundamentals Mobile Application Development Selected Topics – CPIT 490 21-Sep-15](https://reader030.vdocuments.net/reader030/viewer/2022033106/56649e695503460f94b6576a/html5/thumbnails/17.jpg)
17
Bundles Activities offer onSaveInstanceState handler
Works like SharedPreferences Bundle parameter represents key/value map of primitive types that can be
used save the Activity’s instance values Bundle made available as a parameter passed in to the onCreate and
onRestoreInstance method handlers Bundle stores info needed to recreate UI state
![Page 18: Android Fundamentals Mobile Application Development Selected Topics – CPIT 490 21-Sep-15](https://reader030.vdocuments.net/reader030/viewer/2022033106/56649e695503460f94b6576a/html5/thumbnails/18.jpg)
18
Saving Bundle
@Override public void onSaveInstanceState(Bundle savedInstanceState) { // Save UI state changes to the savedInstanceState. // This bundle will be passed to onCreate if the process is // killed and restarted. savedInstanceState.putBoolean("MyBoolean", true); savedInstanceState.putDouble("myDouble", 1.9); savedInstanceState.putInt("MyInt", 1); savedInstanceState.putString("MyString", "Welcome back to Android"); // etc. super.onSaveInstanceState(savedInstanceState); }
![Page 19: Android Fundamentals Mobile Application Development Selected Topics – CPIT 490 21-Sep-15](https://reader030.vdocuments.net/reader030/viewer/2022033106/56649e695503460f94b6576a/html5/thumbnails/19.jpg)
19
Restoring Bundle
@Override public void onRestoreInstanceState(Bundle savedInstanceState) {
super.onRestoreInstanceState(savedInstanceState);
// Restore UI state from the savedInstanceState. // This bundle has also been passed to onCreate. boolean myBoolean = savedInstanceState.getBoolean("MyBoolean"); double myDouble = savedInstanceState.getDouble("myDouble"); int myInt = savedInstanceState.getInt("MyInt"); String myString = savedInstanceState.getString("MyString"); }
![Page 20: Android Fundamentals Mobile Application Development Selected Topics – CPIT 490 21-Sep-15](https://reader030.vdocuments.net/reader030/viewer/2022033106/56649e695503460f94b6576a/html5/thumbnails/20.jpg)
20
Saving/loading files Biggest decision: location
Local vs Remote Internal vs External
When you create a new AVD, you can emulate the existence of an SD card. Simply enter the size of the SD card that you want to emulate
Alternatively, you can simulate the presence of an SD card in the Android emulator by creating a disk image first and then attaching it to the AVD. The mksdcard.exe utility (located in the tools folder of the Android SDK) enables you to create an ISO disk image
Code is standard Java String FILE_NAME = "tempfile.tmp"; // Create a new output file stream that’s private to this application. FileOutputStream fos = openFileOutput(FILE_NAME,
Context.MODE_PRIVATE); // Open input file stream. FileInputStream fis = openFileInput(FILE_NAME);
![Page 21: Android Fundamentals Mobile Application Development Selected Topics – CPIT 490 21-Sep-15](https://reader030.vdocuments.net/reader030/viewer/2022033106/56649e695503460f94b6576a/html5/thumbnails/21.jpg)
21
Saving/loading files // MODE_WORLD_READABLE constant means that the file is
only readable FileOutputStream fOut = openFileOutput(“textfile.txt”,
MODE_WORLD_READABLE); MODE_PRIVATE (the file can only be accessed by the
application that created it), MODE_APPEND (for appending to an existing file), and MODE_WORLD_WRITEABLE (all other applications have write access to the file).
Convert a character stream into a byte stream
OutputStreamWriter osw = new OutputStreamWriter(fOut); Use write() to write to a file: osw.write(str); To ensure everything is written to the file: osw.flush(); Close the file using: osw.close();
![Page 22: Android Fundamentals Mobile Application Development Selected Topics – CPIT 490 21-Sep-15](https://reader030.vdocuments.net/reader030/viewer/2022033106/56649e695503460f94b6576a/html5/thumbnails/22.jpg)
22
Saving/loading files Read the file: FileInputStream fIn = openFileInput(“textfile.txt”); InputStreamReader isr = new InputStreamReader(fIn); To read from the file:
char[] inputBuffer = new char[100]; String s = “”; int charRead;while ((charRead = isr.read(inputBuffer))>0){ //---convert the chars to a String---String readString = String.copyValueOf(inputBuffer, 0, charRead);s += readString; inputBuffer = new char[100];}
Using DDMS (under File Explorer) in Eclipse, we could see /data/data/net.learn2develop.Files/files
To copy a file from emulator or device to computer: adb pull <source path on emulator>
To upload a file to emulator or device: adb push <filename> <destination path on emulator>
To modify file permissions: adb shell and chmod
![Page 23: Android Fundamentals Mobile Application Development Selected Topics – CPIT 490 21-Sep-15](https://reader030.vdocuments.net/reader030/viewer/2022033106/56649e695503460f94b6576a/html5/thumbnails/23.jpg)
23
Saving/Loading files Can only write in current application folder (
/data/data/<package_name>/files/<filename>) or external storage (e.g., /mnt/sdcard/<filename>)
Exception thrown otherwise For external, must be careful about availability of storage card
Behavior when docked Cards get wiped
SD Card Writing Permission (AndroidManifest.xml) <uses-permission android:name= "android.permission.WRITE_EXTERNAL_STORAGE"> </uses-permission>
![Page 24: Android Fundamentals Mobile Application Development Selected Topics – CPIT 490 21-Sep-15](https://reader030.vdocuments.net/reader030/viewer/2022033106/56649e695503460f94b6576a/html5/thumbnails/24.jpg)
24
Check SD card
private static final String ERR_SD_MISSING_MSG = “ERRSD cannot see your SD card. Please reinstall it and do not remove it."; private static final String ERR_SD_UNREADABLE_MSG = "CITY cannot read your SD (memory) card. This is probably because your phone is plugged into your computer. Please unplug it and try again."; public static String getSDCard() throws ERRSDException { if (Environment.getExternalStorageState().equals(Environment.MEDIA_REMOVED)) throw new ERRSDException(ERR_SD_MISSING_MSG); else if (!Environment.getExternalStorageState().equals(Environment.MEDIA_MOUNTED)) throw new ERRSDException(ERR_SD_UNREADABLE_MSG); File sdCard = Environment.getExternalStorageDirectory(); // “/mnt/sdcard” if (!sdCard.exists()) throw new ERRSDException(ERR_SD_MISSING_MSG); if (!sdCard.canRead()) //for writing sdCard.canWrite() throw new ERRSDException(ERR_SD_UNREADABLE_MSG); return sdCard.toString(); }
![Page 25: Android Fundamentals Mobile Application Development Selected Topics – CPIT 490 21-Sep-15](https://reader030.vdocuments.net/reader030/viewer/2022033106/56649e695503460f94b6576a/html5/thumbnails/25.jpg)
25
SD Card storage
getExternalStorageDirectory() method is used to get the full path to the external storage returns the “/sdcard” path for a real device, and “/mnt/sdcard”
for an Android emulator Don’t hardcode the path of the SD card as different
manufacturers can assign different path for the SD card
![Page 26: Android Fundamentals Mobile Application Development Selected Topics – CPIT 490 21-Sep-15](https://reader030.vdocuments.net/reader030/viewer/2022033106/56649e695503460f94b6576a/html5/thumbnails/26.jpg)
26
Static Resources You could add files to your package during design time This is done in res/raw folder Use the getResources() method (of the Activity class) to return a Resources
object, and then use its openRawResource() method to open the file contained in the res/raw folder
InputStream is = this.getResources().openRawResource(R.raw.textfile);BufferedReader br = new BufferedReader(new InputStreamReader(is));String str = null;try {while ((str = br.readLine()) != null) {Toast.makeText(getBaseContext(), str, Toast.LENGTH_SHORT).show();}is.close(); br.close();} catch (IOException e) { e.printStackTrace(); }
![Page 27: Android Fundamentals Mobile Application Development Selected Topics – CPIT 490 21-Sep-15](https://reader030.vdocuments.net/reader030/viewer/2022033106/56649e695503460f94b6576a/html5/thumbnails/27.jpg)
27
SQLite Embedded database for Android Supports 3 main data types
TEXT (like Java String), INTEGER (like Java long), REAL (like Java double)
No type checking inherent in SQLite. SQLite does not verify that the type written to each cell is of the defined type
Each DB is private to Application that created it Data is stored at:
/data/data/<package name>/databases/<db name>
Documentation on SQLITE available at: http://www.sqlite.org/sqlite.html Good GUI tool for SQLITE available at: http://sqliteadmin.orbmu2k.de/ SQL and SQLite Language Syntax at: http://www.sqlite.org/lang.html
![Page 28: Android Fundamentals Mobile Application Development Selected Topics – CPIT 490 21-Sep-15](https://reader030.vdocuments.net/reader030/viewer/2022033106/56649e695503460f94b6576a/html5/thumbnails/28.jpg)
28
Using SQLite Use a helper class called DBAdapter that creates, opens, closes, and uses a SQLite
database Create a subclass of SQLiteOpenHelper
Override at least onCreate() - where you can create tables Can also override onUpgrade() - make a modification to the tables structures
Call getWritableDatabase() to get read/write instance of SQLiteDatabase Can then call insert(), delete(), update() execSQL(String sql, [Object[] bindArgs]) – executes the SQL directly (not a
SELECT/INSERT/UPDATE/DELETE) rawQuery(String sql, String[] selectionArgs) – runs provided SQL and returns a
Cursor over result set query() – has many different parameters but returns a Cursor over result set If you want to e.g. CREATE TABLE that does not return values you can
use execSQL(), if you want a Cursor as result use rawQuery() (=SELECT statements).
If you want to execute something in database without concerning its output (e.g create/alter tables), then use execSQL, but if you are expecting some results in return against your query (e.g. select records) then use rawQuery
![Page 29: Android Fundamentals Mobile Application Development Selected Topics – CPIT 490 21-Sep-15](https://reader030.vdocuments.net/reader030/viewer/2022033106/56649e695503460f94b6576a/html5/thumbnails/29.jpg)
29
Subclass SQLiteOpenHelper
public class DatabaseHelper extends SQLiteOpenHelper { static final String dbName= "demoDB" ; static final int dbVersion= 1 ; static final String employeeTable= "Employees" ; static final String colID= "EmployeeID" ; static final String colName= "EmployeeName" ; static final String colAge= "Age" ; static final String colDept= "Dept" ; static final String deptTable= "Dept" ; static final String colDeptID= "DeptID" ; static final String colDeptName= "DeptName" ; public DatabaseHelper(Context context) { super (context, dbName, null, dbVersion); } }
![Page 30: Android Fundamentals Mobile Application Development Selected Topics – CPIT 490 21-Sep-15](https://reader030.vdocuments.net/reader030/viewer/2022033106/56649e695503460f94b6576a/html5/thumbnails/30.jpg)
30
onCreate(SQLiteDatabase db)
public void onCreate(SQLiteDatabase db) { // TODO Auto-generated method stub db.execSQL( "CREATE TABLE " + deptTable + " (" + colDeptID + " INTEGER, " + colDeptName + " TEXT);" ); db.execSQL( "CREATE TABLE " + employeeTable + " (" + colID + " INTEGER, " + colName + " TEXT, " + colAge + " INTEGER, " + colDept + " INTEGER);" ); }// SQLiteOpenHelper class is a helper class in Android to manage database creation and version management// The onCreate() method creates a new database if the required database is not present. // The onUpgrade() method is called when the database needs to be upgraded.// Using Cursor enables Android to more efficiently manage rows and columns as needed
![Page 31: Android Fundamentals Mobile Application Development Selected Topics – CPIT 490 21-Sep-15](https://reader030.vdocuments.net/reader030/viewer/2022033106/56649e695503460f94b6576a/html5/thumbnails/31.jpg)
31
Handling Records
SQLiteDatabase db=this.getWritableDatabase(); //Inserting Records ContentValues cv=new ContentValues(); cv.put(colDeptID, 1); cv.put(colDeptName, "Sales"); db.insert(deptTable, colDeptID, cv); db.execSQL( “INSERT INTO “ + deptTable + “ ( “ + colDeptID + “,” + colDeptName + “) values ( ‘2', ‘Services' ); "); //Deleting Record db.delete(deptTable, colDeptID + "=" + dept_1, null); //dept_1=“1” //Updating Record cv.put(colDeptName, “newIT” ); db.update(deptTable, cv, colDeptID + "=?", dept_2); //dept_2=“2” db.close(); http://developer.android.com/reference/android/database/sqlite/SQLiteDatabase.html
![Page 32: Android Fundamentals Mobile Application Development Selected Topics – CPIT 490 21-Sep-15](https://reader030.vdocuments.net/reader030/viewer/2022033106/56649e695503460f94b6576a/html5/thumbnails/32.jpg)
32
Querying SQL
SQL Select Syntax (see http://www.sqlite.org/lang.html)SQL-select statements are based on the following components The first two lines are mandatory, the rest is optional.
![Page 33: Android Fundamentals Mobile Application Development Selected Topics – CPIT 490 21-Sep-15](https://reader030.vdocuments.net/reader030/viewer/2022033106/56649e695503460f94b6576a/html5/thumbnails/33.jpg)
33
Querying SQLite SQLiteDatabase.query() returns a Cursor object that points to results Cursor is a iterator. Call moveToNext() to get to next element. Cursor can be examined at runtime
getCount(), getColumnCount() getColumnIndex(String name) getColumnName(int index) getInt(int index), getLong(int index), getString(int index), etc.
To upgrade the database, change the DATABASE_VERSION constant to a value higher than the previous one
![Page 34: Android Fundamentals Mobile Application Development Selected Topics – CPIT 490 21-Sep-15](https://reader030.vdocuments.net/reader030/viewer/2022033106/56649e695503460f94b6576a/html5/thumbnails/34.jpg)
34
Querying SQLite – query()
Android Simple Queries The signature of the Android’s simple query method is: http://developer.android.com/reference/android/database/sqlite/SQLiteDatabase.html
![Page 35: Android Fundamentals Mobile Application Development Selected Topics – CPIT 490 21-Sep-15](https://reader030.vdocuments.net/reader030/viewer/2022033106/56649e695503460f94b6576a/html5/thumbnails/35.jpg)
35
Querying SQLite – Example
Android Simple Queries Example Query the EmployeeTable, find the average salary of female employees supervised by 123456789. Report results by Dno. List first the highest average, and so on, do not include depts. having less than two employees.
![Page 36: Android Fundamentals Mobile Application Development Selected Topics – CPIT 490 21-Sep-15](https://reader030.vdocuments.net/reader030/viewer/2022033106/56649e695503460f94b6576a/html5/thumbnails/36.jpg)
36
Cursor – Example
![Page 37: Android Fundamentals Mobile Application Development Selected Topics – CPIT 490 21-Sep-15](https://reader030.vdocuments.net/reader030/viewer/2022033106/56649e695503460f94b6576a/html5/thumbnails/37.jpg)
37
SQLite Pre-create the database using tools like
SQLite Database Browser: http://sourceforge.net/projects/sqlitebrowser/
A filename for files added to the assets folder must be in lowercase letters
NOTE: For the SharedPreferences object (by default) and the SQLite database, the data is accessible only by the application that creates it. In other words, it is not shareable. If you need to share data among different applications, you need to create a content provider
By default, SharedPreferences are not shareable. But changing the mode to “World Readable” or “World Writable”, you could make SharedPreferences as shareable among different applications.
![Page 38: Android Fundamentals Mobile Application Development Selected Topics – CPIT 490 21-Sep-15](https://reader030.vdocuments.net/reader030/viewer/2022033106/56649e695503460f94b6576a/html5/thumbnails/38.jpg)
38
SQL Creating a table: CREATE TABLE table (col1 type, col2 type, …) Inserting into a table: INSERT INTO table (col1, col2, …) VALUES (val1,
val2,…) Updating a table: UPDATE table SET col2 = newVal2 WHERE col1 = val1 Deleting from a table: DELETE FROM table WHERE col1 = val1 Create a String array of result_columns for the columns of data you want to
retrieve String[] cols = new String[] {col1, col2, …};
Create a cursor object that retrieves the result of the query Cursor cursor = db.query(table, cols, whereClause, selectionArgs,
groupBy, having, orderBy) All are parameters for how to filter data
![Page 39: Android Fundamentals Mobile Application Development Selected Topics – CPIT 490 21-Sep-15](https://reader030.vdocuments.net/reader030/viewer/2022033106/56649e695503460f94b6576a/html5/thumbnails/39.jpg)
39
SQL query() returns a Cursor object Relevant Cursor functions getCount(): Returns the number of elements returned in Cursor moveToFirst(), moveToNext(): Moves between the rows in the Cursor getColumnIndexOrThrow(String col): Gets the index of the column for the
parameter Display the data List<Object>
Create a list of your stored objects ArrayAdapter<Object>
Bind each object to an item layout
![Page 40: Android Fundamentals Mobile Application Development Selected Topics – CPIT 490 21-Sep-15](https://reader030.vdocuments.net/reader030/viewer/2022033106/56649e695503460f94b6576a/html5/thumbnails/40.jpg)
40
Content Provider
A content provider makes a specific set of the application's data available to other applications => Share data to other apps
Any app with appropriate permission, can read and write the data.
Many native databases are available via the content providers, for example Contact Manager
Common interface for querying the data – consistent approach to add or delete or query or edit content
![Page 41: Android Fundamentals Mobile Application Development Selected Topics – CPIT 490 21-Sep-15](https://reader030.vdocuments.net/reader030/viewer/2022033106/56649e695503460f94b6576a/html5/thumbnails/41.jpg)
41
About Content Provider
Content providers expose their data as a simple table on a database model
Every record includes a numeric _ID field that uniquely identifies the record within the table.
![Page 42: Android Fundamentals Mobile Application Development Selected Topics – CPIT 490 21-Sep-15](https://reader030.vdocuments.net/reader030/viewer/2022033106/56649e695503460f94b6576a/html5/thumbnails/42.jpg)
42
About Content Provider Content provider exposes a public URI that uniquely identifies its data set:
content://<Authority>/[data_path]/[instance identifier] the URI starts with content:// scheme. Authority is a unique identifier for the content provider. Example “ contacts”. data_path specifies the kind of data requested. For example, “ people ” is used to refer
to all the contacts within “ contacts ”. there can be an instance identifier that refers to a specific data instance.
content://media/internal/images - return the list of all internal images on the device.
content://media/external/images - return the list of all the images on external storage (e.g., SD card) on the device.
content://call_log/calls - return a list of all the calls registered in the call log. content://browser/bookmarks - return a list of bookmarks stored in the browser. content://contacts/people/45 - return the single result row, the contact with ID=45.
![Page 43: Android Fundamentals Mobile Application Development Selected Topics – CPIT 490 21-Sep-15](https://reader030.vdocuments.net/reader030/viewer/2022033106/56649e695503460f94b6576a/html5/thumbnails/43.jpg)
43
Android Native ContentProvider Browser — Read or modify bookmarks, browser history, or web searches. CallLog — View or update the call history. Contacts — Retrieve, modify, or store the personal contacts. three-tier data
model of tables under a ContactsContract object: ContactsContract.Data — Contains all kinds of personal data. ContactsContract.RawContacts — Contains a set of Data objects
associated with a single account or person. ContactsContract.Contacts — Contains an aggregate of one or more
RawContacts, presumably describing the same person. MediaStore — Access audio, video, and images. Setting — View and retrieve Bluetooth settings, ring tones, and other device
preferences.
![Page 44: Android Fundamentals Mobile Application Development Selected Topics – CPIT 490 21-Sep-15](https://reader030.vdocuments.net/reader030/viewer/2022033106/56649e695503460f94b6576a/html5/thumbnails/44.jpg)
44
Android Native ContentProvider Android defines CONTENT_URI constants for all the providers that come
with the platform. ContactsContract.CommonDataKinds.Phone.CONTENT_URI
(content://com.android.contacts/data/phones) Browser.BOOKMARKS_URI
(content://browser/bookmarks) MediaStore.Video.Media.EXTERNAL_CONTENT_URI
(content://media/external/video/media) Browser.SEARCHES_URI CallLog.CONTENT_URI MediaStore.Images.Media.INTERNAL_CONTENT_URI MediaStore.Images.Media.EXTERNAL_CONTENT_URI Settings.CONTENT_URIClasses section under : http://developer.android.com/reference/android/provider/package-
summary.html (if a provider, CONTENT_URI field exist)
![Page 45: Android Fundamentals Mobile Application Development Selected Topics – CPIT 490 21-Sep-15](https://reader030.vdocuments.net/reader030/viewer/2022033106/56649e695503460f94b6576a/html5/thumbnails/45.jpg)
45
Android Native ContentProvider
![Page 46: Android Fundamentals Mobile Application Development Selected Topics – CPIT 490 21-Sep-15](https://reader030.vdocuments.net/reader030/viewer/2022033106/56649e695503460f94b6576a/html5/thumbnails/46.jpg)
46
Querying Native Content Provider You need
URI ContactsContract.Contacts.CONTENT_URI
Names of data fields (result comes in table) ContactsContract.Contacts.DISPLAY_NAME
Data types of those fields String
Remember to modify the manifest file for permissions! To retrieve the contacts: <uses-permission android:name="android.permission.READ_CONTACTS"> </uses-permission>
![Page 47: Android Fundamentals Mobile Application Development Selected Topics – CPIT 490 21-Sep-15](https://reader030.vdocuments.net/reader030/viewer/2022033106/56649e695503460f94b6576a/html5/thumbnails/47.jpg)
47
Content Provider The equivalent of
Uri allContacts = Uri.parse(“content://contacts/people/1”); Is using predefined constant together with the withAppendedId() method of
the ContentUris class:import android.content.ContentUris;...Uri allContacts = ContentUris.withAppendedId(ContactsContract.Contacts.CONTENT_URI, 1);
Remember to modify the manifest file for permissions!
![Page 48: Android Fundamentals Mobile Application Development Selected Topics – CPIT 490 21-Sep-15](https://reader030.vdocuments.net/reader030/viewer/2022033106/56649e695503460f94b6576a/html5/thumbnails/48.jpg)
48
Queryimport android.provider.Contacts.People ; import android.content.ContentUris ; import android.net.Uri ; import android.database.Cursor ; // Use the ContentUris method to produce the base URI for the contact with _ID == 23. // “content://com.android.contacts/people/23” Uri myPerson = ContentUris.withAppendedId(People.CONTENT_URI , 23); // Alternatively, use the Uri method to produce the base URI. // It takes a string rather than an integer. // “content://com.android.contacts/people/23” Uri myPerson = Uri.withAppendedPath(People.CONTENT_URI , "23"); // Then query for this specific record: Cursor cur = managedQuery(myPerson, null, null, null, null); // second parameter of managedQuery (third in CursorLoader class) is called as projectection. It indicates how many columns are returned by the query// third and fourth parameters (fourth and fifth in CursorLoader class) are for filtering// last parameter is for sortingFor more information on URI handling functions: http://developer.android.com/reference/android/net/Uri.html
![Page 49: Android Fundamentals Mobile Application Development Selected Topics – CPIT 490 21-Sep-15](https://reader030.vdocuments.net/reader030/viewer/2022033106/56649e695503460f94b6576a/html5/thumbnails/49.jpg)
49
Query
import android.provider.Contacts.People; import android.database.Cursor; // Form an array specifying which columns to return. String [] projection = new String [] {People._ID, People._COUNT, People.NAME, People.NUMBER}; // Get the base URI for the People table in the Contacts content provider. Uri contacts = People.CONTENT_URI; // Make the query. // managedQuery is deprecatedCursor managedCursor = managedQuery(contacts, projection, // Which columns to return null, // Which rows to return (all rows) null, // Selection arguments (none) // Put the results in ascending order by name People.NAME + "ASC");
![Page 50: Android Fundamentals Mobile Application Development Selected Topics – CPIT 490 21-Sep-15](https://reader030.vdocuments.net/reader030/viewer/2022033106/56649e695503460f94b6576a/html5/thumbnails/50.jpg)
50
Query Instead of managedQuery() use Content Resolver Content Resolver
getContentResolver().query( ) getContentResolver().insert( ) getContentResolver().update( ) getContentResolver().delete( )
Cursor cur = managedQuery( ) is equivalent to Cursor cur = getContentResolver().query( );
startManagingCursor(cur); Starting HoneyComb(API level 11)
CursorLoader cl = new CursorLoader(this, );
Cursor cur = cl.loadInBackground() The CursorLoader class (only available beginning with Android API level 11
and later) performs the cursor query on a background thread and hence does not block the application UI
![Page 51: Android Fundamentals Mobile Application Development Selected Topics – CPIT 490 21-Sep-15](https://reader030.vdocuments.net/reader030/viewer/2022033106/56649e695503460f94b6576a/html5/thumbnails/51.jpg)
51
Insert/Update/Delete
private void insertRecords(String name, String phoneNo) { ContentValues values = new ContentValues(); values.put(People.NAME, name); Uri uri = getContentResolver().insert(People.CONTENT_URI, values); }
private void updateRecord(int recNo, String name) { //appending recNo, record to be updated Uri uri = ContentUris.withAppendedId(People.CONTENT_URI, recNo); ContentValues values = new ContentValues(); values.put(People.NAME, name); getContentResolver().update(uri, values, null, null);
} private void deleteRecords(){
Uri uri = People.CONTENT_URI;getContentResolver().delete(uri, null, null);}
The SimpleCursorAdapter object maps a cursor to TextViews (or ImageViews) defined in your XML file (main.xml).
![Page 52: Android Fundamentals Mobile Application Development Selected Topics – CPIT 490 21-Sep-15](https://reader030.vdocuments.net/reader030/viewer/2022033106/56649e695503460f94b6576a/html5/thumbnails/52.jpg)
52
Content Provider
SimpleCursorAdapter constructor has an additional argument from Honeycomb and later//---Honeycomb and later---adapter = new SimpleCursorAdapter(this, R.layout.main, c, columns, views, CursorAdapter.FLAG_REGISTER_CONTENT_OBSERVER);
In AndroidManifest.xml, appropriate permission to access the Contacts of the mobile is required
<uses-permission android:name="android.permission.READ_CONTACTS"/>
![Page 53: Android Fundamentals Mobile Application Development Selected Topics – CPIT 490 21-Sep-15](https://reader030.vdocuments.net/reader030/viewer/2022033106/56649e695503460f94b6576a/html5/thumbnails/53.jpg)
53
Implementing your own Content Provider
Set up a system for storing the data (storage can be on a file or database or using a webservice)
e.g., SQLite using SQLiteOpenHelper; you could refer to the database creation and update code to do similar things here
Extend ContentProvider class to provide access: query() —Allows third-party applications to retrieve content. insert() —Allows third-party applications to insert content. update() —Allows third-party applications to update content. delete() —Allows third-party applications to delete content. getType() —Allows third-party applications to read each of URI
structures supported. onCreate() —Creates a database instance to help retrieve the content.
Declare the Content Provider in manifest
![Page 54: Android Fundamentals Mobile Application Development Selected Topics – CPIT 490 21-Sep-15](https://reader030.vdocuments.net/reader030/viewer/2022033106/56649e695503460f94b6576a/html5/thumbnails/54.jpg)
54
Extend Content Provider
public class MyContentProvider extends ContentProvider { public static final String AUTHORITY = "edu.odu.phonenumber"; public static final Uri CONTENT_URI = Uri.parse("content://"+ AUTHORITY + "/phones"); private MySQLDatabase mDB; private static final int PHONES = 1; private static final int PHONES_ID = 2; private static final UriMatcher uriMatcher; static{ uriMatcher = new UriMatcher(UriMatcher.NO_MATCH); uriMatcher.addURI(AUTHORITY, "phones", PHONES); uriMatcher.addURI(AUTHORITY, "phones/#", PHONES_ID); } public boolean onCreate() { mDB = new MySQLDatabase(getContext()); return true; } }
![Page 55: Android Fundamentals Mobile Application Development Selected Topics – CPIT 490 21-Sep-15](https://reader030.vdocuments.net/reader030/viewer/2022033106/56649e695503460f94b6576a/html5/thumbnails/55.jpg)
55
Extend Content Providerpublic class MyContentProvider extends ContentProvider { public Cursor query(Uri uri, String[] projection, String selection, String[] selectionArgs, String sortOrder) { Cursor c=null; SQLiteDatabase db = mDB.getWritableDatabase(); switch (uriMatcher.match(uri)) { case PHONES: //get all phones records ... break; case PHONES_ID: //get a particular phone record break; } } public String getType(Uri uri) {...} public int delete(Uri uri, String selection, String[] selectionArgs) {...} public Uri insert(Uri uri, ContentValues values) {...} public int update(Uri uri, ContentValues values, String selection, String[] selectionArgs) {...} } For more information on URI handling functions: http://developer.android.com/reference/android/net/Uri.html
![Page 56: Android Fundamentals Mobile Application Development Selected Topics – CPIT 490 21-Sep-15](https://reader030.vdocuments.net/reader030/viewer/2022033106/56649e695503460f94b6576a/html5/thumbnails/56.jpg)
56
Extend Content Provider//---add a book to the Content Provider ---ContentValues values = new ContentValues();values.put(BooksProvider.TITLE, ((EditText) findViewById(R.id.txtTitle)).getText().toString());Uri uri = getContentResolver().insert(BooksProvider.CONTENT_URI, values);
// update a bookContentValues editedValues = new ContentValues();editedValues.put(BooksProvider.TITLE, “Android Tips and Tricks”);getContentResolver().update(Uri.parse(“content://net.learn2develop.provider.Books/books/2”),editedValues, null, null); // Based on book ID
//---delete a title based on book ID---getContentResolver().delete(Uri.parse(“content://net.learn2develop.provider.Books/books/2”),null, null);
//---delete all titles---getContentResolver().delete(Uri.parse(“content://net.learn2develop.provider.Books/books”), null, null);
![Page 57: Android Fundamentals Mobile Application Development Selected Topics – CPIT 490 21-Sep-15](https://reader030.vdocuments.net/reader030/viewer/2022033106/56649e695503460f94b6576a/html5/thumbnails/57.jpg)
57
Manifest file update
<application android:icon="@drawable/icon" android:label="@string/app_name"> <provider android:name=".MyContentProvider" android:authorities=" edu.odu.phonenumber"></provider> </application>
![Page 58: Android Fundamentals Mobile Application Development Selected Topics – CPIT 490 21-Sep-15](https://reader030.vdocuments.net/reader030/viewer/2022033106/56649e695503460f94b6576a/html5/thumbnails/58.jpg)
58
Recommendations to try
(Menus from previous class) p235 Creating the Menu Helper Methods; p238: Displaying an Option Menu p240: Displaying a Context Menu
Shared Preferences p252: Saving Data Using the SharedPreferences Object p259: Retrieving and Modifying Preferences
p263: Saving Data to Internal Storage
Database p274: Creating the Database Helper Class; p279: Adding Contacts to a Table p280: Retrieving All Contacts from a Table; p281: Retrieving a Contact from a Table; p282: Updating a Contact in a Table p283: Deleting a Contact from a Table
Content Provider p295: Using the Contacts Content Provider p305: Creating Your Own Content Provider
![Page 59: Android Fundamentals Mobile Application Development Selected Topics – CPIT 490 21-Sep-15](https://reader030.vdocuments.net/reader030/viewer/2022033106/56649e695503460f94b6576a/html5/thumbnails/59.jpg)
59
References
App Development for Smart Devices http://www.cs.odu.edu/~cs495/