内容提供者ContentProvider

来源:互联网 发布:怎么注册淘宝小号安全 编辑:程序博客网 时间:2024/06/03 07:15

内容提供者ContentProvider

  • 案例-内容提供者,内容解析者
  • 案例-操作系统短信
  • 案例-操作系统联系人
  • 案例-内容观察者



案例-内容提供者,内容解析者

  • 概念:
    • 将本app的数据库中的数据,提供给为外部应用访问(对外提供一个url地址)
  • 创建一个内容提供者
    • 在清单文件中注册
<provider            android:name="com.example.contentprovicer.ContentProvicer"            android:authorities="com.example.contentprovicer"            android:exported="true" >        </provider>
  • 方法:
  • onCreate():
    • 当应用启动时,被回调,用于初始化数据库访问的工具
    • 返回返回值是boolean,TRUE为初始化完成,FALSE说明有问题
  • 数据库创建

    • 创建一个类去继承SQLIiteOpenHerlper类
  • onCreate():

    • 创建一个数据可子类的对象
    • 初始化数据库内容
    • 获取context对象调用getContext()
  • insert():返回值URI
  • 参数一和参数二正是内容解析者ContentResolver的参数
  • 插入数据
  • 创建一个数据库database调用getWriteableDatabase();

- 拼接行号,调用工具类,ContentUris

Uri withAppendedId = ContentUris.withAppendedId(uri, insert);
  • 匹配不同表名

- 调用UriMatcher类去添加uri地址

    private static final UriMatcher sURIMatcher = new UriMatcher(UriMatcher.NO_MATCH);
  • 创建一个内容解析者工程
  • 在MainActivity中
  • 获取 内容解析者 调用 getContentResolver()
  • 调用内容解析者的CRUD方法
  • 用内容解析者调用 insert(url,values),query(),delete(),update();
    • 参数1:url,用找到内容提供者,获取方法Uri.parse(String 地址值);
    • 参数2:要添加数据

==注意,在内容提供者在查询时,先不要关闭数据库和cursor,因为他要接收解析者穿过来得数据,谁用谁在关闭就行==


这里放insert方法的代码
- 内容提供者

private static final UriMatcher uriMatcher = new UriMatcher(            UriMatcher.NO_MATCH);    private static final int TABLE_MAN = 1;    private static final int TABLE_WMAN = 2;    static {        /*         * addURI(); 参数一:APP主机地址 参数二:表名 参数三:各个拼接好的地址对应的常量值         */        uriMatcher.addURI("com.example.contentprovicer", "t_man", TABLE_MAN);        uriMatcher.addURI("com.example.contentprovicer", "t_wman", TABLE_WMAN);    }    @Override    public boolean onCreate() {        Context context = getContext();        userSQLiteOpenHenpler = new UserSQLiteOpenHenpler(context, DB_NAME,                null, VERSION);        return true;// 返回true代表初始化完成    }    @Override    public Uri insert(Uri uri, ContentValues values) {        Log.d("tag", uri.toString());        // 获取封装地址对应的码数,也就是addURI的第三个参数        String tableName = getTableName(uri);        SQLiteDatabase database = userSQLiteOpenHenpler.getReadableDatabase();        long insert = database.insert(tableName, null, values);        // 字符串拼接把地址和行号拼接起来,然后返回到内容解析者中,返回插入的第几行        Uri withAppendedId = ContentUris.withAppendedId(uri, insert);        database.close();        return withAppendedId;    }    private String getTableName(Uri uri) {        String tableName = "";        int match = uriMatcher.match(uri);        switch (match) {        case TABLE_MAN:            tableName = "t_man";            break;        case TABLE_WMAN:            tableName = "t_wman";            break;        default:            break;        }        return tableName;    }

  • 解析者
public void insertMan(View view) {        ContentResolver contentResolver = getContentResolver();        ContentValues values = new ContentValues();        values.put("t_name", "hhh");        values.put("t_age", 11 + new Random().nextInt(100));        values.put("t_phone", "1234567412");        // insert返回类型是uri        Uri insert = contentResolver.insert(                Uri.parse("content://com.example.contentprovicer/t_man"),                values);        // 调用ContentUris.parseId(insert);,把主机地址的id解析出来        long parseId = ContentUris.parseId(insert);        Toast.makeText(this, "在" + parseId + "插入成功", Toast.LENGTH_SHORT).show();    }


- 案例-操作系统短信

  • 创建UI,
    • 创建一个button获取短信
    • 创建一个listview放短信内容
  • 在MainActivity里初始化UI
  • 观察系统短信数据库,看看怎么写什么数据

    • 获取内容解析者
    • 内容借解析者调用query();
    • 看源码需要什么权限,以及主机名是什么
    • 主机名 sms

    - 添加权限

    <uses-permission android:name="android.permission.READ_SMS"/>
    • 创建一个类包含数据库的内容
    • 把查询内容添加到List<..>

    - 把内容添加到adapter中调用arrayadapter(),给listview设置布局

        ```    public void getsms(View view) {    List<Sms> lSms = new ArrayList<Sms>();    ContentResolver contentResolver = getContentResolver();    Cursor cursor = contentResolver.query(Uri.parse("content://sms"),            new String[] { "address,date,type,body" }, null, null, null);    while (cursor.moveToNext()) {        Sms sms = new Sms();        sms.setAddress(cursor.getString(0));        sms.setDate(cursor.getString(1));        sms.setType(cursor.getInt(2));        sms.setBody(cursor.getString(3));        lSms.add(sms);    }    cursor.close();    smsView.setAdapter(new ArrayAdapter<Sms>(MainActivity.this,            android.R.layout.simple_list_item_1, lSms));    }        ```
    • 插入短信

      • 创建一个UI两个edittext和一个button
      • 初始化UI
      • 插入
      • 拿到解析者,调用insert

        “`
        public void insertSms(View view) {
        String phone = ed_Phone.getText().toString().trim();
        String sms = ed_Sms.getText().toString().trim();

            ContentResolver resolver = getContentResolver();    ContentValues values = new ContentValues();    values.put("address", phone);

        // 设置当前时间
        values.put(“date”,getDataString(new Date().getTime()));
        values.put(“type”, “1”);
        values.put(“body”, sms);
        Uri insert = resolver.insert(Uri.parse(“content://sms”), values);
        Log.d(“tag”, insert.toString());
        long parseId = ContentUris.parseId(insert);
        Toast.makeText(this, “插入成功:”+parseId, Toast.LENGTH_SHORT).show();

        }
      • 解析时间

        private String getDataString(long data) {
        SimpleDateFormat format = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
        return format.format(new Date(data));
        }
  • 获取URI(uri.parse()),values

  • 添加权限

     <uses-permission android:name="android.permission.WRITE_SMS"/>


案例-操作系统联系人

  • 步骤:

    • 查询联系人

      • 创建两个button,和一个listView,用来获取查询的联系人
      • 创建一个工具类,用来放联系人的姓名,电话,以及邮箱,以及地址
      • 查看安卓数据库,看需要什么(一共需要3个表,一个存放id,一个存放信息data.一个用来存放信息类型mimetype)
      • 需要添加权限
      //读取联系人的权限 <uses-permission android:name="android.permission.READ_CONTACTS" /> //添加联系人的权限<uses-permission android:name="android.permission.WRITE_CONTACTS" />
    • 获取内容解析者
      1. 查询raw_contacts表,遍历contact_id,当遍历到cotnact_id = 1;
      1. 查询data表,遍历所有contact_id =
        1的数据。然后根据数据的mimeType确定这个数据是什么字段,然后封装到当前javaBean的字段上
        • 注意:表名必须是data,但是其底层走的是视图
        • (view_data),因此要查询的mimetype_id字段已经映射为mimetype了
        • 注意:同上理,raw_contact_id写成contact_id即可 根据id去查找存储的类型以及信息
    • // 最后把获取id的结果集关闭
    • 把获取的内容部署到listview上
    public void getContact(View view) {        ContentResolver contentResolver = getContentResolver();        Cursor cursor = contentResolver.query(                Uri.parse("contant://com.android.contacts/raw_contacts"),                new String[] { "contant_id" }, "delete=?",                new String[] { "0" }, null);        while (cursor.moveToNext()) {            // 每遍历一次就会创建一个新的对象,因为在安卓系统源码中是分类存放的,id一个,不同的信息一个            Contacts contacts = new Contacts();            int id = cursor.getInt(0);            /**             * 2. 查询data表,遍历所有contact_id =             * 1的数据。然后根据数据的mimeType确定这个数据是什么字段,然后封装到当前javaBean的字段上             * 注意:表名必须是data,但是其底层走的是视图             * (view_data),因此要查询的mimetype_id字段已经映射为mimetype了             * 注意:同上理,raw_contact_id写成contact_id即可 *根据id去查找存储的类型以及信息             */            Cursor dataCursor = contentResolver.query(                    Uri.parse("contant://com.android.contacts/data"),                    new String[] { "mimetype", "data1" }, "id=?",                    new String[] { "" + id }, null);            while (dataCursor.moveToNext()) {                String type = dataCursor.getString(0);                String data1 = dataCursor.getString(1);                 switch (type) {                 case "vnd.android.cursor.item/name":                 contacts.name = data1;                 break;                 case "vnd.android.cursor.item/email_v2":                 contacts.phone = data1;                 break;                 case "vnd.android.cursor.item/postal-address_v2":                 contacts.email = data1;                 break;                 case "vnd.android.cursor.item/phone_v2":                 contacts.address = data1;                 break;                 default:                 break;                 }                dataCursor.close();                list.add(contacts);            }            // 最后把获取id的结果集关闭            cursor.close();            lView.setAdapter(new ArrayAdapter<Contacts>(this,                    android.R.layout.simple_expandable_list_item_1, list));        }    }
  • 添加联系人

    • 步骤:

      • 获取内容解析者,调用getContactResolver()
      • 先在id表中(rew_contact_id)查询最大的id,调用query(),查询的uri是rew_contact_id,查询完要记得关闭结果集cursor
      • 用来确定要插入的id数,用最大id加一,就是要插入的id数
      • 添加要添加数据
        • 创建JavaBean的对象,设置要添加数据
      • 用内容解析者调用insert(),插入的uri是data
        • 插入name
        • 清空values
        • 插入phone
        • 清空values
        • 插入email
        • 清空values
        • 插入address
      • 最后弹吐司,告诉用户添加完成

      “`
      public void insertContacts(View view) {
      Contacts contacts = new Contacts();
      contacts.name = “徐嘉”;
      contacts.address = “江苏南京雨花台区前门大街118号”;
      contacts.email = “888888888@qq.com”;
      contacts.phone = “1383838383838”;
      /**

        1. 先往raw_contacts表中插入contact_id (1). 先读取当前最大的contact_id (2).
      • contact_id+1 得到新的id

      • */
        ContentResolver resolver = getContentResolver();
        int new_contact_id = 1;
        Cursor cursor = resolver.query(Uri.parse(“content://com.android.contacts/raw_contacts”),
        new String[]{“contact_id”}, null, null, “contact_id desc limit 1”);
        if (cursor.moveToNext()) {
        int contact_id = cursor.getInt(0);
        new_contact_id = contact_id+1;
        }
        cursor.close();

      ContentValues values = new ContentValues();
      values.put(“contact_id”, new_contact_id);
      resolver.insert(Uri.parse(“content://com.android.contacts/raw_contacts”), values);

      /*

        1. 往data表中插入name,data是视图表 出入rew_contacts_id 插入mimetype 插入name 内容
          */
          values.clear();
          values.put(“raw_contact_id”, new_contact_id);
          values.put(“data1”, contacts.name);
          values.put(“mimetype”, “vnd.android.cursor.item/name”);
          resolver.insert(Uri.parse(“content://com.android.contacts/data”), values);

      // 插入phone
      values.clear();
      values.put(“raw_contact_id”, new_contact_id);
      values.put(“data1”, contacts.phone);
      values.put(“mimetype”, “vnd.android.cursor.item/phone_v2”);
      resolver.insert(Uri.parse(“content://com.android.contacts/data”), values);

      /**

        1. 插入email
          */
          values.clear();
          values.put(“raw_contact_id”, new_contact_id);
          values.put(“data1”, contacts.email);
          values.put(“mimetype”, “vnd.android.cursor.item/email_v2”);
          resolver.insert(Uri.parse(“content://com.android.contacts/data”), values);
          /**
        1. 插入address
          */
          values.clear();
          values.put(“raw_contact_id”, new_contact_id);
          values.put(“data1”, contacts.address);
          values.put(“mimetype”, “vnd.android.cursor.item/postal-address_v2”);
          resolver.insert(Uri.parse(“content://com.android.contacts/data”), values);

      Toast.makeText(this, “插入完毕”, Toast.LENGTH_SHORT).show();
      }

}
“`



案例-内容观察者

  • 步骤:

    • 在onCreate()方法中注册内容观察者用内容解析者调用registerContentObserver()

      mContentObsever = new MyContentObsever(new Handler());//这个是参数三的监听对象getContentResolver().registerContentObserver(Uri.parse("contact://sms"), true, mContentObsever);
      • 参数一:要观察的主机名
      • 参数二:是否给派生的子uri也发出通知,再接收到短信给观察者发送通知
        -参数三:监听对象,每次发送短信时都会回调监听对象里的onCHange()方法
      • 创建监听对象的一个子类对象
        // 创建内容观察第三个参数,回调方法的一个子类    class MyContentObsever extends ContentObserver {        public MyContentObsever(Handler handler) {            super(handler);        }        @Override        public void onChange(boolean selfChange, Uri uri) {            super.onChange(selfChange,uri);            Log.i("jjjj", uri.toString());            Toast.makeText(MainActivity.this, "观察到了信息的变化"+uri.toString(), Toast.LENGTH_LONG)                    .show();        }    }
    • 在onDestroy()取消观察者用内容解析者调用unregisterContentObserver()

      @Override    protected void onDestroy() {        super.onDestroy();        // 取消内容观察者        if (mContentObsever != null) {            getContentResolver().unregisterContentObserver(mContentObsever);            mContentObsever = null;        }    }
0 0