【Android源码 栏目提醒】:网学会员鉴于大家对Android源码 十分关注,论文会员在此为大家搜集整理了“Android应用程序组件Content Provider应用实例 - 电子设计”一文,供大家参考学习
Android应用程序组件Content Provider应用实例 本文中的应用程序是按照上一篇文章
Android应用程序组件Content Provider简要介绍和学习计划中提到的一般应用程序架构方法来设计的。
本文包含两个应用程序其中第一个应用程序命名为ArticlesProvider它使用了SQLite数据库来维护一个文章信息列表同时它定义了访问这个文章信息列表的URI这样我们就可以通过一个Content Provider组件来向第三方应用程序提供访问这个文章信息列表的接口第二个应用程序命名为Article它提供了管理保存在ArticlesProvider应用程序中的文章信息的界面入口在这个应用程序中用户可以添加、删除和修改这些文章信息。
接下来我们就分别介绍这两个应用程序的实现。
1. ArticlesProvider应用程序的实现 首先是参照在Ubuntu上为
Android系统内置Java应用程序测试Application Frameworks层的硬件服务一文在packages/experimental目录下建立工程文件目录ArticlesProvider。
在继续介绍这个应用程序的实现之前我们先介绍一下这个应用程序用来保存文章信息的数据库的设计。
我们知道在
Android系统中内置了一款轻型的数据库SQLite。
SQLite是专门为嵌入式产品而设计的它具有占用资源低的特点而且是开源的非常适合在
Android平台中使用关于SQLite的更多信息可以访问官方网站http://www.sqlite.org。
ArticlesProvider应用程序就是使用SQLite来作为数据库保存文章信息的数据库文件命名为Articles.db它里面只有一张表ArticlesTable表的结构如下所示 ------------------------------------------------------------- -- _id -- -- _title -- -- _abstrat -- -- _url -- ------------------------------------------------------------- 它由四个字段表示第一个字段_id表示文章的ID类型为自动递增的integer它作为表的key值第二个字段_title表示文章的题目类型为text第三个字段_abstract表示文章的摘要类型为text第四个字段_url表示文章的URL类型为text。
注意当我们打算将数据库表的某一列的数据作为一个数据行的ID时就约定它的列名为_id。
这是因为我们经常需要从数据库中获取一批数据这些数据以Cursor的形式返回对这些返回来的数据我们一般用一个ListView来显示而这个ListView需要一个数据适配器Adapter来作为数据源这时候就我们就可以以这个Cursor来构造一个Adapter。
有些Adapter例如
android.widget.CursorAdapter它们在实现自己的getItemId成员函数来获取指定数据行的ID时就必须要从这个Cursor中相应的行里面取出列名为_id的字段的内容出来作为这个数据行的ID返回给调用者。
当然我们不在数据库表中定义这个_id列名也是可以的不过这样从数据库中查询数据后得到的Cursor适合性就变差了因此建议我们在设计数据库表时尽量设置其中一个列名字_id并且保证这一列的内容是在数据库表中是唯一的。
下面我们就开始介绍这个应用程序的实现了。
这个应用程序只有两个源文件分别是Articles.java和ArticlesProvider都是放在shy.luo.providers.articles这个package下面。
在Articles.java文件里面主要是定义了一些常量例如用来访问文章信息数据的URI、MIMEMultipurpose Internet Mail Extensions类型以及格式等这些常量是第三方应用程序访问这些文章信息数据时要使用到的因此我们把它定义在一个单独的文件中稍后我们会介绍如果把这个Articles.java文件打包成一个jar文件然后第三方应用程序就可以引用这个常量了这样也避免了直接把这个源代码文件暴露给第三方应用程序。
源文件Articles.java位于src/shy/luo/providers/articles目录下它的内容如下所示 java view plaincopy 1. package shy.luo.providers.articles 2. 3. import
android.net.Uri 4. 5. public class Articles 6. /Data Field/ 7. public static final String ID quot_idquot 8. public static final String TITLE quot_titlequot 9. public static final String ABSTRACT quot_abstractquot 10. public static final String URL quot_urlquot 11. 12. /Default sort order/ 13. public static final String DEFAULT_SORT_ORDER quot_id ascquot 14. 15. /Call Method/ 16. public static final String METHOD_GET_ITEM_COUNT quotMETHOD_GET_ITEM_COUNTquot 17. public static final String KEY_ITEM_COUNT quotKEY_ITEM_COUNTquot 18. 19. /Authority/ 20. public static final String AUTHORITY quotshy.luo.providers.articlesquot 21. 22. /Match Code/ 23. public static final int ITEM 1 24. public static final int ITEM_ID 2 25. public static final int ITEM_POS 3 26. 27. /MIME/ 28. public static final String CONTENT_TYPE quotvnd.
android.cursor.dir/vnd.shy.luo.articlequot 29. public static final String CONTENT_ITEM_TYPE quotvnd.
android.cursor.item/vnd.shy.luo.articlequot 30. 31. /Content URI/ 32. public static final Uri CONTENT_URI Uri.parsequotcontent://quot AUTHORITY quot/itemquot 33. public static final Uri CONTENT_POS_URI Uri.parsequotcontent://quot AUTHORITY quot/posquot 34. ID、TITLE、ABSTRACT和URL四个常量前面已经解释过了它是我们用来保存文章信息的数据表的四个列名DEFAULT_SORT_ORDER常量是调用ContentProvider接口的query函数来查询数据时用的它表示对查询结果按照_id列的值从小到大排列METHOD_GET_ITEM_COUNT和KEY_ITEM_COUNT两个常量是调用ContentProvider接口的一个未公开函数call来查询数据时用的它类似于微软COM中的IDispatch接口的Invoke函数使用这个call函数时传入参数METHOD_GET_ITEM_COUNT表示我们要调用我们自定义的ContentProvider子类中的getItemCount函数来获取数据库中的文章信息条目的数量结果放在一个Bundle中以KEY_ITEM_COUNT为关键字的域中。
剩下的常量都是跟数据URI相关的这个需要详细解释一下。
URI的全称是Universal Resource Identifier即通用资源标志符通过它用来唯一标志某个资源在网络中的位置它的结构和我们常见的HTTP形式URL是一样的其实我们可以把常见的HTTP形式的URL看成是URI结构的一个实例URI是在更高一个层次上的抽象。
在
Android系统中它也定义了自己的用来定痊某个特定的Content Provider的URI结构它通常由四个组件来组成如下所示 content://shy.luo.providers.articles/item/123 ------A-----------------------B----------------------C------D-- A组件称为Scheme它固定为content://表示它后面的路径所表示的资源是由Content Provider来提供的。
B组件称为Authority它唯一地标识了一个特定的Content Provider因此这部分内容一般使用Content Provider所在的package来命名使得它是唯一的。
C组件称为资源路径它表示所请求的资源的类型这部分内容是可选的。
如果我们自己所实现的Content Provider只提供一种类型的资源访问那么这部分内部就可以忽略如果我们自己实现的Content Provider同时提供了多种类型的资源访问那么这部分内容就不可以忽略了。
例如我们有两种电脑资源可以提供给用户访问一种是笔记本电脑一种是平板电脑我们就把分别它们定义为notebook和pad如果我们想进一步按照系统类型来进一步细分这两种电脑资源对笔记本电脑来说一种是安装了windows系统的一种是安装了linux系统的我们就分别把它们定义为notebook/windows和notebook/linux对平板电脑来说一种是安装了ios系统的一种是安装了
android系统的我们就分别把它们定义为pad/ios和pad/
android。
D组件称为资源ID它表示所请求的是一个特定的资源它通常是一个数字对应前面我们所介绍的数据库表中的_id字段的内容它唯一地标志了某一种资源下的一个特定的实例。
继续以前面的电脑资源为例如果我们请求的是编号为123的装了
android系统的平板电脑我们就把它定义为pad/
android/123。
当忽略这部分内容时它有可能是表示请求某一种资源下的所有实例取决于我们的URI匹配规则后面我们将会进一步解释如何设置URI匹配规则。
回到上面的Articles.java源文件中我们定义了两个URI分别用COTENT_URI和CONTENT_POS_URI两个常量来表示它们的Authority组件均指定为shy.luo.providers.articles。
其中COTENT_URI常量表示的URI表示是通过ID来访问文章信息的而CONTENT_POS_URI常量表示的URI表示是通过位置来访问文章信息的。
例如content://shy.luo.providers.articles/item表示访问所有的文章信息条目content://shy.luo.providers.articles/item/123表示只访问ID值为123的文章信息条目content://shy.luo.providers.articles/pos/1表示访问数据库表中的第1条文章信息条目这条文章信息条目的ID值不一定为1。
通过常量CONTENT_POS_URI来访问文章信息条目时必须要指定位置这也是我们设置的URI匹配规则来指定的后面我们将会看到。
此外我们还需要定义与URI对应的资源的MIME类型。
每个MIME类型由两部分组成前面是数据的大类别后面定义具体的种类。
在Content Provider中URI所对应的资源的MIME类型的大类别根据同时访问的资源的数量分为两种对于访问单个资源的URI它的大类别就为vnd.
android.cursor.item而对于同时访问多个资源的URI它的大类别就为vnd.
android.cursor.dir。
Content Provider的URI所对应的资源的MIME类型的具体类别就需要由Content Provider的提供者来设置了它的格式一般为vnd.company name.resource type的形式。
例如在我们的例子中CONTENT_TYPE和COTENT_ITEM_TYPE两个常量分别定义了两种MIME类型它们的大类别分别为vnd.
android.cursor.dir和vnd.
android.cursor.item而具体类别均为vdn.shy.luo.article其中shy.luo就是表示公司名了而article表示资源的类型为文章。
这两个MIME类型常量主要是在实现ContentProvider的getType函数时用到的后面我们将会看到。
最后ITEM、ITEM_ID和POS_ID三个常量分别定了三个URI匹配规则的匹配码。
如果URI的形式为content://shy.luo.providers.articles/item则匹配规则返回的匹配码为ITEM如果URI的形式为content://shy.luo.providers.articles/item/其中表示任意一个数字则匹配规则返回的匹配码为ITEM_ID如果URI的形式为也是表示任意一个数字则匹配规则返回的匹配码为ITEM_POS。
这三个常量的用法我们在后面也将会看到。
这样Articles.java文件的内容就介绍完了。
下面我们再接着介绍位于src/shy/luo/providers/articles目录下的ArticlesProvider.java文件它的内容如下所示 java view plaincopy 1. import java.util.HashMap 2. 3. import
android.content.ContentValues 4. import
android.content.Context 5. import
android.content.UriMatcher 6. import
android.content.ContentProvider 7. import
android.content.ContentUris 8. import
android.content.ContentResolver 9. import
android.database.Cursor 10. import
android.database.sqlite.SQLiteDatabase 11. import
android.database.sqlite.SQLiteDatabase.CursorFactory 12. import
android.database.sqlite.SQLiteException 13. import
android.database.sqlite.SQLiteOpenHelper 14. import
android.database.sqlite.SQLiteQueryBuilder 15. import
android.net.Uri 16. import
android.os.Bundle 17. import
android.text.TextUtils 18. import
android.util.Log 19. 20. public class ArticlesProvider extends ContentProvider 21. private static final String LOG_TAG quotshy.luo.providers.articles.ArticlesProviderquot 22. 23. private static final String DB_NAME quotArticles.dbquot 24. private static final String DB_TABLE quotArticlesTablequot 25. private static final int DB_VERSION 1 26. 27. private static final String DB_CREATE quotcreate table quot DB_TABLE 28. quot quot Articles.ID quot integer primary key autoincrement quot 29. Articles.TITLE quot text not null quot 30. Articles.ABSTRACT quot text not null quot 31. Articles.URL quot text not nullquot 32. 33. private static final UriMatcher uriMatcher 34. static 35. uriMatcher new UriMatcherUriMatcher.NO_MATCH 36. uriMatcher.addURIArticles.AUTHORITY quotitemquot Articles.ITEM 37. uriMatcher.addURIArticles.AUTHORITY quotitem/quot Articles.ITEM_ID 38. uriMatcher.addURIArticles.AUTHORITY quotpos/quot Articles.ITEM_POS 39. 40. 41. private static final HashMapltString Stringgt articleProjectionMap 42. static 43. articleProjectionMap new HashMapltString Stringgt 44. articleProjectionMap.putArticles.ID Articles.ID 45. articleProjectionMap.putArticles.TITLE Articles.TITLE 46. articleProjectionMap.putArticles.ABSTRACT Articles.ABSTRACT 47. articleProjectionMap.putArticles.URL Articles.URL 48. 49. 50. private DBHelper dbHelper null 51. private ContentResolver resolver null 52. 53. Override 54. public boolean onCreate 55. Context context getContext 56. resolver context.getContentResolver 57. dbHelper new DBHelpercontext DB_NAME null DB_VERSION 58. 59. Log.iLOG_TAG quotArticles Provider Createquot 60. 61. return true 62. 63. 64. Override 65. public String getTypeUri uri 66. switch uriMatcher.matchuri 67. case Articles.ITEM: 68. return Articles.CONTENT_TYPE 69. case Articles.ITEM_ID: 70. case Articles.ITEM_POS: 71. return Articles.CONTENT_ITEM_TYPE 72. default: 73. throw new IllegalArgumentExceptionquotError Uri: quot uri 74. 75. 76. 77. Override 78. public Uri insertUri uri ContentValues values 79. ifuriMatcher.matchuri Articles.ITEM 80. throw new IllegalArgumentExceptionquotError Uri: quot uri 81. 82. 83. SQLiteDatabase db dbHelper.getWritableDatabase 84. 85. long id db.insertDB_TABLE Articles.ID values 86. ifid lt 0 87. throw new SQLiteExceptionquotUnable to insert quot values quot for quot uri 88. 89. 90. Uri newUri ContentUris.withAppendedIduri id 91. resolver.notifyChangenewUri null 92. 93. return newUri 94. 95. 96. Override 97. public int updateUri uri ContentValues values String selection String selectionArgs 98. SQLiteDatabase db dbHelper.getWritableDatabase 99. int count 0 100. 101. switchuriMatcher.matchuri 102. case Articles.ITEM: 103. count db.updateDB_TABLE values selection selectionArgs 104. break 105. 106. case Articles.ITEM_ID: 107. String id uri.getPathSegments.get1 108. count db.updateDB_TABLE values Articles.ID quotquot id 109. TextUtils.isEmptyselection quot and quot selection : quotquot selectionArgs 110. break 111. 112. default: 113. throw new IllegalArgumentExceptionquotError Uri: quot uri 114. 115. 116. resolver.notifyChangeuri null 117. 118. return count 119. 120. 121. Override 122. public int deleteUri uri String selection String selectionArgs 123. SQLiteDatabase db dbHelper.getWritableDatabase 124. int count 0 125. 126. switchuriMatcher.matchuri 127. case Articles.ITEM: 128. count db.deleteDB_TABLE selection selectionArgs 129. break 130. 131. case Articles.ITEM_ID: 132. String id uri.getPathSegments.get1 133. count db.deleteDB_TABLE Articles.ID quotquot id 134. TextUtils.isEmptyselection quot and quot selection : quotquot selectionArgs 135. break 136. 137. default: 138. throw new IllegalArgumentExceptionquotError Uri: quot uri 139. 140. 141. resolver.notifyChangeuri null 142. 143. return count 144. 145. 146. Override 147. public Cursor queryUri uri String projection String selection String selectionArgs String sortOrder 148. Log.iLOG_TAG quotArticlesProvider.query: quot uri 149. 150. SQLiteDatabase db dbHelper.getReadableDatabase 151. 152. SQLiteQueryBuilder sqlBuilder new SQLiteQueryBuilder 153. String limit null 154. 155. switch uriMatcher.matchu.