Content Providers in Android

Posted By : Ajit Jati | 15-Jul-2013

Content provider android

A database in Android System is private to the application which creates it
. There is no common storage space in Android that multiple application can share. Therefore, for different applications to use a database, Android system needs an interface to have such inter-application data sharing. This is what content providers exactly do.Content Providers are used to share data between applications.

When you need a Content Provider ?

  • If you want to create a database which will be private to your application(Which will not be shared with other applications) then you do not need a Content Provider.
  • You will need a Custom content provider to be able to have a custom search suggestions in your own application system.
  • You also need a Content Provider to move and use useful data from your app to other apps.

Some basic operations provided by Content provider are : Querying, insert, update, delete etc.Some default Content Providers Provided by Android OS are :

Contacts – Contact details

Call log – All call history

Media Store – Audio/Video details

Browser – Bookmarks, history, etc.

Settings – All phone settings like Wi-Fi, Bluetooth, Security, etc.

 

To create our own content provider we need to extend the ContentProvider class and override some methods defined within it.

In order to extract/manipulate data we mainly need two things:

  • Uri
  • Content Resolver object.

Uri

To get the data from an application we need Uri, the path where actual data is stored in a table. Example :

-to get contact details

      content: //contacts/people

-to get bookmark details from browser

      content: //browser/bookmarks

The general syntax for the URI is

      <Standard prefix> ://< authority>/< data path>/<id>

In Android every content provider URI starts with

      content://

if we want to get the 5th contact from the Contact list then the example would be :

content: //contacts/people/5

Content Resolver

To extract/get the data provided by the content provider’s we use content resolvers. The content resolver job is to dispatch our requests to a content provider, based on the given Uri. so whenever, we try to get data from  ContentResolver, the system evaluates the given Uri and passes the request to theContentProvider. To get the content resolver object, we use getContentResolver() method within our application’s context.

         ContentResolver resolver = getContentResolver();

The ContentResolver object provides the basic “RCUD” (Read,Create,Update and Delete) functions associated with the android storage.

Inorder to start with Content providers create a new project in android.

Read
 
To get the data from the content provider, we call resolver.query() method.
 
Note: The resolver.query() method calls the ContentProvider.query() method defined in the ContentProvider Class.
 
resolver.query() method is having 4 parameters which returns Cursor object containing result of the query. Following is the syntax
 
cursor = resolver.query(Uri,        -- The Uri that identifies data in a provider
                             projection,     -- Columns to be returned
                             selection,         -- Selection Criteria
                             selectionArgs,     -- Defining criteria with specific value
                             sortOrder);      -- Sort order in the returning rows
 
 
ReadRecords.java
 
public class ReadRecords extends ListActivity{
 
  private String[] colummns = new String[]{
ContactsContract.Contacts._ID, ContactsContract.Contacts.DISPLAY_NAME, ContactsContract.Contacts.HAS_PHONE_NUMBER};
 private Uri contactsListUri = ContactsContract.Contacts.CONTENT_URI;
 private Uri phoneUri = ContactsContract.CommonDataKinds.Phone.CONTENT_URI;
 private String contactIdUri = ContactsContract.CommonDataKinds.Phone.CONTACT_ID;
 private String numberUri = ContactsContract.CommonDataKinds.Phone.NUMBER;
 private Cursor cursor;
 private ArrayList<string> arrayList;
 
 @Override
 protected void onCreate(Bundle savedInstanceState) {
  super.onCreate(savedInstanceState);
  arrayList = new ArrayList<string>();
  cursor = managedQuery(contactsListUri, null, null, null,null);
  
  readContacts();
  
 }

  void readContacts() {

  if(cursor == null || cursor.getCount() == 0){
   Toast.makeText(getApplicationContext(), "No Contacts in Your Directory", Toast.LENGTH_SHORT).show();
  }
  else{
   while(cursor.moveToNext()){
    String id = cursor.getString(cursor.getColumnIndex(colummns[0]));
    String name = cursor.getString(cursor.getColumnIndex(colummns[1]));
    if(Integer.parseInt(cursor.getString(cursor.getColumnIndex(colummns[2]))) > 0){

     Cursor numCursor = managedQuery(phoneUri, null, contactIdUri + "=?", new String[] {id}, null);
     if(numCursor.getCount()>0)
     while(numCursor.moveToNext()){
      String phone = numCursor.getString(numCursor.getColumnIndex(numberUri));
      arrayList.add(name+"~"+phone);
     }
    }
   }
   
   getListView().setAdapter(new MyAdapter(arrayList,R.layout.namenumber,getLayoutInflater()));
  }
  
 }

}
  

Delete

To delete a row we use resolver.delete() method, which is having 3 parameters. Following is the syntax. rowDeleted = resolver.delete(Uri, selection, selectionArgs);

DeleteRecord.java

public class DeleteRecord extends ListActivity{

private String[] colummns = new String[]{
ContactsContract.Contacts._ID, ContactsContract.Contacts.DISPLAY_NAME, ContactsContract.Contacts.HAS_PHONE_NUMBER};
private Uri contactsListUri = ContactsContract.Contacts.CONTENT_URI;
private Uri phoneUri = ContactsContract.CommonDataKinds.Phone.CONTENT_URI;
private String contactIdUri = ContactsContract.CommonDataKinds.Phone.CONTACT_ID;
private String numberUri = ContactsContract.CommonDataKinds.Phone.NUMBER;
private Cursor cursor;
private ArrayList<String> arrayList;
private String deleteName, deleteNum,deleteCombi;
private String[] splitCombi;
private AlertDialog.Builder builder;

@Override
protected void onCreate(Bundle savedInstanceState) {
 super.onCreate(savedInstanceState);
 arrayList = new ArrayList<String>();
 builder = new AlertDialog.Builder(DeleteRecord.this);
 cursor = managedQuery(contactsListUri, null, null, null,null); 
 readContacts();
 getListView().setOnItemClickListener(new OnItemClickListener() {

  @Override
  public void onItemClick(AdapterView<?> arg0, View arg1, int arg2,
    long arg3) {
   deleteCombi = arrayList.get(arg2);
   splitCombi = deleteCombi.split("~");
   deleteName = splitCombi[0];
   deleteNum = splitCombi[1];
   builder.setTitle("Confirm");
   builder.setMessage("Are You Sure to delete contact "+deleteName+"?");
   builder.setPositiveButton("Yes", new DialogInterface.OnClickListener() {
   
    @Override
    public void onClick(DialogInterface dialog, int which) {
     deleteContact();
      finish();
      startActivity(getIntent());
      Toast.makeText(getApplicationContext(), "Deleted Successfully", Toast.LENGTH_SHORT).show();
    }
   });
   builder.setNegativeButton("No", new DialogInterface.OnClickListener() {
   
    @Override
    public void onClick(DialogInterface dialog, int which) {
     dialog.dismiss();
    }
   });
   builder.show();
  }
 });
}


private void deleteContact() {
 Uri contactUri = Uri.withAppendedPath(PhoneLookup.CONTENT_FILTER_URI, Uri.encode(deleteNum));
 Cursor cur = managedQuery(contactUri, null, null, null, null);
 try{
  if(cur.moveToNext()){
   do{
    if(cur.getString(cur.getColumnIndex(PhoneLookup.DISPLAY_NAME)).equals(deleteName)){
     String key = cur.getString(cur.getColumnIndex(ContactsContract.Contacts.LOOKUP_KEY));
     Uri uri = Uri.withAppendedPath(ContactsContract.Contacts.CONTENT_LOOKUP_URI, key);
     getContentResolver().delete(uri, null, null);
    }
   }while(cur.moveToNext());
  }
 }catch(Exception e){
  e.printStackTrace();
 }
}

}
        

Insert

ContentProviderOperation is used for performing batch operations. This class is useful for inserting a large number of rows or for inserting rows in multiple tables(batch operations).

InsertRecords.java

 

public class InsertARecord extends Activity{
 
 private EditText name,number;
 private Button buttonInsert;
 private ArrayList<contentprovideroperation> operations;
 
 @Override
 protected void onCreate(Bundle savedInstanceState) {
  super.onCreate(savedInstanceState);
  setContentView(R.layout.insertarecord);
  operations = new ArrayList<contentprovideroperation>();
  name = (EditText)findViewById(R.id.name);
  number = (EditText)findViewById(R.id.number);
  buttonInsert = (Button)findViewById(R.id.buttonInsert);
  
  buttonInsert.setOnClickListener(new OnClickListener() {
   
   @Override
   public void onClick(View v) {
    if(operations.size() > 0)
     operations.clear();
    operations.add(ContentProviderOperation.newInsert(ContactsContract.RawContacts.CONTENT_URI)
.withValue(ContactsContract.RawContacts.ACCOUNT_TYPE, null)       .withValue(ContactsContract.RawContacts.ACCOUNT_NAME, null).build());      String displayName = name.getText().toString();
    String phoneNumber = number.getText().toString();
    if(!displayName.trim().equals("") && !phoneNumber.trim().equals("")){
     operations.add(ContentProviderOperation.newInsert(ContactsContract.Data.CONTENT_URI)
       .withValueBackReference(ContactsContract.Data.RAW_CONTACT_ID, 0)
       .withValue(ContactsContract.Data.MIMETYPE, ContactsContract.CommonDataKinds.StructuredName.CONTENT_ITEM_TYPE)
       .withValue(ContactsContract.CommonDataKinds.StructuredName.DISPLAY_NAME, displayName).build());
     
     operations.add(ContentProviderOperation.newInsert(ContactsContract.Data.CONTENT_URI)
       .withValueBackReference(ContactsContract.Data.RAW_CONTACT_ID, 0)
       .withValue(ContactsContract.Data.MIMETYPE, ContactsContract.CommonDataKinds.Phone.CONTENT_ITEM_TYPE)
       .withValue(ContactsContract.CommonDataKinds.Phone.NUMBER, phoneNumber)
       .withValue(ContactsContract.CommonDataKinds.Phone.TYPE, ContactsContract.CommonDataKinds.Phone.TYPE_MOBILE).build());
    }
    try{
     getContentResolver().applyBatch(ContactsContract.AUTHORITY, operations);
     Toast.makeText(getApplicationContext(), "Insert Success", Toast.LENGTH_SHORT).show();
     name.setText("");number.setText("");
    }catch(Exception e){
     e.printStackTrace();
     Toast.makeText(getApplicationContext(), "Insertion failed", Toast.LENGTH_SHORT).show();
    }
   }
  });
 }

}
Update
 
To update a value we use ContentProviderOperations.newUpdate() method. 
 
UpdateRecord.java
 
public class UpdateRecord extends ListActivity{
 
 private String[] colummns = new String[]{
ContactsContract.Contacts._ID, ContactsContract.Contacts.DISPLAY_NAME,ContactsContract.Contacts.HAS_PHONE_NUMBER};
 private Uri contactsListUri = ContactsContract.Contacts.CONTENT_URI;
 private Uri phoneUri = ContactsContract.CommonDataKinds.Phone.CONTENT_URI;
 private String contactIdUri = ContactsContract.CommonDataKinds.Phone.CONTACT_ID;
 private String numberUri = ContactsContract.CommonDataKinds.Phone.NUMBER;
 private Cursor cursor;
 private ArrayList arrayList;
 private String combi,b4Name,b4phNumber,upNumber;
 private String[] split;
 private Dialog dialog;
 private EditText eName, eNumber;
 private Button bUpdate, bCancel;
 private ArrayList ops;
 
 @Override
 protected void onCreate(Bundle savedInstanceState) {
  super.onCreate(savedInstanceState);
  arrayList = new ArrayList();
  dialog = new Dialog(this);
  dialog.setContentView(R.layout.update_dialog);
  eName = (EditText)dialog.findViewById(R.id.editName);
  eName.setKeyListener(null);
  eNumber = (EditText)dialog.findViewById(R.id.editNum);
  bUpdate = (Button)dialog.findViewById(R.id.update);
  bCancel = (Button)dialog.findViewById(R.id.cancel);
  bCancel.setOnClickListener(new OnClickListener() {
   
   @Override
   public void onClick(View v) {
    dialog.dismiss();
   }
  });
  
  bUpdate.setOnClickListener(new OnClickListener() {
   
   @Override
   public void onClick(View v) {
    upNumber = eNumber.getText().toString();
    updateRecord();
    finish();
    startActivity(getIntent());
   }
  });
  
  cursor = managedQuery(contactsListUri, null, null, null,null);
  
  readContacts();
  
 }

   protected void updateRecord() {
   Uri contactUri = Uri.withAppendedPath(PhoneLookup.CONTENT_FILTER_URI, Uri.encode(b4phNumber));
   Cursor cur = managedQuery(contactUri, null, null, null, null);
   try{
    if(cur.moveToNext()){
     do{
      if(cur.getString(cur.getColumnIndex(PhoneLookup.DISPLAY_NAME)).equals(b4Name)){
       String id = cur.getString(cur.getColumnIndex(ContactsContract.Contacts._ID));
       ops = new ArrayList();
       String selection = Data.CONTACT_ID + "=? AND " + Data.MIMETYPE + " = '" + Phone.CONTENT_ITEM_TYPE +
         "' AND " + Phone.TYPE + "=?";
       String[] selectionArgs = new String[]{id,String.valueOf(Phone.TYPE_MOBILE)};
       ops.add(ContentProviderOperation.newUpdate(Data.CONTENT_URI)
         .withSelection(selection, selectionArgs)
         .withValue(Phone.NUMBER,upNumber).build());
       getContentResolver().applyBatch(ContactsContract.AUTHORITY, ops);
       dialog.dismiss();
       Toast.makeText(getApplicationContext(), "Update Success", Toast.LENGTH_SHORT).show();
      }
     }while(cur.moveToNext());
    }
   }catch(Exception e){
    e.printStackTrace();
   }
 }
}
        

Hope it helps understanding Content providers.

you can have a copy of the demo implementation using content providers to insert, modify, delete and read contacts within your Android phonebook.

Download full source

cheers !! :)

[email protected]

 

About Author

Author Image
Ajit Jati

Ajit is an proficient Project Manager specializing in Mobile technologies. He possesses extensive development experience in Titanium, Android, Kotlin, Roku, and PHP. Ajit has successfully delivered various projects in the OTT, AR/VR, and Travel industries. His skill set includes developing and maintaining project plans, schedules, and budgets, ensuring timely delivery while staying within the allocated budget. He excels in collaborating closely with clients to define project scope and requirements, establish project timelines and milestones, and effectively manage expectations. He conducts regular project status meetings, ensuring effective communication and providing updates to clients and stakeholders on project progress, risks, and issues. Furthermore, Ajit takes on the role of a coach and mentor for team,offering guidance on project management best practices and assisting in their skill development.

Request for Proposal

Name is required

Comment is required

Sending message..