内容提供者基础(含有自己的例子)
步骤:
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; } } }