内容提供者ContentProvider

内容提供者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
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值