Presentation is loading. Please wait.

Presentation is loading. Please wait.

David Sutton USING CONTENT PROVIDERS. TOPICS COVERED THIS WEEK  Persistence  Introduction to databases  Content providers  Cursors  Cursor adapters.

Similar presentations


Presentation on theme: "David Sutton USING CONTENT PROVIDERS. TOPICS COVERED THIS WEEK  Persistence  Introduction to databases  Content providers  Cursors  Cursor adapters."— Presentation transcript:

1 David Sutton USING CONTENT PROVIDERS

2 TOPICS COVERED THIS WEEK  Persistence  Introduction to databases  Content providers  Cursors  Cursor adapters  The Contacts content provider  Extracting and displaying contact photos

3 PERSISTENCE  We can use simple data structures such as arrays and ArrayLists to store data within an application.  The snag is that the data disappears when the application shuts down  We therefore need ways of making data persist.  In general we can use  Files (perhaps in XML format)  Databases  Android provides with various ways of presenting databases and files which we will cover later.

4 DATABASE OPERATIONS: PROJECTION  A projection extracts particular columns from a table Staff No. First Name Last Name P03489FayeMitchell P02345DavidSutton P01234JoeBloggs Staff No. Last Name P03489Mitchell P02345Sutton P01234Bloggs

5 DATABASE OPERATIONS: SELECTION  A selection extracts particular rows from a table Module No. TitleModule Leader U08928Mobile Software P03489 U08223Data Structures P02345 U08071NetworksP03489 Module No. TitleModule Leader U08928Mobile Software P03489 U08071NetworksP03489

6 DATABASE OPERATIONS: JOIN Module No. TitleModule Leader U08928Mobile Software P03489 U08223Data Structures P02345 U08071NetworksP03489 Staff No. First Name Last Name P03489FayeMitchell P02345DavidSutton P01234JoeBloggs Module No. TitleModule Leader First Name Last Name U08928Mobile Software P03489FayeMitchell U08223Data Structures P02345DavidSutton U08071NetworksP03489FayeMitchell A join combines two tables, usually by taking rows from one table and looking for rows in the second whose primary key matches a foreign key in the first

7 SQL The Structured (English) Query Language, or SQL for short. Is an almost universally used language for the construction of relational database queries. SELECT * FROM Modules where Leader = "P03489"; SELECT ModuleNo, Title from Modules; SELECT ModuleNo, Title FROM Modules WHERE Leader ="P03489"; A projection query A selection query Projection and selection in one query

8 SQLITE  SQLite is a highly popular “embedded” data base management system.  “Embedded” means that programs can access the database without having to talk to some external server.  Android is lightweight (an approx 350Kb library) and open source.  Included in Android and many other software systems.

9 PERSISTENCE IN ANDROID  Android provides a number of ways of achieving persistence, including:  Shared Preferences (key-value pairs often used for storing user preferences)  Local files  SQLite databases  Content Providers (see next slide)

10 CONTENT PROVIDERS  Content Providers allow applications to store, and potentially share, data in a standard form.  The data is wrapped up so that it looks as if it is in the form of tables (often the data will be stored in an SQLite database, so it actually is in that form, but it doesn’t have to be).  Each content provider has a URI (Uniform Resource Identifier) beginning with the scheme “content://”. For example content://user_dictionary/words is the URI for the Android content provider in which users may store the spellings of any non-standard words that they might want to use.

11 PERMISSIONS AND CONTENT PROVIDERS  If an application wants to use a content provider then its manifest must contain a element that specifically says that it needs permission to access the provider in a particular way. For example an app that needs to read the user dictionary must request android.permission.READ_USER_DICTIONARY in its manifest.  When a user installs an app they will be asked whether they want to grant the app the permissions that its manifest says that it needs.

12 ANDROID NATIVE CONTENT PROVIDERS  Android contains “native” content providers that give access to among, other things a user’s:  Calendar  Browser history  Call log  Contacts  Media Store  Device Settings  In the rest of this week’s lecture we will create a simple application that accesses the contacts provider.  Next week, we will learn how to create our own content providers.

13 THIS WEEK’S TASK  This week’s practical task is to create an application that shows a list of our contacts and displays the contact photo of a selected contact.

14 A DIGRESSION ON TO DEVELOPMENT METHODOLOGIES  There are two different kinds of methodology that one can adopt when developing a software system:  “Waterfall” or “Big Design Up Front” methodologies require you to have a complete design for your finished product before you begin implementing it.  Iterative methodologies allow you to develop the project in stages. Each stage can be a sort of mini-waterfall in which you design and implement a system that has some, but not all of the features that you want. The Waterfall approach does not work well in cases where unexpected difficulties may crop up. This probably applies to anything you do as a student, so an iterative approach is probably better for any project or substantial coursework.

15 AN ITERATIVE PROTOTYPING APPROACH TO THIS WEEKS TASK  Rather than attempting to implement this week’s task in one go, we will take an iterative approach and build three versions of the project.  Version 1: Simply lists our contacts in a text view.  Version 2: Creates a ListView displaying our contacts. Allows us to select and display details of any contact in the list, but does not display the contact photo.  Version 3: Finished system with display of contact photos.

16 A NOTE ON AVDS  To test the final version of the application, you will need to create an AVD with an SD card large enough to hold some contact photos, and you will need to actually get photos to put on that SD card.  This can be a bit fiddly, so it might be better to use a simpler AVD for the first two versions.

17 APPLICATION VERSION 1 Our first version of the application will just read the contacts database and display the name and id of each contact in a TextView This is a TextView, not a ListView!

18 PROBLEMS TO SOLVE  Our application needs to request permission access to the Contacts Content Provider.  It needs to find out the URI of the Contacts Content Provider.  It needs to work through the Contacts database and read appropriate data from each entry.

19 PERMISSIONS  Permissions for an application need to be added to the manifest. It is probably easiest to use graphical editor for this file (you need to select the “Permissions” tab).  Click on “Add…” and then select “Uses Permission” from the dialog that appears.

20 PERMISSIONS  Select ‘Uses Permission” and then pick the “READ_CONTACTS” permission

21 ANDROID MANIFEST <manifest xmlns:android="http://schemas.android.com/apk/res/android" package="brookes.ac.uk.contactlistv1" android:versionCode="1" android:versionName="1.0" > <uses-sdk android:minSdkVersion="8" android:targetSdkVersion="17" /> <application android:allowBackup="true” …

22 FINDING THE CONTACTS PROVIDER  The Contacts Provider exposes a number of tables to the user. The table we will be interested in for this week’s task is the “Contacts” table.  The ContractsContact class contains details of the “contract” between the Contacts Content Provider and applications that use it. That is to say that it provides details of the URIs, column names, etc. that will be user.  The class ContactsContract.Contacts class contains details specific to the Contacts table. It defines a number of constants including:  CONTENT_URI the URI of the contacts table.  DISPLAY_NAME the name of the column which contains names of contacts  _ID the name of a column containing a unique ID for each row

23 READING FROM A CONTENT PROVIDER  To read from a content provider we make use of a Cursor.  A Cursor is associated with a particular query over a content provider, and at any point in time is pointing at a particular row in that query. getCount() moveToFirst() moveToNext() moveToPosition(int position) getString(int columnIndex) getInt(int columnIndex) getColumnIndexOrThrow( String columnName) Cursor Get the number of rows in the query Move cursor to first row in query Move cursor to next row in query Move cursor to specified row in query Get value at a particular column in query (throws an exception if type is not what was expected). Get the index of a particular column (e.g. column “Name” might be at index 2). Throws an exception if there is no column with the specified name. N.B We are only showing a selection of the methods in the Cursor class

24 QUERYING A CONTENT PROVIDER AND OBTAINING A CURSOR The Activity class contains a method managedQuery that allows us to pass a query to a content provider and obtain Cursor over that query. N.B. This method is deprecated in recent versions of Android. If you want to be up to date you can use the CursorLoader class instead. We will stick with the old fashioned version because there are more tutorial examples of its use. public final Cursor managedQuery (Uri uri, String[] projection, String selection, String[] selectionArgs, String sortOrder) Parameters: uri – the URI of the content provider projection, selection, selectionArgs – allow us to specify a projection and/or selection query. If they are null then the cursor is for an entire table. sortOrder – allows us to specify the way rows in the query are to be ordered. Can be null if we are not bothered what order rows are in.

25 VERSION 1 CODE protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_contact_list_v1); TextView contactText = (TextView) findViewById(R.id.contact_list_text); Cursor cursor = managedQuery( ContactsContract.Contacts.CONTENT_URI, null,null,null,null); int idIdx = cursor.getColumnIndexOrThrow( ContactsContract.Contacts._ID); int nameIdx= cursor.getColumnIndexOrThrow ( ContactsContract.Contacts.DISPLAY_NAME); if (cursor.moveToFirst()) { do { String name = cursor.getString(nameIdx); int id = cursor.getInt(idIdx); contactList += id + ". " + name + "\n”; } while (cursor.moveToNext()); } contactText.setText(contactList); }

26 WHAT YOU SHOULD SEE WHEN YOU RUN THE APP

27 VERSION 2 Version 2 of our application will display the contact list in a ListView. When we click on an item in the ListView details of that item will be displayed in a TextView beneath it. This is a ListView This is a TextView. The information it contains is not very useful, but it allows us to check that our application works

28 PROBLEMS TO BE SOLVED  We need to bind a ListView to data returned by a Cursor.  We need to implement an OnClickListener to display values at a given row in the ListView.

29 CURSORADAPTERS  A CursorAdapter works in a similar way as the ArrayAdapters we have used in previous weeks. It takes data from a Cursor and uses it to populate rows in a ListView 1 Ratty 2 Mole 3 Badger 4 Toad 5 Otter ListViewCursorAdapterCursorContent Provider The Cursor allows us to iterate through the rows produced by a query over the content provider. The CursorAdapter examines each row returned by the Cursor and generates a View which is added to the ListView

30 CREATING A CURSOR ADAPTER  The Android API includes a SimpleCursorAdapter class.  This populates the ListView by inflating a layout file and populating individual views in that layout with the data from specified columns in the query.

31 LAYOUT FILE FOR LISTVIEW ROWS <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" android:layout_width="match_parent" android:layout_height="match_parent" android:orientation="horizontal" > <TextView android:id="@+id/id_text" android:layout_width="wrap_content" android:layout_height="wrap_content" /> <TextView android:id="@+id/name_text" android:layout_width="wrap_content" android:layout_height="wrap_content" android:paddingLeft="20sp" /> This LinearLayout describes the arrangement of a row in the ListView This TextView will be populated with values from the _ID column of a query. This TextView will be populated with values from the DISPLAY_NAME column of a query. The paddingLeft creates a gap between it an the other TextView

32 MAIN ACTIVITY (SLIDE 1) public class ContactListV2 extends Activity { private Cursor cursor; private int nameIdx; private int idIdx; private TextView detailsText; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_contact_list_v2); cursor = managedQuery(ContactsContract.Contacts.CONTENT_URI, null, null, null, null); String [] from = new String[] {ContactsContract.Contacts._ID, ContactsContract.Contacts.DISPLAY_NAME}; int[] to = new int[] {R.id.id_text, R.id.name_text}; These are the rows we want to read from the query. These are the TextViews that we want to populate

33 MAIN ACTIVITY (SLIDE 2) SimpleCursorAdapter adapter = new SimpleCursorAdapter(this, R.layout.contact_details_layout, cursor, from, to); ListView listView = (ListView) findViewById(R.id.contact_list); listView.setAdapter(adapter); This is the layout file that describes rows in the ListView N.B The SimpleCursorAdapter used here is deprecated in recent versions of Android

34 MAIN ACTIVITY (SLIDE 3) nameIdx = cursor.getColumnIndexOrThrow ( ContactsContract.Contacts.DISPLAY_NAME); idIdx = cursor.getColumnIndexOrThrow(ContactsContract.Contacts._ID); detailsText = (TextView) findViewById(R.id.details_text); listView.setOnItemClickListener(new OnItemClickListener() { public void onItemClick(AdapterView parent, View view, int position, long id) { cursor.moveToPosition(position); String name = cursor.getString(nameIdx); String personId = cursor.getString(idIdx); detailsText.setText("Id: " + personId + " Name: " + name); } });

35 WHAT WE SHOULD SEE NOW

36 VERSION 3 Version 3 of our application will display the contact photo of the selected icon.

37 PROBLEMS TO SOLVE  Add photos to contacts (if you don’t already have them).  Retrieve photos and display them.

38 ADDING PHOTOS TO THE CONTACTS  If you are working with the emulator, this is a bit fiddly.  You need to make sure that your emulator has a big enough SD card to store contact images (probably at least 500MB).  If you want to capture photos using the camera then you also need to set the camera on the emulator to either use your web cam, or to be emulated.  You can also capture images by using the emulator’s browser, searching for images and long clicking on them. The long click will give you the option of saving them. After this you can find the image by going to the downloads app on your emulator. Select the image and then click on the “Menu” button. This should give you the option of setting the image as a contact photo (this may not work with all image types, but JPEGs should be fine).

39 READING PHOTO DATA To read photo data we need to  Get a URI for a particular contact. This is done by taking the URI for the Contacts Content Provider, and adding an extra item to the path, to indicate an individual entry.  For example to get the first element in the contacts table content://com.android.contacts/contacts/1  Set up an input stream to read the photo data.  Use that data to create a bitmap image, which we then associate with an ImageView which we will to our layout.

40 CODE TO ADD TO THE MAIN LAYOUT FILE <LinearLayout … <ListView … <ImageView android:id="@+id/contact_image" android:layout_width="wrap_content" android:layout_height="wrap_content" android:src="@android:drawable/sym_def_app_icon" /> <TextView … />

41 CODE TO ADD TO THE ONITEMCLICK LISTENER String personId = cursor.getString(idIdx); Uri person = ContentUris.withAppendedId( ContactsContract.Contacts.CONTENT_URI, Long.parseLong(personId)); detailsText.setText("Id: " + personId + " Name: " + name + " URI: " + person); InputStream photoStream = ContactsContract.Contacts.openContactPhotoInputStream (getContentResolver(), person);

42 CODE TO ADD TO THE ONITEMCLICK LISTENER if (photoStream != null) { Bitmap photo = BitmapFactory.decodeStream(photoStream); contactImage.setImageBitmap(photo); try { photoStream.close(); } catch (IOException e) { e.printStackTrace(); } else { contactImage.setImageResource (android.R.drawable.sym_def_app_icon); } });

43 WHAT WE SHOULD NOW SEE When you click on an row in the list, you should now see its photo, or a default image if there is no photo.

44 SUMMARY  Persistence in Android can be achieved using files, databases, shared preferences and/or content providers.  A content provider is identified with a URI beginning with the scheme content://  Cursors allow us to examine the results of queries over content providers.  CursorAdapters can be used to map cursor rows on to ListView rows.  Contact details, including photos, can be obtained from the Contacts content provider.


Download ppt "David Sutton USING CONTENT PROVIDERS. TOPICS COVERED THIS WEEK  Persistence  Introduction to databases  Content providers  Cursors  Cursor adapters."

Similar presentations


Ads by Google