Mobile Programming Lecture 10. ContentProviders

Similar documents
Database Development In Android Applications

CS371m - Mobile Computing. Content Providers And Content Resolvers

ContentProvider & ContentResolver ContentResolver methods CursorLoader Implementing ContentProviders

CS Android. Vitaly Shmatikov

How-to s and presentations. Be prepared to demo them in class. ons

CSCU9YH: Development with Android

App Development for Smart Devices. Lec #5: Content Provider

07. Data Storage

ContentProviders. CS 282 Principles of Operating Systems II Systems Programming for Android

Eng. Jaffer M. El-Agha Android Programing Discussion Islamic University of Gaza. Data persistence

An Android Studio SQLite Database Tutorial

Automatically persisted among application sessions

Learn about Android Content Providers and SQLite

Content Provider. Introduction 01/03/2016. Session objectives. Content providers. Android programming course. Introduction. Built-in Content Provider

Object-Oriented Databases Object-Relational Mappings and Frameworks. Alexandre de Spindler Department of Computer Science

Mobile Application Development Android

Mobile and Ubiquitous Computing: Android Programming (part 4)

Applied Cognitive Computing Fall 2016 Android Application + IBM Bluemix (Cloudant NoSQL DB)

SharedPreferences Internal Storage External Storage SQLite databases

Accelerating Information Technology Innovation

Mobile Application Development Android

Managing Data. However, we'll be looking at two other forms of persistence today: (shared) preferences, and databases.

Change in Orientation. Marco Ronchetti Università degli Studi di Trento

Agenda. Overview of Xamarin and Xamarin.Android Xamarin.Android fundamentals Creating a detail screen

Android Application Model II. CSE 5236: Mobile Application Development Instructor: Adam C. Champion, Ph.D. Course Coordinator: Dr.

Mobile Computing Practice # 2d Android Applications Local DB

Mobile Programming Lecture 3. Resources, Selection, Activities, Intents

Android: Data Storage

SQLite. 5COSC005W MOBILE APPLICATION DEVELOPMENT Lecture 6: Working with Databases. What is a Database Server. Advantages of SQLite

Android Programming - Jelly Bean

The Basis of Data. Steven R. Bagley

Mobile Computing Practice # 2c Android Applications - Interface

Android Application Development

Data storage and exchange in Android

A Tour of Android. and some of it s APIs. Bryan Noll

SQLite Database. References. Overview. Structured Databases

SharedPreference. <map> <int name="access_count" value="3" /> </map>

Produced by. Mobile Application Development. Higher Diploma in Science in Computer Science. Eamonn de Leastar

Creating a Custom ListView

Android Specifics. Jonathan Diehl (Informatik 10) Hendrik Thüs (Informatik 9)

CS371m - Mobile Computing. Persistence - SQLite

Data storage overview SQLite databases

Developing Android Applications Introduction to Software Engineering Fall Updated 1st November 2015

Required Core Java for Android application development

Writing Efficient Drive Apps for Android. Claudio Cherubino / Alain Vongsouvanh Google Drive Developer Relations

Mobile Application Development Android

CS378 -Mobile Computing. Content Providers

Diving into Android. By Jeroen Tietema. Jeroen Tietema,

Wireless Vehicle Bus Adapter (WVA) Android Library Tutorial

10.1 Introduction. Higher Level Processing. Word Recogniton Model. Text Output. Voice Signals. Spoken Words. Syntax, Semantics, Pragmatics

ANDROID APPS DEVELOPMENT FOR MOBILE AND TABLET DEVICE (LEVEL I)

CS378 -Mobile Computing. Persistence -SQLite

CMSC436: Fall 2013 Week 4 Lab

Produced by. Mobile Application Development. Higher Diploma in Science in Computer Science. Eamonn de Leastar

Accelerating Information Technology Innovation

ANDROID APPS DEVELOPMENT FOR MOBILE AND TABLET DEVICE (LEVEL I)

Lecture 2 Android SDK

Adapter.

Android development. Outline. Android Studio. Setting up Android Studio. 1. Set up Android Studio. Tiberiu Vilcu. 2.

Android Programming Lecture 16 11/4/2011

Mobile Programming Lecture 7. Dialogs, Menus, and SharedPreferences

Practical 1.ListView example

Android App Development. Mr. Michaud ICE Programs Georgia Institute of Technology

Mobile User Interfaces

EMBEDDED SYSTEMS PROGRAMMING Android Services

Mobile Programming Lecture 5. Composite Views, Activities, Intents and Filters

Single Application Persistent Data Storage. CS 282 Principles of Operating Systems II Systems Programming for Android

Safety First - Android sicher programmieren! Benjamin Reimold & Stephan Linzner

Android Programming Lecture 15 11/2/2011

Android HelloWorld - Example. Tushar B. Kute,

Islamic University of Gaza. Faculty of Engineering. Computer Engineering Department. Mobile Computing ECOM Eng. Wafaa Audah.

MyDatabaseHelper. public static final String TABLE_NAME = "tbl_bio";

CS 234/334 Lab 1: Android Jump Start

Android Components Android Smartphone Programming. Outline University of Freiburg. Data Storage Database University of Freiburg. Notizen.

Android Programs Day 5

ListView Containers. Resources. Creating a ListView

M.C.A. Semester V Subject: - Mobile Computing (650003) Week : 2

App Development for Smart Devices. Lec #18: Advanced Topics

Intents. Your first app assignment

Understand applications and their components. activity service broadcast receiver content provider intent AndroidManifest.xml

Produced by. Design Patterns. MSc in Computer Science. Eamonn de Leastar

Android User Interface Android Smartphone Programming. Outline University of Freiburg

Mobile Programming Lecture 2. Layouts, Widgets, Toasts, and Event Handling

Mobile Application Development

Screen Slides. The Android Studio wizard adds a TextView to the fragment1.xml layout file and the necessary code to Fragment1.java.

Upon completion of the second part of the lab the students will have:

Produced by. Mobile Application Development. David Drohan Department of Computing & Mathematics Waterford Institute of Technology

Android Application Development 101. Jason Chen Google I/O 2008

INTRODUCTION TO ANDROID

CS 4518 Mobile and Ubiquitous Computing Lecture 4: Data-Driven Views, Android Components & Android Activity Lifecycle Emmanuel Agu

Produced by. Mobile Application Development. Higher Diploma in Science in Computer Science. Eamonn de Leastar

Android System Architecture. Android Application Fundamentals. Applications in Android. Apps in the Android OS. Program Model 8/31/2015

Solving an Android Threading Problem

THE CATHOLIC UNIVERSITY OF EASTERN AFRICA A. M. E. C. E. A

Produced by. Mobile Application Development. Higher Diploma in Science in Computer Science. Eamonn de Leastar

Lecture 14. Android Application Development

Our First Android Application

EMBEDDED SYSTEMS PROGRAMMING Application Tip: Saving State

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

Produced by. Mobile Application Development. David Drohan Department of Computing & Mathematics Waterford Institute of Technology

Transcription:

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? Why at that point? How would you implement turn-by-turn directions? When should you disable a Sensor?

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?

Agenda ContentProviders Querying existing databases Creating a database for your app Inserting data Updating data Deleting data Content provider permissions Viewing ContentProvider data

Android Application Components 1. Activity 2. Broadcast Receiver 3. Content Provider 4. Service

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

Content Provider Basics When you want to access data in a Content Provider, you 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.

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

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 word app id frequency locale _ID mapreduce user1 100 en_us 1 precompiler user14 200 fr_fr 2 applet user2 225 fr_ca 3 const user1 255 pt_br 4 int user5 100 en_uk 5

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

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

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... _ID LOOKUP_KEY NAME_RAW_CONTACT_ID DISPLAY_NAME_PRIMARY PHOTO_ID PHOTO_URI IN_VISIBLE_GROUP HAS_PHONE_NUMBER TIMES_CONTACTED long String long String long long int int int

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; public void oncreate(bundle savedinstancestate) { super.oncreate(savedinstancestate);

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; 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 public void oncreate(bundle savedinstancestate) { super.oncreate(savedinstancestate);

Constructing a Query Consider the following SQL queries

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

Constructing a Query - Query 1 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);

Constructing a Query - Query 1 public void oncreate(bundle savedinstancestate) { mcursor = getcontentresolver().query( ContactsContract.Contacts.CONTENT_URI, null, null, null, null); When you want to access data in a content provider, you need to use a ContentResolver. You can get the ContentResolver by calling getcontentresolver() 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);

Constructing a Query - Query 1 public void oncreate(bundle savedinstancestate) { mcursor = getcontentresolver().query( ContactsContract.Contacts.CONTENT_URI, null, null, null, It returns a Cursor null); object. 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);

Constructing a Query - Query 1 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); Using a Cursor object, you can call the query() method to execute a query on a content provider. setlistadapter(mcursoradapter);

Constructing a Query - Query 1 public void oncreate(bundle savedinstancestate) { mcursor = getcontentresolver().query( ContactsContract.Contacts.CONTENT_URI, null, null, null, null); mlistcolumns = new String[] { ContactsContract.Contacts.DISPLAY_NAME Passing null means return all columns, ; mlistitems = new int[] { R.id.contact_name ; mcursoradapter = new SimpleCursorAdapter(this, R.layout.query1, mcursor, mlistcolumns, mlistitems); The second argument is a String array (i.e. String[ ]) of which columns we want to be returned by the query. i.e. SELECT * setlistadapter(mcursoradapter);

Constructing a Query - Query 1 public void oncreate(bundle savedinstancestate) { mcursor = getcontentresolver().query( ContactsContract.Contacts.CONTENT_URI, null, null, null, null); The first argument to Cursor.query() is a Uri. It specifies the table that you want to access, i.e. SELECT * FROM table 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);

Constructing a Query - Query 1 public void oncreate(bundle savedinstancestate) { mcursor = getcontentresolver().query( ContactsContract.Contacts.CONTENT_URI, null, null, null, null); ContactsContract is a content provider. You can think of it as the database 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);

Constructing a Query - Query 1 public void oncreate(bundle savedinstancestate) { mcursor = getcontentresolver().query( ContactsContract.Contacts.CONTENT_URI, null, null, null, null); ContactsContract.Contacts is a content provider. You can think of it as a table in the database 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);

Constructing a Query - Query 1 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); This is one of the Uris for the table, which says how you want to access the table. Some tables have multiple Uris setlistadapter(mcursoradapter);

Constructing a Query - Query 1 public void oncreate(bundle savedinstancestate) { mcursor = getcontentresolver().query( ContactsContract.Contacts.CONTENT_URI, null, null, null, null); mlistcolumns = new String[] { ContactsContract.Contacts.DISPLAY_NAME query. Passing null means don't ; mlistitems = new int[] { R.id.contact_name ; The third argument is a String. Here you specify the conditions for your specify any conditions mcursoradapter = new SimpleCursorAdapter(this, R.layout.query1, mcursor, mlistcolumns, mlistitems); setlistadapter(mcursoradapter);

Constructing a Query - Query 1 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); The fourth argument is a String[ ]. We will get back to this soon setlistadapter(mcursoradapter);

Constructing a Query - Query 1 public void oncreate(bundle savedinstancestate) { mcursor = getcontentresolver().query( ContactsContract.Contacts.CONTENT_URI, null, null, null, null); The fifth argument is a String. It says how we want to sort our results. Passing null means don't specify any sorting 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);

Constructing a Query - Query 1 public void oncreate(bundle savedinstancestate) { mcursor = getcontentresolver().query( ContactsContract.Contacts.CONTENT_URI, null, null, null, null); SELECT * FROM ContactsContract.Contacts 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);

Constructing a Query - Query 1 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 ; Our query is now complete, and the Cursor can iterate through the results. But since we want to attach our results to a ListView, we need to add a few more lines of code mcursoradapter = new SimpleCursorAdapter(this, R.layout.query1, mcursor, mlistcolumns, mlistitems); setlistadapter(mcursoradapter);

Constructing a Query - Query 1 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 ; Although our query was on all columns, here we create a String array of the columns we want to have displayed in our ListView. mcursoradapter = new SimpleCursorAdapter(this, R.layout.query1, mcursor, mlistcolumns, mlistitems); setlistadapter(mcursoradapter);

Constructing a Query - Query 1 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); The column names are usually constants that you can reference via the database table setlistadapter(mcursoradapter);

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 has the following TextView

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" />

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" Note the android:id attribute of the TextView android:layout_height="wrap_content" android:text="large Text" android:textappearance="?android:attr/textappearancelarge"/>

Constructing a Query - Query 1 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);

Constructing a Query - Query 1 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); So, String[ ] mlistcolumns specifies which columns we want to select setlistadapter(mcursoradapter);

Constructing a Query - Query 1 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); and int[] mlistitems is a corresponding array, telling us where to place the actual value of the DISPLAY_NAME setlistadapter(mcursoradapter);

Constructing a Query - Query 1 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); It will be placed in this TextView, whose android:id="@+id/contact_name" setlistadapter(mcursoradapter);

Constructing a Query - Query 1 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)

Constructing a Query - Query 1 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); First argument is a Context setlistadapter(mcursoradapter);

Constructing a Query - Query 1 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); Second argument is our Layout XML file resource used to construct the ListView setlistadapter(mcursoradapter);

Constructing a Query - Query 1 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

Constructing a Query - Query 1 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

Constructing a Query - Query 1 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 our int array of TextView resources

Constructing a Query - Query 1 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, Finally, we call setlistadapter and mlistitems); pass our SimpleCursorAdapter setlistadapter(mcursoradapter);

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

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"

Constructing a Query - Query 2 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);

Constructing a Query - Query 2 public void oncreate(bundle savedinstancestate) { mprojection = new String[] { ContactsContract.Contacts._ID, ContactsContract.Contacts.DISPLAY_NAME ; mcursor = getcontentresolver().query( Here we make a String array ContactsContract.Contacts.CONTENT_URI, of the columns that we need. 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);

Constructing a Query - Query 2 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); Instead of passing null, we pass our String array of mlistcolumns = new String[] { column names ContactsContract.Contacts.DISPLAY_NAME ; mlistitems = new int[] { R.id.contact_name ; mcursoradapter = new SimpleCursorAdapter(this, R.layout.query1, mcursor, mlistcolumns, mlistitems);

Constructing a Query - Query 2 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[] SELECT { _ID, DISPLAY_NAME FROM ContactsContract.Contacts ContactsContract.Contacts.DISPLAY_NAME ; mlistitems = new int[] { R.id.contact_name ; mcursoradapter = new SimpleCursorAdapter(this, R.layout.query1, mcursor, mlistcolumns, mlistitems);

Constructing a Query - Query 2 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, This hasn't changed 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);

Constructing a Query - Query 2 See the query2() method inside of ContactsContractQueryExample.tar

Constructing a Query - Query 3 Consider the following SQL query SELECT _ID, DISPLAY_NAME FROM ContactsContract.Contacts WHERE HAS_PHONE_NUMBER = 1 "Get the _ID and DISPLAY_NAME for all contacts that have phone numbers"

Constructing a Query - Query 3 public void oncreate(bundle savedinstancestate) { mprojection = new String[] { ContactsContract.Contacts. _ID, ContactsContract.Contacts. DISPLAY_NAME ; mselectionclause = ContactsContract.Contacts. HAS_PHONE_NUMBER + " =?"; mselectionargs = new String[]{ "1"; 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);

Constructing a Query - Query 3 mprojection has not changed public void oncreate(bundle savedinstancestate) { mprojection = new String[] { ContactsContract.Contacts._ID, ContactsContract.Contacts.DISPLAY_NAME ; mselectionclause = ContactsContract.Contacts.DISPLAY_NAME + " =? "; mselectionargs = new String[]{"Fred"; 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);

Constructing a Query - Query 3 public void oncreate(bundle savedinstancestate) { Here we use "?" as a placeholder. ContactsContract.Contacts.HAS_PHONE_NUMBER mprojection = new String[] { ContactsContract.Contacts._ID, is a String, so we're appending ContactsContract.Contacts.DISPLAY_NAME " =?" to this String0 ; mselectionclause = ContactsContract.Contacts.HAS_PHONE_NUMBER + " =? "; mselectionargs = new String[]{"1"; 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);

Constructing a Query - Query 3 public void oncreate(bundle savedinstancestate) { mprojection = new String[] { ContactsContract.Contacts._ID, ContactsContract.Contacts.DISPLAY_NAME ; mselectionclause = ContactsContract.Contacts.HAS_PHONE_NUMBER + " =? "; mselectionargs = new String[]{"1"; Each "?" will be replaced by an element mcursor = getcontentresolver().query( in this String array, sequentially. In this case we only have one "?" 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);

Constructing a Query - Query 3 public void oncreate(bundle savedinstancestate) { mprojection = new String[] { ContactsContract.Contacts._ID, ContactsContract.Contacts.DISPLAY_NAME ; mselectionclause = ContactsContract.Contacts.HAS_PHONE_NUMBER + " =? "; mselectionargs = new String[]{"1"; mcursor = getcontentresolver().query( ContactsContract.Contacts.CONTENT_URI, mprojection, mselectionclause, mselectionargs, null); mlistcolumns = new String[] { Now instead of passing null for the ContactsContract.Contacts.DISPLAY_NAME selection clause, we pass our ; mlistitems = new int[] { R.id.contact_name mselectionclause ; String mcursoradapter = new SimpleCursorAdapter(this, R.layout.query1, mcursor, mlistcolumns, mlistitems);

Constructing a Query - Query 3 public void oncreate(bundle savedinstancestate) { mprojection = new String[] { ContactsContract.Contacts._ID, ContactsContract.Contacts.DISPLAY_NAME ; mselectionclause = ContactsContract.Contacts.HAS_PHONE_NUMBER + " =? "; mselectionargs = new String[]{"1"; mcursor = getcontentresolver().query( ContactsContract.Contacts.CONTENT_URI, mprojection, mselectionclause, mselectionargs, null); mlistcolumns = new String[] { Instead of passing null, we pass our ContactsContract.Contacts.DISPLAY_NAME ; selection args array mselectionargs mlistitems = new int[] { R.id.contact_name ; mcursoradapter = new SimpleCursorAdapter(this, R.layout.query1, mcursor, mlistcolumns, mlistitems);

Constructing a Query - Query 3 public void oncreate(bundle savedinstancestate) { mprojection = new String[] { ContactsContract.Contacts._ID, ContactsContract.Contacts.DISPLAY_NAME ; mselectionclause = ContactsContract.Contacts.HAS_PHONE_NUMBER + " =? "; mselectionargs = new String[]{"1"; mcursor = getcontentresolver(). query( ContactsContract.Contacts.CONTENT_URI, mprojection, mselectionclause, mselectionargs, null); SELECT _ID, DISPLAY_NAME mlistcolumns = new String[] { FROM ContactsContract.Contacts WHERE ContactsContract.Contacts.DISPLAY_NAME HAS_PHONE_NUMBER = 1 ; mlistitems = new int[] { R.id.contact_name ; mcursoradapter = new SimpleCursorAdapter(this, R.layout.query1, mcursor, mlistcolumns, mlistitems);

Constructing a Query - Query 3 public void The? is oncreate(bundle a placeholder here, savedinstancestate) just { mprojection as %d or %s = is new a placeholder String[] { ContactsContract.Contacts._ID, when you call printf() ContactsContract.Contacts.DISPLAY_NAME ; mselectionclause = ContactsContract.Contacts.HAS_PHONE_NUMBER + " =? "; mselectionargs = new String[]{"1"; 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);

Constructing a Query - Query 3 See the query3() method inside of ContactsContractQueryExample.tar

Constructing a Query - Query 4 Consider the following SQL query SELECT _ID, DISPLAY_NAME, TIMES_CONTACTED FROM ContactsContract.Contacts WHERE HAS_PHONE_NUMBER = 1 AND TIMES_CONTACTED > 5 "Get the _ID and DISPLAY_NAME for all contacts that have a phone number and that I've contacted more than 5 times"

Constructing a Query - Query 4 public void oncreate(bundle savedinstancestate) { mprojection = new String[] { ContactsContract.Contacts._ID, ContactsContract.Contacts.DISPLAY_NAME ; mselectionclause = ContactsContract.Contacts.HAS_PHONE_NUMBER + " =? AND " + ContactsContract.Contacts.TIMES_CONTACTED + " >? "; mselectionargs = new String[]{ "1", "5" ; mcursor = getcontentresolver().query( ContactsContract.Contacts.CONTENT_URI, mprojection, mselectionclause, mselectionargs, 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);

Constructing a Query - Query 4 We modify our selection clause slightly, to also have the condition public that void the oncreate(bundle contact must have savedinstancestate) been { mprojection contacted more = new than String[] 5 times { ContactsContract.Contacts._ID, ContactsContract.Contacts.DISPLAY_NAME ; mselectionclause = ContactsContract.Contacts.HAS_PHONE_NUMBER + " =? AND " + ContactsContract.Contacts.TIMES_CONTACTED + " >? "; mselectionargs = new String[]{"1", "5"; mcursor = getcontentresolver().query( ContactsContract.Contacts.CONTENT_URI, mprojection, mselectionclause, mselectionargs, 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);

Constructing a Query - Query 4 public void oncreate(bundle savedinstancestate) { mprojection = new String[] { ContactsContract.Contacts._ID, ContactsContract.Contacts.DISPLAY_NAME ; mselectionclause = ContactsContract.Contacts.HAS_PHONE_NUMBER + " =? AND " + Since we have a new condition, ContactsContract.Contacts.TIMES_CONTACTED + " >? "; we also add the argument to the mselectionargs = new String[]{"1", "5"; condition to our selection mcursor = getcontentresolver().query( arguments String array ContactsContract.Contacts.CONTENT_URI, mprojection, mselectionclause, mselectionargs, 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);

Constructing a Query - Query 4 public void oncreate(bundle savedinstancestate) { mprojection = new String[] { ContactsContract.Contacts._ID, ContactsContract.Contacts.DISPLAY_NAME ; mselectionclause = ContactsContract.Contacts.HAS_PHONE_NUMBER + " =? AND " + ContactsContract.Contacts.TIMES_CONTACTED + " >? "; mselectionargs = new String[]{"1", "5"; mcursor = getcontentresolver().query( ContactsContract.Contacts.CONTENT_URI, mprojection, mselectionclause, mselectionargs, null); SELECT _ID, DISPLAY_NAME, TIMES_CONTACTED mlistcolumns = new String[] { FROM ContactsContract.Contacts WHERE HAS_PHONE_NUMBER ContactsContract.Contacts.DISPLAY_NAME = 1 ; mlistitems = AND new int[] TIMES_CONTACTED { R.id.contact_name > 5 ; mcursoradapter = new SimpleCursorAdapter(this, R.layout.query1, mcursor, mlistcolumns, mlistitems);

Constructing a Query - Query 4 public void oncreate(bundle savedinstancestate) { mprojection = new String[] { ContactsContract.Contacts._ID, ContactsContract.Contacts.DISPLAY_NAME ; mselectionclause = ContactsContract.Contacts.HAS_PHONE_NUMBER + " =? AND " + ContactsContract.Contacts.TIMES_CONTACTED The rest hasn't + " >? "; mselectionargs = new String[]{"1", "5"; changed mcursor = getcontentresolver().query( ContactsContract.Contacts.CONTENT_URI, mprojection, mselectionclause, mselectionargs, 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);

Constructing a Query - Query 4 See the query4() method inside of ContactsContractQueryExample.tar

Constructing a Query - Query 5 Consider the following SQL query SELECT _ID, DISPLAY_NAME FROM ContactsContract.Contacts WHERE HAS_PHONE_NUMBER = 1 ORDER BY DISPLAY_NAME "Get the _ID and DISPLAY_NAME for all contacts that have phone numbers, and sort the results by DISPLAY_NAME"

Constructing a Query - Query 5 FYI, we will build this query off of query3, not query4

Constructing a Query - Query 5 public void oncreate(bundle savedinstancestate) { mprojection = new String[] { ContactsContract.Contacts. _ID, ContactsContract.Contacts. DISPLAY_NAME ; mselectionclause = ContactsContract.Contacts. HAS_PHONE_NUMBER + " =? "; mselectionargs = new String[]{ "1" ; morderby = ContactsContract.Contacts. DISPLAY_NAME; mcursor = getcontentresolver().query( ContactsContract.Contacts. CONTENT_URI, mprojection, mselectionclause, mselectionargs, morderby); mlistcolumns = new String[] { ContactsContract.Contacts. DISPLAY_NAME ; mlistitems = new int[] { R.id. contact_name ; mcursoradapter = new SimpleCursorAdapter( this, R.layout.query1, mcursor, mlistcolumns, mlistitems);

Constructing a Query - Query 5 public void oncreate(bundle savedinstancestate) { mprojection = new String[] { ContactsContract.Contacts._ID, ContactsContract.Contacts.DISPLAY_NAME ; mselectionclause = ContactsContract.Contacts.HAS_PHONE_NUMBER Here we have + a String specifying the column by " =? "; which we want to sort. In this mselectionargs = new String[]{"1"; case, the DISPLAY_NAME morderby = ContactsContract.Contacts.DISPLAY_NAME; mcursor = getcontentresolver().query( ContactsContract.Contacts.CONTENT_URI, mprojection, mlistcolumns = new String[] { mselectionclause, mselectionargs, morderby); ContactsContract.Contacts.DISPLAY_NAME ; mlistitems = new int[] { R.id.contact_name ; mcursoradapter = new SimpleCursorAdapter(this, R.layout.query1, mcursor, mlistcolumns, mlistitems);

Constructing a Query - Query 5 public void oncreate(bundle savedinstancestate) { mprojection = new String[] { ContactsContract.Contacts._ID, ContactsContract.Contacts.DISPLAY_NAME ; mselectionclause = ContactsContract.Contacts.HAS_PHONE_NUMBER + " =? "; mselectionargs = new String[]{"1"; morderby = ContactsContract.Contacts.DISPLAY_NAME; mcursor = getcontentresolver(). query( ContactsContract.Contacts.CONTENT_URI, mprojection, mselectionclause, mselectionargs, morderby); mlistcolumns SELECT = new _ID, String[] DISPLAY_NAME { FROM ContactsContract.Contacts ContactsContract.Contacts.DISPLAY_NAME ; WHERE HAS_PHONE_NUMBER = 1 mlistitems = new int[] { R.id.contact_name ; ORDER BY DISPLAY_NAME mcursoradapter = new SimpleCursorAdapter(this, R.layout.query1, mcursor, mlistcolumns, mlistitems);

Constructing a Query - Query 5 See the query5() method inside of ContactsContractQueryExample.tar

Iterating through query results You may not always want to add the results from a query to a ListView. Sometimes you just need to go through the results one-by-one

Iterating through query results Cursor cursor = getcontentresolver().query( ContactsContract.Contacts.CONTENT_URI, projection, selectionclause, selectionargs, null); if (cursor!= null) { while (cursor.movetonext()) { cursor.getstring(1);

Iterating through query results Cursor cursor = getcontentresolver().query( ContactsContract.Contacts.CONTENT_URI, projection, selectionclause, selectionargs, null); if(cursor!= null) { while(cursor.movetonext()) { cursor.getstring(1); After executing the query...

Iterating through query results Cursor cursor = getcontentresolver().query( ContactsContract.Contacts.CONTENT_URI, projection, selectionclause, selectionargs, null); if(cursor!= null) { while(cursor.movetonext()) { cursor.getstring(1); Make sure that the Cursor is not null before using it

Iterating through query results Cursor cursor = getcontentresolver().query( ContactsContract.Contacts.CONTENT_URI, projection, selectionclause, selectionargs, null); if(cursor!= null) { while(cursor.movetonext()) { cursor.getstring(1); This returns true as long as there are more results to be fetched

Iterating through query results Cursor cursor = getcontentresolver().query( ContactsContract.Contacts.CONTENT_URI, projection, selectionclause, selectionargs, null); if(cursor!= null) { while(cursor.movetonext()) { cursor.getstring(1); Get the String represention of column number 1 (or use another integer if you want a different column value)

Iterating through query results See ContentProviderExample.tar

Creating a Content Provider There are two ways to store your data using a Content Provider 1. File data photos, audio, video, etc 2. Structured data data fit for a database We will look at structured data using SQLite databases

Creating a Content Provider Because writing to databases is a sensitive operation, in the next examples we will perform operations on our own SQLite database

Creating a Content Provider The steps for creating an SQLite DB for your app is not what you're used to, because doing it right means that you also need to understand URIs

Creating a Content Provider You should add the content provider via the Android Studio menu Click File > New > Other > Content Provider Provide a name for the Content Provider Provide an Authorities URI This should be your package name followed by.provider Click Finish

Creating a Content Provider Decide on the name of your database now, and we will add it as a field to the ContentProvider public class MyProvider extends ContentProvider { public final static String DBNAME = "NameDatabase";...

Creating a Content Provider Next we need to add a String containing the SQL query for creating the necessary tables for our database In our example, we will create a table in our database with the following structure Column Name _ID FirstName LastName Type Integer PRIMARY KEY TEXT TEXT

Creating a Content Provider public class MyProvider extends ContentProvider { public final static String DBNAME = "NameDatabase"; private static final String SQL_CREATE_MAIN = "CREATE TABLE Users ( " + " _ID INTEGER PRIMARY KEY, " + "FirstName TEXT, " + "LastName TEXT )";... If you're unfamiliar with SQL, see this page

Creating a Content Provider We will also add the CONTENT_URI Uri as a convenient way to get the URI for our database. We make it final because we don't want it to be modified after it has been set

Creating a Content Provider public class MyProvider extends ContentProvider { public final static String DBNAME = "NameDatabase"; private static final String SQL_CREATE_MAIN = "CREATE TABLE Users ( " + " _ID INTEGER PRIMARY KEY, " + "FirstName TEXT, " + "LastName TEXT )"; public static final Uri CONTENT_URI = Uri.parse("content://my.package.name.provider");...

Creating a Content Provider Before we implement any of the methods inside of your new ContentProvider, we need to add an inner class which extends SQLiteOpenHelper. This class will take care of Opening the database if it exists Creating it if it does not

Creating a Content Provider public class MyProvider extends ContentProvider {... protected static final class MainDatabaseHelper extends SQLiteOpenHelper { MainDatabaseHelper(Context context) { super(context, "NamesDatabase", null, 1); public void oncreate(sqlitedatabase db) { db.execsql(sql_create_main); public void onupgrade(sqlitedatabase arg0, int arg1, int arg2) {

Creating a Content Provider public class MyProvider extends ContentProvider {... The String we created previously protected static final class MainDatabaseHelper extends SQLiteOpenHelper { are here MainDatabaseHelper(Context context) { super(context, "NamesDatabase", null, 1); public void oncreate(sqlitedatabase db) { db.execsql(sql_create_main); public void onupgrade(sqlitedatabase arg0, int arg1, int arg2) {

Creating a Content Provider public class MyProvider extends ContentProvider {... protected static final class MainDatabaseHelper extends SQLiteOpenHelper { MainDatabaseHelper(Context context) { super(context, "NamesDatabase", null, 1); Make sure to call super, and pass the name of the database as the second argument public void oncreate(sqlitedatabase db) { db.execsql(sql_create_main); public void onupgrade(sqlitedatabase arg0, int arg1, int arg2) {

Creating a Content Provider public class MyProvider extends ContentProvider {... protected static final class MainDatabaseHelper extends SQLiteOpenHelper { MainDatabaseHelper(Context context) { super(context, "NamesDatabase", null, 1); public void oncreate(sqlitedatabase db) { The database will be created when db.execsql(sql_create_main); oncreate() is called on our inner class. Note that this oncreate() doesn't get called until you try to access the database public void onupgrade(sqlitedatabase arg0, int arg1, int arg2) {

Creating a Content Provider Now we can implement the methods for our ContentProvider

Implementing the oncreate() method public class MyContentProvider extends ContentProvider {... public boolean oncreate() { mopenhelper = new MainDatabaseHelper(getContext());... return true;

Implementing the oncreate() method public class MyContentProvider extends ContentProvider {... public boolean oncreate() { mopenhelper = new MainDatabaseHelper(getContext());... return true; We create an instance of our MainDatabaseHelper so that we can use it later for reading and modifying our NamesDatabase

Implementing the insert() method public class MyContentProvider extends ContentProvider {... public Uri insert(uri uri, ContentValues values) { String fname = values.getasstring("firstname"); String lname = values.getasstring("lastname"); long id = mopenhelper.getwritabledatabase().insert("users", null, values); return Uri.withAppendedPath(CONTENT_URI, "" + id);...

Implementing the insert() method public class MyContentProvider extends ContentProvider {... public Uri insert(uri uri, ContentValues values) { String fname = values.getasstring("firstname"); We must return a Uri. We will return a Uri that has the new id of the item that will be inserted in this method String lname = values.getasstring("lastname"); long id = mopenhelper.getwritabledatabase().insert("users", null, values); return Uri.withAppendedPath(CONTENT_URI, "" + id);...

Implementing the insert() method public class MyContentProvider extends ContentProvider {... public Uri insert(uri uri, ContentValues values) { String fname = values.getasstring("firstname"); This Uri can be used to identify the table in our database, but since we only have one table, we don't need to use it in this function String lname = values.getasstring("lastname"); long id = mopenhelper.getwritabledatabase().insert("users", null, values); return Uri.withAppendedPath(CONTENT_URI, "" + id);...

Implementing the insert() method public class MyContentProvider extends ContentProvider {... public Uri insert(uri uri, ContentValues values) { String fname = values.getasstring("firstname"); These are the values that will be String lname = values.getasstring("lastname"); inserted. They are key-value pairs long id = mopenhelper.getwritabledatabase().insert("users", null, values); return Uri.withAppendedPath(CONTENT_URI, "" + id);...

Implementing the insert() method public class MyContentProvider extends ContentProvider {... public Uri insert(uri uri, ContentValues values) { String fname = values.getasstring("firstname"); String lname = values.getasstring("lastname"); We get the FirstName and LastName values that were passed in long id = mopenhelper.getwritabledatabase().insert("users", null, values); return Uri.withAppendedPath(CONTENT_URI, "" + id);...

Implementing the insert() method public class MyContentProvider extends ContentProvider {... public Uri insert(uri uri, ContentValues values) { String fname = values.getasstring("firstname"); String lname = values.getasstring("lastname"); Before you call insert() and update(), you should check for invalid values and return null if there is any invalid input. We don't use fname and lname afterward, as we are just trying to illustrate how to use ContentValues long id = mopenhelper.getwritabledatabase().insert("users", null, values); return Uri.withAppendedPath(CONTENT_URI, "" + id);...

Implementing the insert() method public class MyContentProvider extends ContentProvider {... public Uri insert(uri uri, ContentValues values) { String fname = values.getasstring("firstname"); String lname = values.getasstring("lastname"); long id = mopenhelper.getwritabledatabase().insert("users", null, values); We need to call getwritabledatabase() to create and/or open our database which will be used for reading and writing return Uri.withAppendedPath(CONTENT_URI, "" + id);...

Implementing the insert() method public class MyContentProvider extends ContentProvider {... public Uri insert(uri uri, ContentValues values) { String fname = values.getasstring("firstname"); String lname = values.getasstring("lastname"); long id = mopenhelper.getwritabledatabase().insert("users", null, values); return Uri.withAppendedPath(CONTENT_URI, "" + id); We can insert() on our Users table, passing the values that need to be inserted...

Implementing the insert() method public class MyContentProvider extends ContentProvider {... public Uri insert(uri uri, ContentValues values) { String fname = values.getasstring("firstname"); String lname = values.getasstring("lastname"); long id = mopenhelper.getwritabledatabase().insert("users", null, values); Because the _ID column is the primary key, we don't need to specify a value for it. It will automatically be added for us return Uri.withAppendedPath(CONTENT_URI, "" + id);...

Implementing the insert() method public class MyContentProvider extends ContentProvider {... public Uri insert(uri uri, ContentValues values) { String fname = values.getasstring("firstname"); String lname = values.getasstring("lastname"); long id = mopenhelper.getwritabledatabase().insert("users", null, values); That _ID value is returned from the call to insert(), we store it in this long int return Uri.withAppendedPath(CONTENT_URI, "" + id);...

Implementing the insert() method public class MyContentProvider extends ContentProvider {... public Uri insert(uri uri, ContentValues values) { String fname = values.getasstring("firstname"); String lname = values.getasstring("lastname"); long id = mopenhelper.getwritabledatabase().insert("users", null, values);... return Uri.withAppendedPath(CONTENT_URI, "" + id); Here we return the Uri that can be used to identify the row that was just inserted. For example content://my.package.name.provider/users/1

Implementing the update() method public class MyContentProvider extends ContentProvider {... public int update(uri uri, ContentValues values, String selection, String[] selectionargs) { return mopenhelper.getwritabledatabase(). update("users", values, selection, selectionargs);...

Implementing the update() method public class MyContentProvider extends ContentProvider {... public int update(uri uri, ContentValues values, String selection, String[] selectionargs) {... return mopenhelper.getwritabledatabase(). update("users", values, selection, selectionargs); After checking for invalid values (not shown here), we simply use our mopenhelper to update the Users table, and return that value. Next we implement the delete() method

Implementing the delete() method public class MyContentProvider extends ContentProvider {... public int delete(uri uri, String whereclause, String[] whereargs) { return mopenhelper.getwritabledatabase(). delete(table_namestable, whereclause, whereargs);...

Implementing the delete() method public class MyContentProvider extends ContentProvider {... public int delete(uri uri, String whereclause, String[] whereargs) { return mopenhelper.getwritabledatabase(). delete(table_namestable, whereclause, whereargs); Next, we implement the query() method...

Implementing the delete() method public class MyContentProvider extends ContentProvider {... public Cursor query(uri table, String[] columns, String selection, String[] args, String orderby) {... return mopenhelper.getreadabledatabase().query("users", columns, selection, args, null, null, orderby);

Content Provider Permissions Now that you've set up your ContentProvider, you will want to have external apps require permission to read/write your data More on your own permissions here

Content Provider Permissions By default, anyone can read from or write to your ContentProvider Take the steps necessary to protect you data

Content Provider Permissions 1. Open the AndroidManifest.xml file 2. Add a <permission /> tag above the <application> tag 3. Set the android:name attribute for your permission my.package.name.provider.permission.read_permission (Create a String resource for this permission String) 4. Save the file You can add as many permission Strings you want, how you use them is more important

Content Provider Permissions Single read-write provider-level permission One permission that controls both read and write access to the entire provider, specified with the android:permission attribute of the <provider> element. Separate read and write provider-level permission android:readpermission android:writepermission They take precedence over the permission required by A read permission and a write permission for the entire provider android:permission.

Content Provider Permissions See ContentProviderExternalUserExample.tar Make sure that you've also installed ContentProviderExample.tar on the same device, so that the external user can use its content provider

Viewing ContentProvider data We want to create a class to view ContentProvider data when an application calls ACTION_VIEW Implement gettype() in ContentProvider to return MimeType Can have multiple Activities One displays single entry One displays list of entries