`

android开发之contentprovider(转)

 
阅读更多

ContentProvider的作用:

1、为存储和获取数据提供了一个统一的接口;

2、使用ContentProvider可以在不同的应用程序之间共享数据;

3、Android为常见的一些数据提供了ContentProvider(包括音频、视频、图片和通讯录等等);

ContentProvider使用表的结构来存储数据;每个ContentProvider都提供了一个公共的URI,这个URL用于表示这个ContentProvider所提供的数据;

下面列举一些常用的接口:

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

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

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

4、deleteUri uri,String where,String[] selectionArgs:删除指定Uri并且符合一定条件的数据。

5、getType():得到数据类型;

 

6、OnCreate():创建时的回调函数

实现一个ContentProvider的过程:

1 定义个CONTENT_URI常量;

2 定义一个类,继承ContentProvider;

3 实现一些方法;

4 在AndroidMainfest.xml中进行声明;

 

 

外界程序通过ContentResolver接口可以访问ContentProvider提供的数据,在Activity当中通过getContentResolver()可以得到当前应用ContentResolver实例。其提供的接口与ContentProvider提供的接口对应:

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

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

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

4deleteUri uri,String where,String[] selectionArgs:删除指定Uri并且符合一定条件的数据。


以下代码来自:http://blog.csdn.net/linshutao/article/details/5779558


1】要为当前应用程序的私有数据定义URI,就需要专门定义个继承自ContentProvider的类,然后实现各个不同的操作所调用的方法。

首先在该应用程序的某个类中定义所有与数据库操作有关的静态字段,以便打包成jar文件供其他应用程序调用

此例子没有新定义一个专门的类来存放这些字段,而是在继承了SQLiteOpenHelper的类StudentData中定义:

  1. package com.shutao.testsqlite2;  
  2.   
  3. public class StudentData extends SQLiteOpenHelper {  
  4.     /* 
  5.      * 分别定义了数据库和表的名称、表中各个字段的名称、数据库的版本号 
  6.      */  
  7.     public final static String DB_NAME = "student";  
  8.     public final static String TABLE_NAME = "hero";  
  9.     public final static String SNAME = "name";  
  10.     //Be sure to include an integer column named "_id" (with the constant _ID) for the IDs of the records   
  11.     public final static String SID = "_id";  
  12.     public final static int DB_VERSION = 1;  
  13.     /* 
  14.      * AUTHORITY:定义了标识ContentProvider的字符串 ; 
  15.      * ITEM和ITEM_ID分别用于UriMatcher(资源标识符匹配器)中对路径item和item/id的匹配号码 
  16.      * CONTENT_TYPE和CONTENT_ITEM_TYPE定义了数据的MIME类型。需要注意的是: 单一数据的MIME 类型字符串应该以 
  17.      * vnd.android.cursor.item/开头,数据集的MIME类型字符串应该以vnd.android.cursor.dir开头 
  18.      * CONTENT_URI定义的是查询当前表数据的content://样式URI 
  19.      */  
  20.     //类名的路径名   
  21.     public static final String AUTHORITY = "com.shutao.testsqlite2.provider.studentdata";  
  22.     public static final int ITEM = 1;  
  23.     public static final int ITEM_ID = 2;  
  24.     public static final String CONTENT_TYPE = "vnd.android.cursor.dir/vnd.shutao.testsqlite2.studentdata";  
  25.     public static final String CONTENT_ITEM_TYPE = "vnd.android.cursor.item/vnd.shutao.testsqlite2.studentdata";  
  26.     public static final Uri CONTENT_URI = Uri.parse("content://" + AUTHORITY  
  27.             + "/item");  
  28.   
  29.     public StudentData(Context context) {  
  30.         super(context, DB_NAME, null, DB_VERSION);  
  31.     }  
  32.   
  33.     @Override  
  34.     public void onCreate(SQLiteDatabase db) {  
  35.         db.execSQL("CREATE TABLE " + TABLE_NAME + "(" + SID  
  36.                 + " VARCHAR PRIMARY KEY," + SNAME + " VARCHAR NOT NULL);");  
  37.     }  
  38.   
  39.     @Override  
  40.     public void onUpgrade(SQLiteDatabase db, int arg1, int arg2) {  
  41.         db.execSQL("DROP TABLE IF EXISTS " + TABLE_NAME);  
  42.     }  
  43. }  

2】接下来定义一个继承自ContentProvider的类:MyProvider.java,来实现对数据进行操作的各个方法。这里将用到StudentData来辅助得到SQLiteDatabase对象:

 

 

 

  1. package com.shutao.testsqlite2;  
  2.   
  3. public class MyProvider extends ContentProvider {  
  4.     StudentData sd;  
  5.     private static final UriMatcher sMatcher;  
  6.     static {  
  7.         // 传入匹配码如果大于0表示匹配根路径或传入-1,即常量UriMatcher.NO_MATCH表示不匹配根路径   
  8.         // addURI()方法是用来增加其他URI匹配路径的:   
  9.         // 第一个参数代表传入标识ContentProvider的AUTHORITY字符串   
  10.         // 第二个参数是要匹配的路径,#代表任意数字,另外还可以用*来匹配任意文本   
  11.         // 第三个参数必须传入一个大于零的匹配码,用于match()方法对相匹配的URI返回相对应的匹配码   
  12.         sMatcher = new UriMatcher(UriMatcher.NO_MATCH);  
  13.         sMatcher.addURI(StudentData.AUTHORITY, "item", StudentData.ITEM);  
  14.         sMatcher.addURI(StudentData.AUTHORITY, "item/#", StudentData.ITEM_ID);  
  15.     }  
  16.   
  17.     /* 
  18.      * 每当ContentProvider启动时都会回调onCreate()方法。此方法主要执行一些ContentProvider初始化 
  19.      * 的工作,返回true表示初始化成功,返回false则初始化失败。 
  20.      */  
  21.     @Override  
  22.     public boolean onCreate() {  
  23.         sd = new StudentData(this.getContext());  
  24.         return true;  
  25.     }  
  26.   
  27.     // getType()是用来返回数据的MIME类型的方法。使用sMatcher对URI进行匹配,并返回相应的MIME类型字符串   
  28.     @Override  
  29.     public String getType(Uri uri) {  
  30.         switch (sMatcher.match(uri)) {  
  31.         case StudentData.ITEM:  
  32.             return StudentData.CONTENT_TYPE;  
  33.         case StudentData.ITEM_ID:  
  34.             return StudentData.CONTENT_ITEM_TYPE;  
  35.         default:  
  36.             throw new IllegalArgumentException("Unknown URI " + uri);  
  37.         }  
  38.     }  
  39.   
  40.     /* 
  41.      * 插入数据,返回新插入数据的URI,只接受数据集的URI,即指向表的URI 
  42.      */  
  43.     @Override  
  44.     public Uri insert(Uri uri, ContentValues values) {  
  45.         SQLiteDatabase sdb = sd.getWritableDatabase();  
  46.         long rowId;  
  47.         if (sMatcher.match(uri) != StudentData.ITEM) {  
  48.             throw new IllegalArgumentException("Unknow URI " + uri);  
  49.         }  
  50.         rowId = sdb.insert(StudentData.TABLE_NAME, StudentData.SID, values);  
  51.         if (rowId > 0) {  
  52.             Uri noteUri = ContentUris.withAppendedId(StudentData.CONTENT_URI,  
  53.                     rowId);  
  54.             //通知监听器,数据已经改变   
  55.             this.getContext().getContentResolver().notifyChange(noteUri, null);  
  56.             return noteUri;  
  57.         }  
  58.         throw new SQLException("Failed to insert row into " + uri);  
  59.     }  
  60.   
  61.     /* 
  62.      * 用于数据的删除,返回的是所影响数据的数目,首先利用数据库辅助对象获取一个SQLiteDatabase对象 
  63.      * 然后根据传入Uri用sMatcher进行匹配,对单个数据或数据集进行删除或修改。notifyChange()方法 
  64.      * 用来通知注册在次URI上的观察者(observer)数据发生了改变。 
  65.      */  
  66.     @Override  
  67.     public int delete(Uri uri, String selection, String[] selectionArgs) {  
  68.         SQLiteDatabase sdb = sd.getWritableDatabase();  
  69.         int count;  
  70.         switch (sMatcher.match(uri)) {  
  71.         case StudentData.ITEM:  
  72.             count = sdb.delete(StudentData.DB_NAME, selection, selectionArgs);  
  73.             break;  
  74.         case StudentData.ITEM_ID:  
  75.             String id = uri.getPathSegments().get(1);  
  76.             count = sdb.delete(StudentData.DB_NAME, StudentData.SID  
  77.                     + "="  
  78.                     + id  
  79.                     + (!TextUtils.isEmpty(selection) ? " AND (" + selection  
  80.                             + ")" : ""), selectionArgs);  
  81.             break;  
  82.         default:  
  83.             throw new IllegalArgumentException("Unknown URI " + uri);  
  84.         }  
  85.         this.getContext().getContentResolver().notifyChange(uri, null);  
  86.         return count;  
  87.     }  
  88.   
  89.     /* 
  90.      * 查询数据,将数据装入一个Cursor对象并返回 
  91.      */  
  92.     @Override  
  93.     public Cursor query(Uri uri, String[] projection, String selection,  
  94.             String[] selectionArgs, String sortOrder) {  
  95.         SQLiteDatabase sdb = sd.getReadableDatabase();  
  96.         Cursor c;  
  97.         switch (sMatcher.match(uri)) {  
  98.         case StudentData.ITEM:  
  99.             c = sdb.query(StudentData.TABLE_NAME, projection, selection,  
  100.                     selectionArgs, nullnull, sortOrder);  
  101.             break;  
  102.         case StudentData.ITEM_ID:  
  103.             String id = uri.getPathSegments().get(1);  
  104.             c = sdb.query(StudentData.TABLE_NAME, projection, StudentData.SID  
  105.                     + "="  
  106.                     + id  
  107.                     + (!TextUtils.isEmpty(selection) ? " AND (" + selection  
  108.                             + ")" : ""), selectionArgs, nullnull, sortOrder);  
  109.             break;  
  110.         default:  
  111.             Log.i("sMatcher.match(uri)", String.valueOf(sMatcher.match(uri)));  
  112.             throw new IllegalArgumentException("Query with unknown URI: " + uri);  
  113.         }  
  114.         c.setNotificationUri(getContext().getContentResolver(), uri);  
  115.         return c;  
  116.     }  
  117.   
  118.     // 更新,与删除类方法类似   
  119.     @Override  
  120.     public int update(Uri uri, ContentValues values, String selection,  
  121.             String[] selectionArgs) {  
  122.         SQLiteDatabase sdb = sd.getWritableDatabase();  
  123.         int count;  
  124.         switch (sMatcher.match(uri)) {  
  125.         case StudentData.ITEM:  
  126.             count = sdb.update(StudentData.TABLE_NAME, values, selection,  
  127.                     selectionArgs);  
  128.             break;  
  129.         case StudentData.ITEM_ID:  
  130.             String id = uri.getPathSegments().get(1);  
  131.             count = sdb.update(StudentData.DB_NAME, values, StudentData.SID  
  132.                     + "="  
  133.                     + id  
  134.                     + (!TextUtils.isEmpty(selection) ? " AND (" + selection  
  135.                             + ")" : ""), selectionArgs);  
  136.             break;  
  137.         default:  
  138.             throw new IllegalArgumentException("Unknown URI " + uri);  
  139.         }  
  140.         this.getContext().getContentResolver().notifyChange(uri, null);  
  141.         return count;  
  142.     }  
  143. }  


3】完成以上方法以后,还要AndroidManifest.xml中对这个ContentProvider声明:

 

  1. <provider  
  2. android:name="MyProvider"  
  3. android:authorities="com.shutao.testsqlite2.provider.studentdata"/>  
  4.  <!-- 其中 android:name必须跟定义的ContentProvider的类名一样  
  5.  android:authorities则指定了content://样式的URI中标识这个ContentProvider的字符串-->  


【4】接下来在另一个程序中使用ContentResolver来操作数据:

 

  1. package com.shutao.contentprovider;  
  2.   
  3. public class TestContentProvider extends Activity {  
  4.     private EditText stu_name;  
  5.     private EditText stu_sid;  
  6.     Button commit;  
  7.     ListView studList;  
  8.     ContentResolver resolver;  
  9.     // 由于在AlertDialog中用到,所以定义为全局变量。   
  10.     String sid = "";  
  11.     private final int DIALOG_IN_USED = 1;  
  12.   
  13.     /** Called when the activity is first created. */  
  14.     @Override  
  15.     public void onCreate(Bundle savedInstanceState) {  
  16.         super.onCreate(savedInstanceState);  
  17.         setContentView(R.layout.main);  
  18.         stu_name = (EditText) this.findViewById(R.id.edit_name);  
  19.         stu_sid = (EditText) this.findViewById(R.id.edit_sid);  
  20.         commit = (Button) this.findViewById(R.id.butt_add);  
  21.         studList = (ListView) this.findViewById(R.id.show_stud);  
  22.         // 【重要】得到ContentResolver()   
  23.         resolver = this.getContentResolver();  
  24.         String[] projection = { StudentData.SNAME, StudentData.SID };  
  25.         Cursor c = resolver.query(StudentData.CONTENT_URI, nullnullnull,  
  26.                 StudentData.SID);  
  27.         CursorAdapter adapter = new SimpleCursorAdapter(this,  
  28.                 android.R.layout.simple_list_item_2, c, projection, new int[] {  
  29.                         android.R.id.text1, android.R.id.text2 });  
  30.         studList.setAdapter(adapter);  
  31.         commit.setOnClickListener(new OnClickListener() {  
  32.             @Override  
  33.             public void onClick(View v) {  
  34.                 if (!(stu_name.getText().length() > 0)) {  
  35.                     Toast.makeText(TestContentProvider.this,  
  36.                             "Please input the student's name!",  
  37.                             Toast.LENGTH_LONG).show();  
  38.                 } else if (!(stu_sid.getText().length() > 0)) {  
  39.                     Toast  
  40.                             .makeText(TestContentProvider.this,  
  41.                                     "Please input the student's ID!",  
  42.                                     Toast.LENGTH_LONG).show();  
  43.                 } else {  
  44.                     String name = stu_name.getText().toString();  
  45.                     sid = stu_sid.getText().toString();  
  46.                     Uri quri = Uri.parse(StudentData.CONTENT_URI + "/" + sid);  
  47.                     Cursor c = resolver.query(quri, nullnullnullnull);  
  48.                     if (c.moveToFirst()) {  
  49.                         // 采用Toast方式提醒   
  50.                         /* 
  51.                          * Toast.makeText(TestContentProvider.this, 
  52.                          * "Fail to add!This ID is already in used!", 
  53.                          * Toast.LENGTH_LONG).show(); 
  54.                          */  
  55.                         // 采用AlertDialog方式提醒   
  56.                         TestContentProvider.this.showDialog(DIALOG_IN_USED);  
  57.                     } else {  
  58.                         ContentValues values = new ContentValues();  
  59.                         values.put(StudentData.SNAME, name);  
  60.                         values.put(StudentData.SID, sid);  
  61.                         resolver.insert(StudentData.CONTENT_URI, values);  
  62.                     }  
  63.                 }  
  64.             }  
  65.         });  
  66.     }  
  67.   
  68.     // 如果插入的Id已经存在则用提示框进行提示   
  69.     @Override  
  70.     protected Dialog onCreateDialog(int id, Bundle args) {  
  71.         // // TODO Auto-generated method stub   
  72.         // return super.onCreateDialog(id, args);   
  73.         switch (id) {  
  74.         case DIALOG_IN_USED:  
  75.             return new AlertDialog.Builder(this).setTitle("Fail to add!")  
  76.                     .setIcon(R.drawable.fail).setMessage(  
  77.                             "This ID:" + sid + " is already in used!")  
  78.                     .setPositiveButton("确定",  
  79.                     // 特别注意:必须为:new DialogInterface.OnClickListener()   
  80.                             // 不能为new   
  81.                             // OnClickListener(),否则会跟View.OnClickListener冲突。   
  82.                             new DialogInterface.OnClickListener() {  
  83.                                 @Override  
  84.                                 public void onClick(DialogInterface dialog,  
  85.                                         int which) {  
  86.                                     // TODO Auto-generated method stub   
  87.                                 }  
  88.                             }).create();  
  89.         default:  
  90.             return super.onCreateDialog(id, args);  
  91.         }  
  92.     }  
  93. }  

【注】:ContentProviderContentResolver当中用到了Uri的形式通常有两种,一种是指定全部数据,另一种是指定某个ID的数据,如:

1、content://contacts/people/:这个Uri指定的就是全部联系人的数据。

2、content://contacts/people/1:这个Uri指定的就是ID1的联系人的数据。

Uri一般由3部分组成:

1、"content://"

2、要获得数据的一个字符串片段

3、最后就是ID,如果没有ID则返回全部数据。

但因为URI通常比较长,容易出错,所以在Android当中定义了一些辅助类,并定义了一些常量来代替这些这些字符串的使用,如:

Contacts.People.CONTENT_URI:联系人的URI.

分享到:
评论

相关推荐

    Android+Room+ContentProvider

    在Android应用开发中,数据持久化是一个至关重要的环节,而Android Room和ContentProvider是其中的两个关键组件。本文将深入探讨这两个技术,并结合实际案例,解释如何在Android应用中使用它们来管理和共享SQLite...

    Android应用开发使用ContentProvider以及SQLite实现对数据库的相关操作

    接下来,ContentProvider是Android四大组件之一,它提供了一种标准接口,使得其他应用程序可以访问和修改由ContentProvider管理的数据,无论这些数据是存储在SQLite数据库、文件系统还是网络中。要创建一个...

    从头学Android之ContentProvider示例源代码

    在Android开发中,ContentProvider是四大组件之一,它充当了数据共享和访问的桥梁,使得不同应用程序之间可以安全地共享数据。本示例源代码旨在帮助初学者理解ContentProvider的工作原理及其使用方法。通过分析和...

    android开发contentprovider教学ppt(内部资料).pptx

    在Android开发中,ContentProvider是四大核心组件之一,它扮演着跨应用数据共享的角色。通过ContentProvider,一个应用可以将自己的数据暴露给其他应用,实现数据的透明访问。本篇内容将深入讲解ContentProvider的...

    android-关于ContentProvider的使用例子

    在Android开发中,ContentProvider是四大组件之一,它扮演着数据共享的重要角色。ContentProvider使得应用程序之间能够安全、有序地访问彼此的数据,无论是系统内置的数据(如联系人、日历等)还是自定义的数据存储...

    Android之ContentProvider事例

    在Android开发中,ContentProvider是四大组件之一,它扮演着数据共享和访问的重要角色。ContentProvider使得应用程序可以安全地分享内部数据,同时也为其他应用程序提供了一种标准接口来访问这些数据,无论是SQLite...

    Android联系人ContentProvider

    在Android系统中,ContentProvider是四大组件之一,它充当了数据共享和访问的桥梁,使得应用程序之间能够安全地共享数据。本主题将深入探讨如何...理解和熟练运用ContentProvider,是提升Android开发能力的重要一步。

    Android四大组件ContentProvider

    学习和理解ContentProvider及ContentResolver的使用,对于开发Android应用尤其是涉及到数据共享和跨应用交互的场景至关重要。通过实践这些示例代码,开发者可以更好地掌握这两者的工作原理,并能灵活地应用于实际...

    Android ContentProvider简单实现

    在Android开发中,ContentProvider是四大组件之一,它充当了数据共享的桥梁,使得不同的应用程序之间可以安全地访问和共享数据。本篇文章将详细介绍如何在Android中实现一个简单的ContentProvider。 首先,理解...

    Android ContentProvider全面解析

    在Android系统中,ContentProvider是四大组件之一,它扮演着数据共享和访问的重要角色。ContentProvider使得应用程序可以将自己的数据结构暴露给其他应用,同时也能够访问其他应用公开的数据。本篇文章将全面解析...

    Android开发ContentResolver与ContentProvider的使用

    在Android应用开发中,ContentResolver和ContentProvider是两个至关重要的组件,它们负责应用程序间的数据共享和访问。ContentResolver充当客户端,而ContentProvider作为服务端,实现了Android系统中不同应用程序...

    android ContentProvider Demo

    在Android开发中,ContentProvider是一种重要的组件,它允许应用程序之间共享数据。本示例"android ContentProvider Demo"将深入探讨如何创建和使用ContentProvider来实现跨应用的数据交换。ContentProvider作为...

    android开发ContentProvider(增删改查)实例

    同我前面的资源一样,我的每个功能的实例都是力图实现最简短话...这个实例不讲求大而全的实现ContentProvider的所有功能,而只是为了便于理解而实现。对应于我的博客“How:ContentProvider基本功能核心框架(增删改查)”

    Android 之 ContentProvider手机簿使用

    在Android系统中,ContentProvider是四大组件之一,它充当了数据共享的桥梁,使得不同的应用程序之间可以安全地访问和操作彼此的数据。这篇博客"Android之ContentProvider手机簿使用"主要探讨了如何通过...

    Android学习 ContentProvider数据更新与Observer模式.doc

    在Android开发中,ContentProvider和Observer模式是两个关键的概念,它们在数据管理和更新中起着重要作用。ContentProvider作为Android系统中数据共享的桥梁,允许不同的应用程序之间交换数据,而Observer模式则是一...

    android 自定义 ContentProvider 以及 ContentResolver

    在Android开发中,ContentProvider和ContentResolver是两个关键组件,它们构成了Android系统中不同应用程序间数据共享的基础。本文将深入探讨如何自定义ContentProvider和如何有效地使用ContentResolver进行数据操作...

    android contentprovider使用示例

    在Android开发中,ContentProvider是四大组件之一,它充当了数据共享的桥梁,使得不同的应用程序之间可以安全地访问和操作数据。本示例将详细解释如何在Android中使用ContentProvider。 1. **ContentProvider基本...

    android 数据共享(ContentProvider)

    在实际开发中,ContentProvider不仅可以用于应用间的数据共享,还常用于备份和恢复数据,或者与其他系统服务(如ShareActionProvider、Intent等)进行数据交互。它为数据交换提供了一套标准的接口,使得数据操作更加...

Global site tag (gtag.js) - Google Analytics