博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
ContentProvider简要
阅读量:5807 次
发布时间:2019-06-18

本文共 15978 字,大约阅读时间需要 53 分钟。

1.什么是ContentProvider
 数据库在Android其中是私有的,当然这些数据包含文件数据和数据库数据以及一些其它类型的数据。


 不能将数据库设为

WORLD_READABLE
,每一个数据库都仅仅能创建它的包訪问,
 这意味着仅仅有由创建数据库的进程可訪问它。假设须要在进程间传递数据。
 则能够使用
AIDL/Binder
或创建一个
ContentProvider
,可是不能跨越进程/包边界直接来使用数据库。


 一个

Content Provider
类实现了一组标准的方法接口,从而可以让其它的应用保存或读取此
Content Provider
的各种数据类型。


 也就是说,一个程序能够通过实现一个

Content Provider
的抽象接口将自己的数据暴露出去。


 外界根本看不到,也不用看到这个应用暴露的数据在应用其中是怎样存储的,或者是用数据库存储还是用文件存储,还是通过网上获得,这些一切都不重要,
 重要的是外界能够通过这一套标准及统一的接口和程序里的数据打交道。能够读取程序的数据,也能够删除程序的数据。
 当然。中间也会涉及一些权限的问题。下边列举一些较常见的接口。这些接口例如以下所看到的


·  
query
(Uri uri, String[] projection, String selection, String[] selectionArgs,String sortOrder):通过Uri进行查询。返回一个Cursor。


·  
insert
(Uri url, ContentValues values):将一组数据插入到Uri 指定的地方。


·  
update
(Uri uri, ContentValues values, String where, String[] selectionArgs):更新Uri指定位置的数据。

·  
delete
(Uri url, String where, String[] selectionArgs):删除指定Uri而且符合一定条件的数据。

2.什么是ContentResolver

外界的程序通过
ContentResolve
r接口能够訪问
ContentProvider
提供的数据,在Activity其中通过
getContentResolver()
能够得到当前应用的 
ContentResolver
实例。
 ContentResolver提供的接口和ContentProvider中须要实现的接口相应,主要有下面几个。

·  
query
(Uri uri, String[] projection, String selection, String[] selectionArgs,String sortOrder):通过Uri进行查询。返回一个Cursor。
·  
insert
(Uri url, ContentValues values):将一组数据插入到Uri 指定的地方。

· 
 update
(Uri uri, ContentValues values, String where, String[] selectionArgs):更新Uri指定位置的数据。

·  
delete
(Uri url, String where, String[] selectionArgs):删除指定Uri而且符合一定条件的数据。


3.ContentProvider和ContentResolver中用到的Uri

在ContentProvider和 ContentResolver其中用到了Uri的形式通常有两种。一种是指定所有数据。还有一种是指定某个ID的数据。
我们看以下的样例。


·  
content://contacts/people/  这个Uri指定的就是所有的联系人数据。


·  content://contacts/people/1 这个Uri指定的是ID为1的联系人的数据。 
在上边两个类中用到的Uri一般由3部分组成。


·  第一部分是方案:"content://" 这部分永远不变
·  第二部分是授权:"contacts"
·  第二部分是路径:"people/","people/1"(假设没有指定ID。那么表示返回所有)。
因为URI通常比較长,并且有时候easy出错,且难以理解。所以,在Android其中定义了一些辅助类,并且定义了一些常量来取代这些长字符串的使用。比例如以下边的代码:
·  Contacts.People.CONTENT_URI (联系人的URI)。


在我们的实例MyProvider中是例如以下定义的:

public static final String AUTHORITY="com.teleca.PeopleProvider";
public static final String PATH_SINGLE="people/#";
public static final String PATH_MULTIPLE="people";
public static final Uri content_URI=Uri.parse("content://"+AUTHORITY+"/"+PATH_MULTIPLE);

实例1

文件MyProvider.java

package com.teleca.provider;

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.SQLException;

import android.database.sqlite.SQLiteDatabase;

import android.database.sqlite.SQLiteOpenHelper;

import android.database.sqlite.SQLiteQueryBuilder;

import android.net.Uri;

import android.text.TextUtils;

import android.util.Log;

public class 
MyProvider
 
extends
 ContentProvider {

 public static final String MIME_DIR_PREFIX="vnd.android.cursor.dir";

 public static final String MIME_ITEM_PREFIX="vnd.android.cursor.item";

 public static final String MIME_ITEM="vnd.msi.people";

 public static final String MIME_TYPE_SINGLE=MIME_ITEM_PREFIX+"/"+MIME_ITEM;

 public static final String MIME_TYPE_MULTIPLE=MIME_DIR_PREFIX+"/"+MIME_ITEM;

 public static final String AUTHORITY="com.teleca.PeopleProvider";

 public static final String 
PATH_SINGLE
="people/#";

 public static final String 
PATH_MULTIPLE
="people";

 public static final Uri content_URI=Uri.parse("content://"+AUTHORITY+"/"+PATH_MULTIPLE);

 public static final String DEFAULT_SORT_ORDER="name DESC";

 public static final String _ID="_id";

 public static final String NAME="name";

 public static final String PHONE="phone";

 public static final String AGE="age";

 public static final int PEOPLE=1;

 public static final int PEOPLES=2;

 private static UriMatcher URI_MATCHER;

 private static HashMap<String,String> PROJECTION_MAP;

 public static String DB_NAME="peopledb";

 public static String DB_TABLE_NAME="people";

 SQLiteDatabase db;

 DBOpenHelper dbOpenHelper;

 static 

 {

  URI_MATCHER=new UriMatcher(UriMatcher.NO_MATCH);

  URI_MATCHER.addURI(AUTHORITY, PATH_MULTIPLE, PEOPLES);

  URI_MATCHER.addURI(AUTHORITY, PATH_SINGLE, PEOPLE);

  PROJECTION_MAP=new HashMap<String,String>();

  PROJECTION_MAP.put(_ID, "_id");

  PROJECTION_MAP.put(NAME, "name");

  PROJECTION_MAP.put(PHONE, "phone");

  PROJECTION_MAP.put(AGE, "age");

 }

 @Override

 
public int 
delete
(Uri uri, String selection, String[] selectionArgs) {

  // TODO Auto-generated method stub

  
int
 count=0;

  
switch
(URI_MATCHER.match(uri))

  {

  
case
 PEOPLES:

   count=db.delete(DB_TABLE_NAME,  selection, selectionArgs);

   break;

 
 case
 PEOPLE:

   String segment =uri.getPathSegments().get(1);

   String where="";

   
if
(!TextUtils.isEmpty(selection))

   {

    where=" AND ("+selection+")";

   }

   count=db.delete(DB_TABLE_NAME, "_id="+segment+where, selectionArgs);

   
break
;

  
default
:

   
throw
 new IllegalArgumentException("Unkonw URI"+uri);

  }

  getContext().getContentResolver().notifyChange(uri, null);//@2

  
return
 count;

 }

 @Override

 
public
 String getType(Uri uri) {

  
// TODO Auto-generated method stub

  
switch
(URI_MATCHER.match(uri))

  {

  
case
 PEOPLES:

   
return
 MIME_TYPE_MULTIPLE;

  
case 
PEOPLE:

  
 return
 MIME_TYPE_SINGLE;

  
default
:

   
throw
 new IllegalArgumentException("Unkown URI "+uri);

  }

 }

 @Override

 public Uri insert(Uri uri, ContentValues values) {

 
 // TODO Auto-generated method stub

  long rowId=0L;

  
if
(URI_MATCHER.match(uri)!=PEOPLES)

  {

   
throw
 new IllegalArgumentException("Unkown URI"+uri);

  }

  rowId=db.insert(DB_TABLE_NAME, null, values);

  
if
(rowId>0)

  {

   Uri result=ContentUris.withAppendedId(content_URI, rowId);

   getContext().getContentResolver().notifyChange(result, null);//@2

   
return
 result;

  }

  
else

   throw new SQLException("Failed to insert row into "+uri);

 }

 @Override

 public boolean onCreate() {

  // TODO Auto-generated method stub

  dbOpenHelper=new DBOpenHelper(this.getContext(),DB_NAME,1);

  db=dbOpenHelper.getWritableDatabase();

  
return 
false;

 }

 @Override

 public Cursor
 
query
(Uri uri, String[] projection, String selection,

   String[] selectionArgs, String sortOrder) {

  // TODO Auto-generated method stub

  SQLiteQueryBuilder queryBuilder=new SQLiteQueryBuilder();

  queryBuilder.setTables(DBInfo.DB_TABLE_NAME);

  queryBuilder.setProjectionMap(PROJECTION_MAP);

  
switch
(URI_MATCHER.match(uri))
  {

  
case
 PEOPLES:
   break;
  
case
  PEOPLE:
   queryBuilder.appendWhere("_id="+uri.getPathSegments().get(1));
   break;
  
default
:
   throw new IllegalArgumentException("Unkonw URI"+uri);
  }
  String orderBy=null;
  
if
(TextUtils.isEmpty(sortOrder))
  {

   orderBy=DEFAULT_SORT_ORDER;
  }
  
else

   orderBy=sortOrder;

  Cursor c=queryBuilder.query(db, projection, selection, selectionArgs, null, null, orderBy);

  c.setNotificationUri(getContext().getContentResolver(), uri);
//@1

  
return
 c;

 }

 
@Override

 
public int 
update
(Uri uri, ContentValues values, String selection,

   String[] selectionArgs) {

  // TODO Auto-generated method stub

  int count=0;

  
switch
(URI_MATCHER.match(uri))

  {

  
case
 PEOPLES:

   count=db.update(DB_TABLE_NAME, values, selection, selectionArgs);

   break;

  
case
 PEOPLE:

   String segment =uri.getPathSegments().get(1);

   String where="";

   
if
(!TextUtils.isEmpty(selection))

   {

    where=" AND ("+selection+")";

   }

   count=db.update(DB_TABLE_NAME, values, "_id="+segment+where, selectionArgs);

   
break
;

  
default
:

   
throw 
new IllegalArgumentException("Unkonw URI"+uri);

  }

  getContext().getContentResolver().notifyChange(uri, null);//@2

  
return
 count;

 }

}

class 
DBOpenHelper 
extends SQLiteOpenHelper

{

 
private static final String 
DB_CREATE="CREATE TABLE "

  +DBInfo.DB_TABLE_NAME

  +" (
_id INTEGER PRIMARY KEY,name TEXT UNIQUE NOT NULL,"

  +"
phone TEXT,age INTEGER);";

 final static String tag="hubin";

 
public 
DBOpenHelper(Context context,String dbName,int version)

 {

  
super(context,dbName,null,version);

 }

 
public void 
onCreate(SQLiteDatabase db)

 {

  
try{

   db.execSQL(DB_CREATE);

  }

  
catch(SQLException e )

  {

   Log.e(tag,"",e);

  }

 }

 
public void onOpen(SQLiteDatabase db)

 {

  super.onOpen(db);

 }

 public void onUpgrade(SQLiteDatabase db,int oldVersion,int newVersion)

 {

  db.execSQL("DROP TABLE IF EXISTS "+DBInfo.DB_TABLE_NAME);

  this.onCreate(db);

 }

}

class DBInfo

{

 public static String DB_NAME="peopledb";

 public static String DB_TABLE_NAME="people"; 

}

注意1:c.setNotificationUri(getContext().getContentResolver(), uri);

这里是把Cursor C加入到ContentResolver的监督对象组中去。

一旦有与uri相关的变化。ContentResolver就回通知Cursor C.

可能Cursor有个私有的内部类ContentObserver的实现。ContentResolver是通过该类来通知Cursor的。

public abstract void
  
setNotificationUri
  (ContentResolver  cr, Uri  uri)
Register to watch a content URI for changes. This can be the URI of a specific data row (for example, "content://my_provider_type/23"), 
or a a generic URI for a content type.

Parameters

cr  The content resolver from the caller's context. The listener attached to this resolver will be notified.

uri  The content URI to watch. 

注意2: 
getContext().getContentResolver().notifyChange(uri, null)

通知数据发生了变化。


  public void  notifyChange  (Uri  uri, ContentObserver  observer)
Notify registered observers that a row was updated. To register, call registerContentObserver(). By default, CursorAdapter objects will get this notification.
Parameters
observer  The observer that originated the change, may be null 
这里为null的意思可能就是调用在ContentResolver中注冊的ContentObserver,反之则是调用參数指定的
文件People.java
package com.teleca.provider;
public class People {


 public long id;
 public String name;
 public String phone;
 public int age;
}
文件
Hello.java
package com.teleca.provider;
import java.util.ArrayList;
import java.util.List;
import android.app.Activity;
import android.content.ContentUris;
import android.content.ContentValues;
import android.database.Cursor;
import android.database.SQLException;
import android.net.Uri;
import android.os.Bundle;
import android.os.Handler;
import android.util.Log;
import android.view.View;
import android.view.View.OnClickListener;
import android.widget.Button;
public class Hello extends Activity {

    
/** Called when the activity is first created. */
 final static String tag="hubin";
    @Override
    public void onCreate(Bundle savedInstanceState) {

        super.onCreate(savedInstanceState);
        setContentView(R.layout.main);
  Button button = (Button) findViewById(R.id.Button01);
  OnClickListener listener = new OnClickListener() {

   @Override
   public void onClick(View v) {

    cmd = CMD_ADD;
    doAction();

   }
  };
  button.setOnClickListener(listener);
  Button button2 = (Button) findViewById(R.id.Button02);
  OnClickListener listener2 = new OnClickListener() {

   @Override
   public void onClick(View v) {

    cmd = CMD_UPDATE;
    doAction();

   }
  };
  button2.setOnClickListener(listener2);
  Button button3 = (Button) findViewById(R.id.Button03);
  OnClickListener listener3 = new OnClickListener() {

   @Override
   public void onClick(View v) {

    cmd = CMD_QUERY;
    doAction();

   }
  };
  button3.setOnClickListener(listener3);
  Button button4 = (Button) findViewById(R.id.Button04);
  OnClickListener listener4 = new OnClickListener() {

   @Override
   public void onClick(View v) {

    cmd = CMD_QUERY_ALL;
    doAction();

   }
  };
  button4.setOnClickListener(listener4);
  Button button5 = (Button) findViewById(R.id.Button05);
  OnClickListener listener5 = new OnClickListener() {

   @Override
   public void onClick(View v) {

    cmd = CMD_DELETE;
    doAction();

   }
  };
  button5.setOnClickListener(listener5);
  Button button6 = (Button) findViewById(R.id.Button06);
  OnClickListener listener6 = new OnClickListener() {

   @Override
   public void onClick(View v) {

    cmd = CMD_DELETE_ALL;
    doAction();

   }
  };
  button6.setOnClickListener(listener6);
  mHandler = new Handler();
    }
 int cnt = 0;
 private Handler mHandler;
 int cmd = 0;
 final int CMD_ADD = 1;
 final int CMD_UPDATE = 2;
 final int  CMD_QUERY= 3;
 final int CMD_QUERY_ALL = 4;
 final int CMD_DELETE = 5;
 final int CMD_DELETE_ALL = 6;
 People people=new People();
 final static String projection[]=new String[]
                                       {"_id","name","phone","age"};
 class DatabaseThread implements Runnable {

  public void run() {

   if (cmd == CMD_ADD) {

    people.name="robin"+System.currentTimeMillis()%100;
    people.phone=""+System.currentTimeMillis();
    people.age=1;
    ContentValues values=new ContentValues();
    values.put("name", people.name);
    values.put("phone", people.phone);
    values.put("age", people.age);
    Uri uri=getContentResolver().insert(MyProvider.content_URI, values);
    people.id=ContentUris.parseId(uri);
    Log.i("hubin",uri.toString());
   } else if (cmd == CMD_UPDATE) {

    ContentValues values=new ContentValues();
    people.phone=""+System.currentTimeMillis();
    values.put("phone", people.phone);
    Uri uri=ContentUris.withAppendedId(MyProvider.content_URI, people.id);
    getContentResolver().update(uri,values,null,null);
   } else if (cmd == CMD_QUERY) {

    Uri uri=ContentUris.withAppendedId(MyProvider.content_URI, people.id);
    Cursor c=
getContentResolver().query(uri, projection, null, null, null);
    People p=get(c);
    printPeople(p);
   } else if (cmd == CMD_QUERY_ALL) {

    Uri uri=MyProvider.content_URI;
    Cursor c=
getContentResolver().query(uri, projection, null, null, null);
    List<People> list=getAll(c);
    int total=list.size();
    for(int i=0;i<total;i++)
    {

     printPeople(list.get(i));
    }
   }
   else if (cmd==CMD_DELETE)
   {

    Uri uri=ContentUris.withAppendedId(MyProvider.content_URI, people.id);
    getContentResolver().delete(uri, null, null);
   }
   else if (cmd==CMD_DELETE_ALL)
   {

    Uri uri=MyProvider.content_URI;
    getContentResolver().delete(uri, null, null);
   }
   cnt++;
  }
 }
 void printPeople(People p)
 {

 Log.i(tag, "id:"+p.id);
 Log.i(tag, "name:"+p.name);
 Log.i(tag,"phone:"+p.phone);
 Log.i(tag,"age:"+p.age);
 }
 DatabaseThread dataDealer=new DatabaseThread();
 void doAction() {

  mHandler.post(dataDealer);
 }
 public People get(Cursor c)
 {

  People people=new People();
  try{

   Log.i(tag,"count:"+c.getCount());
   if(c.getCount()>0)
   {

    c.moveToFirst();
    people=new People();
    people.id=c.getLong(0);
    people.name=c.getString(1);
    people.phone=c.getString(2);
    people.age=c.getInt(3);
   }
  }catch(SQLException e)
  {

   Log.i(tag,"",e);
  }
  finally
  {

   if(c!=null&&!c.isClosed())
   {

    c.close();
   }
  }
  return people;
 }
 public List<People> getAll(Cursor c)
 {

  ArrayList<People> ret=new ArrayList<People>();
  try
  {

   int count=c.getCount();
   c.moveToFirst();
   People people;
   for(int i=0;i<count;i++)
   {

    people=new People();
    people.id=c.getLong(0);
    people.name=c.getString(1);
    people.phone=c.getString(2);
    people.age=c.getInt(3);
    ret.add(people);
    c.moveToNext();
   }
   
  }catch(SQLException e)
  {

   Log.i(tag,"",e);
  }
  finally
  {

   if(c!=null&&!c.isClosed())
   {

    c.close();
   }
  }
  return ret;
 }
}
注意:Cursor c不用时要关掉。
文件AndroidManifest.xml
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android=""
      package="com.teleca.provider"
      android:versionCode="1"
      android:versionName="1.0">
    <application android:icon="@drawable/icon" android:label="@string/app_name">
        <activity android:name=".Hello"
                  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:syncable="true" android:name="MyProvider" android:authorities="com.teleca.PeopleProvider"></provider>
</application>
    <uses-sdk android:minSdkVersion="7" />
</manifest>

list_row.xml文件 
<?xml version="1.0" encoding="utf-8"?> 
<TextView xmlns:android="http://schemas.android.com/apk/res/android" android:layout_width="fill_parent" android:layout_height="wrap_content" android:text="@string/hello" android:id="@+id/list_row" />
main.xml文件
 <?

xml version="1.0" encoding="utf-8"?>

 <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" android:orientation="vertical" android:layout_width="fill_parent" android:layout_height="fill_parent" > 
<ListView android:id="@id/android:list" android:layout_width="match_parent" android:layout_height="match_parent" android:background="#00FF00" android:layout_weight="1" android:drawSelectorOnTop="false"/> 
<Button android:text="@+string/Add" android:id="@+id/Button01" android:layout_width="wrap_content" android:layout_height="wrap_content"></Button>
<Button android:text="@+string/DeleteAll" android:id="@+id/Button02" android:layout_width="wrap_content"></Button>
</LinearLayout>
须要的权限:
<uses-permission android:name="android.permission.READ_CONTACTS" />
 <uses-permission android:name="android.permission.WRITE_CONTACTS" />
<uses-permission android:name="android.permission.READ_CONTACTS"></uses-permission>
真的需要这些特权?为什么你需要它?也许我错了

转载地址:http://hhkbx.baihongyu.com/

你可能感兴趣的文章
Zend Studio去除编辑器的语法警告
查看>>
linux驱动current关键词
查看>>
让SQL再快一点儿
查看>>
而尔维尔
查看>>
ios获取手机状态 idfa idfv 网络类型 分辨率 获取运营商 ip
查看>>
微信小程序下nginx代理wss,实现兼容原本服务协议ws,Java版本
查看>>
Linux RPS RFS
查看>>
通过Secure CRT导出设备配置
查看>>
我的友情链接
查看>>
jmeter从上一个请求使用正则表达式抓取Set-Cookie值,在下一个请求中运用
查看>>
【Mybatis框架】输入映射-pojo包装类型
查看>>
js 动态添加input代码
查看>>
oldboy 27期学习计划
查看>>
我的友情链接
查看>>
Caused by: javax.el.ELException:
查看>>
我的友情链接
查看>>
【Nocti推荐】Sublime text!超赞代码编辑器
查看>>
《笨方法学Python》ex22(1)
查看>>
jquery 点击空白处将下拉的list收回
查看>>
8.3磁盘3
查看>>