the android file system onboard: linux architecture user privileges – initially quite limited;...

61
The Android File System Onboard: Linux Architecture User privileges Initially quite limited; some directories hidden Rooting gives users super user access o Procedure is different for different devices o Destroying the operation of the device: bricking Onboard data: Applications have their reserved storage areas (sandbox) External data SD card or USB connection Public shared: /mnt/sdcard/ Writing to external storage has no security protection

Post on 20-Jan-2016

229 views

Category:

Documents


0 download

TRANSCRIPT

Page 1: The Android File System Onboard: Linux Architecture User privileges – Initially quite limited; some directories hidden – Rooting gives users super user

The Android File System• Onboard: Linux Architecture• User privileges

– Initially quite limited; some directories hidden– Rooting gives users super user access

o Procedure is different for different deviceso Destroying the operation of the device: bricking

• Onboard data: Applications have their reserved storage areas (sandbox)

• External data– SD card or USB connection– Public shared: /mnt/sdcard/– Writing to external storage has no security protection

Page 2: The Android File System Onboard: Linux Architecture User privileges – Initially quite limited; some directories hidden – Rooting gives users super user

Managing Data (Alternatives)• Application Direct Access: Read only from res/raw or assets directories• Web-based: Interact through web-URLs to access cloud-based data• Direct File I/O: Read/write files onboard or on SD cards

– Use Standard Java stream and Random Access File classes– Restriction: Onboard file I/O restricted to application sandbox– Restriction: SD card writes requires access permission

• Preferences: Key/Value pairs of data• Database Tables: Use the built-in SQL-Lite database facility• Increase functionality:

– Content Providers: expose data to other applications– Services: background processes that run detached from any view

Page 3: The Android File System Onboard: Linux Architecture User privileges – Initially quite limited; some directories hidden – Rooting gives users super user

Application Direct Access• Static application files

– Custom codecs that are not widely supported– XML-based configuration data

• Store either in res/raw or in assets– res/raw enables creating sub-directories for specific device configurations– Files stored either in res/raw or in assets are not pre-compiled by Android– Files stored directly in the application are read-only and cannot be modified– Access using standard Java I/O operations

InputStream is = app.getResources().openRawResource(R.raw.foo); in = BufferedReader in = new BufferedReader(new InputStreamReader(is)));

InputStream rawRes = context.getAssets().open(“foo.bar"); Reader r = new BufferedReader(new InputStreamReader(rawRes, "UTF8"));

Note: Use lower case alphanumerics to name files in res/raw

Page 4: The Android File System Onboard: Linux Architecture User privileges – Initially quite limited; some directories hidden – Rooting gives users super user

Downloading Files

• Downloading quickly degrades battery life• Solutions

– Pre-fetch: A single large download has less impact than multiple smaller downloads

– Reuse existing connections rather than reestablishing them

– Schedule regular downloads at the longest intervals that are possible

– Bundle non-time sensitive requests together

Page 5: The Android File System Onboard: Linux Architecture User privileges – Initially quite limited; some directories hidden – Rooting gives users super user

Download XML from Server

String myFeed = getString(R.string.my_feed); // HTTP Web addresstry { URL url = new URL(myFeed); // Create a new HTTP URL connection

URLConnection connection = url.openConnection(); HttpURLConnection httpConnection = (HttpURLConnection)connection;

int responseCode = httpConnection.getResponseCode(); if (responseCode == HttpURLConnection.HTTP_OK) { InputStream in = httpConnection.getInputStream();

processStream(in); // Use standard Java DOM parsing classes}

} catch (MalformedURLException e) { Log.d(TAG, "Malformed URL", e); }

catch (IOException e) { Log.d(TAG, "IO Exception.", e); }

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

Page 6: The Android File System Onboard: Linux Architecture User privileges – Initially quite limited; some directories hidden – Rooting gives users super user

Download Using Download ManagerDownloadManager m= (DownloadManager)getSystemService(Context.DOWNLOAD_SERVICE); long myReference = m.enqueue(new Request(Uri.parse(R.string.webLoc))); BroadcastReceiver receiver = new BroadcastReceiver() { @Override public void onReceive(Context context, Intent intent)

{ long reference = intent.getLongExtra(DownloadManager.EXTRA_DOWNLOAD_ID, -1); if (myReference == reference)

{ Query query = new Query(); Cursor cursor = downloadManager.query(query.setFilterById(reference)); if (cursor.moveToFirst()) { int fileX = cursor.getColumnIndex(DownloadManager.COLUMN_LOCAL_FILENAME);

int uriX = cursor.getColumnIndex(DownloadManager.COLUMN_LOCAL_URI); String fileName = cursor.getString(fileX), fileUri = cursor.getString(uriX);

// TODO Do something with the file. } cursor.close();

} } }; registerReceiver(receiver,

new IntentFilter(DownloadManager.ACTION_DOWNLOAD_COMPLETE) );

Note: The cursor object contains information about downloaded files

Page 7: The Android File System Onboard: Linux Architecture User privileges – Initially quite limited; some directories hidden – Rooting gives users super user

Listen for Downloaded Files<receiver android:name=".DownloadReceiver" android:exported="true" android:icon="@drawable/download_icon" > <intent-filter> <action android:name="android.intent.action.DOWNLOAD_COMPLETE"/> </intent-filter></receiver>

IntentFilter f = new IntentFilter(DownloadManager.ACTION_DOWNLOAD_COMPLETE));registerReceiver(receiver, f); }BroadcastReceiver receiver = new BroadcastReceiver() { @Override public void onReceive(Context context, Intent intent)

{ String id = DownloadManager.EXTRA_DOWNLOAD_ID; long[] references = intent.getLongArrayExtra(id); // Array of

downloaded file idsfor (long reference : references) { String mime = getMimeTypeForDownloadedFile (reference);

{ // Handle files that this activity recognizes. } }}} ;

Page 8: The Android File System Onboard: Linux Architecture User privileges – Initially quite limited; some directories hidden – Rooting gives users super user

Specifying Download Locations

• Default Location: A shared download cache with system generated file names

• Overriding the download location requires:<uses-permission android:name = "android.permission.WRITE_EXTERNAL_STORAGE" />

• To designate an arbitrary path in external storageRequest request = new Request(uri);

request.setDestinationUri(Uri.fromFile(f));• To designate a standard external download folder for the application

request.setDestinationInExternalFilesDir(this, Environment.DIRECTORY_DOWNLOADS, fileName);

• To designate location which shares with music playersrequest.setDistinationInExternalPublicDir

(Environment.DIRECTORY_MUSIC, fileName);

Note: We cannot download to internal storage using DownloadManager

Page 9: The Android File System Onboard: Linux Architecture User privileges – Initially quite limited; some directories hidden – Rooting gives users super user

SD Card File IO• SD Card path: getExternalStorageDirectory()• How: Use standard Java File I/O• Notes:

– Manifest: "android.permission.WRITE_EXTERNAL_STORAGE"– Application manifests can set preference to SD Card installation– Check SD Availability in Java:

Environment.getExternalStorageState().equals(Environment.MEDIA_MOUNTED)

• Convention: write to /Android/data/<package_name>/files/• Example

File sdCard = Environment.getExternalStorageDirectory();File dir = new File (sdcard.getAbsolutePath()

+ " /Android/data/<package_name>/files/ ");dir.mkdirs(); // Make directories with missing parents.File file = new File(dir, "filename"); // Instantiate a file objectFileOutputStream f = new FileOutputStream(file); // Open for writing

Page 10: The Android File System Onboard: Linux Architecture User privileges – Initially quite limited; some directories hidden – Rooting gives users super user

Writing to Internal Storage• Writing to internal storage

– Each application has a designated directory to which to write files– There is a maximum storage amount, varying per device– Flags exist to control inter-application access

• MODE_PRIVATE - No access for other applications • MODE_WORLD_READABLE - Read access for other applications • MODE_WORLD_WRITABLE - Write access for other applications • MODE_WORLD_READABLE | MODE_WORLD_WRITABLE - Read / Write access

• Open file for writing new BufferedWriter(

new OutputStreamWriter(openFileOutput(fileName, MODE_PRIVATE)));

Page 11: The Android File System Onboard: Linux Architecture User privileges – Initially quite limited; some directories hidden – Rooting gives users super user

Onboard File I/O• Write to a designated place for each application

– Where: /data/data/package/files/ using onboard storage– How: Use standard java.io classes, with relative, not absolute, paths– Applications can:

o Write into its application directoryo Create subdirectorieso Give read/write permissions to other applications

(MODE_PRIVATE, MODE_WORLD_READABLE | MODE_WORLD_WRITABLE)

• Android Helper classes in the Context object– getDir(String fileName, int permissions): Creates or access directory– getFilesDir(): Get absolute path to application directory– getCacheDir(): Get non-permanent temporary storage directory– openFileInput(String fileName): Open a file for input– openFileOutput(String fileName, int permissions): Create a new file

Note: There is also a sharedPreferences directory for preferences, a databases directory for SQLite tables, and a cache directory

Page 12: The Android File System Onboard: Linux Architecture User privileges – Initially quite limited; some directories hidden – Rooting gives users super user

Copy File from Serverpublic void DownloadFile(String fileURL, String fileName) { try { HttpURLConnection c = (HttpURLConnection) fileURL.openConnection();

c.setRequestMethod("GET");c.setDoOutput(false); // Tru for “POST” with intent to send to serverc.connect(); // Establish connection with serverInputStream in = c.getInputStream(); // Ready to read

File root = Environment.getExternalFilesDir(null); // Application area// Prepare output streamFileOutputStream out = new FileOutputStream(new File(root, fileName)); byte[] buffer = new byte[1024];int len = 0; // Note the buffer overflow possibilitywhile ((len = in.read(buffer)) > 0) { out.write(buffer, 0, len); } // Write

blockf.close();

} } } catch (Exception e) { Log.d("Downloader", e.getMessage()); }

Page 13: The Android File System Onboard: Linux Architecture User privileges – Initially quite limited; some directories hidden – Rooting gives users super user

Preferences• Initial Purpose:

– Persistent storage for user options– Analogous to cookies in Web-based applications

• More General Purpose: – Maintains the application state across terminations and restarts– Provides mechanism for applications to persistently store

additional data without using SQL or Files

• Preferences Framework1.Define preferences2.Display settings3.Persist user selections

Page 14: The Android File System Onboard: Linux Architecture User privileges – Initially quite limited; some directories hidden – Rooting gives users super user

Accessing Shared Preference Data// getPreferences is a method in the Activity classSharedPreferences prefs = getPreferences(Activity.MODE_PRIVATE); int intValue = getInt("IntKey", 22);long longValue = getLong("LongKey", 0);String name = getString("NameKey", "");int floatValue = getFloat("FloatKey", 0.0);int booleanValue = getBoolean("BoolKey", false);Set<String> set = getStringSet("SetKey", 22);Map<String, ?> keysAndValues = getAll();

Notes: 1.The second argument is the default if the key was not previously stored2.There is no getDouble() method

Page 15: The Android File System Onboard: Linux Architecture User privileges – Initially quite limited; some directories hidden – Rooting gives users super user

Modifying SharedPreference DataSharedPreferences preferences = getPreferences(Activity.MODE_PRIVATE); // or getSharedPreferences("fileName"); SharedPreferences.Editor editor = preferences.edit();editor.putInt("IntKey", 22);editor.putLong("LongKey", 0);editor.putString("NameKey", "");editor.putFloat("FloatKey", 0.0);editor.putBoolean("BoolKey", false);editor.commit();

Notes:1.puts can be chained: editor.putInt(“intKey”, 22).putLong(“LongKey”, 0);2.editor.apply() works asynchronously, editor.commit() is synchronous3.editor.clear() erases all of the preference keys4.editor.remove(“Key”) deletes a preference5.Shared preferences use a file name for multi-activity sharing

Page 16: The Android File System Onboard: Linux Architecture User privileges – Initially quite limited; some directories hidden – Rooting gives users super user

Preference Views

• Preference Screen The view on the left View on the right appears

When the user clicks after preference screen clicked

• Selection Screen Modal Dialog on the right Saves selection and disappears

after a user selection

Page 17: The Android File System Onboard: Linux Architecture User privileges – Initially quite limited; some directories hidden – Rooting gives users super user

Step 1: Defining Preferences

<?xml version="1.0" encoding="utf-8"?> <!-- /res/xml/flightoptions.xml --><PreferenceScreen xmlns:android="http://schemas.android.com/apk/res/android"

android:key="flight_option_preference" android:title="@string/PrefTitle" android:summary="@string/PrefSummary"><ListPreference android:key="@string/SelectedSortOption"

android:title="@string/ListTitle" android:summary="@string/ListSummary"android:entries="@array/FlightSortOptions"

android:entryValues="@array/FlightSortValues"android:dialogTitle="@string/ChooseFlightOptions"android:defaultValue="@string/SortDefaultValue" />

</PreferenceScreen>public class FlightPreferenceActivity extends PreferenceActivity{ @Override protected void onCreate(Bundle savedInstanceState)

{ super.onCreate(savedInstanceState);addPreferencesFromResource(R.xml.flightoptions);

} }

XML Listing (in res/xml) for the preferences shown on the previous screen

Page 18: The Android File System Onboard: Linux Architecture User privileges – Initially quite limited; some directories hidden – Rooting gives users super user

Define Strings in res/values<?xml version="1.0" encoding="utf-8"?><resources>

<string name="AppName">Preferences Demo</string><string name="PrefTitle">My Preferences</string><string name="PrefSummary">Set Search Options</string><string name="ListTitle">Flight Options</string><string name="ListSummary">Set Search Options</string><string-array name="FlightSortOptions"> <item>Total Cost</item><item># of Stops</item><item>Airline</item></string-array><string-array name="FlightSortValues"> <item>0</item><item>1</item><item>2</item></string-array><string name="ChooseFlightOptions">Choose Flight Options</string><string name="SortDefaultValue">1</string><string name="SelectedSortOption">Selected Sort Option</string><string name="menu_prefs_title">Settings</string><string name="menu_quit_title">Quit</string>

</resources>

Page 19: The Android File System Onboard: Linux Architecture User privileges – Initially quite limited; some directories hidden – Rooting gives users super user

Manifest<?xml version="1.0" encoding="utf-8"?> <!-- AndroidManifest.xml --><manifest xmlns:android="http://schemas.android.com/apk/res/android"

package="com.syh" android:versionCode="1" android:versionName="1.0"><application android:icon="@drawable/icon" android:label="@string/AppName"><activity android:name=".MainActivity" android:label="@string/AppName">

<intent-filter><action android:name="android.intent.action.MAIN" /><category android:name="android.intent.category.LAUNCHER" />

</intent-filter></activity><activity android:name=".PreferenceActivity" android:label="@string/PrefTitle"><intent-filter><action android:name="com.syh.intent.action.FlightPreferences" />

<category android:name="android.intent.category.PREFERENCE" /></intent-filter></activity></application><uses-sdk android:minSdkVersion="3" /></manifest>

Page 20: The Android File System Onboard: Linux Architecture User privileges – Initially quite limited; some directories hidden – Rooting gives users super user

Define Main Android Activity// This is MainActivity.java@Override public void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState);

setContentView(R.layout.main); // Assuming there is a TextView layouttv = (TextView)findViewById(R.id.text1);setOptionText(); // Helper method to get user preference and adjust view

}@Override public boolean onCreateOptionsMenu(Menu menu){ MenuInflater inflater = getMenuInflater();

// Inflate main menu XML with link to preference optioninflater.inflate(R.menu.mainmenu, menu);return true; // Menu is now active

}

Page 21: The Android File System Onboard: Linux Architecture User privileges – Initially quite limited; some directories hidden – Rooting gives users super user

Main Activity Selection Responses@Override public boolean onOptionsItemSelected (MenuItem item){ if (item.getItemId() == R.id.menu_prefs)

{ Intent intent = new Intent().setClass(this, com.syh.PreferenceActivity.class);this.startActivityForResult(intent, 0); // Second parameter is for a switch in

listener} else if (item.getItemId() == R.id.menu_quit) { finish(); }return true; // Start preference menu when its item is selected

}@Override public void onActivityResult(int reqCode, int resCode, Intent data){ super.onActivityResult(reqCode, resCode, data);

SharedPreferences prefs = getDefaultSHaredPreferences(this); String key = this.getResources().getString(R.string.SelectedSortOption);String default = this.getResources().getString(R.string.SortDefaultValue); String selection = prefs.getString(key , default);String[] optionText = this.getResources().getStringArray(R.string.FlightSortOptions);tv.setText("option = " + pref + " (" + optionText[Integer.parseInt(pref)] + ")");

}

Page 22: The Android File System Onboard: Linux Architecture User privileges – Initially quite limited; some directories hidden – Rooting gives users super user

CheckBoxPreference (/res/xml/chkbox.xml)

<?xml version="1.0" encoding="utf-8"?><PreferenceScreen

xmlns:android ="http://schemas.android.com/apk/res/android"android:key="flight_columns_pref">

<CheckBoxPreference android:key="show_airline_column_pref"android:title="Airline" android:summary="Show Airline column" />

<CheckBoxPreference android:key="show_departure_column_pref"android:title="Departure" android:summary="Show Departure column" />

<CheckBoxPreference android:key="show_arrival_column_pref"android:title="Arrival" android:summary="Show Arrival column" />

<CheckBoxPreference android:key="show_total_travel_time_column_pref"android:title="Total Travel Time"android:summary="Show Total Travel Time column" />

<CheckBoxPreference android:key="show_price_column_pref"android:title="Price" android:summary="Show Price column" />

</PreferenceScreen>

Note: For Radio Buttons, use the List Preference

Page 23: The Android File System Onboard: Linux Architecture User privileges – Initially quite limited; some directories hidden – Rooting gives users super user

Using Check Box Preferences// CheckBoxPreferenceActivity.javaimport android.os.Bundle;import android.preference.PreferenceActivity;public class CheckBoxPreferenceActivity extends PreferenceActivity{

@Override protected void onCreate(Bundle savedInstanceState) {

super.onCreate(savedInstanceState);addPreferencesFromResource(R.xml.chkbox);

}}

// Access preference in an activitySharedPreferences prefs = getSharedPreferences("fileName");Boolean option = prefs.getBoolean("show_price_column_pref", false);

Page 24: The Android File System Onboard: Linux Architecture User privileges – Initially quite limited; some directories hidden – Rooting gives users super user

EditTextPreference<?xml version="1.0" encoding="utf-8"?><PreferenceScreen xmlns:android=http://schemas.android.com/apk/res/android

android:title=“Set Package Name" android:summary="Set the package name for generated code">

<EditTextPreference android:key="package_name_preference"android:title="Set Package Name" android:dialogTitle="Package Name" android:summary="Set the package name for generated code" />

</PreferenceScreen>

Page 25: The Android File System Onboard: Linux Architecture User privileges – Initially quite limited; some directories hidden – Rooting gives users super user

Categories of Preferences<?xml version="1.0" encoding="utf-8"?><PreferenceScreen xmlns:android="http://schemas.android.com/apk/res/android"

android:key="using_categories_in_root_screen" android:title="Categories"android:summary="Using Preference Categories">

<PreferenceCategory xmlns:android=http://schemas.android.com/apk/res/androidandroid:key="meats_category" android:title="Meats" android:summary="Meat preferences"><CheckBoxPreference android:key="fish_selection_pref" android:title="Fish"

android:summary="Fish is great for the healthy" /><CheckBoxPreference android:key="chicken_selection_pref" android:title="Chicken"

android:summary="A common type of poultry" /><CheckBoxPreference android:key="lamb_selection_pref" android:title="Lamb"

android:summary="Lamb is a young sheep" /></PreferenceCategory><PreferenceCategory xmlns:android=http://schemas.android.com/apk/res/android

android:key="vegi_category" android:title="Vegetables" android:summary="Vegetable preferences"><CheckBoxPreference android:key="tomato_selection_pref" android:title="Tomato "

android:summary="It's actually a fruit" /><CheckBoxPreference android:key="potato_selection_pref" android:title="Potato"android:summary="My favorite vegetable" /></PreferenceCategory></PreferenceScreen>

Purpose: Provide titles to groups of similar preferences

Page 26: The Android File System Onboard: Linux Architecture User privileges – Initially quite limited; some directories hidden – Rooting gives users super user

Preference Fragments• Android versions 3.0 and newer recommend using fragments for

preferences instead of activities

• Check Android Version: if (Build.VERSION.SKK_INT<Build.VERSION_CODES.HONEYCOME)

{ /* Use preference activity approach */ }else { /* Use preference fragment approach */ }

• Implementation Steps1. Define preference screens in XML (as shown on previous slides)2. Add PreferenceFragment to the activity using the FragmentManager3. Create the PreferenceFragment class

Page 27: The Android File System Onboard: Linux Architecture User privileges – Initially quite limited; some directories hidden – Rooting gives users super user

Preference Fragment in an Activitypublic class PreferenceFragmentActivity extends Activity { @Override

public void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState);

setContentView(R.layout.main);

FragmentManager manager = getFragmentManager();FragmentTransaction trans = manager.beginTransaction();MyFragment fragment = new MyFragment();trans.replace(android.R.id.content, fragment1); trans.addToBackStack(null); trans.commit();

}} Note: Don’t add the fragment to the application manifest

Page 28: The Android File System Onboard: Linux Architecture User privileges – Initially quite limited; some directories hidden – Rooting gives users super user

Preference Fragment Classpublic class MyFragment extends PreferenceFragment { @Override public void onCreate(Bundle savedInstanceState)

{ super.onCreate(savedInstanceState);

// configure the preferences from an XML fileaddPreferencesFromResource(R.xml.preferences);

PreferenceManager manager = getPreferenceManager();SharedPreferences shared = manager.getSharedPreferences();shared.registerOnSharedPreferenceChangeListener(this);

} onSharedPreferenceChanged(SharedPreferences pref, String key){ /* Handle preference change here */ }

}

Page 29: The Android File System Onboard: Linux Architecture User privileges – Initially quite limited; some directories hidden – Rooting gives users super user

SQLite• Android SQLite:

– Lightweight database system– Standards-compliant– Single Tier (no server involved)– Open source

• Standard SQL queries“SELECT ID, CITY, STATE FROM STATION WHERE LAT_N > 39.7;”

• Application content providers provide – Standard interface to SQL tables to other applications– For application private tables, content providers are not needed

Page 30: The Android File System Onboard: Linux Architecture User privileges – Initially quite limited; some directories hidden – Rooting gives users super user

Authorities / URI

• Definition: An authority is a registered name on an android device (ex: Content Provider name. Authorities must be unique on the system.

• Registration: Accomplished in an application manifest

• Syntax: com.company.someProvider

• Examples: org.acorns.LessonProvider or com.android.provider.BookProvider

• Analogy: Authorities are to Android what domain names are to the Web

• Activity access using URIs– Syntax: content://authority-name/path-segment/path-segment/…

– Access book table: content://com.anroidbook.provider.BookProvider/books

– Access particular book: content://com.anroidbook.provider.BookProvider/books/12

• Activity Interface: Through Content Providers, which fill in abstract methods

Purpose: Publish application SQL tables and data for external activity access

Page 31: The Android File System Onboard: Linux Architecture User privileges – Initially quite limited; some directories hidden – Rooting gives users super user

MIME Types

• Definition: Industry standard way to indicate a particular data format

• Syntax: Two text strings separated by slashes

• First part (category): application, audio, image, text, video, etc

• Second Part (codec): html, css, xml, pdf, rtf, etc.

• Examples: text/htm, application/pdf, image/jpeg, audio/mpeg, etc.

• Android MIME Types (Similar syntax as standard MIME types)

– First Parto Access single items: vnd.android.cursor.itemo Access multiple items: vnd.android.cursor.dir

– Second Part: vnd.yourCompany.type– Examples: vnd.android.cursor.dir/vnd.google.note or

vnd.android.cursor.item/vnd.google.note

Purpose: Indicate a type of data that a content provider deals with

Page 32: The Android File System Onboard: Linux Architecture User privileges – Initially quite limited; some directories hidden – Rooting gives users super user

Content Provider Framework

• An application registers its content provider using its manifest• The code for the content provider is written• An application request data using the published MIME type• Android looks through the registered manifests for an

appropriate provider• The provider activity is launched to manipulate or return data• If more than one provider exists, the user selects the one to use• Android Built-in content providers:

content://media/internal/images/, content://media/external/images/,content://contacts/people/

Page 33: The Android File System Onboard: Linux Architecture User privileges – Initially quite limited; some directories hidden – Rooting gives users super user

Content Providers

• Register an authority using the AndroidManifest.xml file– Definition: An authority is a registered name– Analogy: authority is to an Android device what a domain name is

to the Internet

• Syntax: ( Using a package name minimizes redundancies on a system)<provider android:name="fooProvider"

android:authorities="com.company.fooProvider" />

• Example:<provider android:name=" com.acorns.LessonProvider"

android:authorities="com.acorns.provider.Lessons" />

• Another application example:<provider android:name=“NotePadProvider"

android:authorities="com.google.provider.NotePad" />

A well-defined interface to data for application access

Page 34: The Android File System Onboard: Linux Architecture User privileges – Initially quite limited; some directories hidden – Rooting gives users super user

MIME Types

• Specifies the data type an activity can process– Register in the AndroidManifest.xml file– Example: "vnd.android.cursor.dir/vnd.google.note"

OR "vnd.android.cursor.dir/vnd.google.note"

• Sample Syntax: vnd.android.cursor.<opt>/vnd.company.type– vnd: non-standard type (vendor)– android.cursor: required for ContentProvider Manifest registrations – item: single record; dir: collection of records– google: company name– note: content type

• AndroidManifest.xml registration<data android:mimeType="vnd.android.cursor.dir/vnd.google.note" />

Acronym: Multipurpose Internet Mail Extension

Page 35: The Android File System Onboard: Linux Architecture User privileges – Initially quite limited; some directories hidden – Rooting gives users super user

Referring to a Content Provider• URI and URL

– Uniform resource identifier (URI) Identifies the name of a resource, but not necessarily information regarding its location

– Uniform resource Location (URL) is a URI, that identifies a resource location– Text usage: URI for content providers; URL for referring to Web locations

• URI of a content providercontent://com.company.fooProvider/content://com.acorns.provider.Lessons/content://com.google.provider.NotePad/

• Note: Android provided shortcut URIs: contacts for com.google.android.contacts

• Refer to the notes SQLite notes tablecontent://com.google.provider.NotePad/notes/

• Refer to the tenth notecontent://com.google.provider/NotePad/notes/10

Page 36: The Android File System Onboard: Linux Architecture User privileges – Initially quite limited; some directories hidden – Rooting gives users super user

Register the Provider <provider android:name="NotePadProvider" android:authorities="com.google.provider.NotePad" />

<activity android:name="NotesList" android:label="@string/title_notes_list"><intent-filter> <action android:name="android.intent.action.MAIN" /> <category android:name="android.intent.category.LAUNCHER" /></intent-filter><intent-filter>

<action android:name="android.intent.action.VIEW" /><data android:mimeType="vnd.android.cursor.dir/vnd.google.note" />

</intent-filter><intent-filter> <action android:name="android.intent.action.GET_CONTENT" />

<data android:mimeType="vnd.android.cursor.item/vnd.google.note" ></intent-filter> </activity>

Page 37: The Android File System Onboard: Linux Architecture User privileges – Initially quite limited; some directories hidden – Rooting gives users super user

Implement the Provider

• Plan the Database• Extend the ContentProvider class• Fill in a variety of methods to be overloaded

– onCreate(): When the database is created– onUpgrade(): When the database layout changes– getType(): Return the MIME data type– query(): Handle queries to the data– insert(), delete(), and update() methods

Page 38: The Android File System Onboard: Linux Architecture User privileges – Initially quite limited; some directories hidden – Rooting gives users super user

A Managed Query in Content Provider

// Specify needed columns string[] projection = new string[]

{ People._ID, People.NAME, People.NUMBER };

// Specivy URI using static Contacts constantsUri contactUri = Contacts.People.CONTENT_URI;

// Invoke a content provider queryCursor cursor = managedQuery( contactUri,projection, //Which columns to returnnull, null, // Selection and WHERE clausesContacts.People.NAME + " ASC"); // Order-by (ascending by name)

Purpose: Query SQL lite table for relevant data (cursor)Definition: An Android cursor is a collection of rows of data

Other classes exist (ex: SQLiteQueryBuilder) for using standard SQL strings

Page 39: The Android File System Onboard: Linux Architecture User privileges – Initially quite limited; some directories hidden – Rooting gives users super user

Navigating through a cursor• Manipulate the cursor (row pointer)

– if (cursor.moveToFirst() == false)– cursor.isBeforeFirst(), cursor.isAfterLast, cursor.isClosed()– while (cursor.moveToNext()) { /* code here */ }– for (cursor.moveToFirst(); !cursor.isAfterLast(); cur.moveToNext) { … }

• Get column numbers from names– int nameColumn = cursor.getColumnIndex(People.NAME);– int phoneColumn = cursor.getColumnIndex(People.NUMBER);

• Get Data from column– String name = cursor.getString(nameColumn);– String number = cursor.getString(phoneColumn);

• Prerequisites: Know column names, data types, column name to index relationship

After a query, the cursor points before the first; use moveToFirst(); use moveToNext() for the initial access

Page 40: The Android File System Onboard: Linux Architecture User privileges – Initially quite limited; some directories hidden – Rooting gives users super user

Other Access Methods• AddContentValues values = new ContentValues();values.put(BookProviderMetaData.BookTableMetaData.BOOK_NAME, "book1");values.put(BookProviderMetaData.BookTableMetaData.BOOK_AUTHOR, "author-1");ContentResolver resolve = context.getContentResolver();URI uri = BookProviderMetaData.BookTableMetaData.CONTENT.URI;Uri inserted = resolve.insert(uri, values);

• Delete: Assume that bookIndex is pre-definedContentResolver resolve = context.getContentResolver();URI uri = BookProviderMetaData.BookTableMetaData.CONTENT.URI;Uri delURI = uri.withAppendedPath(uri, Integer.toString(bookIndex));resolve.delete(delUri, null, null);

• CountURI uri = BookProviderMetaData.BookTableMetaData.CONTENT.URI;Cursor cursor = activity.managedQuery(uri, null, null, null, null);Int numberOfRecords = cursor.getCount();cursor.close();

See next slide for symbolic constant definitions

Page 41: The Android File System Onboard: Linux Architecture User privileges – Initially quite limited; some directories hidden – Rooting gives users super user

BookProviderMetaData class

Page 42: The Android File System Onboard: Linux Architecture User privileges – Initially quite limited; some directories hidden – Rooting gives users super user

Content Resolver• Definition: A Content Resolver is an Android class that

matches the URI to an available Content Provider that can handle the data

• Purpose: Separate the provider from the data, enabling the possibility of multiple content providers available to handle the same data types

• Access: Use a collection of method calls to insert, retrieve, delete, update data records

• Example: (insert a new note into the notepad)ContentResolver resolver = activity.getContentResolver();Uri newUri = resolver.insert(Notepad.Notes.CONTENT_URI,

values);

Note: values is an instance of the ContentValues class

Page 43: The Android File System Onboard: Linux Architecture User privileges – Initially quite limited; some directories hidden – Rooting gives users super user

Store Files in an SQLite DatabaseSteps

1. Create the SQLite table with a column called _data2. Get a writeable output stream3. Write the file to the reserved column name _data

I/O Example//Use a content resolver to insert the recordContentResolver contentResolver = activity.getContentResolver();Uri newUri = contentResolver.insert(Notepad.Notes.CONTENT_URI, values);//Use the content resolver to get an output stream directlyOutputStream outStream = contentResolver().openOutputStream(newUri);writeFileToRecord(outStream);outStream.close();

ContentValues object contains a set of values

Note: The data is actually stored in a separate area. The _data column contains the Uri reference to the data

Page 44: The Android File System Onboard: Linux Architecture User privileges – Initially quite limited; some directories hidden – Rooting gives users super user

DataBase Helper• Purpose

– Manage database creation and version management– Responsible for creating and upgrading an SQLite database– Defer database opening and updating to the first use– Avoids blocking application startup with compute intensive database

upgrades– Contains methods for getWritableDatabase and

getReadableDatabase– Simplifies Content Provider access to files– Eliminates concern over whether the application was terminated

• Implementation– Create a class that extends SQLiteOpenHelper– Override onCreate() and onUpgrade() methods

Page 45: The Android File System Onboard: Linux Architecture User privileges – Initially quite limited; some directories hidden – Rooting gives users super user

Helper Code (Two tables: Employees, Department)

public class DatabaseHelper extends SQLiteOpenHelper { static final String dbName="demoDB";

static final String employees="Employees";static final String colID="EmployeeID"; static final String colName="EmployeeName"; static final String colAge="Age"; static final String colDept="Dept";

static final String depts="Department"; static final String colDeptID="DeptID"; static final String colDeptName="DeptName";static final String viewEmps="ViewEmps";

public DatabaseHelper(Context context) // Constructor{ super(context, dbName, null /* Extension to cursor class */, 1 /* version */); }

This application will need to override onCreate and onUpgrade

Page 46: The Android File System Onboard: Linux Architecture User privileges – Initially quite limited; some directories hidden – Rooting gives users super user

Helper Example (cont.)public void onCreate(SQLiteDatabase db) { db.execSQL("CREATE TABLE " + "depts +

" (" + colDeptID +" INTEGER PRIMARY KEY , " + colDeptName+ " TEXT)");

db.execSQL("CREATE TABLE "+employees + " ("+ colID + " INTEGER PRIMARY KEY AUTOINCREMENT, " + colName + " TEXT, "+ colAge + " Integer, " + colDept + " INTEGER NOT NULL , FOREIGN KEY ("+ colDept +") REFERENCES " + deptTable+" ("+colDeptID+"));");

db.execSQL("CREATE TRIGGER fk_empdept_deptid "+" BEFORE INSERT ON "+employees+" FOR EACH ROW BEGIN" + " SELECT CASE WHEN ( (SELECT " + colDeptID + " FROM " +

depts + " WHERE " + colDeptID + "=new." + colDept + " ) IS NULL)" + " THEN RAISE (ABORT, 'Foreign Key Violation') END;" + " END;");

db.execSQL("CREATE VIEW "+ viewEmps + " AS SELECT " + employees + "." + colID + " AS _id," + " " + employees + "." + colName + ", " + employees + "." + colAge + ", " +depts + "." + colDeptName + "" + " FROM "+ employees + " JOIN " + depts + " ON " + employees +"." + colDept+" =" + depts + "." + colDeptID );

}

Page 47: The Android File System Onboard: Linux Architecture User privileges – Initially quite limited; some directories hidden – Rooting gives users super user

Helper Example (cont.) Upgrading the DB

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

db.execSQL("DROP TABLE IF EXISTS "+employees); db.execSQL("DROP TABLE IF EXISTS "+depts);

db.execSQL("DROP TRIGGER IF EXISTS dept_id_trigger"); db.execSQL("DROP TRIGGER IF EXISTS dept_id_trigger22"); db.execSQL("DROP TRIGGER IF EXISTS fk_empdept_deptid"); db.execSQL("DROP VIEW IF EXISTS "+viewEmps); onCreate(db);

}

Called when the version number in the constructor changes

Note: The activity can respond to menu selections to insert, remove, and update rows

Page 48: The Android File System Onboard: Linux Architecture User privileges – Initially quite limited; some directories hidden – Rooting gives users super user

Using a Database helperHelper = new Helper(context, Helper.DATABASE_NAME, null, Helper.VERSION);SQLiteDatabase db = Helper.getWritableDatabase(); // Perform queryCursor cursor = db.query(Helper.DATABASE_TABLE, result_columns, where,

whereArgs, group, having, order);

SQLiteDatabase db = hoardDBOpenHelper.getWritableDatabase(); // Insert rowdb.insert(HoardDBOpenHelper.DATABASE_TABLE, null, newValues);

SQLiteDatabase db = hoardDBOpenHelper.getWritableDatabase(); // Update rowdb.update(Helper.DATABASE_TABLE, newValues, where, whereArgs);

SQLiteDatabase db = Helper.getWritableDatabase(); // Delete matching rowsdb.delete(Helper.DATABASE_TABLE, where, whereArgs);

Page 49: The Android File System Onboard: Linux Architecture User privileges – Initially quite limited; some directories hidden – Rooting gives users super user

Find media titles and albums

String[] projection = { MediaStore.Audio.AudioColumns.ALBUM, MediaStore.Audio.AudioColumns.TITLE };

Uri uri = MediaStore.Audio.Media.EXTERNAL_CONTENT_URI; Cursor cursor = getContentResolver().query(uri, projection, null, null, null); int aX= cursor.getColumnIndexOrThrow(MediaStore.Audio.AudioColumns.ALBUM); int tX = cursor.getColumnIndexOrThrow(MediaStore.Audio.AudioColumns.TITLE); String[] result = new String[cursor.getCount()]; while (cursor.moveToNext()) { String title = cursor.getString(tX), album = cursor.getString(aX);

result[cursor.getPosition()] = title + " (" + album + ")"; }

cursor.close();

Using the Android provided Media Store Content Provider

Other Native Content Providers: Browser, Contacts, Calendar, Call log

Page 50: The Android File System Onboard: Linux Architecture User privileges – Initially quite limited; some directories hidden – Rooting gives users super user

Accessing the Contact Listint iDCol = ContactsContract.Contacts.ID;int nameCol = ContactsContract.Contacts.DISPLAY_NAME;Uri uri = ContactsContract.Contacts.CONTENT_URI;String[] projection = { iDCol, nameCol }; Cursor cursor = getContentResolver().query(uri, projection, null, null, null);int nameIndex = cursor.getColumnIndexOrThrow(nameCol); int idIndex = cursor.getColumnIndexOrThrow(contactIDCol); String[] result = new String[cursor.getCount()]; while(cursor.moveToNext()) { String name = cursor.getString(nameIndex);

String id = cursor.getString(idIndex); result[cursor.getPosition()] = name + " (" + id + ")";

} cursor.close();

Page 51: The Android File System Onboard: Linux Architecture User privileges – Initially quite limited; some directories hidden – Rooting gives users super user

Searchable Applications• Expose the application to search-facilities• Alternatives

– Search bar appearing after hardware search button pressed or a program method call

– Search widget placed somewhere on the application view

– Quick Search implemented as a home screen widget

– Enable voice search

Page 52: The Android File System Onboard: Linux Architecture User privileges – Initially quite limited; some directories hidden – Rooting gives users super user

Making an Application Searchable• In the manifest

– Create an xml file with the searchable attributes– Mark the application searchable– Define the intent for the activity processing searches

• Either create a search activity– Launch when the search is initiated– Process and display the results

• Or use a search dialog (floating search box)– Hidden by default, but can be initiated by calling

onSearchRequested(), which is an Activity class method– If the device doesn’t contain a dedicated search button, add a menu

option or widget that calls onSearchRequested()• Or use the SearchView widget

Page 53: The Android File System Onboard: Linux Architecture User privileges – Initially quite limited; some directories hidden – Rooting gives users super user

Searchable configuration in res/xml

<?xml version="1.0" encoding="utf-8"?><searchable xmlns:android=http://schemas.android.com/apk/res/android android:label="@string/app_label“ android:hint="@string/search_hint" ></searchable>

•The label (required attribute) becomes visible when search is launched and contains the search application name•The hint appears in the search box before users enter a query. It contains a hint about what can be searched•Other attributes are for search suggestions and voice search

Filename: searchable.xml

Page 54: The Android File System Onboard: Linux Architecture User privileges – Initially quite limited; some directories hidden – Rooting gives users super user

Searchable launch in Manifest<application> …<activity android:name=".SearchActivity“

android:launchMode="singleTop"><intent-filter>

<action android:name="android.intent.action.SEARCH" />

</intent-filter> <meta-data android:name="android.app.searchable"

android:resource="@xml/searchable" /></activity>

Note: singleTop prevents multiple instances on the back stack

Page 55: The Android File System Onboard: Linux Architecture User privileges – Initially quite limited; some directories hidden – Rooting gives users super user

Search Activity

@Overridepublic void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState);

setContentView(R.layout.search);

// Get the intent, verify the action and get the queryIntent intent = getIntent();if (Intent.ACTION_SEARCH.equals(intent.getAction())) { String query = intent.getStringExtra(SearchManager.QUERY);

doMySearch(query); // Process the request}

}

Page 56: The Android File System Onboard: Linux Architecture User privileges – Initially quite limited; some directories hidden – Rooting gives users super user

Services• Services handle background

events separate from a View• Services reside in the main thread

of the launching process! Use thread facilities to avoid blocking the main thread

• Only foreground activities have a higher priority, so services are rarely terminated by the OS

• Proper Handling– Main activity makes requests– Service starts worker threads to

perform requests– Bind services to the main

thread– Callbacks to the main activity

completes transactions. Downloading Threads (maybe thread pool?)

Main Activity

Service

onButtonClick() method gets control in the executing activity

Activity uses an intent to request the download from the Service!)

Worker Thread(downloading)

New worker thread

Done downloading!Start new worker thread

User selects item to download

Page 57: The Android File System Onboard: Linux Architecture User privileges – Initially quite limited; some directories hidden – Rooting gives users super user

Creating a Service1. Create a class extending the service class2. Register the service in the application manifest

<service android:enabled="true"android:name=".MyService"android:permission="foo.bar.MY_SERVICE_PERMISSION"/>

4. Start and stop of the service in the main activity5. Use separate threads for compute-bound operations

– Bind service to the main activities so the main activity can call service class methods and then update its user interface views

6. Self-terminate the service when it is no longer needed

Page 58: The Android File System Onboard: Linux Architecture User privileges – Initially quite limited; some directories hidden – Rooting gives users super user

Starting and Stopping Services• Explicitly start My Service

Intent intent = new Intent(this, MyService.class); // TODO Add extras if required. startService(intent); }

• Implicitly start a music Service Intent intent = new Intent(MyMusicService.PLAY_ALBUM); intent.putExtra(MyMusicService.ALBUM_NAME_EXTRA, "United"); intent.putExtra(MyMusicService.ARTIST_NAME_EXTRA, "Pheonix"); startService(intent);

• Explicitly stop My Service : stopService(new Intent(this, MyService.class));

• Implicitly stop Music ServicestopService(new Intent(MyMusicService.PLAY_ALBUM));

Page 59: The Android File System Onboard: Linux Architecture User privileges – Initially quite limited; some directories hidden – Rooting gives users super user

Creating a Bindable Service

public class LocalService extends Service { private final IBinder binder = new LocalBinder(); public class LocalBinder extends Binder

{ LocalService getService() { return LocalService.this; } }

@Override public void onCreate() { // TODO: Actions to perform when service is created. }

// Return instance after activity call onBindService() call @Override public IBinder onBind(Intent intent)

{ return binder; }

/** method for clients */ public int getRandomNumber() { return Math.random(); }}

Purpose: Enable activities to access service methods

Page 60: The Android File System Onboard: Linux Architecture User privileges – Initially quite limited; some directories hidden – Rooting gives users super user

public class BindingActivity extends Activity // An Activity using a Bound Service{ LocalService service; boolean bound = false;

private ServiceConnection connection = new ServiceConnection() // Anonymous instance{ @Override public void onServiceConnected(ComponentName name, IBinder service)

{ LocalBinder binder=(LocalBinder) service; service=binder.getService(); bound=true; }

@Override public void onServiceDisconnected(ComponentName arg0) { bound = false; }

}; @Override protected void onCreate(Bundle savedInstanceState)

{ super.onCreate(savedInstanceState); setContentView(R.layout.main); }

@Override protected void onStart() { super.onStart(); Intent intent = new Intent(this, LocalService.class);

bindService(intent, connection, Context.BIND_AUTO_CREATE); }

@Override protected void onStop() ` { super.onStop(); if (bound) { unbindService(connection); bound = false; } }

public void onButtonClick(View v) { if (bound) { int num = service.getRandomNumber(); Toast.makeText(this, "number: "+num, Toast.LENGTH_SHORT).show(); } }

}

Page 61: The Android File System Onboard: Linux Architecture User privileges – Initially quite limited; some directories hidden – Rooting gives users super user

Updating the GUI from a Service1. The activity registers a listening object with the service2. The service broadcasts an intent and the activity responds3. Use a Handler in an activity

private final Handler handler = new Handler(); // Process queue of runnablesprivate OnClickListener buttonListener = new OnClickListener() { public void onClick(View v)

{ new Thread(new Runnable() { pubic void run()

{ //.... hard work in separate thread handler.post(new Runnable() { public void run() { // ... update the UI } });

}).start(); } };}

Note: There are other possibilities. For example, one could use AsyncTask, IntentService or Loader objects