Android ContentProvider数据共享

一、构造一个自己的Provider实现App之间数据共享

 1、我们先来了解一下   Uri(统一资源定位符) 

定义:每一个Content Provider使用一个公开的URI唯一标示其数据集,Android所提供的ContentProvider都存放android.provider包中  
结构:分为A、B、C、D四个部分

A:标准前缀,用来说明一个Content Provider控制这些数据,无法改变的;
B:URI 的标识,唯一标识ContentProvider,外部调用者可以根据这个标识来找到它。为了保证URI标识的唯一性,它必须是一个完整的、小写的类名。一般是定义该ContentProvider的包.类的名称
C:路径(path),通俗的讲就是你要操作的数据库中表的名字,或者你也可以自己定义,记得在使用的时候保持一致就可以了;
D:如果URI中包含表示需要获取的记录的ID;则就返回该id对应的数据,如果没有ID,就表示返回全部; "content://com.gdnf.provider/tablename/#" #表示数据id。

路径(path)可以用来表示我们要操作的数据,路径的构建应根据业务而定,如下:
1、要操作person表中id为10的记录,可以构建这样的路径:/person/10
2、要操作person表中id为10的记录的name字段,
person/10/name
3、要操作person表中的所有记录,可以构建这样的路径:/person
4、当然要操作的数据不一定来自数据库,也可以是文件、xml或网络等其他存储方式,如下:要操作xml文件中person节点下的name节点,可以构建这样的路径:/person/name
5、如果要把一个字符串转换成Uri,可以使用Uri类中的parse()方法,如下:Uri
uri
= Uri.parse("content://com.bing.provider.personprovider/person")

 2、UriMatcher

UriMatcher主要用在ContentProvider中,用来构建URI匹配项和判断Uri的正确性,如在insert之前先判断用户传进来的Uri是否与UriMatcher定义的匹配。

 3、ContentUris

Long id=ContentUris.parseId(uri);取出URI中传递的ID
Uri uri=ContentUris.withAppendedId(uri,id);为Uri追加ID

4、案例代码

package com.example.provider;

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.net.Uri;
import android.support.annotation.Nullable;

import com.example.dao.StuDao;

/**
 * Created by Administrator on 2017/12/18.
 */

public class StuProvider extends ContentProvider {

    //定义authorities--这是表示Uri的“B部分”,获取ContentProvider的包名
    private static final String  authorities="com.example.provider.stuprovider";

    //构建UriMatcher对象(用于管理和匹配Uri)
    private static UriMatcher matcher=new UriMatcher(UriMatcher.NO_MATCH);

    //为每一个Uri定义一个编码
    //所有Stu的编码为1
    private static final int STUS=1;
    //一个Stu的编码为2
    private static final int STU=2;
    //根据姓名查找Stu的编码为3
    private static final int STU_NAME=3;
    //根据性别查找Stu的编码为4
    private static final int STU_SEX=4;
    //应用UriMatcher对象构建Uri匹配项
    static{
        //A部分默认为:content:。只需带入B、C、D的值
        matcher.addURI(authorities,"/stu",STUS);
        matcher.addURI(authorities,"/stu/#",STU);
        matcher.addURI(authorities,"/stu/#/name",STU_NAME);
        matcher.addURI(authorities,"/stu/#/sex",STU_SEX);
    }

    //声明上下文
    private Context context;
    @Override
    public boolean onCreate() {
        context=getContext();
        return false;
    }

    @Nullable
    @Override
    public String getType(Uri uri) {
        if(matcher.match(uri)==STUS){
            return "vnd.android.cursor.dir/stu";
        }else if(matcher.match(uri)==STU){
            return "vnd.android.cursor.item/stu";
        }
        return null;
    }

    @Nullable
    @Override
    public Uri insert(Uri uri, ContentValues contentValues) {
        if(matcher.match(uri)==STUS){
            long id=new StuDao(context).addStu(contentValues);//添加学生
            Uri newUri=ContentUris.withAppendedId(uri,id);

            //发生了数据变化,给出一个通知信号
            getContext().getContentResolver().notifyChange(uri,null);
            return newUri;
        }
        return null;
    }

    @Override
    public int delete(Uri uri, String s, String[] strings) {
        StuDao dao=new StuDao(context);
        switch (matcher.match(uri)){
            case STUS:
                dao.delete("tb_stu",null,null);
                break;
            case STU:
                long id=ContentUris.parseId(uri);//从Uri里面解析出Id
                dao.delete("tb_stu","_id="+id,null);
                break;
        }
        //发生了数据编号,给出一个通知信号
        getContext().getContentResolver().notifyChange(uri,null);
        return 0;
    }

    @Override
    public int update(Uri uri, ContentValues contentValues, String s, String[] strings) {
        StuDao dao=new StuDao(context);
        int i=-1;
        switch (matcher.match(uri)){
            case STUS:
                i=dao.update("tb_stu",contentValues,s,strings);
                break;
            case STU:
                long id=ContentUris.parseId(uri);//从Uri里面解析出Id
                i=dao.update("tb_stu",contentValues,"_id="+id,null);
                break;
        }
        //发生了数据编号,给出一个通知信号
        getContext().getContentResolver().notifyChange(uri,null);
        return 0;
    }

    @Nullable
    @Override
    public Cursor query(Uri uri, String[] strings, String s, String[] strings1, String s1) {
        StuDao dao=new StuDao(context);
        Cursor cursor=null;
        switch (matcher.match(uri)){
            case STUS:
                cursor=dao.queryStu(strings,s,strings1,null,null,s1,null);
                break;
            case STU:
                long id=ContentUris.parseId(uri);//从Uri里面解析出Id
                cursor=dao.queryStu(strings,"_id="+id,null,null,null,s1,null);
                break;
        }
        return cursor;
    }
}

二、在另一个程序中如何使用ContentResolver内容解析器进行数据操作

 1、ContentResolver操作ContentProvider中的数据

当外部应用需要对ContentProvider中的数据进行添加、删除、修改和查询操作时,可以使用ContentResolver 类来完成,要获取ContentResolver 对象,可以使用getContentResolver()方法获取ContentResolver对象

 2、监听ContentProvider中数据的变化

如果ContentProvider的访问者需要监听ContentProvider中的数据变化,可以注册一个观察者getContentResolver().registerContentObserver(uri,bool,observer)

 3、数据提供者在数据发生改变时发出消息

getContent().getContentResolver().notifyChange(uri,null)

 4、案例代码

package com.example.android_contentprover_test;

import android.app.Activity;
import android.content.ContentProvider;
import android.content.ContentResolver;
import android.content.ContentUris;
import android.content.ContentValues;
import android.database.ContentObserver;
import android.database.Cursor;
import android.net.Uri;
import android.os.Bundle;
import android.os.Handler;
import android.os.Message;
import android.util.Log;
import android.view.View;
import android.widget.Toast;

public class MainActivity extends Activity {

    //定义一个ContentResolver内容解析器
    private ContentResolver resolver;
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);

        //获取系统的ContentResolver对象
        resolver=getContentResolver();
        //为resolver添加一个监听事件,监听数据是否发生变化
        Uri uri=Uri.parse("content://com.example.provider.stuprovider/stu");
        resolver.registerContentObserver(uri,true,new StuObServer(handler));
    }

    //构建一个handler对象执行数据操作
    private Handler handler=new Handler(){
        @Override
        public void handleMessage(Message msg) {
            super.handleMessage(msg);
            if(msg.what==1){
                //为所欲为
                findStuList(null);//执行查询
            }
        }
    };

    //构建一个观察者类
    private class StuObServer extends ContentObserver{

        private Handler handler;
        public StuObServer(Handler handler) {
            super(handler);
            this.handler=handler;
        }
        //当发生改变时
        @Override
        public void onChange(boolean selfChange) {
            super.onChange(selfChange);
            //监听到数据发生改变时,发出一个编号为1的消息
            handler.sendEmptyMessage(1);
        }
    }

    public void addStu(View view){
        //声明数据来源——路径
        Uri addUri=Uri.parse("content://com.example.provider.stuprovider/stu");
        //创建一个数据对象
        ContentValues values=new ContentValues();
        values.put("sname","Join");
        values.put("sage",21);
        values.put("ssex","男");
        //使用内容解析器执行添加(参数为:数据的来源,更改的数据)
        Uri newUri=resolver.insert(addUri,values);
        //通过解析器得到更改数据的ID
        long id= ContentUris.parseId(newUri);
        Toast.makeText(this, "添加学生成功,ID="+id, Toast.LENGTH_SHORT).show();

        //使用内容解析器调用查询方法,查询数据
        Cursor cursor=resolver.query(newUri,null,null,null,null);
        if(cursor.moveToNext()){
            int _id=cursor.getInt(cursor.getColumnIndex("_id"));
            String name=cursor.getString(cursor.getColumnIndex("sname"));
            Toast.makeText(this, "ID="+_id+",Name="+name, Toast.LENGTH_SHORT).show();
        }
        cursor.close();
    }

    public void findStuList(View view){
        Uri uri=Uri.parse("content://com.example.provider.stuprovider/stu");
        Cursor cursor=resolver.query(uri,null,null,null,null);
        while(cursor.moveToNext()){
            int _id=cursor.getInt(cursor.getColumnIndex("_id"));
            String name=cursor.getString(cursor.getColumnIndex("sname"));
            Log.i("App1 StuList", "ID="+_id+",Name="+name);
        }
        cursor.close();
    }
}
时间: 2024-08-04 20:35:49

Android ContentProvider数据共享的相关文章

Android ContentProvider、ContentResolver和ContentObserver的使用

1.ContentProvider.ContentResolver和ContentObserver ContentProvider是Android的四大组件之一,可见它在Android中的作用非同小可.它主要的作用是:实现各个应用程序之间的(跨应用)数据共享,比如联系人应用中就使用了ContentProvider,你在自己的应用中可以读取和修改联系人的数据,不过需要获得相应的权限.其实它也只是一个中间人,真正的数据源是文件或者SQLite等. 一个应用实现ContentProvider来提供内容

Android基础 : Android ContentProvider

Android 应用程序通过ContentProvider实现方式统一的数据共享功能. 外界的程序通过ContentResolver接口可以访问ContentProvider提供的数据,在Activity当中通过getContentResolver()可以得到当前应用的 ContentResolver实例. 参考文章 Android ContentProvider和getContentResolver

Android ContentProvider基本用法

转自:https://www.jianshu.com/p/601086916c8f 一.基本概念 ContentProvider是Android系统中提供的专门用户不同应用间进行数据共享的组件,提供了一套标准的接口用来获取以及操作数据,准许开发者把自己的应用数据根据需求开放给其他应用进行增删改查,而无须担心直接开放数据库权限而带来的安全问题.系统预置了许多ContentProvider用于获取用户数据,比如消息.联系人.日程表等. 二.ContentResolver 在ContentProvid

Android ContentProvider完整案例

ContentData类,提供数据常量: /** * 提供ContentProvider对外的各种常量,当外部数据需要访问的时候,就可以参考这些常量操作数据. * @author HB * */ public class ContentData { public static final String AUTHORITY = "hb.android.contentProvider"; public static final String DATABASE_NAME = "te

Android ContentProvider详解

1.适用场景 1) ContentProvider为存储和读取数据提供了统一的接口 2) 使用ContentProvider,应用程序可以实现数据共享 3) android内置的许多数据都是使用ContentProvider形式,供开发者调用的(如视频,音频,图片,通讯录等) 2.相关概念介绍 1)ContentProvider简介 当应用继承ContentProvider类,并重写该类用于提供数据和存储数据的方法,就可以向其他应用共享其数据.虽然使用其他方法也可以对外共享数据,但数据访问方式会

Android ContentProvider+ContentObserver

说明:文章仅供本人学习记录所用. 1.理解含义: ContentProvider: 内容提供者,将数据以表的形式进行操作.主要实现应用程序间数据共享,操作系统本地数据(包括短       信.音频.视屏.数据库). ContentObserver:内容观察者,监听数据变化. 2.使用方法: ContentProvider: 1)步骤:新建MyProvider类继承ContentProvider类;注册URI;重写方法(onCreate.query.bulkInsert.insert.      

android ContentProvider实现资源共享实例

ContentProvider为存储和读取数据提供了统一的接口,使用ContentProvider,应用程序可以实现数据共享,android内置的许多数据都是使用ContentProvider形式,供开发者调用的(如视频,音频,图片,通讯录等). 本实例将SQLite作为存储数据的方式. Activity代码: protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setC

[Android] ContentProvider实例详解

1.ContentProvider是什么? ContentProvider(内容提供者)是Android的四大组件之一,管理android以结构化方式存放的数据,以相对安全的方式封装数据(表)并且提供简易的处理机制和统一的访问接口供其他程序调用. Android的数据存储方式总共有五种,分别是:Shared Preferences.网络存储.文件存储.外储存储.SQLite.但一般这些存储都只是在单独的一个应用程序之中达到一个数据的共享,有时候我们需要操作其他应用程序的一些数据,就会用到Cont

android,ContentProvider+ContentObserver+ContentResolver,用法。

这个是传智播客老师讲android开发时的一个图. 一. PersonProvider继承ContentProvider,实现ContentProvider中的数据操作类. 在需要监听的操作中添加添加数据变化通知. this.getContext().getContentResolver().notifyChange(uri, null); 第二个参数,数据变化的监听者,可以不设置,也即是设为null,如果给定了这个监听者,不管外面有多少个应用要设置监听,进行监听数据变化,这个getConten