Content Provider in Android


In my last tutorial, I have discussed the service that is the most important component in android. I would be recommended to you, please check all post related android services. Here are the details of link Service in Android Part1Service in Android Part2 and Service in Android Part3.

Now In this article, I am focusing on the share the content from different -2 ways. We will check that how many ways we can share the content to multiple apps. What are the best procedure and which is most recommended by android?

Ok, Let's see how many ways we can share the data from an app to multiple apps. Actually, you can share the content many ways but some of all are not recommended by an android framework.

1. Share the shared preference to other apps.
2. Share the SQLite database to other apps.
3. Share the internal storage files
4. Share data with content provider (recommended)
5. Share data by AIDL service
6. Share data by TCP/IP or HTTP network communication.

I have pointed some of the mechanism that we can share the content with other applications. It might be many more mechanisms also available for sharing but these are the basics that everyone is known for sharing data. The first point is here sharing the shared preference data to other apps. If we talk about the SharedPreferenece it means that we can store limited data. You can not share the huge data from this way. For a small amount of data if you want to share then its possible and make sure the database would be public for share. If you made private then is difficult to share the data,  Data has stored in device sandbox that not have permission to access by any other apps. We are using SharedPreference for storing the user information.

For a large amount of data,  if you want to share then you can share by SQLite database. You can access the database tables and data of each table by simple SQL query. You can make a copy of SQLite DB into assets folder for access the data. Or the other one is shared by storage files. It does not need to explanation it is pretty simple. You can write the information into storage files of sd card and shared the files to other applications.

Content Provider is the recommended by the Android framework to share any data from one app to other apps. By name it clear that it provide the content data to any application. Content Resolver is the mediator to help to get access the share data. By ContentResolver you can make the query on Content Provide which kind of data you want to access. It works well in the different process to share the content data with multiple apps.

Even You can share data from the ADIL IPC mechanism. IPC remote mechanism is very strong to get access data from one application to other applications. Here other applications need to bind remotely. I have already focused here Service in Android Part3.

You can share data from HTTP request to any other application. But it required the internet connection to get the data from the server.

Let's create the App1 that maintain the database as a provider. We need to make the method synchronized to avoid the collision.  It makes the method thread safe if multiple thread access the same method subsequently. Content Provider works very well in the different process. Here is uploaded the video that helps you to understand.


Article.java

   
import android.content.ContentValues;
import android.database.Cursor;

/**
 * Created by sunil on 3/11/2017.
 */

public class Article {

    public static final String TABLE_NAME = "Article";

    // Naming the id column with an underscore is good to be consistent
    // with other Android things. This is ALWAYS needed
    public static final String ARTICLE_ID = "_id";
    // These fields can be anything you want.
    public static final String TITLE = "title";
    public static final String DESCRIPTION = "description";
    public static final String AUTHOR_NAME = "author";

    public long id = -1;
    public String title = "";
    public String description = "";
    public String author = "";

    public Article(){

    }

    public static final String CREATE_TABLE =
            "CREATE TABLE " + TABLE_NAME + "("
                    + ARTICLE_ID + " INTEGER PRIMARY KEY,"
                    + TITLE + " TEXT NOT NULL DEFAULT '',"
                    + DESCRIPTION + " TEXT NOT NULL DEFAULT '',"
                    + AUTHOR_NAME + " TEXT NOT NULL DEFAULT ''"
                    + ")";

    public Article(final Cursor cursor) {
        // Indices expected to match order in FIELDS!
        this.id = cursor.getLong(0);
        this.title = cursor.getString(1);
        this.description = cursor.getString(2);
        this.author = cursor.getString(3);
    }


    public ContentValues getContent(Article article) {
        final ContentValues values = new ContentValues();
        // Note that ID is NOT included here
        values.put(TITLE, article.getTitle());
        values.put(DESCRIPTION, article.getDescription());
        values.put(AUTHOR_NAME, article.getAuthor());
        return values;
    }

    public static final String[] FIELDS = { ARTICLE_ID, TITLE, DESCRIPTION, AUTHOR_NAME };

    public String getTitle() {
        return title;
    }

    public void setTitle(String title) {
        this.title = title;
    }

    public String getDescription() {
        return description;
    }

    public void setDescription(String description) {
        this.description = description;
    }

    public String getAuthor() {
        return author;
    }

    public void setAuthor(String author) {
        this.author = author;
    }
}

DatabaseHelper.java

   
import android.content.Context;
import android.database.Cursor;
import android.database.sqlite.SQLiteDatabase;
import android.database.sqlite.SQLiteOpenHelper;

import java.util.ArrayList;
import java.util.List;

/**
 * Created by sunil on 03/11/2017.
 */

public class DatabaseHelper extends SQLiteOpenHelper{

    private static final int DATABASE_VERSION = 1;
    private static final String DATABASE_NAME = "AndroidPoint";
    private final Context context;

    private static DatabaseHelper databaseHandlerInstance;

    public static DatabaseHelper getInstance(final Context context) {
        if (databaseHandlerInstance == null) {
            databaseHandlerInstance = new DatabaseHelper(context);
        }
        return databaseHandlerInstance;
    }

    public DatabaseHelper(Context context){
        super(context, DATABASE_NAME, null, DATABASE_VERSION);
        this.context = context.getApplicationContext();
    }

    @Override
    public void onCreate(SQLiteDatabase db) {
        db.execSQL(Article.CREATE_TABLE);

        Article article = new Article();
        article.setTitle("Service in android part1");;
        article.setDescription("Service is important component");
        article.setAuthor("sunil");
        db.insert(Article.TABLE_NAME, null, article.getContent(article));

        Article article1 = new Article();
        article1.setTitle("Service in android part2");
        article1.setDescription("Service is running in background.");
        article1.setAuthor("sunil");
        db.insert(Article.TABLE_NAME, null, article.getContent(article1));
    }

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

    }

    public synchronized Article getArticle(final long id) {
        final SQLiteDatabase db = this.getReadableDatabase();
        final Cursor cursor = db.query(Article.TABLE_NAME, Article.FIELDS,
                Article.ARTICLE_ID + " IS ?", new String[] { String.valueOf(id) },
                null, null, null, null);
        if (cursor == null || cursor.isAfterLast()) {
            return null;
        }

        Article item = null;
        if (cursor.moveToFirst()) {
            item = new Article(cursor);
        }
        cursor.close();
        return item;
    }

    public synchronized List getAllArticle() {
List articleList = new ArrayList<>();
final SQLiteDatabase db = this.getReadableDatabase(); final Cursor cursor = db.query(Article.TABLE_NAME, Article.FIELDS, null, null, null, null, null, null); try { while (cursor.moveToNext()) { Article article = new Article(); article.setTitle(cursor.getString(1)); article.setDescription(cursor.getString(2)); article.setAuthor( cursor.getString(3)); articleList.add(article); } } finally { cursor.close(); } return articleList; } public synchronized boolean addArticle(final Article article) { boolean success = false; int result = 0; final SQLiteDatabase db = this.getWritableDatabase(); if (article.id > -1) { result += db.update(Article.TABLE_NAME, article.getContent(article), Article.ARTICLE_ID + " IS ?", new String[] { String.valueOf(article.id) }); } if (result > 0) { success = true; } else { // Update failed or wasn't possible, insert instead final long id = db.insert(Article.TABLE_NAME, null, article.getContent(article)); if (id > -1) { article.id = id; success = true; } } if (success) { notifyProviderOnArticleChange(); } return success; } private void notifyProviderOnArticleChange() { context.getContentResolver().notifyChange(ArticleProvider.URI_ARTICLE, null, false); } }

ArticleProvider.java

   
import android.content.ContentProvider;
import android.content.ContentValues;
import android.database.Cursor;
import android.net.Uri;
import android.support.annotation.Nullable;

/**
 * Created by sunil on 3/11/2017.
 */

public class ArticleProvider extends ContentProvider{

    public static final String AUTHORITY = "com.example.testapp.contentprovider";
    public static final String SCHEME = "content://";

    // URIs
    // Used for all articles
    public static final String ARTICLES = SCHEME + AUTHORITY + "/article";
    public static final Uri URI_ARTICLE = Uri.parse(ARTICLES);
    // Used for a single Article, just add the id to the end
    public static final String ARTICLE_BASE = ARTICLES + "/";

    public ArticleProvider(){

    }

    @Override
    public boolean onCreate() {
        return true;
    }

    @Nullable
    @Override
    public Cursor query(Uri uri, String[] projection, String selection, String[] selectionArgs, String sortOrder) {
        Cursor result = null;
        if (URI_ARTICLE.equals(uri)) {
            result = DatabaseHelper.getInstance(getContext()).getReadableDatabase()
                    .query(Article.TABLE_NAME, Article.FIELDS, null, null, null, null, null, null);
            result.setNotificationUri(getContext().getContentResolver(), URI_ARTICLE);

        } else if (uri.toString().startsWith(ARTICLE_BASE)) {
            final long id = Long.parseLong(uri.getLastPathSegment());
            result = DatabaseHelper.getInstance(getContext()).getReadableDatabase()
                    .query(Article.TABLE_NAME, Article.FIELDS,
                            Article.ARTICLE_ID + " IS ?",
                            new String[] { String.valueOf(id) }, null, null, null, null);

            result.setNotificationUri(getContext().getContentResolver(), URI_ARTICLE);
        } else {
            throw new UnsupportedOperationException("Not yet implemented");
        }
        return result;
    }

    @Nullable
    @Override
    public String getType(Uri uri) {
        throw new UnsupportedOperationException("Not yet implemented");
    }

    @Nullable
    @Override
    public Uri insert(Uri uri, ContentValues values) {
        throw new UnsupportedOperationException("Not yet implemented");
    }

    @Override
    public int delete(Uri uri, String selection, String[] selectionArgs) {
        throw new UnsupportedOperationException("Not yet implemented");
    }

    @Override
    public int update(Uri uri, ContentValues values, String selection, String[] selectionArgs) {
        throw new UnsupportedOperationException("Not yet implemented");
    }
}

AddArticleActivity.java

   
import android.os.Bundle;
import android.support.annotation.Nullable;
import android.support.v7.app.AppCompatActivity;
import android.widget.Button;
import android.widget.EditText;
import android.widget.Toast;

import com.example.testapp.R;

import butterknife.BindView;
import butterknife.ButterKnife;
import butterknife.OnClick;

/**
 * Created by sunil on 11-03-2017.
 */

public class AddArticleActivity extends AppCompatActivity {

    @BindView(R.id.articleName)
    EditText articleName;
    @BindView(R.id.articleDesc)
    EditText articleDesc;
    @BindView(R.id.addButton)
    Button addButton;

    DatabaseHelper db;

    @Override
    protected void onCreate(@Nullable Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.add_article_activity);
        ButterKnife.bind(this);

        db = DatabaseHelper.getInstance(this);
    }

    @OnClick(R.id.addButton)
    public void addArticle(){
        String articleTitle = articleName.getText().toString();
        String articleDescription = articleDesc.getText().toString();
        if (articleTitle.isEmpty() && articleDescription.isEmpty()){
            Toast.makeText(AddArticleActivity.this, "Please enter details.", Toast.LENGTH_LONG).show();
        }else{
            Article article = new Article();
            article.setTitle(articleTitle);
            article.setDescription(articleDescription);
            article.setAuthor("Sunil");
            db.addArticle(article);

            finish();
        }

    }
}

add_article_activity.xml

  
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:orientation="vertical" android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:padding="10dp">

    <EditText
        android:id="@+id/articleName"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:hint="Enter Article"
        />

   <EditText
        android:layout_marginTop="10dp"
        android:layout_below="@+id/articleName"
        android:id="@+id/articleDesc"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:hint="Enter Article Description"
        />

   <Button
        android:textColor="#fff"
        android:background="@color/colorPrimary"
        android:layout_alignParentBottom="true"
        android:id="@+id/addButton"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:text="Add Article"/>

</RelativeLayout> 

So this is the App1 that contain the data. Now Let's access this data on App2 by using the content provider.

MainActivity.java

   
import android.content.ContentProviderClient;
import android.content.DialogInterface;
import android.content.Intent;
import android.content.pm.PackageManager;
import android.database.Cursor;
import android.net.Uri;
import android.os.Bundle;
import android.os.RemoteException;
import android.support.v4.app.ActivityCompat;
import android.support.v4.content.ContextCompat;
import android.support.v7.app.AlertDialog;
import android.support.v7.app.AppCompatActivity;
import android.support.v7.widget.LinearLayoutManager;
import android.support.v7.widget.RecyclerView;
import android.view.View;
import android.widget.Button;
import android.widget.Toast;

import com.example.contentprovideraccess.aidl.MultiplyNumberAidlActivity;

import java.util.ArrayList;
import java.util.List;

import butterknife.BindView;
import butterknife.ButterKnife;

public class MainActivity extends AppCompatActivity {

    @BindView(R.id.recyclerView)
    RecyclerView recyclerView;
    @BindView(R.id.aidlButton)
    Button aidlButton;

    private ArticleAdapter articleAdapter;

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

        initView();
    }

    private void initView() {
        recyclerView.setLayoutManager(new LinearLayoutManager(this));
        List
list = getArticles(); articleAdapter = new ArticleAdapter(this, list); recyclerView.setAdapter(articleAdapter); } private List getArticles() {
List articleList = new ArrayList<>();
String ARTICLES_URI = "content://com.example.testapp.contentprovider/article"; Uri uri = Uri.parse(ARTICLES_URI); /* ContentProvider cp = getContentResolver().acquireContentProviderClient(uri).getLocalContentProvider(); ArticleProvider articleProvider = (ArticleProvider)cp; // for same process*/ // for different process ContentProviderClient contentProviderClient = getContentResolver().acquireContentProviderClient(uri); // for different process if (contentProviderClient != null) { Cursor cursor = null; String[] FIELDS = {"_id", "title", "description", "author"}; try { cursor = contentProviderClient.query(uri, FIELDS, null, null, null); } catch (RemoteException e) { e.printStackTrace(); } try { while (cursor.moveToNext()) { Article article = new Article(); article.setTitle(cursor.getString(1)); article.setDescription(cursor.getString(2)); article.setAuthor(cursor.getString(3)); articleList.add(article); } } finally { cursor.close(); } } else { Toast.makeText(MainActivity.this, "Looks like provider is not available", Toast.LENGTH_LONG).show(); } return articleList; } }
Thanks for the reading post.



No comments:

Post a Comment

Debug Database in Android

In my last tutorial, we have learned how we can use persistence database in android. We also understood which database wrapper we can use...

Contact Me

Name

Email *

Message *