Download
mobile programming lecture 10 n.
Skip this Video
Loading SlideShow in 5 Seconds..
Mobile Programming Lecture 10 PowerPoint Presentation
Download Presentation
Mobile Programming Lecture 10

Mobile Programming Lecture 10

183 Views Download Presentation
Download Presentation

Mobile Programming Lecture 10

- - - - - - - - - - - - - - - - - - - - - - - - - - - E N D - - - - - - - - - - - - - - - - - - - - - - - - - - -
Presentation Transcript

  1. Mobile Programming Lecture 10 ContentProviders

  2. Lecture 9 Review • In creating a bound service, why would you choose to use a Messenger over extending Binder? • What are the differences between using GPS provider and Network provider? • When should you stop listening for location updates? • When should you disable a Sensor?

  3. Lecture 9 Review • How do you start an Activity B from and Activity A, and get a result back from Activity B when B has completed? • How can you find out the structure of the intent filter for a given intent in the system?

  4. Agenda • ContentProviders • Querying existing databases • Creating a database for your app • Manipulating data: insert, update, and delete • Content provider permissions

  5. Android Application Components • Activity • Broadcast Receiver • Content Provider • Service

  6. Content Provider Basics • A content provider manages access to a central repository of data • content providers are primarily intended to be used by other applications, which access the provider using a provider client object • A content provider presents data to external applications as one or more tables that are similar to the tables found in a relational database

  7. Content Provider Basics • When you want to access data in a content provider, you must use the ContentResolver object in your application's Context to communicate with the provider as a client • The ContentResolver object communicates with the provider object, an instance of a class that implements ContentProvider • The provider object receives data requests from clients, performs the requested action, and returns the results.

  8. Content Provider Basics • You don't need to develop your own provider if you don't intend to share your data with other applications, instead • Use SharedPreferences • The reason you use a ContentProvider is • data is too complex for SharedPreferences • expose your data to other applications

  9. Content Provider Basics • _ID column serves as the primary key column that the content provider automatically maintains • Here's an example of a table with an _ID column

  10. Contacts ContentProvider In our examples, we will look at the Contacts ContentProvider A lot of the work for a query goes into reading the documentation online http://developer.android.com/reference/android/provider/ContactsContract.Contacts.html

  11. Requesting Permission In order to read the user's contacts, you need to request permission first android.permission.READ_CONTACTS

  12. Constructing a Query Let's build several queries for ContractsContract.Contacts The columns can be found in the documentation here A few of the columns are ...

  13. Constructing a Query We will use the following fields in our class in our examples public class ContactsContractExampleActivity extends ListActivity { Cursor mCursor; CursorAdapter mCursorAdapter; String[] mProjection; String[] mListColumns; String mSelectionClause; String[] mSelectionArgs; String mOrderBy; @Override public void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); } }

  14. Constructing a Query We will use the following fields in our class in our examples public class ContactsContractExampleActivity extends ListActivity { Cursor mCursor; CursorAdapter mCursorAdapter; String[] mProjection; String[] mListColumns; String mSelectionClause; String[] mSelectionArgs; String mOrderBy; @Override public void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); } } Note that we're extending ListActivity, so we don't need to add a ListView to our XML layout file. We don't even need an XML layout file

  15. Constructing a Query Consider the following SQL queries

  16. Constructing a Query - Query 1 SELECT * FROM ContactsContract.Contacts "Get every column for every contact in this database table"

  17. Constructing a Query - Query 1 @Override public void onCreate(Bundle savedInstanceState) { mCursor = getContentResolver().query( ContactsContract.Contacts.CONTENT_URI, null, null, null, null); mListColumns = new String[] { ContactsContract.Contacts.DISPLAY_NAME }; mListItems = new int[] { R.id.contact_name }; mCursorAdapter = new SimpleCursorAdapter(this, R.layout.query1, mCursor, mListColumns, mListItems); setListAdapter(mCursorAdapter); }

  18. Constructing a Query - Query 1 @Override public void onCreate(Bundle savedInstanceState) { mCursor = getContentResolver().query( ContactsContract.Contacts.CONTENT_URI, null, null, null, null); mListColumns = new String[] { ContactsContract.Contacts.DISPLAY_NAME }; mListItems = new int[] { R.id.contact_name }; mCursorAdapter = new SimpleCursorAdapter(this, R.layout.query1, mCursor, mListColumns, mListItems); setListAdapter(mCursorAdapter); } When you want to access data in a content provider, you need to use a ContentResolver. You can get the ContentResolver by calling getContentResolver()

  19. Constructing a Query - Query 1 @Override public void onCreate(Bundle savedInstanceState) { mCursor = getContentResolver().query( ContactsContract.Contacts.CONTENT_URI, null, null, null, null); mListColumns = new String[] { ContactsContract.Contacts.DISPLAY_NAME }; mListItems = new int[] { R.id.contact_name }; mCursorAdapter = new SimpleCursorAdapter(this, R.layout.query1, mCursor, mListColumns, mListItems); setListAdapter(mCursorAdapter); } It returns a Cursor object.

  20. Constructing a Query - Query 1 @Override public void onCreate(Bundle savedInstanceState) { mCursor = getContentResolver().query( ContactsContract.Contacts.CONTENT_URI, null, null, null, null); mListColumns = new String[] { ContactsContract.Contacts.DISPLAY_NAME }; mListItems = new int[] { R.id.contact_name }; mCursorAdapter = new SimpleCursorAdapter(this, R.layout.query1, mCursor, mListColumns, mListItems); setListAdapter(mCursorAdapter); } Using a Cursor object, you can call the query() method to execute a query on a content provider.

  21. Constructing a Query - Query 1 @Override public void onCreate(Bundle savedInstanceState) { mCursor = getContentResolver().query( ContactsContract.Contacts.CONTENT_URI, null, null, null, null); mListColumns = new String[] { ContactsContract.Contacts.DISPLAY_NAME }; mListItems = new int[] { R.id.contact_name }; mCursorAdapter = new SimpleCursorAdapter(this, R.layout.query1, mCursor, mListColumns, mListItems); setListAdapter(mCursorAdapter); } The second argument is a String array (i.e. String[ ]) of which columns we want to be returned by the query. Passing null means return all columns, i.e. SELECT *

  22. Constructing a Query - Query 1 @Override public void onCreate(Bundle savedInstanceState) { mCursor = getContentResolver().query( ContactsContract.Contacts.CONTENT_URI, null, null, null, null); mListColumns = new String[] { ContactsContract.Contacts.DISPLAY_NAME }; mListItems = new int[] { R.id.contact_name }; mCursorAdapter = new SimpleCursorAdapter(this, R.layout.query1, mCursor, mListColumns, mListItems); setListAdapter(mCursorAdapter); } The first argument to Cursor.query() is a Uri. It specifies the table that you want to access, i.e. SELECT * FROM table

  23. Constructing a Query - Query 1 @Override public void onCreate(Bundle savedInstanceState) { mCursor = getContentResolver().query( ContactsContract.Contacts.CONTENT_URI, null, null, null, null); mListColumns = new String[] { ContactsContract.Contacts.DISPLAY_NAME }; mListItems = new int[] { R.id.contact_name }; mCursorAdapter = new SimpleCursorAdapter(this, R.layout.query1, mCursor, mListColumns, mListItems); setListAdapter(mCursorAdapter); } ContactsContract is a content provider. You can think of it as the database

  24. Constructing a Query - Query 1 @Override public void onCreate(Bundle savedInstanceState) { mCursor = getContentResolver().query( ContactsContract.Contacts.CONTENT_URI, null, null, null, null); mListColumns = new String[] { ContactsContract.Contacts.DISPLAY_NAME }; mListItems = new int[] { R.id.contact_name }; mCursorAdapter = new SimpleCursorAdapter(this, R.layout.query1, mCursor, mListColumns, mListItems); setListAdapter(mCursorAdapter); } ContactsContract.Contacts is a content provider. You can think of it as a table in the database

  25. Constructing a Query - Query 1 @Override public void onCreate(Bundle savedInstanceState) { mCursor = getContentResolver().query( ContactsContract.Contacts.CONTENT_URI, null, null, null, null); mListColumns = new String[] { ContactsContract.Contacts.DISPLAY_NAME }; mListItems = new int[] { R.id.contact_name }; mCursorAdapter = new SimpleCursorAdapter(this, R.layout.query1, mCursor, mListColumns, mListItems); setListAdapter(mCursorAdapter); } This is one of the Uris for the table, which says how you want to access the table. Some tables have multiple Uris

  26. Constructing a Query - Query 1 @Override public void onCreate(Bundle savedInstanceState) { mCursor = getContentResolver().query( ContactsContract.Contacts.CONTENT_URI, null, null, null, null); mListColumns = new String[] { ContactsContract.Contacts.DISPLAY_NAME }; mListItems = new int[] { R.id.contact_name }; mCursorAdapter = new SimpleCursorAdapter(this, R.layout.query1, mCursor, mListColumns, mListItems); setListAdapter(mCursorAdapter); } The third argument is a String. Here you specify the conditions for your query. Passing null means don't specify any conditions

  27. Constructing a Query - Query 1 @Override public void onCreate(Bundle savedInstanceState) { mCursor = getContentResolver().query( ContactsContract.Contacts.CONTENT_URI, null, null, null, null); mListColumns = new String[] { ContactsContract.Contacts.DISPLAY_NAME }; mListItems = new int[] { R.id.contact_name }; mCursorAdapter = new SimpleCursorAdapter(this, R.layout.query1, mCursor, mListColumns, mListItems); setListAdapter(mCursorAdapter); } The fourth argument is a String[ ]. We will get back to this soon

  28. Constructing a Query - Query 1 @Override public void onCreate(Bundle savedInstanceState) { mCursor = getContentResolver().query( ContactsContract.Contacts.CONTENT_URI, null, null, null, null); mListColumns = new String[] { ContactsContract.Contacts.DISPLAY_NAME }; mListItems = new int[] { R.id.contact_name }; mCursorAdapter = new SimpleCursorAdapter(this, R.layout.query1, mCursor, mListColumns, mListItems); setListAdapter(mCursorAdapter); } The fifth argument is a String. It says how we want to sort our results. Passing null means don't specify any sorting

  29. Constructing a Query - Query 1 @Override public void onCreate(Bundle savedInstanceState) { mCursor = getContentResolver().query( ContactsContract.Contacts.CONTENT_URI, null, null, null, null); mListColumns = new String[] { ContactsContract.Contacts.DISPLAY_NAME }; mListItems = new int[] { R.id.contact_name }; mCursorAdapter = new SimpleCursorAdapter(this, R.layout.query1, mCursor, mListColumns, mListItems); setListAdapter(mCursorAdapter); } SELECT * FROM ContactsContract.Contacts

  30. Constructing a Query - Query 1 @Override public void onCreate(Bundle savedInstanceState) { mCursor = getContentResolver().query( ContactsContract.Contacts.CONTENT_URI, null, null, null, null); mListColumns = new String[] { ContactsContract.Contacts.DISPLAY_NAME }; mListItems = new int[] { R.id.contact_name }; mCursorAdapter = new SimpleCursorAdapter(this, R.layout.query1, mCursor, mListColumns, mListItems); setListAdapter(mCursorAdapter); } Our query is now complete, and the Cursor can iterate through the results now. But since we want to attach our results to a ListView, we need to add a few more lines of code

  31. Constructing a Query - Query 1 @Override public void onCreate(Bundle savedInstanceState) { mCursor = getContentResolver().query( ContactsContract.Contacts.CONTENT_URI, null, null, null, null); mListColumns = new String[] { ContactsContract.Contacts.DISPLAY_NAME }; mListItems = new int[] { R.id.contact_name }; mCursorAdapter = new SimpleCursorAdapter(this, R.layout.query1, mCursor, mListColumns, mListItems); setListAdapter(mCursorAdapter); } Although our query was on all columns, here we create a String array of the columns we want to have displayed in our ListView.

  32. Constructing a Query - Query 1 @Override public void onCreate(Bundle savedInstanceState) { mCursor = getContentResolver().query( ContactsContract.Contacts.CONTENT_URI, null, null, null, null); mListColumns = new String[] { ContactsContract.Contacts.DISPLAY_NAME }; mListItems = new int[] { R.id.contact_name }; mCursorAdapter = new SimpleCursorAdapter(this, R.layout.query1, mCursor, mListColumns, mListItems); setListAdapter(mCursorAdapter); } The column names are usually constants that you can reference via the database table

  33. Constructing a Query - Query 1 @Override public void onCreate(Bundle savedInstanceState) { mCursor = getContentResolver().query( ContactsContract.Contacts.CONTENT_URI, null, null, null, null); mListColumns = new String[] { ContactsContract.Contacts.DISPLAY_NAME }; mListItems = new int[] { R.id.contact_name }; mCursorAdapter = new SimpleCursorAdapter(this, R.layout.query1, mCursor, mListColumns, mListItems); setListAdapter(mCursorAdapter); } The column names are usually constants that you can reference via the database table

  34. Constructing a Query - Query 1 In order to setup our ListView properly, we need to create an XML layout file that can represent each row in the list. We create a Layout XML file called query1.xml, which as has following TextView

  35. Constructing a Query - Query 1 <?xml version="1.0" encoding="utf-8"?> <TextView xmlns:android="http://schemas.android.com/apk/res/android" android:id="@+id/contact_name" android:layout_width="wrap_content" android:layout_height="wrap_content" android:text="Large Text" android:textAppearance="?android:attr/textAppearanceLarge" />

  36. Constructing a Query - Query 1 <?xml version="1.0" encoding="utf-8"?> <TextView xmlns:android="http://schemas.android.com/apk/res/android" android:id="@+id/contact_name" android:layout_width="wrap_content" android:layout_height="wrap_content" android:text="Large Text" android:textAppearance="?android:attr/textAppearanceLarge" /> Note the android:id attribute of the TextView

  37. Constructing a Query - Query 1 @Override public void onCreate(Bundle savedInstanceState) { mCursor = getContentResolver().query( ContactsContract.Contacts.CONTENT_URI, null, null, null, null); mListColumns = new String[] { ContactsContract.Contacts.DISPLAY_NAME }; mListItems = new int[] { R.id.contact_name }; mCursorAdapter = new SimpleCursorAdapter(this, R.layout.query1, mCursor, mListColumns, mListItems); setListAdapter(mCursorAdapter); }

  38. Constructing a Query - Query 1 @Override public void onCreate(Bundle savedInstanceState) { mCursor = getContentResolver().query( ContactsContract.Contacts.CONTENT_URI, null, null, null, null); mListColumns = new String[] { ContactsContract.Contacts.DISPLAY_NAME }; mListItems = new int[] { R.id.contact_name }; mCursorAdapter = new SimpleCursorAdapter(this, R.layout.query1, mCursor, mListColumns, mListItems); setListAdapter(mCursorAdapter); } So, String[ ] mListColumns specifies which columns we want to select

  39. Constructing a Query - Query 1 @Override public void onCreate(Bundle savedInstanceState) { mCursor = getContentResolver().query( ContactsContract.Contacts.CONTENT_URI, null, null, null, null); mListColumns = new String[] { ContactsContract.Contacts.DISPLAY_NAME }; mListItems = new int[] { R.id.contact_name }; mCursorAdapter = new SimpleCursorAdapter(this, R.layout.query1, mCursor, mListColumns, mListItems); setListAdapter(mCursorAdapter); } and int[] mListItems is a corresponding array, telling us where to place the actual value of the DISPLAY_NAME

  40. Constructing a Query - Query 1 @Override public void onCreate(Bundle savedInstanceState) { mCursor = getContentResolver().query( ContactsContract.Contacts.CONTENT_URI, null, null, null, null); mListColumns = new String[] { ContactsContract.Contacts.DISPLAY_NAME }; mListItems = new int[] { R.id.contact_name }; mCursorAdapter = new SimpleCursorAdapter(this, R.layout.query1, mCursor, mListColumns, mListItems); setListAdapter(mCursorAdapter); } It will be placed in this TextView, whose android:id="@+id/contact_name"

  41. Constructing a Query - Query 1 @Override public void onCreate(Bundle savedInstanceState) { mCursor = getContentResolver().query( ContactsContract.Contacts.CONTENT_URI, null, null, null, null); mListColumns = new String[] { ContactsContract.Contacts.DISPLAY_NAME }; mListItems = new int[] { R.id.contact_name }; mCursorAdapter = new SimpleCursorAdapter(this, R.layout.query1, mCursor, mListColumns, mListItems); setListAdapter(mCursorAdapter); } We've been using ArrayAdapters with ListViews in the past, but here we use a SimpleCursorAdapter instead, because we have a Cursor (i.e. mCursor)

  42. Constructing a Query - Query 1 @Override public void onCreate(Bundle savedInstanceState) { mCursor = getContentResolver().query( ContactsContract.Contacts.CONTENT_URI, null, null, null, null); mListColumns = new String[] { ContactsContract.Contacts.DISPLAY_NAME }; mListItems = new int[] { R.id.contact_name }; mCursorAdapter = new SimpleCursorAdapter(this, R.layout.query1, mCursor, mListColumns, mListItems); setListAdapter(mCursorAdapter); } First argument is a Context

  43. Constructing a Query - Query 1 @Override public void onCreate(Bundle savedInstanceState) { mCursor = getContentResolver().query( ContactsContract.Contacts.CONTENT_URI, null, null, null, null); mListColumns = new String[] { ContactsContract.Contacts.DISPLAY_NAME }; mListItems = new int[] { R.id.contact_name }; mCursorAdapter = new SimpleCursorAdapter(this, R.layout.query1, mCursor, mListColumns, mListItems); setListAdapter(mCursorAdapter); } Second argument is our Layout XML file resource used to construct the ListView

  44. Constructing a Query - Query 1 @Override public void onCreate(Bundle savedInstanceState) { mCursor = getContentResolver().query( ContactsContract.Contacts.CONTENT_URI, null, null, null, null); mListColumns = new String[] { ContactsContract.Contacts.DISPLAY_NAME }; mListItems = new int[] { R.id.contact_name }; mCursorAdapter = new SimpleCursorAdapter(this, R.layout.query1, mCursor, mListColumns, mListItems); setListAdapter(mCursorAdapter); } Third argument is our Cursor object

  45. Constructing a Query - Query 1 @Override public void onCreate(Bundle savedInstanceState) { mCursor = getContentResolver().query( ContactsContract.Contacts.CONTENT_URI, null, null, null, null); mListColumns = new String[] { ContactsContract.Contacts.DISPLAY_NAME }; mListItems = new int[] { R.id.contact_name }; mCursorAdapter = new SimpleCursorAdapter(this, R.layout.query1, mCursor, mListColumns, mListItems); setListAdapter(mCursorAdapter); } Fourth argument is our String array of column names

  46. Constructing a Query - Query 1 @Override public void onCreate(Bundle savedInstanceState) { mCursor = getContentResolver().query( ContactsContract.Contacts.CONTENT_URI, null, null, null, null); mListColumns = new String[] { ContactsContract.Contacts.DISPLAY_NAME }; mListItems = new int[] { R.id.contact_name }; mCursorAdapter = new SimpleCursorAdapter(this, R.layout.query1, mCursor, mListColumns, mListItems); setListAdapter(mCursorAdapter); } Fifth argument is our int array of TextView resources

  47. Constructing a Query - Query 1 @Override public void onCreate(Bundle savedInstanceState) { mCursor = getContentResolver().query( ContactsContract.Contacts.CONTENT_URI, null, null, null, null); mListColumns = new String[] { ContactsContract.Contacts.DISPLAY_NAME }; mListItems = new int[] { R.id.contact_name }; mCursorAdapter = new SimpleCursorAdapter(this, R.layout.query1, mCursor, mListColumns, mListItems); setListAdapter(mCursorAdapter); } Finally, we call setListAdapter and pass our SimpleCursorAdapter

  48. Constructing a Query - Query 1 See the query1() method inside of ContactsContractQueryExample.tar This query is inefficient, because we're requesting all columns, but yet only using one column after we get the results

  49. Constructing a Query - Query 2 Consider the following SQL query SELECT _ID, DISPLAY_NAME FROM ContactsContract.Contacts "Get the _ID and DISPLAY_NAME for all contacts"

  50. Constructing a Query - Query 2 @Override public void onCreate(Bundle savedInstanceState) { mProjection = new String[] { ContactsContract.Contacts._ID, ContactsContract.Contacts.DISPLAY_NAME }; mCursor = getContentResolver().query( ContactsContract.Contacts.CONTENT_URI, mProjection, null, null, null); mListColumns = new String[] { ContactsContract.Contacts.DISPLAY_NAME }; mListItems = new int[] { R.id.contact_name }; mCursorAdapter = new SimpleCursorAdapter(this, R.layout.query1, mCursor, mListColumns, mListItems); }