MAD Unit 4
MAD Unit 4
Typically you work with content providers in one of two scenarios: implementing code to access
an existing content provider in another application or creating a new content provider in your
application to share data with other applications.
This page covers the basics of working with existing content providers. To learn about
implementing content providers in your own applications, see Create a content provider.
Overview
A content provider presents data to external applications as one or more tables that are similar to
the tables found in a relational database. A row represents an instance of some type of data the
provider collects, and each column in the row represents an individual piece of data collected for
an instance.
A content provider coordinates access to the data storage layer in your application for a number
of different APIs and components. As illustrated in figure 1, these include the following:
Access a provider
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. This object has methods that call identically named methods in the provider
object, an instance of one of the concrete subclasses of ContentProvider.
The ContentResolver methods provide the basic "CRUD" (create, retrieve, update, and delete)
functions of persistent storage.
A common pattern for accessing a ContentProvider from your UI uses a CursorLoader to run an
asynchronous query in the background. The Activity or Fragment in your UI calls
a CursorLoader to the query, which in turn gets the ContentProvider using the ContentResolver.
This lets the UI continue to be available to the user while the query is running. This pattern
involves the interaction of a number of different objects, as well as the underlying storage
mechanism, as illustrated in figure 2.
A content provider manages access to a central repository of data. You implement a provider as
one or more classes in an Android application, along with elements in the manifest file. One of
your classes implements a subclass of ContentProvider, which is the interface between your
provider and other applications.
Although content providers are meant to make data available to other applications, you can have
activities in your application that let the user query and modify the data managed by your
provider.
Decide whether you need a content provider. You need to build a content provider if you want
to provide one or more of the following features:
You want to offer complex data or files to other applications.
You want to let users copy complex data from your app into other apps.
You want to provide custom search suggestions using the search framework.
You want to expose your application data to widgets.
You want to implement the AbstractThreadedSyncAdapter, CursorAdapter,
or CursorLoader classes.
You don't need a provider to use databases or other types of persistent storage if the use is
entirely within your own application and you don’t need any of the preceding features listed.
Instead, you can use one of the storage systems described in Data and file storage overview.
If you haven't done so already, read Content provider basics to learn more about providers and
how they work.
Follow these steps to build your provider:
1. Design the raw storage for your data. A content provider offers data in two ways:
File data
Data that normally goes into files, such as photos, audio, or videos. Store the files in your
application's private space. In response to a request for a file from another application,
your provider can offer a handle to the file.
"Structured" data
Data that normally goes into a database, array, or similar structure. Store the data in a
form that's compatible with tables of rows and columns. A row represents an entity, such
as a person or an item in inventory. A column represents some data for the entity, such a
person's name or an item's price. A common way to store this type of data is in a SQLite
database, but you can use any type of persistent storage. To learn more about the storage
types available in the Android system, see the Design data storage section.
2. Define a concrete implementation of the ContentProvider class and its required methods. This
class is the interface between your data and the rest of the Android system. For more information
about this class, see the Implement the ContentProvider class section.
3. Define the provider's authority string, content URIs, and column names. If you want the
provider's application to handle intents, also define intent actions, extras data, and flags. Also
define the permissions that you require for applications that want to access your data. Consider
defining all these values as constants in a separate contract class. Later, you can expose this class
to other developers. For more information about content URIs, see the Design content
URIs section. For more information about intents, see the Intents and data access section.
4. Add other optional pieces, such as sample data or an implementation
of AbstractThreadedSyncAdapter that can synchronize data between the provider and cloud-
based data.
Content URI
Content URI(Uniform Resource Identifier) is the key concept of Content providers. To
access the data from a content provider, URI is used as a query string.
Structure of a Content URI: content://authority/optionalPath/optionalID
Details of different parts of Content URI:
content:// – Mandatory part of the URI as it represents that the given URI is a Content
URI.
authority – Signifies the name of the content provider like contacts, browser, etc. This part
must be unique for every content provider.
optionalPath – Specifies the type of data provided by the content provider. It is essential
as this part helps content providers to support different types of data that are not related to
each other like audio and video files.
optionalID – It is a numeric value that is used when there is a need to access a particular
record.
If an ID is mentioned in a URI then it is an id-based URI otherwise a directory-based
URI.
For a deeper understanding of how to implement Content Providers and other critical Android
components using Kotlin, consider enrolling in the Android Development with Kotlin
course . This course is designed to equip you with the skills necessary to build advanced
Android applications, leveraging Kotlin’s features to enhance your development process.
Operations in Content Provider
Four fundamental operations are possible in Content Provider
namely Create , Read , Update , and Delete . These operations are often termed as CRUD
operations .
Create: Operation to create data in a content provider.
Read: Used to fetch data from a content provider.
Update: To modify existing data.
Delete: To remove existing data from the storage.
Working of the Content Provider
UI components of android applications like Activity and Fragments use an
object CursorLoader to send query requests to ContentResolver. The ContentResolver object
sends requests (like create, read, update, and delete) to the ContentProvider as a client. After
receiving a request, ContentProvider process it and returns the desired result. Below is a
diagram to represent these processes in pictorial form.
query() A method that accepts arguments and fetches the data from the
desired table. Data is retired as a cursor object.
Example
The prime purpose of a content provider is to serve as a central repository of data where users
can store and can fetch the data. The access of this repository is given to other applications also
but in a safe manner in order to serve the different requirements of the user. The following are
the steps involved in implementing a content provider. In this content provider, the user can
store the name of persons and can fetch the stored data. Moreover, another application can also
access the stored data and can display the data.
Note: Following steps are performed on Android Studio version 4.0
Creating a Content Provider:
Step 1: Create a new project
1. Click on File, then New => New Project.
2. Select language as Java/Kotlin.
3. Choose empty activity as a template
4. Select the minimum SDK as per your need.
Step 2: Modify the strings.xml file
All the strings used in the activity are stored here.
<resources>
<string name="app_name">Content_Provider_In_Android</string>
<string name="hintText">Enter User Name</string>
<string name="heading">Content Provider In Android</string>
<string name="insertButtontext">Insert Data</string>
<string name="loadButtonText">Load Data</string>
</resources>
Step 3: Creating the Content Provider class
1. Click on File, then New => Other => ContentProvider.
2. Name the ContentProvider
3. Define authority (it can be anything for example “com.demo.user.provider” )
4. Select Exported and Enabled option
5. Choose the language as Java/Kotlin
This class extends the ContentProvider base class and override the six abstract methods. Below
is the complete code to define a content provider.
package com.example.contentprovidersinandroid;
import android.content.ContentProvider;
import android.content.ContentUris;
import android.content.ContentValues;
import android.content.Context;
import android.content.UriMatcher;
import android.database.Cursor;
import android.database.sqlite.SQLiteDatabase;
import android.database.sqlite.SQLiteException;
import android.database.sqlite.SQLiteOpenHelper;
import android.database.sqlite.SQLiteQueryBuilder;
import android.net.Uri;
import java.util.HashMap;
static {
@Override
public int update(Uri uri, ContentValues values, String selection,
String[] selectionArgs) {
int count = 0;
switch (uriMatcher.match(uri)) {
case uriCode:
count = db.update(TABLE_NAME, values, selection, selectionArgs);
break;
default:
throw new IllegalArgumentException("Unknown URI " + uri);
}
getContext().getContentResolver().notifyChange(uri, null);
return count;
}
@Override
public int delete(Uri uri, String selection, String[] selectionArgs) {
int count = 0;
switch (uriMatcher.match(uri)) {
case uriCode:
count = db.delete(TABLE_NAME, selection, selectionArgs);
break;
default:
throw new IllegalArgumentException("Unknown URI " + uri);
}
getContext().getContentResolver().notifyChange(uri, null);
return count;
}
// creating a database
private static class DatabaseHelper extends SQLiteOpenHelper {
// defining a constructor
DatabaseHelper(Context context) {
super(context, DATABASE_NAME, null, DATABASE_VERSION);
}
db.execSQL(CREATE_DB_TABLE);
}
@Override
public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) {
<LinearLayout
android:id="@+id/linearLayout"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_centerVertical="true"
android:orientation="vertical"
app:layout_constraintBottom_toTopOf="@+id/imageView"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent"
app:layout_constraintVertical_bias="0.13"
tools:ignore="MissingConstraints">
<TextView
android:id="@+id/textView1"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginTop="40dp"
android:layout_marginBottom="70dp"
android:fontFamily="@font/roboto"
android:text="@string/heading"
android:textAlignment="center"
android:textAppearance="@style/TextAppearance.AppCompat.Large"
android:textColor="@android:color/holo_green_dark"
android:textSize="36sp"
android:textStyle="bold" />
<EditText
android:id="@+id/textName"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginStart="20dp"
android:layout_marginEnd="20dp"
android:layout_marginBottom="40dp"
android:fontFamily="@font/roboto"
android:hint="@string/hintText" />
<Button
android:id="@+id/insertButton"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:layout_marginStart="20dp"
android:layout_marginTop="10dp"
android:layout_marginEnd="20dp"
android:layout_marginBottom="20dp"
android:background="#4CAF50"
android:fontFamily="@font/roboto"
android:onClick="onClickAddDetails"
android:text="@string/insertButtontext"
android:textAlignment="center"
android:textAppearance="@style/TextAppearance.AppCompat.Display1"
android:textColor="#FFFFFF"
android:textStyle="bold" />
<Button
android:id="@+id/loadButton"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:layout_marginStart="20dp"
android:layout_marginTop="10dp"
android:layout_marginEnd="20dp"
android:layout_marginBottom="20dp"
android:background="#4CAF50"
android:fontFamily="@font/roboto"
android:onClick="onClickShowDetails"
android:text="@string/loadButtonText"
android:textAlignment="center"
android:textAppearance="@style/TextAppearance.AppCompat.Display1"
android:textColor="#FFFFFF"
android:textStyle="bold" />
<TextView
android:id="@+id/res"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginStart="20dp"
android:layout_marginEnd="20dp"
android:clickable="false"
android:ems="10"
android:fontFamily="@font/roboto"
android:textColor="@android:color/holo_green_dark"
android:textSize="18sp"
android:textStyle="bold" />
</LinearLayout>
<ImageView
android:id="@+id/imageView"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:srcCompat="@drawable/banner" />
</androidx.constraintlayout.widget.ConstraintLayout>
import androidx.appcompat.app.AppCompatActivity;
import android.content.ContentValues;
import android.content.Context;
import android.database.Cursor;
import android.net.Uri;
import android.os.Bundle;
import android.view.MotionEvent;
import android.view.View;
import android.view.inputmethod.InputMethodManager;
import android.widget.EditText;
import android.widget.TextView;
import android.widget.Toast;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
}
@Override
public boolean onTouchEvent(MotionEvent event) {
InputMethodManager imm =
(InputMethodManager)getSystemService(Context.INPUT_METHOD_SERVICE);
imm.hideSoftInputFromWindow(getCurrentFocus().getWindowToken(), 0);
return true;
}
public void onClickAddDetails(View view) {
<application
android:allowBackup="true"
android:icon="@mipmap/ic_launcher"
android:label="@string/app_name"
android:roundIcon="@mipmap/ic_launcher_round"
android:supportsRtl="true"
android:theme="@style/AppTheme">
<provider
android:name="com.example.contentprovidersinandroid.MyContentProvider"
android:authorities="com.demo.user.provider"
android:enabled="true"
android:exported="true"></provider>
<activity android:name=".MainActivity">
<intent-filter>
<action android:name="android.intent.action.MAIN" />
</manifest>
Step 4: Open activity_main.xml from the following address and add the below code. Here, in a
Linear Layout, two edittext for taking phone number and a text message and a button for
sending the message is added.
app->res->layout->activitymain.xml
Below is the code implementation of the activity_main.xml file:
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:gravity="center_horizontal"
android:orientation="vertical">
<ImageView
android:id="@+id/imageView"
android:layout_width="120dp"
android:layout_height="120dp"
android:layout_marginTop="60dp"
android:src="@drawable/gfg_icon" />
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginStart="16dp"
android:layout_marginTop="32dp"
android:layout_marginEnd="16dp"
android:orientation="horizontal">
<TextView
android:id="@+id/textView"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="Phone Number:"
android:width="165sp"
android:textSize="18sp" />
<EditText
android:id="@+id/editText"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_weight="1"
android:ems="10"
android:hint="Enter number"
android:inputType="phone" />
</LinearLayout>
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginStart="16dp"
android:layout_marginTop="32dp"
android:layout_marginEnd="16dp"
android:orientation="horizontal">
<TextView
android:id="@+id/textView2"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="Message to be Sent:"
android:width="165sp"
android:textSize="18sp" />
<EditText
android:id="@+id/editText2"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_weight="1"
android:ems="10"
android:gravity="top|start"
android:hint="Enter message"
android:inputType="textMultiLine" />
</LinearLayout>
<Button
android:id="@+id/button"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="center_horizontal"
android:layout_marginTop="32dp"
android:text="SEND" />
</LinearLayout>
Create objects for views used i.e., editTexts and button. In the onCreate method find all the
views using the findViewById() method.
MainActivity.java
package com.example.gfg;
import androidx.appcompat.app.AppCompatActivity;
import android.os.Bundle;
import android.telephony.SmsManager;
import android.view.View;
import android.widget.Button;
import android.widget.EditText;
import android.widget.Toast;
For running application in Android device enable the SMS permission for the app.
Goto permissions->SMS->YourApp and enable permission.
To create a new project in Android Studio please refer to How to Create/Start a New Project
in Android Studio. The code for that has been given in both Java and Kotlin Programming
Language for Android.
Step 2: Working with the XML Files
Next, go to the activity_main.xml file, which represents the UI of the project. Below is the
code for the activity_main.xml file. Comments are added inside the code to understand the
code in more detail. This file contains a Relative Layout which contains three Edit texts for
receiver mail id, another for the subject of the mail, and last one for the body of the email, and
three TextViews for the label and a button for starting intent or sending mail: