内容提供者基础(含有自己的例子)

 步骤:

1.准备需要暴露的数据库
2.需要创建ContentProvider去暴露
3.准备暴露的uri地址
4.去实现需要暴露的增删改查方法
5.需要在清单文件中注册
6.其他应用通过内容解析者contentresolver去访问该数据

说明:获取系统的联系人 短信  通话记录也就是通过系统暴露的uri来对系统的数据库进行操作而已.

所以自定义内容提供者也是同样的道理,需要暴露一个uri,另一个程序通过这个uri就可以对这个应用的数据库进行操作

自定义内容提供者:

MainActivity.java:

public class MainActivity extends Activity {

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
    }
}

MyContentProvider.java

public class MyContentProvider extends ContentProvider{

    private SQLiteDatabase db;
    private static UriMatcher uriMatcher;
    
    static{   //与清单文件里的authorities 域名相同
        uriMatcher=new UriMatcher(UriMatcher.NO_MATCH);
        //为内容提供者设置uri,其它程序就可以通过该uri对数据库进行操作
        uriMatcher.addURI("yuming", "tang", 1);//用它来代表增删改查操作(没有条件限制)
        uriMatcher.addURI("yuming", "tangs", 2);//代表有条件的增删改查
    }

    @Override//第一次打开该应用执行,如果关机重启,打开内容提供者或者有软件访问该内容提供者,该方法也会执行
    public boolean onCreate() {
        System.out.println("内容提供者onCreate执行");
        MySQLite mySqlite=new MySQLite(getContext(), "mysql", null, 1);
        db = mySqlite.getWritableDatabase();
        return true;
    }
//下面的方法都是作为暴露出去的对数据库进行操作的方法
    @Override
    public Cursor query(Uri uri, String[] projection, String selection,
            String[] selectionArgs, String sortOrder) {
        if(uriMatcher.match(uri)==1){
            System.out.println("调用了查询方法(无条件)");
            Cursor cursor = db.query("book", null, null, null, null, null, null);
            return cursor;
        }else if(uriMatcher.match(uri)==2){
            System.out.println("有条件的查询操作");
        }else{
            System.out.println("输入的uri有误,没有匹配成功");
        }
        return null;
    }

    @Override
    public String getType(Uri uri) {
        return null;
    }

    @Override
    public Uri insert(Uri uri, ContentValues values) {
        return null;
    }

    @Override
    public int delete(Uri uri, String selection, String[] selectionArgs) {
        if(uriMatcher.match(uri)==1){
            System.out.println("调用了删除方法(无条件)");
        }else if(uriMatcher.match(uri)==2){
            System.out.println("有条件的删除操作");
        }else{
            System.out.println("删除--输入的uri有误,没有匹配成功");
        }
        return 0;
    }

    @Override
    public int update(Uri uri, ContentValues values, String selection,
            String[] selectionArgs) {
        return 0;
    }

}

MySQLite.java

public class MySQLite extends SQLiteOpenHelper{
    public static final String CREATE_BOOK="create table book(id integer primary key autoincrement,name text,price real);";
    public MySQLite(Context context, String name, CursorFactory factory,
            int version) {
        super(context, name, factory, version);
        System.out.println("创建了数据库对象");
    }

    @Override
    public void onCreate(SQLiteDatabase db) {
        db.execSQL(CREATE_BOOK);//创建数据库,存在就不会执行下面的语句了
        System.out.println("创建数据库");
        for (int i = 1; i <=5; i++) {
            ContentValues values=new ContentValues();
            values.put("name", "第"+i+"本书");
            values.put("price", i+10);
            db.insert("book", null, values);
        }
    }

    @Override
    public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) {
        
    }
}

清单文件:

 <!--authorities为域名, exported为true代表提供出口给外部, multiprocess代表数据库只有一个实例-->
        <provider 
            android:name="com.example.content.MyContentProvider"
            android:authorities="yuming"
             android:exported="true" 
             android:multiprocess="false">
        </provider>

测试的工程:

MainActivity.java

public class MainActivity extends Activity{

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        //调用自己创建的内容提供者里的数据库,该对象就可以调用内容提供者里面的增删改查
        ContentResolver contentResolver = getContentResolver();
        //这个uri就为自己定义的uri
        Uri uri=Uri.parse("content://yuming/tang");
        //这里调用哪个方法就会执行内容提供者里的哪个方法,然后在那个方法里再判断uri
        Cursor cursor = contentResolver.query(uri, null, null, null, null);
        while(cursor.moveToNext()){
            String name = cursor.getString(cursor.getColumnIndex("name"));
            int price = cursor.getInt(cursor.getColumnIndex("price"));
            System.out.println("查询到的数据:"+name+"--"+price);
        }
        uri=Uri.parse("content://yuming/err");//随便写的uri
        contentResolver.delete(uri, null, null);
    }
}

运行结果:

 案例2:

数据库:

public class MySQLiteDatabase extends SQLiteOpenHelper{
    //表名 info (username password sex interest兴趣);
    private String sql="create table info(id integer primary key autoincrement,username text," +
            "password text,sex text,interest text);";
    public MySQLiteDatabase(Context context, String name,
            CursorFactory factory, int version) {
        super(context, name, factory, version);
    }

    @Override
    public void onCreate(SQLiteDatabase db) {
        db.execSQL(sql);//创建表
    }

    @Override
    public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) {
        
    }    
}

内容提供者:

public class MyContentProvider extends ContentProvider{
    //执行uri的匹配操作
    private static UriMatcher matcher;
    private MySQLiteDatabase database;
    static{
        matcher=new UriMatcher(UriMatcher.NO_MATCH);//没有匹配成功的匹配码
        matcher.addURI("yuming", "info", 1);//这里用它来代表操作所有数据
        
        //content://yuming/info/id/5,返回匹配码为3,我这里用来根据id对数据库进行操作 
        matcher.addURI("yuming", "info/id/#", 3);//匹配数字来操作数据
        
        //注意:这里info/*匹配的范围最大,如果放到id/#上面,匹配的时候会匹配/*,而这个与程序里的匹配就不一致了,程序就会报错
        //比如:content://yuming/info/username,返回匹配码为2,代表根据username对数据库进行操作  
        matcher.addURI("yuming", "info/*", 2);//匹配文字来操作数据
    }
    /**
     * ContentProvider创建后就会被调用,Android开机后,
     * ContentProvider在其它应用第一次访问它时才会被创建。
     */
    @Override
    public boolean onCreate() {
        //创建数据库,在这里只是获取数据库对象,因为在程序初始化主活动中就已经创建了数据库
        database = new MySQLiteDatabase(getContext(), "sql", null, 1);//sql为数据库名
        return true;//提供者是否成功加载
    }
//下面都是暴露给内容分解者Content
    /**query方法参数说明:
     * sql语句:String sql = "select * from person";
     * String table, 表名
     * String[] columns,projection  指定查询结果的列名,如果传递null相当于*,会返回所有结果
     * String selection,  指定where条件
     * String[] selectionArgs,  替换where条件中的?占位符号
     * String groupBy,  分组     
     * String having,   having条件
     * String orderBy,  排序
     * String limit     分页查询
     */
    @Override
    public Cursor query(Uri uri, String[] projection, String selection,
            String[] selectionArgs, String sortOrder) {
        //得到db对象,查询info表数据,返回给内容分解者
        SQLiteDatabase db = database.getReadableDatabase();
        Cursor cursor = null;
        switch (matcher.match(uri)) {
        case 1://查询所有数据
            cursor = db.query("info",null,null,null,null,null,null);
            break;
        case 2://根据文本匹配的
            //获取*匹配的文字
            String segment = uri.getLastPathSegment();
            cursor=db.query("info", projection, segment+"=?", selectionArgs, null, null, sortOrder);
            break;
        case 3://根据数字匹配的,这里根据id查询
            //获取#匹配的数字
            long parseId = ContentUris.parseId(uri);
            System.out.println(parseId);
            cursor=db.query("info", projection, "id=?", new String[]{parseId+""}, null, null, sortOrder);
            break;
        }
        System.out.println(matcher.match(uri));
        //db.close();切记不能关,否则内容解析者那边会报错
        return cursor;
    }

    /**
     * 参数说明:
     * 参数1:表名     参数2:通常为null,不能与参数3同时为null   参数3:传入设置值contentvalue
     * 返回值为uri,内容分解者需要使用ContentUris.parseId(uri)来获取插入的主键值
     */
    @Override
    public Uri insert(Uri uri, ContentValues values) {
        //得到db对象,查询info表数据,返回给内容分解者
        SQLiteDatabase db = database.getWritableDatabase();
        switch (matcher.match(uri)) {
        case 1://content://yuming/info来表示插入数据
            //返回新插入的这行的ID(主键值),如果插入失败返回-1
            long insert = db.insert("info", null, values);
            //将插入的行号返回回去,如:content://yuming/info/insert,对方再解析获取insert就可以了
            return ContentUris.withAppendedId(uri, insert);
        }
        return null;
    }
    /**
     * 参数说明:
     * String table, 表名
     * String whereClause, where删除的条件
     * String[] whereArgs)  替换where条件中的?占位符号
     */
    @Override
    public int delete(Uri uri, String selection, String[] selectionArgs) {
        //得到db对象,查询info表数据,返回给内容分解者
        SQLiteDatabase db = database.getWritableDatabase();
        int count=0;
        switch (matcher.match(uri)) {
        case 1://content://yuming/info 这里代表删除所有数据
            count = db.delete("info", null, null);
            break;
        case 2://content://yuming/info/* 删除指定行
            //得到*匹配的文本
            String segment = uri.getLastPathSegment();
            count=db.delete("info", segment+"=?", selectionArgs);
            break;
        case 3://content://yuming/info/id/#
            long parseId = ContentUris.parseId(uri);
            //根据info表的主键id来删除数据
            count=db.delete("info", "id=?", new String[]{parseId+""});
            break;
        }
        return count;
    }
    /**
     *参数说明:
     *String table,  表名
     *ContentValues values, 传入修改值得contentvalue
     *String whereClause,  where条件
     *String[] whereArgs   替换where条件中的?占位符号
     *如:db.update("person", contentValues, "age = ?", new String[]{"28"});
     *
     *上面的操作都是根据uri来得到具体值来对数据库进行操作的,而没完全用到传进来的参数,
     *所以,这里直接用传进来的参数来对数据库进行操作
     */
    @Override
    public int update(Uri uri, ContentValues values, String selection,
            String[] selectionArgs) {
        if(matcher.match(uri)==1){//content://yuming/info的形式
            SQLiteDatabase db = database.getWritableDatabase();
            int count = db.update("info", values, selection, selectionArgs);
            return count;//返回更新的行数
        }
        return 0;
    }
    @Override
    public String getType(Uri uri) {
        return null;
    }

}

注册文件:

 <provider android:name="com.example.db.MyContentProvider"
            android:authorities="yuming" android:exported="true">
        </provider>

另一程序访问内容提供者数据库:

/*注意:
Uri insertUri = Uri.parse("content://yuming/info" + id);等价于
Uri insertUri = ContentUris.withAppendedId(uri, id);
 */
public class MainActivity extends Activity {

    private TextView tv_show;//显示结果
    private ContentResolver contentResolver;
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        tv_show = (TextView) findViewById(R.id.tv_show);
        //获取内容解析者
        contentResolver = getContentResolver();
    }
    /**
     * 按钮单击事件
     */
    public void btnOnClick(View v){
        switch (v.getId()) {
        case R.id.delete_id://删除指定id
            Uri uri5=Uri.parse("content://yuming/info/id/5");
            contentResolver.delete(uri5, null, null);//因为uri指明了删除id=5的数据
            break;
        case R.id.delete_name://删除指定用户
            Uri uri6=Uri.parse("content://yuming/info/sex");
            contentResolver.delete(uri6, null, new String[]{"女"});//删除性别为女的
            break;
        case R.id.insert://插入数据,可以为空,如果指定主键插入,主键存在就插入失败,返回-1
            Uri uri4=Uri.parse("content://yuming/info");
            ContentValues values=new ContentValues();
            values.put("username", "789");
            values.put("password", "789");
            values.put("id", "4");
            Uri insert = contentResolver.insert(uri4, values);
            long parseId = ContentUris.parseId(insert);
            Toast.makeText(this, "该数据所插入的id为:"+parseId, 0).show();
            break;
        case R.id.query_all://查询所有数据
            Uri uri=Uri.parse("content://yuming/info");
            Cursor cursor = contentResolver.query(uri, null, null, null, null);
            StringBuilder sb=new StringBuilder();
            while(cursor.moveToNext()){
                int id=cursor.getInt(cursor.getColumnIndex("id"));
                String name = cursor.getString(cursor.getColumnIndex("username"));
                String pass = cursor.getString(cursor.getColumnIndex("password"));
                String sex=cursor.getString(cursor.getColumnIndex("sex"));
                String like=cursor.getString(cursor.getColumnIndex("interest"));
                sb.append("id:"+id+",用户名:"+name+",密码:"+pass+",性别:"+sex+",爱好:"+like+"\n");
            }
            tv_show.setText(sb.toString());
            break;
        case R.id.query_id://根据id查
            Uri uri2=Uri.parse("content://yuming/info/id/3");
            Cursor cursor2 = contentResolver.query(uri2, null, null, null, null);
            StringBuilder sb2=new StringBuilder();
            while(cursor2.moveToNext()){
                int id=cursor2.getInt(cursor2.getColumnIndex("id"));
                String name = cursor2.getString(cursor2.getColumnIndex("username"));
                String pass = cursor2.getString(cursor2.getColumnIndex("password"));
                String sex=cursor2.getString(cursor2.getColumnIndex("sex"));
                String like=cursor2.getString(cursor2.getColumnIndex("interest"));
                sb2.append("id:"+id+",用户名:"+name+",密码:"+pass+",性别:"+sex+",爱好:"+like+"\n");
            }
            tv_show.setText(sb2.toString());
            break;
        case R.id.query_name://根据名字查数据
            Uri uri3=Uri.parse("content://yuming/info/username");
            Cursor cursor3 = contentResolver.query(uri3, null, null,new String[]{"123"}, null);
            StringBuilder sb3=new StringBuilder();
            while(cursor3.moveToNext()){
                int id=cursor3.getInt(cursor3.getColumnIndex("id"));
                String name = cursor3.getString(cursor3.getColumnIndex("username"));
                String pass = cursor3.getString(cursor3.getColumnIndex("password"));
                String sex=cursor3.getString(cursor3.getColumnIndex("sex"));
                String like=cursor3.getString(cursor3.getColumnIndex("interest"));
                sb3.append("id:"+id+",用户名:"+name+",密码:"+pass+",性别:"+sex+",爱好:"+like+"\n");
            }
            tv_show.setText(sb3.toString());
            break;
        case R.id.update://更新数据
            Uri uri7=Uri.parse("content://yuming/info");
            ContentValues values7=new ContentValues();
            values7.put("interest", "没有");
            contentResolver.update(uri7, values7, "id=?",new String[]{"2"} );
            break;
        }
    }
    
}

 

posted @ 2016-08-10 20:59  ts-android  阅读(529)  评论(0编辑  收藏  举报