android 学习笔记12-内容提供者
2017-01-16 22:26
483 查看
1、内容提供者
2、内容提供者-优化
3、应用-读取系统短信
4、插入系统短信
5、获取联系人
6、插入联系人
实际的开发中,一般也比较少开发自定义的内容提供者,一般都是使用 应用的数据库是不允许其他应用访问的 内容提供者的作用就是让别的应用访问到你的私有数据,就是一个java类 自定义内容提供者,继承ContentProvider类,重写增删改查方法,在方法中写增删改查数据库的代码,举例增方法 使用内容提供者可以自己定义访问规则,选择私有数据中哪些共享出去,哪些不共享 注意(特别重要):我们一定要认真配置清单文件xml <provider android:name="com.example.contentprovider.PersonProvider"//包名.类名 android:authorities="com.example.person"//可以理解为权限 android:exported="true"> </provider> 代码演示: a,内容提供者的xml文件配置 <provider android:name="com.example.contentprovider.PersonProvider"//包名.类名 android:authorities="com.example.person"//可以理解为权限 android:exported="true"> </provider> b,内容提供者定义: public class PersonProvider extends ContentProvider {//继承ContentProvider,重写里面的方法 private SQLiteDatabase db; //内容提供者创建时调用 @Override public boolean onCreate() { MyOpenHelper oh = new MyOpenHelper(getContext()); db = oh.getWritableDatabase(); return false; } //values:其他应用要插的数据 @Override public Uri insert(Uri uri, ContentValues values) {//插入 db.insert("person", null, values);//这里的values是调用者传进来的数据,因为我们内容提供者自己肯定不会去插数据的 return uri; } @Override public int delete(Uri uri, String selection, String[] selectionArgs) {//删除 int i = 0; i = db.delete("person", selection, selectionArgs); return i; } @Override public int update(Uri uri, ContentValues values, String selection, String[] selectionArgs) {//修改 int i = db.update("person", values, selection, selectionArgs); return i; } @Override public Cursor query(Uri uri, String[] projection, String selection, String[] selectionArgs, String sortOrder) {//查询 Cursor cursor = null; cursor = db.query("person", projection, selection, selectionArgs, null, null, sortOrder, null); return cursor; } } c,我们访问者定义 public class MainActivity extends Activity { @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); } public void insert(View v){ //通过内容提供者把数据插入01数据库 //1.获取contentResolver ContentResolver resolver = getContentResolver(); //2.访问内容提供者,插入数据 ContentValues values = new ContentValues(); values.put("name", "张三"); values.put("phone", 123456); values.put("money", 10000); //arg0:指定内容提供者的主机名 resolver.insert(Uri.parse("content://com.example.people"), values); values.clear(); values.put("name", "李四"); values.put("phone", 12345); //arg0:指定内容提供者的主机名 resolver.insert(Uri.parse("content://com.example.people"), values); } public void delete(View v){ ContentResolver resolver = getContentResolver(); int i = resolver.delete(Uri.parse("content://com.example.people"), "name = ?", new String[]{"张三"}); System.out.println(i); } public void update(View v){ ContentResolver resolver = getContentResolver(); ContentValues values = new ContentValues(); values.put("money", 10001); int i = resolver.update(Uri.parse("content://com.example.people"), values, "name = ?", new String[]{"张三"}); System.out.println(i);//更新的记录数 } public void query(View v){ ContentResolver resolver = getContentResolver(); Cursor cursor = resolver.query(Uri.parse("content://com.example.people"), null, null, null, null); while(cursor.moveToNext()){ String name = cursor.getString(1); String phone = cursor.getString(2); String money = cursor.getString(3); System.out.println(name + ";" + phone + ";" + money); } } } 这样大体的定义和访问就可以实现了,但是还有一些问题
2、内容提供者-优化
我们发现上面的内容提供者里面的表名都是写死的 db.insert("person", null, values); 如果我们现在有个handsome表,想操作它就不行了 我们要操作那张表就把表名放到uri里面传过去就行了 resolver.insert(Uri.parse("content://com.example.people/person"), values); 那在提供者就去判断下是哪张表,我们可以使用一个API UriMatcher 在内容提供者里面添加: //创建uri匹配器 UriMatcher um = new UriMatcher(UriMatcher.NO_MATCH);//UriMatcher.NO_MATCH -1 , 如果都不匹配的话就返回-1 { //添加匹配规则 //arg0:主机名 //arg1:路径 //arg2:匹配码,这个是自己定义的,如果匹配成功了,就返回这个匹配码 um.addURI("com.example.people", "person", 1);//content://com.example.people/person um.addURI("com.example.people", "handsome", 2);//content://com.example.people/handsome um.addURI("com.example.people", "person/#", 3);//content://com.example.people/person/10 } uri里面还可以携带数字,一般用于查询的条件 取出数字的API:int id = (int) ContentUris.parseId(uri); mimetype的数据是自己定义的,方便其它同事辨认是那个数据,比如说是person数据 优化后的代码: public class PersonProvider extends ContentProvider { private SQLiteDatabase db; //创建uri匹配器 UriMatcher um = new UriMatcher(UriMatcher.NO_MATCH); { //添加匹配规则 //arg0:主机名 //arg1:路径 //arg2:匹配码 um.addURI("com.example.people", "person", 1);//content://com.example.people/person um.addURI("com.example.people", "handsome", 2);//content://com.example.people/handsome //*代表所有的字符,#号代表所有的数字 um.addURI("com.example.people", "person/#", 3);//content://com.example.people/person/10 } //内容提供者创建时调用 @Override public boolean onCreate() { MyOpenHelper oh = new MyOpenHelper(getContext()); db = oh.getWritableDatabase(); return false; } //values:其他应用要插的数据 //注意这里修改了,里面不再写死表的名称,可以判断到底使用的是哪个表 @Override public Uri insert(Uri uri, ContentValues values) { if(um.match(uri) == 1){ db.insert("person", null, values); //数据库改变了,内容提供者发出通知 //arg0:通知发到哪个uri上,注册在这个uri上的内容观察者都可以收到通知 getContext().getContentResolver().notifyChange(uri, null); } else if(um.match(uri) == 2){ db.insert("handsome", null, values); getContext().getContentResolver().notifyChange(uri, null); } else{ throw new IllegalArgumentException("uri传错"); } return uri; } //上面修改了,下面的和上面的类似修改就好了 @Override public int delete(Uri uri, String selection, String[] selectionArgs) { int i = 0; if(um.match(uri) == 1){ i = db.delete("person", selection, selectionArgs); } else if(um.match(uri) == 2){ i = db.delete("handsome", selection, selectionArgs); } else{ throw new IllegalArgumentException("uri又传错"); } return i; } @Override public int update(Uri uri, ContentValues values, String selection, String[] selectionArgs) { int i = db.update("person", values, selection, selectionArgs); return i; } @Override public Cursor query(Uri uri, String[] projection, String selection, String[] selectionArgs, String sortOrder) { Cursor cursor = null; if(um.match(uri) == 1){ cursor = db.query("person", projection, selection, selectionArgs, null, null, sortOrder, null); } else if(um.match(uri) == 2){ cursor = db.query("handsome", projection, selection, selectionArgs, null, null, sortOrder, null); } else if(um.match(uri) == 3){ //取出uri末尾携带的数字 long id = ContentUris.parseId(uri); //查询一条数据,使用主键查询 cursor = db.query("person", projection, "_id = ?", new String[]{"" + id}, null, null, sortOrder, null); } return cursor; } //返回通过指定uri获取的数据的mimetype, @Override public String getType(Uri uri) { if(um.match(uri) == 1){ return "vnd.android.cursor.dir/person";//也可以定义ab/c,但是为了规范还是规范定义好了 } else if(um.match(uri) == 2){ return "vnd.android.cursor.dir/handsome"; } else if(um.match(uri) == 3){ return "vnd.android.cursor.item/person"; } return null; } } 温馨提示:使用内容提供者的好处,为什么不直接把数据库公开呢。我们主要考虑数据的安全性,如果公开了,那么数据可以被任意访问,我们定义了内容提供者 就可以控制访问的规则,需要共享哪个表,或者哪个字段都可以的。
3、应用-读取系统短信
代码演示: public class MainActivity extends Activity { @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); } public void click1(View v){//点击按钮进行查询 ContentResolver resolver = getContentResolver();//获取一个ContentResolver //定义我们需要查询的字段,不是所有的字段我们都要 Cursor cursor = resolver.query(Uri.parse("content://sms"), new String[]{"address", "date", "type", "body"}, null, null, null); while(cursor.moveToNext()){//获取每条短信记录,这里我们用 0,1,2,3 代替,其实也可以用名称查出索引值的 String address = cursor.getString(0); long date = cursor.getLong(1); int type = cursor.getInt(2); String body = cursor.getString(3); System.out.println(address + ";" + date + ";" + type + ";" + body); } } } 这样不行,因为还需要权限,非常重要的 <uses-permission android:name="android.permission.READ_SMS"/>
4、插入系统短信
代码演示: public class MainActivity extends Activity { @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); } public void click(View v){ Thread t = new Thread(){ @Override public void run() { try { sleep(10000);//等一会10s界面就会显示来的短信 } catch (InterruptedException e) { e.printStackTrace(); } ContentResolver resolver = getContentResolver(); ContentValues values = new ContentValues(); values.put("address", 95555); values.put("date", System.currentTimeMillis()); values.put("type", 1); values.put("body", "您尾号为XXXX的招行储蓄卡收到转账1,000,000"); resolver.insert(Uri.parse("content://sms"), values); } }; t.start(); } }
5、获取联系人
代码演示: MainActivity.java public class MainActivity extends Activity { @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); } public void click(View v){ ContentResolver resolver = getContentResolver(); Cursor cursor = resolver.query(Uri.parse("content://com.android.contacts/raw_contacts"), new String[]{"contact_id"}, null, null, null); while(cursor.moveToNext()){ String contactId = cursor.getString(0); //使用联系人id作为where条件去查询data表,查询出属于该联系人的信息 Cursor cursorData = resolver.query(Uri.parse("content://com.android.contacts/data"), new String[]{"data1", "mimetype"}, "raw_contact_id = ?", new String[]{contactId}, null); Contact contact = new Contact(); while(cursorData.moveToNext()){ String data1 = cursorData.getString(0); String mimetype = cursorData.getString(1); if("vnd.android.cursor.item/email_v2".equals(mimetype)){ contact.setEmail(data1); } else if("vnd.android.cursor.item/phone_v2".equals(mimetype)){ contact.setPhone(data1); } else if("vnd.android.cursor.item/name".equals(mimetype)){ contact.setName(data1); } } System.out.println(contact.toString()); } } } Contact.java public class Contact { private String name; private String phone; private String email; public String getName() { return name; } public void setName(String name) { this.name = name; } public String getPhone() { return phone; } public void setPhone(String phone) { this.phone = phone; } public String getEmail() { return email; } public void setEmail(String email) { this.email = email; } @Override public String toString() { return "Contact [name=" + name + ", phone=" + phone + ", email=" + email + "]"; } }
6、插入联系人
先查询raw\_contacts表,确定新的联系人的id应该是多少 把确定的联系人id插入raw\_contacts表 cv.put("contact_id", _id); cr.insert(Uri.parse("content://com.android.contacts/raw_contacts"), cv); 在data表插入数据 插3个字段:data1、mimetype、raw\_contact_id cv = new ContentValues(); cv.put("data1", "张三"); cv.put("mimetype", "vnd.android.cursor.item/name"); cv.put("raw_contact_id", _id); cr.insert(Uri.parse("content://com.android.contacts/data"), cv); cv = new ContentValues(); cv.put("data1", "123456"); cv.put("mimetype", "vnd.android.cursor.item/phone_v2"); cv.put("raw_contact_id", _id); cr.insert(Uri.parse("content://com.android.contacts/data"), cv);
相关文章推荐
- Android Fragment 真正的完全解析(下)
- android view的测量模式
- android.os.SystemClock类
- android侧滑删除列表
- 10.Android11种传感器介绍
- (转)Android Handler 主线程 子线程 双向通信
- android树形列表实现
- android 拍照与相册使用总结
- android带勾选项的列表
- (转)Android Context 上下文 你必须知道的一切
- 在Android Studio下使用Hierarchy Viewer
- Android内存泄漏的本质原因、解决办法、操作实例
- 2.Android三级缓存概念
- android笔记20170116
- 全球首个Apicloud 视频压缩模块正式上线
- gradle多版本打包设计
- android项目一般所需上传内容
- Android中通过ADB手动发送广播
- 1、Android基础笔试题
- 兔子-android studio中安装butterknife插件