主要用于在不同的应用程序之间实现数据共享的功能,它提供了一套完整的机制,允许一个程序访问另一个程序中的数据,同时还保证被访数据的安全性。
内容提供器的用法一般有两种:
一种是是用那个现有的内容提供其来读取和操作相应程序中的数据。
另一种是创建自己的内容提供器给我们的程序的数据提供外部访问接口。
不同于SQLiteDataBase,ContentResolver中的增删改查的方法都是不接收表名的参数,而是使用一个Uri参数代替,这个参数被称为内容URI。
URI给内容提供器的数据建立了唯一标识符:URI由两部分组成,权限和路径
权限是用于对不同的应用程序做区分的,一般为了避免冲突,都会采用程序包名来进行命名。
路径是用于对同一应用程序中的不同表做区分的,通常都会添加到权限的后面。
通过Uri uri=Uri.parse(“content://com.example.app.provider/table1”)方法,就可以将内容URI字符串解析成Uri对象了。
Cursor cursor=getContentResolver().query(uri,projection,selection,selectionArgs,sortOrder);
query的参数说明
query()方法参数 | 对应的SQL部分 | 描述 |
---|---|---|
uri | from table_name | 指定查询某个应用程序下的某一张表 |
projection | select column1,column2 | 指定查询的列名 |
selection | where column=value | 指定where的约束条件 |
selectionArgs | - | 为where中的占位符提供具体的值 |
orderBy | order by column1,column2 | 指定查询结果的排序方式 |
新建MyProvider继承ContentProvider
public class MyProvider extends ContentProvider{
public static final int BOOK_DIR=0;
public static final int BOOK_ITEM=1;
public static final int CATEGORY_DIR=2;
public static final int CATEGORY_ITEM=3;
public static final String AUTHORITY="cn.sict.mycontentprovider.bookprovider";
private static UriMatcher uriMatcher;
private MyDataBaseHelper dbHelper;
static {
uriMatcher=new UriMatcher(UriMatcher.NO_MATCH);
uriMatcher.addURI(AUTHORITY,"book",BOOK_DIR);
uriMatcher.addURI(AUTHORITY,"book/#",BOOK_ITEM);
uriMatcher.addURI(AUTHORITY,"category",CATEGORY_DIR);
uriMatcher.addURI(AUTHORITY,"category/#",CATEGORY_ITEM);
}
//初始化内容提供器的时候调用,完成对数据库的创建和升级等操作。
//只有当存在ContentResolver尝试访问我们的程序中的数据时,内容提供器才会被初始化
@Override
public boolean onCreate() {
Log.d("MyProvider","onCreate");
dbHelper=new MyDataBaseHelper(getContext(),"BookStore.db",null,2);
return true;
}
//从内容提供器中查询数据
//uri参数确定查询那张表,projection参数确定查询哪些列
//selection和selectionArgs参数用来约束查询哪些行,sortOrder参数用于对结果进行排序,查询的结果存放在Cursor对象中
@Override
public Cursor query(Uri uri, String[] projection, String selection, String[] selectionArgs, String sortOrder) {
Log.d("MyProvider","query");
SQLiteDatabase db=dbHelper.getReadableDatabase();
Cursor cursor=null;
switch (uriMatcher.match(uri))
{
case BOOK_DIR:
//查询table1表中的所有数据
cursor=db.query("Book",projection,selection,selectionArgs,null,null,sortOrder);
break;
case BOOK_ITEM:
//查询table1表中的单条数据
String bookId=uri.getPathSegments().get(1);
cursor=db.query("Book",projection,"id=?",new String[]{bookId},null,null,sortOrder);
break;
case CATEGORY_DIR:
//查询table2表中的所有数据
cursor=db.query("Category",projection,selection,selectionArgs,null,null,sortOrder);
break;
case CATEGORY_ITEM:
//查询table2表中的单条数据
String categoryId=uri.getPathSegments().get(1);
cursor=db.query("Category",projection,"id=?",new String[]{categoryId},null,null,sortOrder);
break;
default:break;
}
return cursor;
}
//根据传入的内容URI来返回相应的MIME类型
@Override
public String getType(Uri uri) {
Log.d("MyProvider","getType");
switch(uriMatcher.match(uri))
{
case BOOK_DIR:
return "vnd.android.cursor.dir/vnd.cn.sict.mycontentprovider.bookproviderbook.book";
case BOOK_ITEM:
return "vnd.android.cursor.item/vnd.cn.sict.mycontentprovider.bookproviderbook.book";
case CATEGORY_DIR:
return "vnd.android.cursor.dir/vnd.cn.sict.mycontentprovider.bookproviderbook.category";
case CATEGORY_ITEM:
return "vnd.android.cursor.item/vnd.cn.sict.mycontentprovider.bookproviderbook.category";
}
return null;
}
@Override
public Uri insert(Uri uri, ContentValues values) {
Log.d("MyProvider","insert");
SQLiteDatabase db=dbHelper.getWritableDatabase();
Uri uriReturn=null;
switch (uriMatcher.match(uri))
{
case BOOK_DIR:
case BOOK_ITEM:
long newBookId=db.insert("Book",null,values);
uriReturn=Uri.parse("content://"+AUTHORITY+"/book/"+newBookId);
break;
case CATEGORY_DIR:
case CATEGORY_ITEM:
long newCategoryId=db.insert("Category",null,values);
uriReturn=Uri.parse("content://"+AUTHORITY+"/category/"+newCategoryId);
break;
default:break;
}
return uriReturn;
}
@Override
public int delete(Uri uri, String selection, String[] selectionArgs) {
Log.d("MyProvider","delete");
SQLiteDatabase db=dbHelper.getWritableDatabase();
int deleteRows=0;
switch (uriMatcher.match(uri))
{
case BOOK_DIR:
deleteRows=db.delete("Book", selection, selectionArgs);
break;
case BOOK_ITEM:
String bookId=uri.getPathSegments().get(1);
deleteRows=db.delete("Book", "id=?", new String[]{bookId});
break;
case CATEGORY_DIR:
deleteRows=db.delete("Category", selection, selectionArgs);
break;
case CATEGORY_ITEM:
String categoryId=uri.getPathSegments().get(1);
deleteRows=db.delete("Category","id=?",new String[]{categoryId});
break;
default:break;
}
return deleteRows;
}
@Override
public int update(Uri uri, ContentValues values, String selection, String[] selectionArgs) {
Log.d("MyProvider","update");
SQLiteDatabase db=dbHelper.getWritableDatabase();
int updateRows=0;
switch (uriMatcher.match(uri))
{
case BOOK_DIR:
updateRows=db.update("Book",values,selection,selectionArgs);
break;
case BOOK_ITEM:
String bookId=uri.getPathSegments().get(1);
updateRows=db.update("Book",values,"id=?",new String[]{bookId});
break;
case CATEGORY_DIR:
updateRows=db.update("Category",values,selection,selectionArgs);
break;
case CATEGORY_ITEM:
String categoryId=uri.getPathSegments().get(1);
updateRows=db.update("Category",values,"id=?",new String[]{categoryId});
default:break;
}
return updateRows;
}
}
-onCreate()
初始化内容提供器的时候调用。通常会在这里完成对数据库的创建和升级等操作。返回true表示内容提供器初始化成功,返回false表示失败。注意:只有当存在ContentResolver尝试访问我们程序中的数据时,内容提供器才会被初始化
-query()
查询的结果存放在Cursor中被返回
-insert()
-update()
-delete()
-getType()
根据传入的内容URI来返回相应的MIME的类型。一个内容URI所对应的MIME字符串主要由三部分组成。
1、必须以vnd开头
2、如果内容URI以路径结尾,则后接android.cursor.dir/,如果内容URI以id结尾,则后接android.cursor.item/
3、最后接上vnd.authority.path
内容URI的格式主要有两种:一是以路径结尾就表示期望访问该表中的所有数据。二是以id结尾就表示期望访问该表中拥有相应id的数据。
“*”:表示匹配任意长度的任意字符
“#”:表示匹配任意长度的数字
为SQLite提供ContentProvider,加入外部访问接口
import android.content.Context;
import android.database.sqlite.SQLiteDatabase;
import android.database.sqlite.SQLiteOpenHelper;
/**
* Created by Fumier on 2015/8/16.
*/
public class MyDataBaseHelper extends SQLiteOpenHelper {
public static final String CREATE_BOOK="create table book("
+"id integer primary key autoincrement,"
+"author text,"
+"price real,"
+"pages integer,"
+"name text,"
+"category_id integer)";
public static final String CREATE_CATEGORY="create table Category("
+"id integer primary key autoincrement,"
+"category_name text,"
+"category_code integer)";
public MyDataBaseHelper(Context context,String name,SQLiteDatabase.CursorFactory factory,int version)
{
super(context,name,factory,version);
}
@Override
public void onCreate(SQLiteDatabase db) {
db.execSQL(CREATE_BOOK);
db.execSQL(CREATE_CATEGORY);
}
@Override
public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) {
switch (oldVersion) {
case 1:
db.execSQL(CREATE_CATEGORY);
case 2:
db.execSQL("alter table Book add column category_id integer");
default:
}
}
}
新建MainActivity类
public class MainActivity extends Activity {
private String newId;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
Button addData=(Button)findViewById(R.id.add_data);
addData.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
Uri uri = Uri.parse("content://cn.sict.mycontentprovider.bookprovider/book");
ContentValues values = new ContentValues();
values.put("name", "A Clash of Kings");
values.put("author", "John Smith");
values.put("pages", 1040);
values.put("price", 22.85);
Uri newUri = getContentResolver().insert(uri, values);
newId = newUri.getPathSegments().get(1);
}
});
Button queryData=(Button)findViewById(R.id.query_data);
queryData.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
Uri uri=Uri.parse("content://cn.sict.mycontentprovider.bookprovider/book");
Cursor cursor=getContentResolver().query(uri,null,null,null,null);
if(cursor!=null)
{
while(cursor.moveToNext())
{
String name=cursor.getString(cursor.getColumnIndex("name"));
String author=cursor.getString(cursor.getColumnIndex("author"));
int pages=cursor.getInt(cursor.getColumnIndex("pages"));
double price=cursor.getDouble(cursor.getColumnIndex("price"));
Log.d("MainActivity","book name is"+name);
Log.d("MainActivity","book author is"+author);
Log.d("MainActivity","book pages is"+pages);
Log.d("MainActivity","book price is"+price);
}
cursor.close();
}
}
});
Button updateData=(Button)findViewById(R.id.update_data);
updateData.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
Uri uri= Uri.parse("content://cn.sict.mycontentprovider.bookprovider/book/"+newId);
ContentValues values=new ContentValues();
values.put("name","A Clash of Kings");
values.put("pages",1240);
values.put("price",28.88);
getContentResolver().update(uri,values,null,null);
}
});
Button deleteData=(Button)findViewById(R.id.delete_data);
deleteData.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
Uri uri= Uri.parse("content://cn.sict.mycontentprovider.bookprovider/book/"+newId);
getContentResolver().delete(uri,null,null);
}
});
}
@Override
public boolean onCreateOptionsMenu(Menu menu) {
// Inflate the menu; this adds items to the action bar if it is present.
getMenuInflater().inflate(R.menu.menu_main, menu);
return true;
}
@Override
public boolean onOptionsItemSelected(MenuItem item) {
// Handle action bar item clicks here. The action bar will
// automatically handle clicks on the Home/Up button, so long
// as you specify a parent activity in AndroidManifest.xml.
int id = item.getItemId();
//noinspection SimplifiableIfStatement
if (id == R.id.action_settings) {
return true;
}
return super.onOptionsItemSelected(item);
}
}
配置Manifest.xml
"http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical">