day09

1    为什么需要内容提供者(contentProvider)
    使用内容提供者    把私有的数据库内容给暴露出来

2    内容提供者原理
     [1]内容提供者把数据进行封装然后提供出来    其他应用都是通过内容解析者来访问
     [2]定义内容提供者    定义一个类继承ContentProvider
    
3    实现内容提供者步骤
    [1]定义一个类继承contentProvider
    [2]在清单文件里配置内容提供者
  1. <provider
  2. android:name="com.phone.dbexec.AccountProvider"
  3. android:authorities="com.phone.provider" >
  4. </provider>
    [3]写一个静态代码块
    [4]暴露你想暴露的方法(增删改查)
    [5]如果你发现日志中出现类似Pub com.phone.provider:com.phone.db.AccountProvider     这样日志,说明你的内容提供没有问题.
    [6]其他应用就可以通过内容的解析者去操作数据库
app1:
  1. package com.phone.dbexec;
  2. import android.content.ContentProvider;
  3. import android.content.ContentValues;
  4. import android.content.UriMatcher;
  5. import android.database.Cursor;
  6. import android.database.sqlite.SQLiteDatabase;
  7. import android.net.Uri;
  8. public class AccountProvider extends ContentProvider {
  9. private static int QUERYSUCCESS = 0;
  10. private static int INSERTSUCCESS = 1;
  11. private static int UPDATESUCCESS = 2;
  12. private static int DELETESUCCESS = 3;
  13. private MyOpenHelper myOpenHelper;
  14. //[1]定义一个urimathcher 定义路径匹配器
  15. private static final UriMatcher sURIMatcher = new UriMatcher(UriMatcher.NO_MATCH);
  16. //[2]定义静态代码块 添加匹配规则
  17. static
  18. {
  19. /**
  20. * authority 注意 这个参数和你在清单文件里面定义的要一样
  21. * path content://com.phone.provider/query
  22. */
  23. sURIMatcher.addURI("com.phone.provider", "query", QUERYSUCCESS);
  24. sURIMatcher.addURI("com.phone.provider", "insert", INSERTSUCCESS);
  25. sURIMatcher.addURI("com.phone.provider", "update", UPDATESUCCESS);
  26. sURIMatcher.addURI("com.phone.provider", "delete", DELETESUCCESS);
  27. }
  28. @Override
  29. public boolean onCreate() {
  30. myOpenHelper = new MyOpenHelper(getContext());
  31. return false;
  32. }
  33. /**
  34. * URL http://www.baidu.com
  35. * URI
  36. */
  37. @Override
  38. public Cursor query(Uri uri, String[] projection, String selection,
  39. String[] selectionArgs, String sortOrder) {
  40. int code = sURIMatcher.match(uri);
  41. if(code == QUERYSUCCESS){
  42. //说明路径匹配成功
  43. //把query方法实现 数据库的查询方法
  44. //对数据库进行查询的操作
  45. //想操作数据库必须获得sqlitedatabase对象
  46. SQLiteDatabase db = myOpenHelper.getReadableDatabase();
  47. Cursor cursor = db.query("info", projection, selection, selectionArgs, null, null, sortOrder);
  48. //cursor不能关闭注意
  49. return cursor;
  50. }else{
  51. //路径不匹配
  52. throw new IllegalArgumentException("你的路径不匹配");
  53. }
  54. }
  55. @Override
  56. public String getType(Uri uri) {
  57. return null;
  58. }
  59. @Override
  60. public Uri insert(Uri uri, ContentValues values) {
  61. int code = sURIMatcher.match(uri);
  62. if(code == INSERTSUCCESS){
  63. //操作数据库 说明数据匹配成功
  64. SQLiteDatabase db = myOpenHelper.getWritableDatabase();
  65. //返回值代表新插入行数的ID
  66. long insert = db.insert("info", null, values);
  67. Uri uri2 = Uri.parse("com.phone.insert/"+insert);
  68. return uri2;
  69. }else{
  70. //路径不匹配
  71. throw new IllegalArgumentException("你的路径不匹配");
  72. }
  73. }
  74. @Override
  75. public int delete(Uri uri, String selection, String[] selectionArgs) {
  76. int match = sURIMatcher.match(uri);
  77. if(match == DELETESUCCESS){
  78. //说明路径匹配成功 对数据库进行删除的操作
  79. SQLiteDatabase db = myOpenHelper.getWritableDatabase();
  80. //代表影响的行数
  81. int delete = db.delete("info", selection, selectionArgs);
  82. return delete;
  83. }else{
  84. //路径不匹配
  85. throw new IllegalArgumentException("你的路径不匹配");
  86. }
  87. }
  88. @Override
  89. public int update(Uri uri, ContentValues values, String selection,
  90. String[] selectionArgs) {
  91. int match = sURIMatcher.match(uri);
  92. if(match == UPDATESUCCESS){
  93. SQLiteDatabase db = myOpenHelper.getWritableDatabase();
  94. int update = db.update("info", values, selection, selectionArgs);
  95. return update;
  96. }else{
  97. //路径不匹配
  98. throw new IllegalArgumentException("你的路径不匹配");
  99. }
  100. }
  101. }
  1. package com.phone.dbexec;
  2. import android.support.v7.app.ActionBarActivity;
  3. import android.database.Cursor;
  4. import android.database.sqlite.SQLiteDatabase;
  5. import android.os.Bundle;
  6. import android.view.Menu;
  7. import android.view.MenuItem;
  8. public class MainActivity extends ActionBarActivity {
  9. @Override
  10. protected void onCreate(Bundle savedInstanceState) {
  11. super.onCreate(savedInstanceState);
  12. setContentView(R.layout.activity_main);
  13. MyOpenHelper helper = new MyOpenHelper(getApplicationContext());
  14. SQLiteDatabase db = helper.getReadableDatabase();
  15. Cursor cursor = db.query("info", null, null, null, null, null, null);
  16. if(cursor!=null && cursor.getCount()>0){
  17. while(cursor.moveToNext()){
  18. String name = cursor.getString(1);
  19. String money = cursor.getString(2);
  20. System.out.println("name:"+name+" money:"+money);
  21. }
  22. }
  23. }
  24. }
  1. package com.phone.dbexec;
  2. import android.content.Context;
  3. import android.database.sqlite.SQLiteDatabase;
  4. import android.database.sqlite.SQLiteDatabase.CursorFactory;
  5. import android.database.sqlite.SQLiteOpenHelper;
  6. public class MyOpenHelper extends SQLiteOpenHelper {
  7. public MyOpenHelper(Context context) {
  8. super(context, "Account.db", null, 1);
  9. }
  10. @Override
  11. public void onCreate(SQLiteDatabase db) {
  12. db.execSQL("create table info(_id integer primary key autoincrement,name varchar(20),money varchar(20))");
  13. db.execSQL("insert into info(name,money) values(?,?)",new String[]{"张三","5000"});
  14. db.execSQL("insert into info(name,money) values(?,?)",new String[]{"李四","3000"});
  15. }
  16. @Override
  17. public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) {
  18. }
  19. }
app2:
  1. package com.phone.readother;
  2. import android.support.v7.app.ActionBarActivity;
  3. import android.content.ContentValues;
  4. import android.database.Cursor;
  5. import android.database.sqlite.SQLiteDatabase;
  6. import android.net.Uri;
  7. import android.os.Bundle;
  8. import android.view.Menu;
  9. import android.view.MenuItem;
  10. import android.view.View;
  11. import android.widget.Toast;
  12. public class MainActivity extends ActionBarActivity {
  13. @Override
  14. protected void onCreate(Bundle savedInstanceState) {
  15. super.onCreate(savedInstanceState);
  16. setContentView(R.layout.activity_main);
  17. // 读取66应用的私有的数据库
  18. /**
  19. * path 路径 Account.db factory 游标工厂 flages 访问的模式
  20. */
  21. // 第一种方式
  22. /*
  23. * SQLiteDatabase db = SQLiteDatabase.openDatabase(
  24. * "data/data/com.phone.dbexec/databases/Acount.db", null,
  25. * SQLiteDatabase.OPEN_READWRITE); Cursor cursor = db.query("info",
  26. * null, null, null, null, null, null); if(cursor!=null &&
  27. * cursor.getCount()>0){ while(cursor.moveToNext()){ String name =
  28. * cursor.getString(1); String money = cursor.getString(2);
  29. *
  30. * System.out.println("67应用--name:"+name+" money:"+money); } }
  31. */
  32. // 第二种方式
  33. // 由于66应用里面的私有数据库已经通过内容提供者给暴露出来了,所以直接通过内容的解析者进行访问
  34. // [1]拿到内容的解析者 直接通过上下文获取
  35. // 路径和你在66应用定义的路径一样
  36. Uri uri = Uri.parse("content://com.phone.provider/query");
  37. Cursor cursor = getContentResolver().query(uri, null, null, null, null);
  38. if (cursor != null && cursor.getCount() > 0) {
  39. while (cursor.moveToNext()) {
  40. String name = cursor.getString(1);
  41. String money = cursor.getString(2);
  42. System.out.println("67应用--name:" + name + " money:" + money);
  43. }
  44. }
  45. }
  46. // 对数据库进行增加一条记录
  47. // 由于66应用里面的私有数据库已经通过内容提供者给暴露出来了,所以直接通过内容的解析者进行访问
  48. public void click1(View v) {
  49. Uri uri = Uri.parse("content://com.phone.provider/insert");
  50. ContentValues values = new ContentValues();
  51. values.put("name", "赵6");
  52. values.put("money", 10000);
  53. Uri insert = getContentResolver().insert(uri, values);
  54. System.out.println("insert:" + insert);
  55. }
  56. // 对数据库进行删除一条记录
  57. public void click2(View v) {
  58. Uri uri = Uri.parse("content://com.phone.provider/delete");
  59. int delete = getContentResolver().delete(uri, "name=?", new String[]{"赵6"});
  60. Toast.makeText(getApplicationContext(), "删除了"+delete+"行", 1).show();
  61. }
  62. // 对数据库进行更新一条记录
  63. public void click3(View v) {
  64. Uri uri = Uri.parse("content://com.phone.provider/update");
  65. ContentValues values = new ContentValues();
  66. values.put("money", 10);
  67. int update = getContentResolver().update(uri, values, "name=?", new String[]{"赵6"});
  68. Toast.makeText(getApplicationContext(), "更新了"+update+"行", 1).show();
  69. }
  70. // 对数据库进行查找一条记录
  71. public void click4(View v) {
  72. Uri uri = Uri.parse("content://com.phone.provider/query");
  73. Cursor cursor = getContentResolver().query(uri, null, null, null, null);
  74. if (cursor != null && cursor.getCount() > 0) {
  75. while (cursor.moveToNext()) {
  76. String name = cursor.getString(1);
  77. String money = cursor.getString(2);
  78. System.out.println("67应用--name:" + name + " money:" + money);
  79. }
  80. }
  81. }
  82. }

4    备份短信案例
  1. package com.phone.backupsms;
  2. import java.io.File;
  3. import java.io.FileNotFoundException;
  4. import java.io.FileOutputStream;
  5. import org.xmlpull.v1.XmlSerializer;
  6. import android.support.v7.app.ActionBarActivity;
  7. import android.text.TextUtils;
  8. import android.util.Xml;
  9. import android.database.Cursor;
  10. import android.net.Uri;
  11. import android.os.Bundle;
  12. import android.os.Environment;
  13. import android.view.Menu;
  14. import android.view.MenuItem;
  15. import android.view.View;
  16. import android.widget.Toast;
  17. public class MainActivity extends ActionBarActivity {
  18. @Override
  19. protected void onCreate(Bundle savedInstanceState) {
  20. super.onCreate(savedInstanceState);
  21. setContentView(R.layout.activity_main);
  22. }
  23. // 点击按钮 查询短信数据库内容 然后进行备份
  24. public void click(View v) {
  25. try {
  26. // [1]获取xml序列化实例
  27. XmlSerializer serializer = Xml.newSerializer();
  28. // [2]设置序列化参数
  29. File file = new File(Environment.getExternalStorageDirectory()
  30. .getPath(), "sms-BackUp.xml");
  31. FileOutputStream fos = new FileOutputStream(file);
  32. serializer.setOutput(fos, "utf-8");
  33. // [3]开始写xml文档开头
  34. serializer.startDocument("utf-8", true);
  35. // [4]开始写根节点
  36. serializer.startTag(null, "smss");
  37. // [5]由于短信数据库 系统也通过内容提供者给暴露出来了 所以我们只需要通过内容解析者去操作数据库
  38. Uri uri = Uri.parse("content://sms/");
  39. Cursor cursor = getContentResolver().query(uri,
  40. new String[] { "address", "date", "body" }, null, null,
  41. null);
  42. while (cursor.moveToNext()) {
  43. String address = cursor.getString(0);
  44. String date = cursor.getString(1);
  45. String body = cursor.getString(2);
  46. // [6]写sms节点
  47. serializer.startTag(null, "sms");
  48. // [7]写address节点
  49. serializer.startTag(null, "address");
  50. serializer.text(address);
  51. serializer.endTag(null, "address");
  52. // [8]写date节点
  53. serializer.startTag(null, "date");
  54. serializer.text(date);
  55. serializer.endTag(null, "date");
  56. // [9]写body节点
  57. serializer.startTag(null, "body");
  58. serializer.text(body);
  59. serializer.endTag(null, "body");
  60. serializer.endTag(null, "sms");
  61. }
  62. serializer.endTag(null, "smss");
  63. serializer.endDocument();
  64. } catch (Exception e) {
  65. e.printStackTrace();
  66. }
  67. }
  68. }
  1. <uses-permission android:name="android.permission.WRITE_SMS"/>
  2. <uses-permission android:name="android.permission.READ_SMS"/>
  3. <uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE"/>


5    利用内容解析者插入短信
 
  1. package com.phone.insertsms;
  2. import android.content.ContentValues;
  3. import android.net.Uri;
  4. import android.os.Bundle;
  5. import android.support.v7.app.ActionBarActivity;
  6. import android.view.View;
  7. public class MainActivity extends ActionBarActivity {
  8. @Override
  9. protected void onCreate(Bundle savedInstanceState) {
  10. super.onCreate(savedInstanceState);
  11. setContentView(R.layout.activity_main);
  12. }
  13. //点击按钮 往短信数据库里面插入一条数据
  14. public void click(View v){
  15. Uri uri = Uri.parse("content://sms/");
  16. ContentValues values = new ContentValues();
  17. values.put("address", "955");
  18. values.put("body", "您的余额为0.0000元");
  19. values.put("date", System.currentTimeMillis());
  20. getContentResolver().insert(uri, values);
  21. }
  22. }
  1. <uses-permission android:name="android.permission.READ_SMS"/>
  2. <uses-permission android:name="android.permission.WRITE_SMS"/>

6    读取联系人案例
    三张重要的表
    1    data    data1    里面存的是所有联系人的信息
    2    data表里面的raw_contact_id实际是raw_contact表的contact_id
    3    data表里面的mimetype_id列 实际对应mimetype表

    实现步骤
    [1]先读取raw_contact表    读取contact_id字段    从而就知道手机里一共有几条联系人
    [2]在读取data表    根据raw_contact_id去读取data1列和mimetype列
  1. package com.phone.readcontacts;
  2. import java.util.ArrayList;
  3. import java.util.List;
  4. import android.content.Context;
  5. import android.database.Cursor;
  6. import android.net.Uri;
  7. public class ReadContactUtils {
  8. public static List<Contacts> readContacts(Context context) {
  9. // [0]创建集合对象
  10. List<Contacts> contactsLists = new ArrayList<Contacts>();
  11. // [1]由于联系人的数据库也是通过内容提供者暴露出来了 所以我想操作数据库直接使用内容解析者
  12. // [2]先查询raw_contacts表 contact_id列
  13. Uri uri = Uri.parse("content://com.android.contacts/raw_contacts");
  14. Uri dataUri = Uri.parse("content://com.android.contacts/data");
  15. Cursor cursor = context.getContentResolver().query(uri,
  16. new String[] { "contact_id" }, null, null, null);
  17. while (cursor.moveToNext()) {
  18. String contact_id = cursor.getString(0);
  19. if (contact_id != null) {
  20. // 创建javabean对象
  21. Contacts contacts = new Contacts();
  22. contacts.setId(contact_id);
  23. // [3]根据raw_contact_id 去查询data表 data列和mimetype_id列
  24. // 小细节 查询的不是data表 查询的是view_data的视图
  25. Cursor dataCursor = context.getContentResolver().query(dataUri,
  26. new String[] { "data1", "mimetype" },
  27. "raw_contact_id=?", new String[] { contact_id }, null);
  28. while (dataCursor.moveToNext()) {
  29. String data1 = dataCursor.getString(0);
  30. String mimetype = dataCursor.getString(1);
  31. if ("vnd.android.cursor.item/name".equals(mimetype)) {
  32. System.out.println("姓名:" + data1);
  33. contacts.setName(data1);
  34. } else if ("vnd.android.cursor.item/phone_v2"
  35. .equals(mimetype)) {
  36. System.out.println("电话号码:" + data1);
  37. contacts.setPhone(data1);
  38. } else if ("vnd.android.cursor.item/email_v2"
  39. .equals(mimetype)) {
  40. System.out.println("邮箱:" + data1);
  41. contacts.setEmail(data1);
  42. }
  43. }
  44. // 把javabean对象加入到集合中
  45. contactsLists.add(contacts);
  46. }
  47. }
  48. return null;
  49. }
  50. }
  1. <uses-permission android:name="android.permission.READ_CONTACTS"/>
7    利用内容内容解析者插入一条联系人
[1]先往raw_contact表    往contact_id列插入数据
[2]同步到data表    data1列存的是所有联系人的数据
  1. //[2]获取数据
  2. String name = et_name.getText().toString().trim();
  3. String phone = et_phone.getText().toString().trim();
  4. String email = et_email.getText().toString().trim();
  5. //定义uri
  6. Uri uri = Uri.parse("content://com.android.contacts/raw_contacts");
  7. Uri dataUri = Uri.parse("content://com.android.contacts/data");
  8. //先查询一下raw_contacts表中一共有几条数据    行数+1就是contact_id的值
  9. Cursor cursor = getContentResolver().query(uri, null, null, null, null);
  10. int count = cursor.getCount();
  11. //代表当前联系人的id
  12. int contact_id = count + 1;
  13. //把数据插入到联系人数据库    由于联系人的数据库也是通过内容提供者暴露出来 所以我们直接通过内容解析者去操作数据库
  14. ContentValues valus = new ContentValues();
  15. values.put("contact_id", contact_id);
  16. getContentResolver().insert(uri, values);

  17. //把name 插入到data表
  18. ContentValues nameValues = new ContentValues();
  19. //把数据插入到data1列
  20. nameValues .put("data1", name);
  21. //告诉数据库我们插入的数据是属于哪条联系人
  22. nameValues .put("raw_contact_id", contact_id);
  23. //告诉数据库插入的数据的数据类型
  24. nameValues .put("mimetype", "vnd.android.cursor.item/name");
  25. getContentResolver().insert(dataUri, nameValues );

  26. //把phone 插入到data表
  27. ContentValues phoneValues = new ContentValues();
  28. //把数据插入到data1列
  29. phoneValues.put("data1", phone);
  30. //告诉数据库我们插入的数据是属于哪条联系人
  31. phoneValues.put("raw_contact_id", contact_id);
  32. //告诉数据库插入的数据的数据类型
  33. phoneValues.put("mimetype", "vnd.android.cursor.item/phone_v2");
  34. getContentResolver().insert(dataUri, phoneValues);

  35. //把email插入到data表
  36. ContentValues emailValues = new ContentValues();
  37. //把数据插入到data1列
  38. emailValues .put("data1", email);
  39. //告诉数据库我们插入的数据是属于哪条联系人
  40. emailValues .put("raw_contact_id", contact_id);
  41. //告诉数据库插入的数据的数据类型
  42. emailValues .put("mimetype", "vnd.android.cursor.item/email_v2");
  43. getContentResolver().insert(dataUri, emailValues );


8    内容观察者
    内容提供者    需要在清单文件配置
 
  1. package com.phone.registercontentobsever;
  2. import android.app.Activity;
  3. import android.database.ContentObserver;
  4. import android.net.Uri;
  5. import android.os.Bundle;
  6. import android.os.Handler;
  7. public class MainActivity extends Activity {
  8. @Override
  9. protected void onCreate(Bundle savedInstanceState) {
  10. super.onCreate(savedInstanceState);
  11. setContentView(R.layout.activity_main);
  12. //[1]注册内容观察者
  13. Uri uri = Uri.parse("content://com.phone.provider");
  14. getContentResolver().registerContentObserver(uri, true, new MyContentObserver(new Handler()));
  15. }
  16. //[2]定义一个内容观察者
  17. private class MyContentObserver extends ContentObserver{
  18. public MyContentObserver(Handler handler) {
  19. super(handler);
  20. }
  21. //当内容发送改变的时候调用
  22. @Override
  23. public void onChange(boolean selfChange) {
  24. System.out.println("ahahha数据库的内容发生了改变");
  25. super.onChange(selfChange);
  26. }
  27. }
  28. }
9    内容观察者的应用场景



    


来自为知笔记(Wiz)


posted on 2016-12-24 21:08  果然朝辉  阅读(165)  评论(0编辑  收藏  举报

导航