Android之Content provider

来源:互联网 发布:可以查数据的网站 编辑:程序博客网 时间:2024/05/17 09:12

转载请标明出处:http://blog.csdn.net/wu_wxc/article/details/51386909
本文出自【吴孝城的CSDN博客】

Content provider是Android的四大组件之一
它用来实现各个应用程序之间的数据共享,如联系人的应用就使用了Content provider,可以在获得权限的情况下对联系人进行增、删、改、查。类似于一个中间人,真正的数据在文件或SQLite中。如果我们想把我们自己程序里的一些数据共享出来,也只可以用Content provider来实现。

ContentResolver用来对Content provider提供的数据进行操作。外界程序通过ContentResolver可以访问Content provider提供的数据。
在Activity中可以通过getContentResolver()访问当前应用的ContentResolver实例。

URI

这里写图片描述
A为schema
B为authority
C、D为path

A是content://表示数据受控于内容提供者,不修改,如http://,ftp://等
B是URI的授权部分,是唯一标识符,用来定位Content provider,在AndroidMainfest.xml中注册provider时,provider中的android:authorities属性所对应的值
C和D是每个Content provider的内部路径部分,C部分指向一个路径集合,一般用表的名字。D部分指向特定记录,如表中ID为1的记录。如果没有D,则返回全部记录。

MIME

MIME是指定某个扩展名的文件用一种应用程序来打开,当该扩展名的文件被访问时,系统会自动使用指定的应用程序来打开。
Content provider会根据URI来返回MIME类型,每个MIME类型有两种,多条和单条记录。
多行记录
vnd.android.cursor.dir/cn.wuxiaocheng
单行记录
vnd.android.cursor.item/cn.wuxiaocheng
其中
vnd.android.cursor.dir
vnd.android.cursor.item
是固定写法。

使用系统自带的Content provider

很多时候我们都用系统提供的Content provider,如获取联系人,系统已经封装好这些数据并提供接口
使用系统自带的Content provider非常简单,用下Uri和ContentResolver来解析就行,如下面的代码,剩下的就是一些数据库的操作了

如下面这两句,用来操作手机的信息,在AndroidManifest.xml中声明,然后就可以写对应的方法对信息进行增、删、改、查了。

Uri uri = Uri.parse("content://sms/");ContentResolver resolver = getContentResolver();

自定义Content provider

当我们想把自己应用的数据共享给其他应用时,就要自定义Content provider。
方法是创建一个类,继承ContentProvider,然后实现Content provider的几个主要方法
onCreate()
query(Uri, String[], String, String[], String)
insert(Uri, ContentValues)
update(Uri, ContentValues, String, String[])
delete(Uri, String, String[])
getType(Uri)
官方文档:http://developer.android.com/intl/zh-cn/reference/android/content/ContentProvider.html
下面这个例子只是做下演示,所有并没有完全写好,差的也就是一些数据库语句之类的而已,数据源用的是SQLite
Content provider的使用可以看: Android用ContentProvider开发通讯录

UriMatcher

在下面扩展自ContentProvider的类里会有一个UriMatcher工具类,对于它的使用,可以看:Android匹配Uri工具类UriMatcher

![这里写图片描述](http://img.blog.csdn.net/20160512192346895)MainActivity.java

package cn.wuxiaocheng.contentprovider;import android.content.ContentResolver;import android.content.ContentValues;import android.net.Uri;import android.support.v7.app.AppCompatActivity;import android.os.Bundle;import android.view.View;public class MainActivity extends AppCompatActivity {    // 读取contentprovider 数据    final ContentResolver resolver = this.getContentResolver();    @Override    protected void onCreate(Bundle savedInstanceState) {        super.onCreate(savedInstanceState);        setContentView(R.layout.activity_main);    }    public void btn(View v) {        // 如插入一条数据        ContentValues values = new ContentValues();        values.put("name", "测试");        Uri uri = Uri.parse("content://com.jay.example.providers.myprovider/test");        resolver.insert(uri, values);    }}

MyDB.java

package cn.wuxiaocheng.contentprovider;import android.content.Context;import android.database.sqlite.SQLiteDatabase;import android.database.sqlite.SQLiteOpenHelper;/** * Created by 吴孝城 on 2016/5/12. */public class MyDB extends SQLiteOpenHelper {    public MyDB(Context context, String name, SQLiteDatabase.CursorFactory factory, int version) {        super(context, name, factory, version);    }    @Override    public void onCreate(SQLiteDatabase sqLiteDatabase) {    }    @Override    public void onUpgrade(SQLiteDatabase sqLiteDatabase, int i, int i1) {    }}

MyContentResolver.java

package cn.wuxiaocheng.contentprovider;import android.content.ContentProvider;import android.content.ContentValues;import android.content.UriMatcher;import android.database.Cursor;import android.net.Uri;import android.support.annotation.Nullable;public class MyContentResolver extends ContentProvider {    private static final UriMatcher sURIMatcher = new UriMatcher(UriMatcher.NO_MATCH);    private MyDB myDB;    // 注册需要的URI    static {        sURIMatcher.addURI("cn.wuxiaocheng.contentprovider.MyContentResolver", "xxx", 1);        sURIMatcher.addURI("cn.wuxiaocheng.contentprovider.MyContentResolver", "xxxx", 2);    }    // 在ContentProvider创建时调用,初始化Provider    // 如果使用,一定不要在onCreate()方法调用getReadableDatabase() 和 getWritableDatabase()    // 相反,应该在第一次打开时覆盖onOpen(SQLiteDatabase)来初始化数据库    @Override    public boolean onCreate() {        myDB = new MyDB(this.getContext(), "test.db", null, 1);        return true;    }    // 向调用者返回数据,根据uri查询出s指定的全部记录。也可指定查询哪些列,以什么方式排序    @Nullable    @Override    public Cursor query(Uri uri, String[] strings, String s, String[] strings1, String s1) {        return null;    }    // 根据uri返回的MIME类型,是单条记录还是集合    @Nullable    @Override    public String getType(Uri uri) {        int match = sURIMatcher.match(uri);        switch (match) {            case 1:                return "vnd.android.cursor.dir/xxxxx";            case 2:                return "vnd.android.cursor.item/xxxxx";            default:                return null;        }    }    // 根据uri插入contentValues对应的数据    @Nullable    @Override    public Uri insert(Uri uri, ContentValues contentValues) {        return null;    }    // 从ContentProvider删除数据,根据uri删除s指定的条目匹配的全部数据    @Override    public int delete(Uri uri, String s, String[] strings) {        return 0;    }    // 在ContentProvider更新现有数据,根据uri修改s指定的全部记录    @Override    public int update(Uri uri, ContentValues contentValues, String s, String[] strings) {        return 0;    }}

AndroidManifest.xml

<?xml version="1.0" encoding="utf-8"?><manifest xmlns:android="http://schemas.android.com/apk/res/android"    package="cn.wuxiaocheng.contentprovider">    <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:name=".MyContentResolver"            android:authorities="cn.wuxiaocheng.contentprovider.MyContentResolver"            android:enabled="true">        </provider>    </application></manifest>


AndroidManifest.xml的一些配置

官方文档:http://developer.android.com/intl/zh-cn/guide/topics/manifest/provider-element.html
android:name=””
定义内容提供器的实现类的名字,它是ContentProvider类的一个子类,这个属性应该使用完整的Java类名来设定(如:com.example.project.TransportationProvider)。但是也可以使用简写(如:.TransporttationProvider),这时系统会使用元素中指定的包名跟这个简写名称的组合来识别内容提供器。

android:authorities=””
标识内容提供器范围内的数据URI的授权列表,有多个授权时,要用分号来分离每个授权。为了避免冲突,授权名应该使用Java样式的命名规则(如:com.example.provider.cartoonprovider)。通常用ContentProvider的子类来命名。

android:enabled=””
这个属性用于指定这个内容提供器是否能够被系统安装。设置为true,则可以安装;否则不能安装。默认值是true。

android:exported=””
这个属性用于指定该内容提供器是否能够被其他的应用程序组件使用。如果设置为true,则可以被使用,如果为false,则不能被使用。该提供器只对同名的应用程序或有相同用户ID的应用程序有效。默认值是true。
虽然能够使用这个属性来公开内容提供器,但是依然还要用permission属性来限制对它的访问。

0 0