Skip to content

Content Provider in Android

Published: at 5 min read

Table of content

Content Provider in Android

How Content Provider works in Android

public class MDataProvider extends ContentProvider {
    // Implement the necessary methods.
}
<uses-permission android:name="com.example.myapp.permission.READ_DATA" />

In the provider definition :

<provider
    android:name=".MDataProvider"
    android:authorities="com.example.myapp.data"
    android:readPermission="com.example.myapp.permission.READ_DATA"
    android:writePermission="com.example.myapp.permission.WRITE_DATA" />
@Override
public Cursor query(Uri uri, String[] projection, String selection, String[] selectionArgs, String sortOrder) {
    // Implement the query operation.
}

@Override
public Uri insert(Uri uri, ContentValues values) {
    // Implement the insert operation.
}

@Override
public int update(Uri uri, ContentValues values, String selection, String[] selectionArgs) {
    // Implement the update operation.
}

@Override
public int delete(Uri uri, String selection, String[] selectionArgs) {
    // Implement the delete operation.
}
ContentResolver contentResolver = getContentResolver();
Uri dataUri = Uri.parse("content://com.example.myapp.data/some_data");
Cursor cursor = contentResolver.query(dataUri, null, null, null, null);

// Process the data from the cursor.

Implementation of Content Provider for fetching Contact List :

Step 1: Add a contact data class to handle the fields cleanly

class ContactData (val name: String, val number: String)

Step 2: Add adapter for the items of contacts list

class ContactListAdapter(private val contacts: List<ContactData>) :
    RecyclerView.Adapter<ContactListAdapter.ContactViewHolder>() {

    private lateinit var binding: ContactBinding

    override fun getItemCount() = contacts.size

    override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): ContactViewHolder {
        val layoutInflater = LayoutInflater.from(parent.context)
        binding = ContactBinding.inflate(layoutInflater, parent, false)
        return ContactViewHolder(binding.root)
    }

    override fun onBindViewHolder(holder: ContactViewHolder, position: Int) {
        holder.apply {
            val contact = contacts[position]
            bind(contact)
        }
    }

    inner class ContactViewHolder(private val v: View) : RecyclerView.ViewHolder(v) {
        fun bind(contact: ContactData) {
            val name = v.findViewById<TextView>(R.id.name)
            val number = v.findViewById<TextView>(R.id.number)
            name.text = contact.name
            number.text = contact.number
        }
    }
}

Step 3: Now implement the content provider

class ContactListActivity : AppCompatActivity() {
    private lateinit var binding: ActivityContactListBinding
    private lateinit var contactAdapter: ContactListAdapter
    private var contacts = ArrayList<ContactData>()
    private var contactsStr = ArrayList<String>()

    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        binding = ActivityContactListBinding.inflate(layoutInflater)
        setContentView(binding.root)
        binding.apply {
            fab.setOnClickListener {
                syncContacts()
            }
        }
    }

    @SuppressLint("ObsoleteSdkInt")
    private fun syncContacts() {
        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M
            && checkSelfPermission(Manifest.permission.READ_CONTACTS)
            != PackageManager.PERMISSION_GRANTED
        ) {
            requestPermissions(
                arrayOf(Manifest.permission.READ_CONTACTS),
                PERMISSION_REQ_READ_CONTACTS
            )
        } else {
            fetchContacts()
            setAdapter()
        }
    }

    override fun onRequestPermissionsResult(
        requestCode: Int,
        permissions: Array<out String>,
        grantResults: IntArray
    ) {
        super.onRequestPermissionsResult(requestCode, permissions, grantResults)
        if (requestCode == PERMISSION_REQ_READ_CONTACTS) {
            if (grantResults[0] == PackageManager.PERMISSION_GRANTED) {
                syncContacts()
            } else {
                Snackbar.make(
                    this,
                    binding.root,
                    "Permission Not Granted",
                    Snackbar.LENGTH_SHORT
                )
                    .show()
            }
        }
    }

    @SuppressLint("Range", "Recycle")
    private fun fetchContacts() {

        val resolver: ContentResolver = contentResolver
        val cursor = resolver.query(
            ContactsContract.Contacts.CONTENT_URI,
            null, null, null, null
        )
        if (cursor!!.count > 0) {
            while (cursor.moveToNext()) {
                val id = cursor.getString(cursor.getColumnIndex(ContactsContract.Contacts._ID))
                val name =
                    cursor.getString(cursor.getColumnIndex(ContactsContract.Contacts.DISPLAY_NAME))
                val phoneNum =
                    cursor.getString(cursor.getColumnIndex(ContactsContract.Contacts.HAS_PHONE_NUMBER))
                        .toInt()
                if (phoneNum > 0) {
                    val cursorPhone = contentResolver.query(
                        ContactsContract.CommonDataKinds.Phone.CONTENT_URI,
                        null,
                        ContactsContract.CommonDataKinds.Phone.CONTACT_ID + " =?",
                        arrayOf(id),
                        null
                    )
                    if (cursorPhone!!.count > 0) {
                        while (cursorPhone.moveToNext()) {
                            val phoneNumValue = cursorPhone.getString(
                                cursorPhone.getColumnIndex(ContactsContract.CommonDataKinds.Phone.NUMBER)
                            )
                            contactsStr.add("$name|$phoneNumValue")
                        }
                    }
                    cursorPhone.close()

                }
            }
        }
        for (contact in contactsStr) {
            val contactSplit = contact.split("|")
            Log.i("CONTACT", contactSplit.toString())
            contacts.add(Contact(contactSplit[0], contactSplit[1]))
        }
    }

    private fun setAdapter() {
        contactAdapter = ContactListAdapter(contacts)
        binding.apply {
            contactRecyclerView.layoutManager = LinearLayoutManager(this@MainActivity)
            contactRecyclerView.adapter = contactAdapter

            ItemTouchHelper(object : ItemTouchHelper.SimpleCallback(0, ItemTouchHelper.LEFT) {
                override fun onMove(
                    recyclerView: RecyclerView,
                    viewHolder: RecyclerView.ViewHolder,
                    target: RecyclerView.ViewHolder
                ): Boolean {
                    return false
                }

                override fun onSwiped(viewHolder: RecyclerView.ViewHolder, direction: Int) {
                    val pos = viewHolder.adapterPosition
                    contacts.removeAt(pos)
                    contactAdapter.notifyItemRemoved(pos)
                    Toast.makeText(this@MainActivity, "Contact Deleted", Toast.LENGTH_LONG)
                        .show()
                }
            }).attachToRecyclerView(contactRecyclerView)

            ItemTouchHelper(object : ItemTouchHelper.SimpleCallback(0, ItemTouchHelper.RIGHT) {
                override fun onMove(
                    recyclerView: RecyclerView,
                    viewHolder: RecyclerView.ViewHolder,
                    target: RecyclerView.ViewHolder
                ): Boolean {
                    return false
                }

                override fun onSwiped(viewHolder: RecyclerView.ViewHolder, direction: Int) {
                    val pos = viewHolder.adapterPosition
                    contacts.removeAt(pos)
                    contactAdapter.notifyItemRemoved(pos)
                    Toast.makeText(this@MainActivity, "Contact Archived", Toast.LENGTH_LONG)
                        .show()
                }
            }).attachToRecyclerView(contactRecyclerView)
        }
    }

    companion object {
        const val PERMISSION_REQ_READ_CONTACTS = 100
    }
}

usageOfContentProvider

More Reference, Please click on the link: Content Provider

Happy Learning !

Share :
Written by:Parita Dey

Interested in Writing Blogs, showcase yourself ?

If you're passionate about technology and have insights to share, we'd love to hear from you! Fill out the form below to express your interest in writing technical blogs for us.

If you notice any issues in this blog post or have suggestions, please contact the author directly or send an email to hi@asdevs.dev.