什么是ContentProvider:
ContentProvider用来管理数据的访问规则。它允许你的应用程序向外界暴露需要被访问的数据。
是Android的四大组件之一。
ContentProviders支持四种基本的操作,即我们平时所见到的CRUD操作(增删改查)。Android系统
本身已经提供了一些内容提供者,它们允许我们查询联系人,媒体库,和短息消息等。
基于Content Uri的查询:
没有Uri,ContentProvider 类基本无法工作,就像我们上网没有网址。当我们要上网,就要在地址栏输入网址。
因此,要了解ContentProvider,我们必须先了解 Content Uri
下面是Uri的基本格式:
class="brush: xhtml; toolbar: false">content://authority/optionalPath/optionalId
content://是内容提供者的标准前缀,而且它必须是content://。authority由我们自己定义,它必须具有唯一性,
因此我们一般使用应用程序包名命名authority。optionalPath和optionalId是可选的。
下面我们来看一下WordPress的文章地址格式:
http://www.whathecode.com/archives/221
http:// 是http协议的标准写法,它是规定的,没有为什么。
www.whathecode.com可以理解为authority,因为域名是唯一的,它可以分辨我们要访问哪一个网站。
arichives可以理解为文章的分类。
最后的221就是文章的id,假如我们要查看第一遍文章,只要将221改成1就可以。
这样理解Uri是不是简单了很多。
建立自己的ContentProvider
建立ContentProvider只需几部:
1. 设计数据库的储存方式,因为ContentProvider提供的是数据,没有数据,ContentProvider就没有了用处。
2. 定义自己的类,继承ContentProvider类,并实现基本的方法。
3. 设计authority字符串。(要被人访问你的网站,你就需要一个网址,当然ip地址也可以)
4. 在AndroidManifest中注册Provider
我们先来研究一下代码:
作为示例下面的代码只实现了query方法,而且只添加了一个Uri,
一般应用程序都不只一个Uri
package com.whathecode.provider; import android.content.ContentProvider; import android.content.ContentValues; import android.content.Context; import android.content.Intent; import android.content.UriMatcher; import android.database.Cursor; import android.database.sqlite.SQLiteDatabase; import android.database.sqlite.SQLiteDatabase.CursorFactory; import android.database.sqlite.SQLiteOpenHelper; import android.net.Uri; import android.util.Log; import android.widget.Toast; public class MemberProvider extends ContentProvider { private static final UriMatcher sMatcher; private static final String MEMBER_NAME = "name"; private static final int QUERY_BY_NAME = 0; private static final String DB_NAME = "member.db"; private static final String TAG = "MemberProvider"; static { sMatcher = new UriMatcher(UriMatcher.NO_MATCH); /** * 添加需要匹配的Uri, 当这个Uri被匹配的时候返回第三个参数。 * 得到这个参数之后就可以在query,insert,update,delete * 方法中做出相应的动作。 */ sMatcher.addURI(Member.AUTHORITY, MEMBER_NAME, QUERY_BY_NAME); } private static class DataBaseHelper extends SQLiteOpenHelper { public DataBaseHelper(Context context, String name, CursorFactory factory, int version) { super(context, name, factory, version); } @Override public void onCreate(SQLiteDatabase db) { //建立数据库表结构 db.execSQL("create table member(_id integer primary key," + "name varchar(20)," + "work varchar(20)," + "age integer)"); } @Override public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) { // TODO Auto-generated method stub } } private DataBaseHelper mHelper; @Override public boolean onCreate() { mHelper = new DataBaseHelper(getContext(), DB_NAME, null, 2); return true; } @Override public Cursor query(Uri uri, String[] projection, String selection, String[] selectionArgs, String sortOrder) { /** * 前面我们在静态代码块中已添加了Uri库 * 当每个Uri作为参数传进来的时候我们都先进行匹配 * */ switch (sMatcher.match(uri)) { case QUERY_BY_NAME: //第一次执行时生成数据库member.db SQLiteDatabase readableDatabase = mHelper.getReadableDatabase(); /** * 当query方法执行的时候向外发送广播 */ Intent intent = new Intent(); intent.setAction("com.contentprovider.execquery"); intent.putExtra("MemberProvider", "query方法执行了"); getContext().sendBroadcast(intent); break; default: /** * 当Uri匹配失败的时候说明Uri参数错误,无法继续进行操作, * 因此程序抛出一个错误 */ throw new IllegalArgumentException("Unknown URI " + uri); } return null; } @Override public String getType(Uri uri) { // TODO Auto-generated method stub return null; } @Override public Uri insert(Uri uri, ContentValues values) { // TODO Auto-generated method stub return null; } @Override public int delete(Uri uri, String selection, String[] selectionArgs) { // TODO Auto-generated method stub return 0; } @Override public int update(Uri uri, ContentValues values, String selection, String[] selectionArgs) { // TODO Auto-generated method stub return 0; } }
这样,一个虽简单但可行的内容提供者就创建好了,现在我们只需在AndroidManifest文件中注册它。
<provider android:name="com.whathecode.provider.MemberProvider" android:authorities="com.whathecode.contentproviderdemo.member"> </provider>
接下来,运行这个程序,将我们刚才定义的ContentProvider部署到模拟器。
然后,我们建立另外一个程序测试这个内容提供者是否真的工作正常。
下面是另外一个程序的代码:
我们需要另外一个类进行访问ContentProvider提供的数据。
这个类就是ContentResolver,它提供了和ContentProvider一样的CRUD方法。
方便我们查询数据。
package com.whathecode.contentprovidertest; import android.app.Activity; import android.content.BroadcastReceiver; import android.content.ContentResolver; import android.content.Context; import android.content.Intent; import android.content.IntentFilter; import android.net.Uri; import android.os.Bundle; import android.view.View; import android.widget.Toast; public class MainActivity extends Activity { private BroadcastReceiver receiver; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); //创建一个广播接受者用于接收MemberProvider发出的广播 receiver = new BroadcastReceiver() { @Override public void onReceive(Context context, Intent intent) { /** * 当广播被接收到的时候Toast提示用户接收到的信息 */ Toast.makeText(getBaseContext(), "收到的信息" + intent.getStringExtra("MemberProvider"), Toast.LENGTH_SHORT).show(); } }; } @Override protected void onResume() { super.onResume(); //注册广播接受者 registerReceiver(receiver, new IntentFilter("com.contentprovider.execquery")); } public void onClick(View view) { /** * 获取ContentResolver实例访问ContentProvider */ ContentResolver resolver = getContentResolver(); Uri uri = Uri .parse("content://com.whathecode.contentproviderdemo.member/name"); resolver.query(uri, null, null, null, null); } @Override protected void onPause() { super.onPause(); //取消注册广播接受者 unregisterReceiver(receiver); } }
运行效果:
如果Toast运行证明MemberProvider中的query方法被成功执行