Friday, September 9, 2016

Android Content Provider Tutorial


A content provider manages a shared set of app data. You can store the data in the file system, an SQLite database, on the web, or any other persistent storage location your app can access. Through the content provider, other apps can query or even modify the data (if the content provider allows it).

For example, the Android system provides a content provider that manages the user's contact information. As such, any app with the proper permissions can query part of the content provider (such as ContactsContract.Data) to read and write information about a particular person.

A content provider component supplies data from one application to others on request. Such requests are handled by the methods of the ContentResolver class. A content provider can use different ways to store its data and the data can be stored in a database, in files, or even over a network.
sometimes it is required to share data across applications. This is where content providers become very useful.

Content providers let you centralize content in one place and have many different applications access it as needed. A content provider behaves very much like a database where you can query it, edit its content, as well as add or delete content using insert(), update(), delete(), and query() methods. In most cases this data is stored in an SQlite database.





A content provider is implemented as a subclass of ContentProvider class and must implement a standard set of APIs that enable other applications to perform transactions.

How to Create Content Provider:

This involves number of simple steps to create your own content provider.
First of all you need to create a Content Provider class that extends the ContentProviderbaseclass.
Second, you need to define your content provider URI address which will be used to access the content.

Next you will need to create your own database to keep the content. Usually, Android uses SQLite database and framework needs to override onCreate() method which will use SQLite Open Helper method to create or open the provider's database. When your application is launched, the onCreate() handler of each of its Content Providers is called on the main application thread.

Next you will have to implement Content Provider queries to perform different database specific operations.

Finally register your Content Provider in your activity file using <provider> tag.

CONTENT PROVIDER Call Backs:

onCreate() This method is called when the provider is started.

query() This method receives a request from a client. The result is returned as a Cursor object.

insert()This method inserts a new record into the content provider.

delete() This method deletes an existing record from the content provider.

update() This method updates an existing record from the content provider.

getType() This method returns the MIME type of the data at the given URI.


Let me provide a simple application where you can add records and retrieve records.

MainActivity.java :

import android.content.ContentValues;
import android.database.Cursor;
import android.net.Uri;
import android.support.v7.app.AppCompatActivity;
import android.os.Bundle;
import android.view.View;
import android.widget.EditText;
import android.widget.Toast; 
 
public class MainActivity extends AppCompatActivity


@Override protected void onCreate(Bundle savedInstanceState) {
{
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
}


public void onClickAddName(View view) {
ContentValues values = new ContentValues();

values.put(StudentsProvider.NAME, ((EditText)findViewById(R.id.editText2)).getText().toString());
values.put(StudentsProvider.GRADE, ((EditText)findViewById(R.id.editText3)).getText().toString());

Uri uri = getContentResolver().insert(StudentsProvider.CONTENT_URI, values);
Toast.makeText(getBaseContext(), uri.toString(), Toast.LENGTH_LONG).show(); }

public void onClickRetrieveStudents(View view) {

// Retrieve student records String URL = "content://com.myandrioid.provider.College/students";
Uri students = Uri.parse(URL);
Cursor c = managedQuery(students, null, null, null, "name");
if (c.moveToFirst()) {
do {
Toast.makeText(this,
c.getString(c.getColumnIndex(StudentsProvider._ID)) +

", " + c.getString(c.getColumnIndex( StudentsProvider.NAME)) +

", " + c.getString(c.getColumnIndex( StudentsProvider.GRADE)),

Toast.LENGTH_SHORT).show();

}
while (c.moveToNext());

} }

}

activity_main.xml:

<?xml version="1.0" encoding="utf-8"?>


<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"


xmlns:tools="http://schemas.android.com/tools"


android:layout_width="match_parent"


android:layout_height="match_parent"


android:paddingBottom="@dimen/activity_vertical_margin"


android:paddingLeft="@dimen/activity_horizontal_margin"


android:paddingRight="@dimen/activity_horizontal_margin"


android:paddingTop="@dimen/activity_vertical_margin"


tools:context="com.myandrioid.abhinaw.MainActivity">



<TextView


android:id="@+id/textView1"

android:layout_width="wrap_content"

android:layout_height="wrap_content"

android:text="Content provider"

android:layout_alignParentTop="true"

android:layout_centerHorizontal="true"

android:textSize="30dp" />


<TextView

android:id="@+id/textView2"

android:layout_width="wrap_content"

android:layout_height="wrap_content"

android:text="Abhinaw Tutorial "

android:textColor="#ff87ff09"

android:textSize="30dp"

android:layout_below="@+id/textView1"

android:layout_centerHorizontal="true" />


<ImageButton

android:layout_width="wrap_content"

android:layout_height="wrap_content"

android:id="@+id/imageButton"

android:src="@mipmap/ic_launcher"

android:layout_below="@+id/textView2"

android:layout_centerHorizontal="true" />


<Button

android:layout_width="wrap_content"

android:layout_height="wrap_content"

android:id="@+id/button2"

android:text="Add Name"

android:layout_below="@+id/editText3"

android:layout_alignRight="@+id/textView2"

android:layout_alignEnd="@+id/textView2"

android:layout_alignLeft="@+id/textView2"

android:layout_alignStart="@+id/textView2"

android:onClick="onClickAddName"/>


<EditText

android:layout_width="wrap_content"

android:layout_height="wrap_content"

android:id="@+id/editText"

android:layout_below="@+id/imageButton"

android:layout_alignRight="@+id/imageButton"

android:layout_alignEnd="@+id/imageButton" />

<EditText

android:layout_width="wrap_content"

android:layout_height="wrap_content"

android:id="@+id/editText2"

android:layout_alignTop="@+id/editText"

android:layout_alignLeft="@+id/textView1"

android:layout_alignStart="@+id/textView1"

android:layout_alignRight="@+id/textView1"

android:layout_alignEnd="@+id/textView1"

android:hint="Name"

android:textColorHint="@android:color/holo_blue_light" />

<EditText

android:layout_width="wrap_content"

android:layout_height="wrap_content"

android:id="@+id/editText3"

android:layout_below="@+id/editText"

android:layout_alignLeft="@+id/editText2"

android:layout_alignStart="@+id/editText2"

android:layout_alignRight="@+id/editText2"

android:layout_alignEnd="@+id/editText2"

android:hint="Grade"

android:textColorHint="@android:color/holo_blue_bright" />

<Button

android:layout_width="wrap_content"

android:layout_height="wrap_content"

android:text="Retrive student"

android:id="@+id/button"

android:layout_below="@+id/button2"

android:layout_alignRight="@+id/editText3"

android:layout_alignEnd="@+id/editText3"

android:layout_alignLeft="@+id/button2"

android:layout_alignStart="@+id/button2"

android:onClick="onClickRetrieveStudents"/>

</RelativeLayout>

StudentsProvider.java :


import java.util.HashMap;

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.SQLException;

import android.database.sqlite.SQLiteDatabase;

import android.database.sqlite.SQLiteOpenHelper;

import android.database.sqlite.SQLiteQueryBuilder;

import android.net.Uri;


import android.text.TextUtils;
public class StudentsProvider extends ContentProvider


static final String PROVIDER_NAME = "com.myandrioid.provider.College"; {
static final String URL = "content://" + PROVIDER_NAME + "/students";


static final Uri CONTENT_URI = Uri.parse(URL);


static final String _ID = "_id";


static final String NAME = "name";


static final String GRADE = "grade";


private static HashMap<String, String> STUDENTS_PROJECTION_MAP;


static final int STUDENTS = 1;


static final int STUDENT_ID = 2;


static final UriMatcher uriMatcher;


static {


uriMatcher = new UriMatcher(UriMatcher.NO_MATCH);


uriMatcher.addURI(PROVIDER_NAME, "students", STUDENTS);


uriMatcher.addURI(PROVIDER_NAME, "students/#", STUDENT_ID);


}


/** * Database specific constant declarations */ private SQLiteDatabase db;


static final String DATABASE_NAME = "College";


static final String STUDENTS_TABLE_NAME = "students";


static final int DATABASE_VERSION = 1;


static final String CREATE_DB_TABLE =


" CREATE TABLE " + STUDENTS_TABLE_NAME +


" (_id INTEGER PRIMARY KEY AUTOINCREMENT, " +


" name TEXT NOT NULL, " +


" grade TEXT NOT NULL);";


/** * Helper class that actually creates and manages * the provider's underlying data repository. */ private static class DatabaseHelper extends SQLiteOpenHelper {


DatabaseHelper(Context context){


super(context, DATABASE_NAME, null, DATABASE_VERSION);


}


@Override public void onCreate(SQLiteDatabase db) {


db.execSQL(CREATE_DB_TABLE);


}


@Override public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) {


db.execSQL("DROP TABLE IF EXISTS " + STUDENTS_TABLE_NAME);


onCreate(db); } }


@Override public boolean onCreate() {


Context context = getContext();


DatabaseHelper dbHelper = new DatabaseHelper(context);


/** * Create a write able database which will trigger its * creation if it doesn't already exist. */ db = dbHelper.getWritableDatabase();


return (db == null)? false:true;


}


@Override public Uri insert(Uri uri, ContentValues values) {


/** * Add a new student record */ long rowID = db.insert( STUDENTS_TABLE_NAME, "", values);


/** * If record is added successfully */


if (rowID > 0)


{


Uri _uri = ContentUris.withAppendedId(CONTENT_URI, rowID);


getContext().getContentResolver().notifyChange(_uri, null);


return _uri;


}


throw new SQLException("Failed to add a record into " + uri); }


@Override public Cursor query(Uri uri, String[] projection, String selection,String[] selectionArgs, String sortOrder) {


SQLiteQueryBuilder qb = new SQLiteQueryBuilder();


qb.setTables(STUDENTS_TABLE_NAME);


switch (uriMatcher.match(uri)) {


case STUDENTS:


qb.setProjectionMap(STUDENTS_PROJECTION_MAP);


break;


case STUDENT_ID:


qb.appendWhere( _ID + "=" + uri.getPathSegments().get(1));


break;


default:


throw new IllegalArgumentException("Unknown URI " + uri);


}


if (sortOrder == null || sortOrder == "")


{


/** * By default sort on student names */ sortOrder = NAME;


}


Cursor c = qb.query(db, projection, selection, selectionArgs,null, null, sortOrder);


/** * register to watch a content URI for changes */ c.setNotificationUri(getContext().getContentResolver(), uri);


return c;


}


@Override public int delete(Uri uri, String selection, String[] selectionArgs) {


int count = 0;


switch (uriMatcher.match(uri)) {


case STUDENTS:


count = db.delete(STUDENTS_TABLE_NAME, selection, selectionArgs);


break;


case STUDENT_ID:


String id = uri.getPathSegments().get(1);


count = db.delete( STUDENTS_TABLE_NAME, _ID + " = " + id +


(!TextUtils.isEmpty(selection) ? " AND (" + selection + ')' : ""), selectionArgs);


break;


default:


throw new IllegalArgumentException("Unknown URI " + uri);


}


getContext().getContentResolver().notifyChange(uri, null);


return count; }


@Override public int update(Uri uri, ContentValues values, String selection, String[] selectionArgs) {


int count = 0;


switch (uriMatcher.match(uri)){


case STUDENTS:


count = db.update(STUDENTS_TABLE_NAME, values, selection, selectionArgs);


break;


case STUDENT_ID:


count = db.update(STUDENTS_TABLE_NAME, values, _ID + " = " + uri.getPathSegments().get(1) +


(!TextUtils.isEmpty(selection) ? " AND (" +selection + ')' : ""), selectionArgs);


break;


default:


throw new IllegalArgumentException("Unknown URI " + uri );


}


getContext().getContentResolver().notifyChange(uri, null);


return count; }


@Override public String getType(Uri uri) {


switch (uriMatcher.match(uri)) {


/** * Get all student records */


case STUDENTS:


return "vnd.android.cursor.dir/vnd.example.students";


/** * Get a particular student */


case STUDENT_ID:


return "vnd.android.cursor.item/vnd.example.students";


default:


throw new IllegalArgumentException("Unsupported URI: " + uri);


} }


}


manifests.xml :

<?xml version="1.0" encoding="utf-8"?>


<manifest xmlns:android="http://schemas.android.com/apk/res/android"

package="com.myandrioid.abhinaw">

<application

android:allowBackup="true"

android:icon="@mipmap/ic_launcher"

android:label="@string/app_name"

android:supportsRtl="true"

android:theme="@style/AppTheme">

<activity android:name=".MainActivity">

<intent-filter>

<action android:name="android.intent.action.MAIN" />

<category android:name="android.intent.category.LAUNCHER" />

</intent-filter>

</activity>

<provider android:authorities="com.myandrioid.provider.College"

android:name=".StudentsProvider">

</provider>

</application>

</manifest>

Run and compile the code and you can able to perform the operation like add and retrieve
using content-provider and sqlite database.
So conclusion is,
Content providers are one of the primary building blocks of Android applications,
providing content to applications. They encapsulate data and provide it to applications
through the single ContentResolver interface. A content provider is only required if you
need to share data between multiple applications.


No comments: