【Android - IPC】之ContentProvider简介

1、Content Provider简介

  Content Provider是Android中提供的一种专门用于不同应用之间进行数据共享的方式,从这一点来看,它天生就适合IPC(Inter-Process Communication,进程间通信)。Content Provider的底层实现是Binder,但它比AIDL要简单很多,因此系统已经给我们做了封装。

  Android系统为我们预置了许多Content Provider,比如通讯录信息、日程表信息等,要想访问这些应用的信息,只需要调用ContentResolver的insert、update、delete、query四个方法即可。但是,我们往往不止需要这些应用的数据,因此,在很多情况下,我们需要创建自定义的Content Provider。

  Content Provider主要是以表格的形式来组织数据的,并且可以包含多张表。除了表格的形式,Content Provider还支持文件格式,比如图片、视频等。

2、Content Provider实例

  在这个例子中,我们要在客户端操作服务端的SQLite数据库,包括查询、删除、添加和修改的操作。

2.1、服务端

  在服务端中,我们先创建一个SQLite数据库,名字叫做server.db,数据库中有一张数据表,名字叫做book表,book表中有两个字段:bookId表示书籍的编号,bookName表示书籍的名称。

  我们创建一个MyDBOpenHelper类继承自SQLiteOpenHelper,来初始化数据库中的信息,代码如下:

package my.itgungnir.server;

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

/**
 * 操作数据库的SQLiteOpenHelper工具类
 * Created by ITGungnir on 2017/4/6.
 */
public class MyDBOpenHelper extends SQLiteOpenHelper {
    private static final String DB_NAME = "server.db";
    public static final String TABLE_NAME = "book";

    private static final int DB_VERSION = 1;

    public MyDBOpenHelper(Context context) {
        super(context, DB_NAME, null, DB_VERSION);
    }

    @Override
    public void onCreate(SQLiteDatabase db) {
        db.execSQL("CREATE TABLE IF NOT EXISTS " + TABLE_NAME + "(bookId INTEGER PRIMARY KEY, bookName TEXT);");
    }

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

  有了数据库之后,我们就可以创建一个Content Provider,用来提供操作数据库的接口。

  我们创建一个Content Provider类BookProvider,继承自ContentProvider类,并实现onCreate()、insert()、update()、delete()、query()和getType()这六个方法。其中,onCreate()方法是ContentProvider创建的时候调用的方法,可以在这个方法中做一些初始化的操作;getType()方法用来返回一个 Uri 请求所对应的MIME类型(媒体类型,比如图片、视频等),如果不关注这个选项,可以直接返回null或“*/*”;剩下的四个方法用于CRUD操作,即实现对数据表的增删改查功能。注意:这六个方法均运行在ContentProvider的进程中,除了onCreate()方法运行在主线程之外,其他五个方法都运行在Binder线程池中。

  下面是我们创建的BookProvider类中的代码:

package my.itgungnir.server;

import android.content.ContentProvider;
import android.content.ContentValues;
import android.content.Context;
import android.content.UriMatcher;
import android.database.Cursor;
import android.database.sqlite.SQLiteDatabase;
import android.net.Uri;
import android.support.annotation.NonNull;
import android.support.annotation.Nullable;

/**
 * 服务端的ContentProvider
 * Created by ITGungnir on 2017/4/6.
 */
public class BookProvider extends ContentProvider {
    private static final String AUTHORITY = "my.itgungnir.server.book_provider";
    private static final Uri CONTENT_URI = Uri.parse("content://" + AUTHORITY + "/book");
    private static final int URI_CODE = 0x001;
    private static final UriMatcher URI_MATCHER = new UriMatcher(UriMatcher.NO_MATCH);

    static {
        URI_MATCHER.addURI(AUTHORITY, "book", URI_CODE);
    }

    private Context context;
    private SQLiteDatabase database;

    private String getTableName(Uri uri) {
        if (URI_MATCHER.match(uri) == URI_CODE) {
            return MyDBOpenHelper.TABLE_NAME;
        }
        return null;
    }

    private void initData() {
        database = new MyDBOpenHelper(context).getWritableDatabase();
        database.execSQL("DELETE FROM " + MyDBOpenHelper.TABLE_NAME + ";");
        database.execSQL("INSERT INTO " + MyDBOpenHelper.TABLE_NAME + " VALUES(1, ‘Android‘);");
        database.execSQL("INSERT INTO " + MyDBOpenHelper.TABLE_NAME + " VALUES(2, ‘iOS‘);");
        database.execSQL("INSERT INTO " + MyDBOpenHelper.TABLE_NAME + " VALUES(3, ‘HTML5‘);");
    }

    @Override
    public boolean onCreate() {
        context = getContext();
        initData();
        return true;
    }

    @Nullable
    @Override
    public Cursor query(@NonNull Uri uri, @Nullable String[] projection, @Nullable String selection, @Nullable String[] selectionArgs, @Nullable String sortOrder) {
        String tableName = getTableName(uri);
        if (tableName == null) {
            throw new IllegalArgumentException("Unsupported URI: " + uri);
        }
        return database.query(tableName, projection, selection, selectionArgs, null, null, sortOrder, null);
    }

    @Nullable
    @Override
    public String getType(@NonNull Uri uri) {
        String tableName = getTableName(uri);
        if (tableName == null) {
            throw new IllegalArgumentException("Unsupported URI: " + uri);
        }
        return null;
    }

    @Nullable
    @Override
    public Uri insert(@NonNull Uri uri, @Nullable ContentValues values) {
        String tableName = getTableName(uri);
        if (tableName == null) {
            throw new IllegalArgumentException("Unsupported URI: " + uri);
        }
        database.insert(tableName, null, values);
        context.getContentResolver().notifyChange(uri, null);
        return uri;
    }

    @Override
    public int delete(@NonNull Uri uri, @Nullable String selection, @Nullable String[] selectionArgs) {
        String tableName = getTableName(uri);
        if (tableName == null) {
            throw new IllegalArgumentException("Unsupported URI: " + uri);
        }
        int count = database.delete(tableName, selection, selectionArgs);
        if (count > 0) {
            context.getContentResolver().notifyChange(uri, null);
        }
        return count;
    }

    @Override
    public int update(@NonNull Uri uri, @Nullable ContentValues values, @Nullable String selection, @Nullable String[] selectionArgs) {
        String tableName = getTableName(uri);
        if (tableName == null) {
            throw new IllegalArgumentException("Unsupported URI: " + uri);
        }
        int count = database.update(tableName, values, selection, selectionArgs);
        if (count > 0) {
            context.getContentResolver().notifyChange(uri, null);
        }
        return count;
    }
}

  由于Content Provider属于Android四大组件,因此,需要在项目的Menifest文件中进行注册。在注册声明Content Provider的时候,需要提供一个name属性和一个authorities属性,name属性是要注册的Content Provider的包路径,而authorities属性是Content Provider的唯一标识。另外,如果服务端和客户端在不同的进程中,我们还需要指定Content Provider的exported属性为true,否则会报错:Permission Denied。下面是我们项目服务端Conttent Provider的注册代码:

<provider
    android:name=".BookProvider"
    android:authorities="my.itgungnir.server.book_provider"
    android:exported="true">
</provider>

  以上就是服务端的代码,可以直接运行。

2.2、客户端

时间: 2024-08-07 01:20:46

【Android - IPC】之ContentProvider简介的相关文章

android IPC及原理简介

什么是Android操作系统,所谓的Android:是基于Linux内核的软件平台和操作系统,早期由Google开发,后由开放手机联盟Open Handset Alliance)开发. Linux系统中进程间通信的方式有:socket, named pipe,message queque, signal,share memory.Java系统中的进程间通信方式有socket, named pipe等.android应用程序理所当然可以应用JAVA的IPC机制实现进程间的通信, 取而代之的是Bin

Android IPC机制(五)用Socket实现跨进程聊天程序

相关文章: Android IPC机制(一)开启多进程 Android IPC机制(二)用Messenger进行进程间通信 Android IPC机制(三)在Android Studio中使用AIDL实现跨进程方法调用 Android IPC机制(四)用ContentProvider进行进程间通信 1.Socket简介 Socket也称作"套接字",是在应用层和传输层之间的一个抽象层,它把TCP/IP层复杂的操作抽象为几个简单的接口供应用层调用已实现进程在网络中通信.它分为流式套接字和

android IPC通信(上)-sharedUserId&amp;amp;&amp;amp;Messenger

看了一本书,上面有一章解说了IPC(Inter-Process Communication,进程间通信)通信.决定结合曾经的一篇博客android 两个应用之间的通信与调用和自己的理解来好好整理总结一下这块的知识.因为内容较多,这部分会分上中下三篇博客来细致分析解说,第一篇上篇要解说的是sharedUserId和Messenger的使用方式. android IPC通信(中)-ContentProvider&&Socket android IPC通信(下)-AIDL sharedUserI

android四大组件--ContentProvider详解

一.相关ContentProvider概念解析: 1.ContentProvider简介 在Android官方指出的Android的数据存储方式总共有五种,分别是:Shared Preferences.网络存储.文件存储.外储存储.SQLite.但是我们知道一般这些存储都只是在单独的一个应用程序之中达到一个数据的共享,有时候我们需要操作其他应用程序的一些数据,例如我们需要操作系统里的媒体库.通讯录等,这时我们就可能通过ContentProvider来满足我们的需求了. 2.为什么要选择Conte

android IPC通信(下)-AIDL

android IPC通信(上)-sharedUserId&&Messenger android IPC通信(中)-ContentProvider&&Socket 这篇我们将会着重介绍AIDL的使用方式和原理,要介绍AIDL先要简单介绍一下Binder,而且Messenger,ContentProvider和AIDL的最底层都是使用的Binder. Binder 直观来说,Binder是Android中的一个类,它实现了IBinder接口.从IPC角度来说,Binder是A

ContentProvider简介

一.ContentProvider简介 当应用继承ContentProvider类,并重写该类用于提供数据和存储数据的方法,就可以向其他应用共享其数据.虽然使用其他方法也可以对外共享数据,但数据访问方式会因数据存储的方式而不同,如:采用文件方式对外共享数据,需要进行文件操作读写数据:采用sharedpreferences共享数据,需要使用sharedpreferences API读写数据.而使用ContentProvider共享数据的好处是统一了数据访问方式. 二.Uri类简介 Uri代表了要操

【转】Android 防破解技术简介

http://www.cnblogs.com/likeandroid/p/4888808.html Android 防破解技术简介 这几年随着互联网的不断发展,Android App 也越来越多!但是随之而来的问题也越来越多,这其中比较令人头疼的问题就是:有些不法分子利用反编译技术破解 App,修改代码,之后再重新编译上传到应用商店!到时候,如果用户下载了这些应用,就可能造成个人信息或者金钱的丢失!所以,作为开发者的我们,有必要学习一些防止被破解的技术手段了! 简介 现在想要破解一个 App,

Android开发之ContentProvider(内容提供者)

1. ContentProvider简介 当应用继承ContentProvider类,并重写该类用于提供数据和存储数据的方法,就可以向其他应用共享其数据.虽然使用其他方法也可以对外共享数据,但数据访问方式会因数据存储的方式而不同. 如:采用文件方式对外共享数据,需要进行文件操作读写数据:采用sharedpreferences共享数据,需要使用sharedpreferences API读写数据. 而使用ContentProvider共享数据的好处是统一了数据访问方式 2.通过ContentProv

Android组件系列----ContentProvider内容提供者

[声明] 欢迎转载,但请保留文章原始出处→_→ 生命壹号:http://www.cnblogs.com/smyhvae/ 文章来源:http://www.cnblogs.com/smyhvae/p/4108017.html 联系方式:[email protected] [正文] 一.ContentProvider简介: ContentProvider内容提供者(四大组件之一)主要用于在不同的应用程序之间实现数据共享的功能. ContentProvider可以理解为一个Android应用对外开放的

Android IPC机制(三)在Android Studio中使用AIDL实现跨进程方法调用

在上一篇文章Android IPC机制(二)用Messenger进行进程间通信中我们介绍了使用Messenger来进行进程间通信的方法,但是我们能发现Messenger是以串行的方式来处理客户端发来的信息,如果有大量的消息发到服务端,服务端仍然一个一个的处理再响应客户端显然是不合适的.另外,Messenger用来进程间进行数据传递但是却不能满足跨进程的方法调用,接下来我们来使用AIDL来实现跨进程方法调用,此前我们都是用Eclipse来实现的,这次我们看看在Android Studio中使用AI