登录 立即注册
安币:

安卓巴士 - 安卓开发 - Android开发 - 安卓 - 移动互联网门户

查看: 796621|回复: 47

编写最简单的Content Provider

  [复制链接]

206

主题

1622

帖子

2720

安币

Android大神

Rank: 6Rank: 6

发表于 2011-11-10 10:35:47 | 显示全部楼层 |阅读模式

在自己的android应用中存储数据,可以用SQLite数据库。不过,如果需要在多个应用中共享数据,在Android中,只有通过Content provider机制。

下面用一个最简单(不完整)的示例来说明Content Provider的创建。在界面中使用这个示例显示的效果:

显示帝王姓名、登基年份和朝代。

在这个简单示例中,包括两部分:

  • 创建一个Content Provider;
  • 使用这个Content Provider(目前是在同一个应用中,可以在其他应用中以相同方式调用)。
创建一个简陋的Content Provider

content provider通过抽象一致的接口,供其他开发者使用Content provider,而实现Content provider,既可以用sqlite3这样的android内置数据库,也可以使用文件系统,甚至可以自己写其他的实现,只要实现规定的接口即可。

实现一个Content provider,需要做:

  • 继承ContentProvider,实现该类的几个抽象方法;
  • 在manifest文件中声明这个Content provider。

实现的Content provider代码:

  1. package com.easymorse.cp;

  2. import android.content.ContentProvider;
  3. import android.content.ContentValues;
  4. import android.content.Context;
  5. import android.database.Cursor;
  6. import android.database.sqlite.SQLiteDatabase;
  7. import android.database.sqlite.SQLiteStatement;
  8. import android.net.Uri;

  9. public class MyContentProvider extends ContentProvider {

  10.     public static final Uri CONTENT_URI = Uri.parse("content://com.easymorse.cp.mycp");

  11.     public static final String _ID = "id";

  12.     public static final String NAME = "name";

  13.     public static final String DYNASTY = "dynasty";

  14.     public static final String START_YEAR = "start_year";

  15.     private static SQLiteDatabase database;

  16.     private static void createTablesIfNotExists() {
  17.         database.execSQL("create table if not exists emperors("
  18.                 + " id integer primary key autoincrement," + " name text,"
  19.                 + "dynasty text," + "start_year text" + ");");

  20.         SQLiteStatement statement = database
  21.                 .compileStatement("insert into emperors(name,dynasty,start_year) values(?,?,?)");
  22.         int index = 1;
  23.         statement.bindString(index++, "朱元璋");
  24.         statement.bindString(index++, "明");
  25.         statement.bindString(index++, "1398");
  26.         statement.execute();

  27.         index = 1;
  28.         statement.bindString(index++, "玄烨");
  29.         statement.bindString(index++, "清");
  30.         statement.bindString(index++, "1722");
  31.         statement.execute();

  32.         statement.close();
  33.     }

  34.     @Override
  35.     public int delete(Uri uri, String selection, String[] selectionArgs) {
  36.         return 0;
  37.     }

  38.     @Override
  39.     public String getType(Uri uri) {
  40.         return null;
  41.     }

  42.     @Override
  43.     public Uri insert(Uri uri, ContentValues contentValues) {
  44.         // TODO Auto-generated method stub
  45.         return null;
  46.     }

  47.     @Override
  48.     public boolean onCreate() {
  49.         if (database == null) {
  50.             database = this.getContext().openOrCreateDatabase("emperors",
  51.                     Context.MODE_PRIVATE, null);
  52.             createTablesIfNotExists();
  53.         }
  54.         return database != null;
  55.     }

  56.     @Override
  57.     public Cursor query(Uri uri, String[] projection, String selection,
  58.             String[] selectionArgs, String sortOrder) {
  59.         Cursor cursor = database.rawQuery("select * from emperors", null);
  60.         return cursor;
  61.     }

  62.     @Override
  63.     public int update(Uri uri, ContentValues contentValues, String selection,
  64.             String[] selectionArgs) {
  65.         // TODO Auto-generated method stub
  66.         return 0;
  67.     }

  68. }
复制代码
需要实现的方法是:

  1. query() <<
  2. insert()
  3. update()
  4. delete()
  5. getType()
  6. onCreate()<<
复制代码
在本例中值实现了标注<<的方法。onCreate方法是创建Content provider时,android调用的。创建Content provider时,本例检查是否创建emperors表,没有就创建一个,并且插入了2条记录。query方法实现的很简单,只是返回表的所有结果集。做完这些还不够,还需要声明一些常量:
  1. public static final Uri CONTENT_URI = Uri.parse("content://com.easymorse.cp.mycp");

  2. public static final String _ID = "id";

  3. public static final String NAME = "name";

  4. public static final String DYNASTY = "dynasty";

  5. public static final String START_YEAR = "start_year";
复制代码
CONTENT_URI 是便于Content provider使用者引用的,下面使用Content provider的时候能看到。另外,要有一个_ID常量,值是具体表的id列名称。其他几个常量是表中列的对应名称常量。目前没有真的使用。在manifest文件中的声明:
  1. <application android:icon="@drawable/icon" android:label="@string/app_name">
  2.     <activity android:name=".UseContactActivity" android:label="@string/app_name">
  3.         <intent-filter>
  4.             <action android:name="android.intent.action.MAIN" />
  5.             <category android:name="android.intent.category.LAUNCHER" />
  6.         </intent-filter>
  7.     </activity>
  8.    <provider android:name="com.easymorse.cp.MyContentProvider"
  9.         android:authorities="com.easymorse.cp.mycp"></provider>
  10. </application>
复制代码
这里的android:name是ContentProvider实现类的类名,android:authorities是CONTENT_URI的值。使用创建的Content Provider代码在一个Activity中,通过TextView显示出emperors表中的数据:
  1. package com.easymorse.cp;

  2. import android.app.Activity;
  3. import android.database.Cursor;
  4. import android.os.Bundle;
  5. import android.widget.TextView;

  6. public class UseContactActivity extends Activity {
  7.     /** Called when the activity is first created. */
  8.     @Override
  9.     public void onCreate(Bundle savedInstanceState) {
  10.         super.onCreate(savedInstanceState);

  11.         TextView textView = new TextView(this);
  12.         textView.setText(getContentProviderValues());
  13.         this.setContentView(textView);
  14.     }

  15.     private String getContentProviderValues() {
  16.         StringBuilder builder = new StringBuilder();

  17.         Cursor cursor = managedQuery(MyContentProvider.CONTENT_URI, null, null,
  18.                 null, null);
  19.         while (cursor.moveToNext()) {
  20.             builder
  21.                     .append(
  22.                             cursor.getString(cursor
  23.                                     .getColumnIndex(MyContentProvider.NAME)))
  24.                     .append(" | ")
  25.                     .append(
  26.                             cursor
  27.                                     .getString(cursor
  28.                                             .getColumnIndex(MyContentProvider.START_YEAR)))
  29.                     .append(" | ")
  30.                     .append(
  31.                             cursor.getString(cursor
  32.                                     .getColumnIndex(MyContentProvider.DYNASTY)))
  33.                     .append("\n");
  34.         }

  35.         return builder.toString();
  36.     }
  37. }
复制代码
主要方法是getContentProviderValues()。通过managedQuery()方法获取到Cursor对象。在方法调用的参数,只用到了MyContentProvider.CONTENT_URI,通过这个参数,android可定位到具体的ContentProvider并启动它(如果没有启动的话)。后面几个参数类似SQL的SELECT子句、WHERE子句和ORDER BY子句。都不写,将返回全部的结果(其实我这个例子中的Content provider也只实现了返回全部结果的逻辑)。源代码见:


本帖子中包含更多资源

您需要 登录 才可以下载或查看,没有帐号?立即注册

x

0

主题

24

帖子

52

安币

初级码农

Rank: 1

发表于 2011-11-13 23:11:30 | 显示全部楼层
很好,值得收藏的好东西

1

主题

75

帖子

98

安币

程序猿

Rank: 2

发表于 2012-4-22 23:32:42 | 显示全部楼层
{:Surprised:}{:Surprised:}{:Surprised:}

0

主题

35

帖子

108

安币

程序猿

Rank: 2

发表于 2012-4-23 09:57:21 | 显示全部楼层
{:Skateboard:}

4

主题

100

帖子

194

安币

程序猿

Rank: 2

发表于 2012-6-14 20:03:17 | 显示全部楼层
带走{:Big Chin 2:}{:Big Chin 2:}

9

主题

47

帖子

77

安币

程序猿

Rank: 2

QQ达人

发表于 2012-6-24 09:07:11 | 显示全部楼层
暴漏contentproider的属性来访问数据

9

主题

47

帖子

77

安币

程序猿

Rank: 2

QQ达人

发表于 2012-6-24 09:07:28 | 显示全部楼层
是这意思么

9

主题

72

帖子

109

安币

程序猿

Rank: 2

发表于 2012-7-5 14:23:30 | 显示全部楼层
实用啊!!好料
您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

站长推荐

通过邮件订阅最新安卓weekly信息
上一条 /4 下一条

下载安卓巴士客户端

全国最大的安卓开发者社区
联系我们
关闭
合作电话:
15618560077
Email:
805941275@qq.com
商务市场合作/投稿
问题反馈及帮助
联系我们

广告投放| 广东互联网违法和不良信息举报中心|中国互联网举报中心|下载客户端|申请友链|手机版|站点统计|安卓巴士 ( 粤ICP备15117877号 )

快速回复 返回顶部 返回列表