入门Android开发--第一行代码--笔记系列(ContentProvider/Resolver)

ContentProvider

内容提供器主要用于在不同的应用程序之间实现数据共享的功能。他提供了一套完整的机制,允许一个程序访问另一个程序中的数据,同时还能保证被访数据的安全性。

访问其他程序中的数据

ContentResolver
可以通过context .getContentResolver()方法获取该类的实例
同样的有CRUD的增删改查,不过查询的内容不是通过表名,而是通过URI
Uri
URI的标准写法是:content://com.example.app.provider/table1
得到URI之后,将之解析成Uri对象即可,解析方法如下
Uri uri =Uri.parse("URI")
然后就可以用这个Uri对象来查询table1中的数据了。代码如下:
Cursor cursor= getContentResolver().query(uri,projection,selection,selectionArgs,sortOrder)

query(方法参数) 对应SQL部分 描述
uri from table_name 指定查询的表名
projection select columns1,columns2 指定查询的列名
selection where column=value 指定where的约束条件
selectionArgs - 为where中的占位符提供具体的值
orderBy order by column1,column2 指定查询结果的排序方式

查询完成后,
if(cursor!=null){
while(cursor.moveToNext()){
String column1=cursor.getString(cursor.getColumnIndex(“column1”));
int column2=cursor.getInt(cursor.getColumnIndex(“column2”));
}
cursor.close();
}
增删改查和数据库差不多,只是操作主体不一样。就不再多说了。

读取系统联系人

权限:android.permission.READ_CONTACTS
主要代码:

private void readContact() {
    Cursor cursor=null;
    try{
        //查询联系人数据
        cursor=getContentResolver().query(ContactsContract.CommonDataKinds.Phone.CONTENT_URI,null,null,null,null);
        while(cursor.moveToNext()){
            //获取联系人姓名
            String name=cursor.getString(cursor.getColumnIndex(ContactsContract.CommonDataKinds.Phone.DISPLAY_NAME));
            //获取联系人手机号
            String number=cursor.getString(cursor.getColumnIndex(ContactsContract.CommonDataKinds.Phone.NUMBER));
            listStr.add(name +":"+number );//List<String>
        }
    }catch (NullPointerException e){
        e.printStackTrace();
    }finally {
        if(cursor!=null){
            cursor.close();
        }
    }
}

创建ContentProvider

基本写法

使用自己的提供器继承CotentProvider需要重写全部六个方法

public class MyProvider extends ContentProvider {
@Override
public boolean onCreate() {     //通常在这里完成数据库的创建和升级等
    return false;//返回true表示初始化成功(用ContentResolver尝试访问数据时,ContentProvider才会被初始化)
}
@Nullable
@Override       //参数的含义可以参照上面的表格。
public Cursor query(Uri uri, String[] projection, String selection, String[] selectionArgs, String sortOrder) {
    return null;
}
@Nullable
@Override
public String getType(Uri uri) {       //根据传入的内容URI来返回相应的MIME类型。
    return null;
}
@Nullable
@Override       
public Uri insert(Uri uri, ContentValues values) {
    return null;
}
@Override
public int delete(Uri uri, String selection, String[] selectionArgs) {
    return 0;
}
@Override
public int update(Uri uri, ContentValues values, String selection, String[] selectionArgs) {
    return 0;
}

}

查询其他类似

很明显的,我们需要解析传入的URI:
content://com.example.app.provider/table1/1最后一个参数表示id为1
通配符:1.* 表示匹配任意长度的任意字符;2.# 表示匹配任意长度的数字。
然后再借助UriMatcher这个类来实现匹配内容URI的功能。

public static final int TABLE_DIR=0;
public static final int TABLE_ITEM=1;
private static UriMatcher uriMatcher;
static{
    uriMatcher=new UriMatcher(UriMatcher.NO_MATCH);
    //addURI参数分离“权限”、“路径”、“自定义代码”,当传入前面两个参数,会返回第三个代码,方便查询
    uriMatcher.addURI("com.example.app.provider","table1",TABLE_DIR);
    uriMatcher.addURI("com.example.app.provider","table1/#",TABLE_ITEM);
}
@Nullable
@Override       //参数的含义可以参照上面的表格。
public Cursor query(Uri uri, String[] projection, String selection, String[] selectionArgs, String sortOrder) {
    switch(uriMatcher.match(uri)){
        case TABLE_DIR:
            //查询所有
            break;
        case TABLE_ITEM:
            //查询某个id数据
            break;
    }
    return null;
}

getType

一个内容URI所对应的MIME字符串主要由三部分组成,规定如下:
1、必须以vnd开头
2、如果内容URI以路径结尾,vnd后面要接android.cursor.dir/,如果内容URI以id结尾,则接android.cursor.item/
3、最后接上vnd..。
举个例子,

content://com.example.app.provider/table1对应的MIME类型是:  
vnd.android.cursur.dir/vnd.com.example.app.provider.table1
content://com.example.app.provider/table1/1对应的MIME类型是:  
vnd.android.cursur.item/vnd.com.example.app.provider.table1

然后可以在getType中根据query中的match方式,返回对应的MIME。

实现跨程序数据共享

如上所诉,先创建一个MyDatabaseHelper,onCreate中添加book表的创建
Provider需要注册authorities是和下面访问用的AUTHORITY需要一致

<provider
    android:authorities="com.example.tpout.myapplication.provider"
    android:name="com.example.tpout.myapplication.MyDatabaseProvider"
    android:exported="true"> <!-- 可以被其他应用访问-->
</provider>

然后实现MyContentProvider,对各方面的请求进行处理

public class MyDatabaseProvider 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="com.example.tpout.myapplication.provider";
    private static UriMatcher uriMatcher;
    //在这里实例化数据库
    private MyDatabaseHelper databaseHelper;
    static {
        uriMatcher=new UriMatcher(UriMatcher.NO_MATCH);
        uriMatcher.addURI(AUTHORITY,"book",BOOK_DIR);
        uriMatcher.addURI(AUTHORITY,"book/#",BOOK_ITEM);
    }
    @Override
    public boolean onCreate() {
        //创建数据库
        databaseHelper=new MyDatabaseHelper(getContext(),"BookStore.db",null,1);
        return true;
    }
//查询的相关解析
@Nullable
@Override
public Cursor query(Uri uri, String[] projection, String selection, String[] selectionArgs, String sortOrder) {
    SQLiteDatabase db=databaseHelper.getReadableDatabase();
    Cursor cursor=null;
    switch (uriMatcher.match(uri)){
        case BOOK_DIR:
            cursor=db.query("Book",projection,selection,selectionArgs,null,null,sortOrder);
            break;
        case BOOK_ITEM:
            //getPathSegments讲URI权限之后的部分已“/”符号进行分割,放入字符串列表。0位为路径,1位为id
            String bookId=uri.getPathSegments().get(1);
            cursor=db.query("Book",projection,"id=?",new String[]{bookId},null,null,sortOrder);
            break;
    }
    return cursor;
}
//获取MIME
@Nullable
@Override
public String getType(Uri uri) {
    switch (uriMatcher.match(uri)){
        case BOOK_DIR:
            return "vnd.android.cursor.dir/vnd.com.example.tpout.myapplication.provider.book";
        case BOOK_ITEM:
            return "vnd.android.cursor.item/vnd.com.example.tpout.myapplication.provider.book";
    }
    return null;
}
//插入。
@Nullable
@Override
public Uri insert(Uri uri, ContentValues values) {
    SQLiteDatabase db=databaseHelper.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;
        default:
            break;
    }
    return uriReturn;
}
//删除。
@Override
public int delete(Uri uri, String selection, String[] selectionArgs) {
    SQLiteDatabase db=databaseHelper.getWritableDatabase();
    int deleteRows=0;
    switch (uriMatcher.match(uri)){
        case BOOK_DIR:
            deleteRows=db.delete("Book",selection,selectionArgs);
            break;
        case BOOK_ITEM:
            String booId=uri.getPathSegments().get(1);
            deleteRows=db.delete("Book","id=?",new String[]{booId});
            break;
        default:
            break;
    }
    return deleteRows;
}
//更新
@Override
public int update(Uri uri, ContentValues values, String selection, String[] selectionArgs) {
    SQLiteDatabase db=databaseHelper.getWritableDatabase();
    int updateRows=0;
    switch (uriMatcher.match(uri)){
        case BOOK_DIR:
            updateRows=db.update("Book",values,selection,selectionArgs);
            break;
        case BOOK_ITEM:
            String booId=uri.getPathSegments().get(1);
            updateRows=db.update("Book",values,"id=?",new String[]{booId});
            break;
        default:
            break;
    }
    return updateRows;
}
}

最后在MainActivity中模拟读取数据

String newId;//用于记录添加的第几个数据
//添加
add.setOnClickListener(new View.OnClickListener() {
        @Override
        public void onClick(View v) {
            Uri uri=Uri.parse("content://com.example.tpout.myapplication.provider/book");
            ContentValues values=new ContentValues();
            values.put("name","A clash");
            values.put("author","A cl");
            values.put("pages",333);
            values.put("price",2.85);
            Uri newUri=getContentResolver().insert(uri,values);
            newId=newUri.getPathSegments().get(1);
        }
    });
//查询
query.setOnClickListener(new View.OnClickListener() {
        @Override
        public void onClick(View v) {
            Uri uri=Uri.parse("content://com.example.tpout.myapplication.provider/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","name :"+name);
                    Log.d("MainActivity","author :"+author);
                    Log.d("MainActivity","pages :"+pages);
                    Log.d("MainActivity","price :"+price);
                }
                cursor.close();
            }
        }
    });
    //更新
    update.setOnClickListener(new View.OnClickListener() {
        @Override
        public void onClick(View v) {
            Uri uri=Uri.parse("content://com.example.tpout.myapplication.provider/book/"+newId);
            ContentValues values=new ContentValues();
            values.put("name","a st");
            values.put("pages",23);
            values.put("price",22.0);
            getContentResolver().update(uri,values,null,null);
        }
    });
    //删除
    delete.setOnClickListener(new View.OnClickListener() {
        @Override
        public void onClick(View v) {
            Uri uri=Uri.parse("content://com.example.tpout.myapplication.provider/book/"+newId);
            getContentResolver().delete(uri,null,null);
        }
    });
}

你可能感兴趣的:(入门Android开发--第一行代码--笔记系列(ContentProvider/Resolver))