Wednesday, 26 August 2015

Android Programming Tutorials 13 : ContentProvider 1 In Android

ContentProvider:

ContentProvider is another component in Android which can also used to stored the data like SQlite Database, but the data can be store in Custom API and that data can be accessed by another application.


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. 

                                             OR

Content provider is the best way to share data across applications. Content provider is a set of data wrapped up in a custom API to read and write. Applications/Processes have to register themselves as a provider of data. Other applications can request Android to read/write that data through a fixed API.
Content provider API adheres to CRUD principle.


Above diagram shows how content provider works. App 1 stores its data in its own database and provides a provider. App 2 communicates with the provider to access App 1's data.

Content providers are simple interfaces which uses standard insert(), query(), update(), delete() methods to access application data. So it is easy to implement a content provider.

A special URI starting with content:// will be assigned to each content providers and that will be recognized across applications.

Writing a content provider:

The ContentProvider class is the central component of a content provider. To create a content provider we have to
1. Create sub class for ContentProvider.
2. Define content URI
3. Implement all the unimplemented methods. insert(), update(), query(), delete(), getType().
4. Declare the content provider in AndroidManifest.xml

Defining URI:
Content provider URI consists of four parts.
content://authority/path/id
content:// All the content provider URIs should start with this value
'authority' is Java namespace of the content provider implementation. (fully qualified Java package name)
'path' is the virtual directory within the provider that identifies the kind of data being requested.
'id' is optional part that specifies the primary key of a record being requested. We can omit this part to request all records.

Adding new records:
We need to override insert() method of the ContentProvider to insert new record to the database via content provider. The caller method will have to specify the content provider URI and the values to be inserted without the ID. Successful insert operation will return the URI value with the newly inserted ID.
For example: If we insert a new record to the content provider content://com.example/sample
the insert method will return content://com.example/sample/1

Updating records:
To update one or more records via content provider we need to specify the content provider URI. update() method of the ContentProvider is used to update records. We have to specify the ID of the record to update a single record. To update multiple records, we have to specify 'selection' parameter to indicate which rows are to be changed.
This method will return the number of rows updated.

Deleting records:
Deleting one or more records is similar to update process. We need to specify either ID or 'selection' to delete records. delete() method of the ContentProvider will return the number of records deleted.

Querying the content provider:
To query the data via content provider we orverride query() method of ContentProvider. This method has many parameters.  We can specify list columns to put into the result cursor using 'projection' parameter. We can specify 'selection' criteria. We can specify 'sortOrder' too.
If we do not specify projection, all the columns will be included in the result cursor. If we do not specify sortOrder the provider will choose its own sort order.

getType() method:

This method is used handle requests for the MIME type of the data at the given URI. We use either vnd.android.cursor.item or vnd.android.cursor.dir/
vnd.android.cursor.item is used to represent specific item. Another one is used to specify all items.

Registering the provider in AndroidManifest.xml
As with any other major parts of Android application, we have to register the content providers too in the AndroidManifest.xml. <provider> element is used to register the content providers. <application> is its parent element.

<provider
   android:name=".MyProvider"
   android:authorities="com.example.contentproviderexample.MyProvider">
</provider>

Here authorities is the URI authority to access the content provider. Typically this will be the fully qualified name of the content provider class.

Let see an Example to understand:

In this tutorial I am using two application one application to store the date and other application used to retrive the data.

NOTE :Please Carefully Observe this Tutorial you wont be getting any tutorial better then this i hope  

Application I: To Store The Data


Create Android Application:
  • File >> New >> Android Application
  • Enter Project name: ContentProviderApp1
  • Package: com.ambilpursunil.newapp
  • Keep other default selections, click Next until you reach Finish


1.Simply Copy and Past the Code which is display below in the    MainActivity.java

package com.ambilpursunil.newapp;

import android.app.Activity;
import android.content.ContentProvider;
import android.content.ContentValues;
import android.net.Uri;
import android.os.Bundle;
import android.view.Menu;
import android.view.View;
import android.widget.EditText;
import android.widget.Toast;


public class MainActivity extends Activity {
           
            EditText contactNameEditText;
           
         @Override
         protected void onCreate(Bundle savedInstanceState) {
            super.onCreate(savedInstanceState);
            setContentView(R.layout.activity_main);
contactNameEditText = (EditText) findViewById(R.id.contactNameEditText);
             }
    public void addName(View view){
            String name = contactNameEditText.getText().toString();
            ContentValues values = new ContentValues();
            values.put(ContentResolver.name, name);
 Uri uri = getContentResolver().insert(ContentResolver.CONTENT_URL, values);
           Toast.makeText(getBaseContext(),"New Contact Added",                                            Toast.LENGTH_LONG).show();
          }
    }

2.Create a new class in your projects src directory and name it as ContentResolver.java simple Copy and Past the below code:

package com.ambilpursunil.newapp;

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.sqlite.SQLiteDatabase;
import android.database.sqlite.SQLiteDatabase.CursorFactory;
import android.database.sqlite.SQLiteOpenHelper;
import android.database.sqlite.SQLiteQuery;
import android.database.sqlite.SQLiteQueryBuilder;
import android.net.Uri;
import android.widget.Toast;

public class ContentResolver extends ContentProvider {
         
         
//Unique NameSpace for my ContentProvider so that other application can access that
static final String PROVIDER_NAME="com.ambilpursunil.newapp.ContentResolver";
          //All The Constants needed for our application
static final String URL = "content://" + PROVIDER_NAME + "/cpcontacts";
          //(our Directory)
          static final Uri CONTENT_URL = Uri.parse(URL);
          //Here We are Defining all the columns that can be in our database
          static final String id = "id";
          static final String name = "name";
          static final int uriCode = 1;
         
          private static HashMap<String, String> values;
         
          static final UriMatcher uriMatcher;
         
          static{
                   uriMatcher = new UriMatcher(UriMatcher.NO_MATCH);
                   uriMatcher.addURI(PROVIDER_NAME, "cpcontacts", uriCode);
          }
         
          private SQLiteDatabase sqlDB;
         
          static final String DATABASE_NAME = "myContacts";
          static final String TABLE_NAME = "names";
          static final int DATABASE_VERSION = 1;
  static final String CREATE_DB_TABLE = "CREATE TABLE " + TABLE_NAME + " (id INTEGER PRIMARY KEY AUTOINCREMENT, " + "name TEXT NOT NULL);";
               
          @Override
          public boolean onCreate() {
                   DatabaseHelper  dbHelper = new DatabaseHelper(getContext());
                   sqlDB = dbHelper.getWritableDatabase();
                   if(sqlDB != null ){
                   return true;
                   }
                   return false;
                   }

          @Override
          public Cursor query(Uri uri, String[] projection, String selection,
                        String[] selectionArgs, String sortOrder) {
                   //SQLiteQueryBuilder is used to Write Queries
                   SQLiteQueryBuilder queryBuilder = new SQLiteQueryBuilder();
                   queryBuilder.setTables(TABLE_NAME);
                   switch(uriMatcher.match(uri)){
                   case uriCode:
                   queryBuilder.setProjectionMap(values);
                   break;
                   default:
  throw new IllegalArgumentException("Unknown URI:" +uri);
                   }
                  //Cursor is used to Read and write the data from the query
 Cursor cursor = queryBuilder.query(sqlDB, projection, selection,                                 selectionArgs, null, null, sortOrder);
 cursor.setNotificationUri(getContext().getContentResolver(), uri);
                  return cursor;
                 }

          @Override
          public String getType(Uri uri) {
                 switch(uriMatcher.match(uri)){
                 case uriCode:
                 return "vnd.android.cursor.dir/cpcontacts";
                 default:
 throw new IllegalArgumentException("UnSupported URI:" +uri);
                }
               }

          @Override
          public Uri insert(Uri uri, ContentValues values) {
               long rowID = sqlDB.insert(TABLE_NAME, null, values);
               if(rowID > 0){
               Uri _uri = ContentUris.withAppendedId(CONTENT_URL, rowID);
               getContext().getContentResolver().notifyChange(_uri, null);
               return _uri;
               }else{
               Toast.makeText(getContext(), "Row Inserted                                                              Failed",Toast.LENGTH_LONG).show();
               return null;
               }
               }

          @Override
          public int delete(Uri uri, String selection, String[] selectionArgs) {
                int rowsDeleted = 0;
                switch(uriMatcher.match(uri)){
                case uriCode:
 rowsDeleted = sqlDB.delete(TABLE_NAME, selection, selectionArgs);
                break;
                default:
                throw new IllegalArgumentException("Unknown URI:" + uri);
                }
                getContext().getContentResolver().notifyChange(uri, null);
                return rowsDeleted;
                }

          @Override
          public int update(Uri uri, ContentValues values, String selection,
                String[] selectionArgs) {
                // TODO Auto-generated method stub
                return 0;
               }

          private class DatabaseHelper extends SQLiteOpenHelper{
              public DatabaseHelper(Context context) {
              super(context, DATABASE_NAME, null, DATABASE_VERSION);
              }
         @Override
         public void onCreate(SQLiteDatabase sqlDB) {
              sqlDB.execSQL(CREATE_DB_TABLE);
              }
        @Override
 public void onUpgrade(SQLiteDatabase sqlDB, int oldVersion, int newVersion) {
              sqlDB.execSQL("DROP TABLE IF EXISTS    " + TABLE_NAME);
              onCreate(sqlDB);
                   }
             }
         }

3.Simple Copy and Past the below code:  actvitiy_main.xml
<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.example.contentproviderbydarekbanas.MainActivity" >

    <EditText
        android:id="@+id/contactNameEditText"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:layout_alignParentTop="true"
        android:layout_centerHorizontal="true"
        android:layout_marginTop="23dp"
        android:ems="10"
        android:hint="Add Name" >

        <requestFocus />
    </EditText>

    <Button
        android:id="@+id/addContactButton"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:layout_alignParentLeft="true"
        android:layout_below="@+id/contactNameEditText"
        android:layout_marginTop="59dp"
        android:onClick="addName"
        android:text="Add Name" />

</RelativeLayout>

4.Copy and past the code for  manifest.xml

<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
    package="com.example.contentproviderbydarekbanas"
    android:versionCode="1"
    android:versionName="1.0" >

    <uses-sdk
        android:minSdkVersion="14"
        android:targetSdkVersion="18" />

    <application
        android:allowBackup="true"
        android:icon="@drawable/ic_launcher"
        android:label="@string/app_name"
        android:theme="@style/AppTheme" >
        <activity
            android:name=".MainActivity"
            android:label="@string/app_name" >

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

          <category android:name="android.intent.category.LAUNCHER" />
            </intent-filter>
        </activity>
       
        <provider 
              android:name="com.ambilpursunil.newapp.ContentResolver"  
              android:authorities="com.ambilpursunil.newapp.ContentResolver"
              android:exported="true"
              android:multiprocess="true">
        </provider>
       
    </application>

</manifest>

5.Right click on the project and Run As-->Android Application


OutPut:

Now enter the Name and click on the Add Name Button then the data can be stored.


Stay Tune For Next Tutorial... Android Progreamming Tutorials 14: ContentProvider 2 In Android:

Please Send Your Comments To ambilpura.sunil@gmail.com




No comments:

Post a Comment