ContentProvider 与Activity、Service、BroadcastReceiver并称四大组件,一个应用程序通过ContentProvoder向外界暴露其数据操作方法,不管其应用程序是否启动,其他应用程序皆可操作程序的内部数据,增删改查。
开发ContentProvider的步骤。
1:定义自己的ContentProvider,该类需要继承安卓提供的ContentProvider基类。
2:需要在配置文件AndroidManifest.xml中配置此ContentProvider
<provider
android:name=”MyContentProvider”
android:authorities=”com.wissen.MyContentProvider” //android:authorities 类似为此Provider的域名
android:exported="true"/> //为能否被外部访问,默认为true
当我们通过上面的配置的文件配置完,那么其他应用程序就可以访问Url来访问暴露的数据。使用暴露数据需要在ContentProvider复写CRUD操作
代码示例:
(一)ContentProvider 应用程序
public class DictProvider extends ContentProvider { private static UriMatcher matcher = new UriMatcher(UriMatcher.NO_MATCH); private static final int WORDS = 1; private static final int WORD = 2; private MyDatabaseHelper dbOpenHelper; static { // 为UriMatcher注册两个Uri matcher.addURI(Words.AUTHORITY, "words", WORDS); matcher.addURI(Words.AUTHORITY, "word/#", WORD); } // 第一次调用该DictProvider时,系统先创建DictProvider对象,并回调该方法 @Override public boolean onCreate() { dbOpenHelper = new MyDatabaseHelper(this.getContext(), "myDict.db3", 1); return true; } // 返回指定Uri参数对应的数据的MIME类型 @Override public String getType(Uri uri) { switch (matcher.match(uri)) { // 如果操作的数据是多项记录 case WORDS: return "vnd.android.cursor.dir/org.crazyit.dict"; // 如果操作的数据是单项记录 case WORD: return "vnd.android.cursor.item/org.crazyit.dict"; default: throw new IllegalArgumentException("未知Uri:" + uri); } } // 查询数据的方法 @Override public Cursor query(Uri uri, String[] projection, String where, String[] whereArgs, String sortOrder) { SQLiteDatabase db = dbOpenHelper.getReadableDatabase(); switch (matcher.match(uri)) { // 如果Uri参数代表操作全部数据项 case WORDS: // 执行查询 return db.query("dict", projection, where, whereArgs, null, null, sortOrder); // 如果Uri参数代表操作指定数据项 case WORD: // 解析出想查询的记录ID long id = ContentUris.parseId(uri); String whereClause = Words.Word._ID + "=" + id; // 如果原来的where子句存在,拼接where子句 if (where != null && !"".equals(where)) { whereClause = whereClause + " and " + where; } return db.query("dict", projection, whereClause, whereArgs, null, null, sortOrder); default: throw new IllegalArgumentException("未知Uri:" + uri); } } // 插入数据方法 @Override public Uri insert(Uri uri, ContentValues values) { // 获得数据库实例 SQLiteDatabase db = dbOpenHelper.getReadableDatabase(); switch (matcher.match(uri)) { // 如果Uri参数代表操作全部数据项 case WORDS: // 插入数据,返回插入记录的ID long rowId = db.insert("dict", Words.Word._ID, values); // 如果插入成功返回uri if (rowId > 0) { // 在已有的 Uri的后面追加ID Uri wordUri = ContentUris.withAppendedId(uri, rowId); // 通知数据已经改变 getContext().getContentResolver().notifyChange(wordUri, null); return wordUri; } break; default : throw new IllegalArgumentException("未知Uri:" + uri); } return null; } // 修改数据的方法 @Override public int update(Uri uri, ContentValues values, String where, String[] whereArgs) { SQLiteDatabase db = dbOpenHelper.getWritableDatabase(); // 记录所修改的记录数 int num = 0; switch (matcher.match(uri)) { // 如果Uri参数代表操作全部数据项 case WORDS: num = db.update("dict", values, where, whereArgs); break; // 如果Uri参数代表操作指定数据项 case WORD: // 解析出想修改的记录ID long id = ContentUris.parseId(uri); String whereClause = Words.Word._ID + "=" + id; // 如果原来的where子句存在,拼接where子句 if (where != null && !where.equals("")) { whereClause = whereClause + " and " + where; } num = db.update("dict", values, whereClause, whereArgs); break; default: throw new IllegalArgumentException("未知Uri:" + uri); } // 通知数据已经改变 getContext().getContentResolver().notifyChange(uri, null); return num; } // 删除数据的方法 @Override public int delete(Uri uri, String where, String[] whereArgs) { SQLiteDatabase db = dbOpenHelper.getReadableDatabase(); // 记录所删除的记录数 int num = 0; // 对于uri进行匹配。 switch (matcher.match(uri)) { // 如果Uri参数代表操作全部数据项 case WORDS: num = db.delete("dict", where, whereArgs); break; // 如果Uri参数代表操作指定数据项 case WORD: // 解析出所需要删除的记录ID long id = ContentUris.parseId(uri); String whereClause = Words.Word._ID + "=" + id; // 如果原来的where子句存在,拼接where子句 if (where != null && !where.equals("")) { whereClause = whereClause + " and " + where; } num = db.delete("dict", whereClause, whereArgs); break; default: throw new IllegalArgumentException("未知Uri:" + uri); } // 通知数据已经改变 getContext().getContentResolver().notifyChange(uri, null); return num; } }
//数据库操作类 public class MyDatabaseHelper extends SQLiteOpenHelper { final String CREATE_TABLE_SQL = "create table dict(_id integer primary key autoincrement , word , detail)"; /** * @param context * @param name * @param version */ public MyDatabaseHelper(Context context, String name, int version) { super(context, name, null, version); } @Override public void onCreate(SQLiteDatabase db) { // 第一个使用数据库时自动建表 db.execSQL(CREATE_TABLE_SQL); } @Override public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) { System.out.println("--------onUpdate Called--------" + oldVersion + "--->" + newVersion); } }
//全局变量 public final class Words { // 定义该ContentProvider的Authority public static final String AUTHORITY = "org.crazyit.providers.dictprovider"; // 定义一个静态内部类,定义该ContentProvider所包的数据列的列名 public static final class Word implements BaseColumns { // 定义Content所允许操作的3个数据列 public final static String _ID = "_id"; public final static String WORD = "word"; public final static String DETAIL = "detail"; // 定义该Content提供服务的两个Uri public final static Uri DICT_CONTENT_URI = Uri .parse("content://" + AUTHORITY + "/words"); public final static Uri WORD_CONTENT_URI = Uri .parse("content://" + AUTHORITY + "/word"); } }
配置文件
<?xml version="1.0" encoding="utf-8"?> <manifest xmlns:android="http://schemas.android.com/apk/res/android" package="org.crazyit.content" android:versionCode="1" android:versionName="1.0"> <uses-sdk android:minSdkVersion="10" android:targetSdkVersion="17" /> <application android:icon="@drawable/ic_launcher"> <!-- 注册一个ContentProvider --> <provider android:exported="true" android:name=".DictProvider" android:authorities="org.crazyit.providers.dictprovider"> </provider> </application> </manifest>
(二)ContentResolver (Words类与上面一致)
public class DictResolverTest extends Activity { ContentResolver contentResolver; Button insert = null; Button search = null; @Override public void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.main); // 获取系统的ContentResolver对象 contentResolver = getContentResolver(); insert = (Button) findViewById(R.id.insert); search = (Button) findViewById(R.id.search); // 为insert按钮的单击事件绑定事件监听器 insert.setOnClickListener(new OnClickListener() { @Override public void onClick(View source) { // 获取用户输入 String word = ((EditText) findViewById(R.id.word)) .getText().toString(); String detail = ((EditText) findViewById(R.id.detail)) .getText().toString(); // 插入生词记录 ContentValues values = new ContentValues(); values.put(Words.Word.WORD, word); values.put(Words.Word.DETAIL, detail); contentResolver.insert( Words.Word.DICT_CONTENT_URI, values); // 显示提示信息 Toast.makeText(DictResolverTest.this, "添加生词成功!" , Toast.LENGTH_LONG).show(); } }); // 为search按钮的单击事件绑定事件监听器 search.setOnClickListener(new OnClickListener() { @Override public void onClick(View source) { // 获取用户输入 String key = ((EditText) findViewById(R.id.key)) .getText().toString(); // 执行查询 Cursor cursor = contentResolver.query( Words.Word.DICT_CONTENT_URI, null, "word like ? or detail like ?", new String[] { "%" + key + "%", "%" + key + "%" }, null); // 创建一个Bundle对象 Bundle data = new Bundle(); data.putSerializable("data", converCursorToList(cursor)); // 创建一个Intent Intent intent = new Intent(DictResolverTest.this, ResultActivity.class); intent.putExtras(data); // 启动Activity startActivity(intent); } }); } private ArrayList<Map<String, String>> converCursorToList(Cursor cursor) { ArrayList<Map<String, String>> result = new ArrayList<Map<String, String>>(); // 遍历Cursor结果集 while (cursor.moveToNext()) { // 将结果集中的数据存入ArrayList中 Map<String, String> map = new HashMap<String, String>(); // 取出查询记录中第2列、第3列的值 map.put(Words.Word.WORD, cursor.getString(1)); map.put(Words.Word.DETAIL, cursor.getString(2)); result.add(map); } return result; }
public class ResultActivity extends Activity { @Override public void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.popup); ListView listView = (ListView) findViewById(R.id.show); Intent intent = getIntent(); // 获取该intent所携带的数据 Bundle data = intent.getExtras(); // 从Bundle数据包中取出数据 @SuppressWarnings("unchecked") List<Map<String, String>> list = (List<Map<String, String>>) data.getSerializable("data"); // 将List封装成SimpleAdapter SimpleAdapter adapter = new SimpleAdapter(ResultActivity.this, list, R.layout.line , new String[] { Words.Word.WORD, Words.Word.DETAIL } , new int[] { R.id.word, R.id.detail }); // 填充ListView listView.setAdapter(adapter); } }
<?xml version="1.0" encoding="utf-8"?> <manifest xmlns:android="http://schemas.android.com/apk/res/android" package="org.crazyit.resolver" android:versionCode="1" android:versionName="1.0"> <uses-sdk android:minSdkVersion="10" android:targetSdkVersion="17" /> <application android:icon="@drawable/ic_launcher" android:label="@string/app_name"> <activity android:name=".DictResolverTest" android:label="@string/app_name"> <intent-filter> <action android:name="android.intent.action.MAIN" /> <category android:name="android.intent.category.LAUNCHER" /> </intent-filter> </activity> <activity android:name=".ResultActivity" android:theme="@android:style/Theme.Dialog" android:label="找到的单词"> </activity> </application> </manifest>