1 / 125

Mobile Programming Lecture 10

Mobile Programming Lecture 10. ContentProviders. 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?

cassia
Download Presentation

Mobile Programming Lecture 10

An Image/Link below is provided (as is) to download presentation Download Policy: Content on the Website is provided to you AS IS for your information and personal use and may not be sold / licensed / shared on other websites without getting consent from its author. Content is provided to you AS IS for your information and personal use only. Download presentation by click this link. While downloading, if for some reason you are not able to download a presentation, the publisher may have deleted the file from their server. During download, if you can't get a presentation, the file might be deleted by the publisher.

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); }

More Related