【问题标题】:How to filter the results of content resolver in android?如何过滤android中内容解析器的结果?
【发布时间】:2017-03-22 18:35:18
【问题描述】:

我想获取用户联系人,然后附加某种正则表达式并将它们附加到列表视图中。我目前可以通过

获取所有联系人

getContentResolver().query(People.CONTENT_URI, null, null, null, null);

然后将它们传递给扩展 SimpleCursorAdapter 的自定义类。

所以我想知道如何只获取与正则表达式匹配的联系人,而不是所有用户联系人。

【问题讨论】:

    标签: android


    【解决方案1】:

    代替

    getContentResolver().query(People.CONTENT_URI, null, null, null, null); 
    

    你应该使用类似的东西

    final ContentResolver resolver = getContentResolver();
    final String[] projection = { People._ID, People.NAME, People.NUMBER };
    final String sa1 = "%A%"; // contains an "A"
    cursor = resolver.query(People.CONTENT_URI, projection, People.NAME + " LIKE ?",
       new String[] { sa1 }, null);
    

    这使用参数化请求(使用 ?)并将实际值作为不同的参数提供,这样可以避免串联并主要在您请求过滤器时防止 SQL 注入来自用户。例如,如果您正在使用

    cursor = resolver.query(People.CONTENT_URI, projection,
       People.NAME + " = '" + name + "'",
       new String[] { sa1 }, null);
    

    想象一下

    name =  "Donald Duck' OR name = 'Mickey Mouse") // notice the " and '
    

    你正在连接字符串。

    【讨论】:

      【解决方案2】:

      您可以使用 sql 类型输入查询内容提供程序,Query 方法只是 sql 命令的包装器。

      这是一个示例,我在给定特定号码的情况下查询联系人姓名

      String [] requestedColumns = {
                   Contacts.Phones.NAME,
                   Contacts.Phones.TYPE
           };
      
      Cursor contacts = context.getContentResolver().query(
                   Contacts.Phones.CONTENT_URI,
                   requestedColumns,
                   Contacts.Phones.NUMBER + "='" + phoneNumber + "'",
                   null, null);
      

      请注意,我有构建 sql 语句的参数,而不是 null。

      requestColumns 是我要取回的数据,Contacts.Phones.NUMBER + "='" + phoneNumber + "'" 是 Where 子句,所以我检索电话号码匹配的名称和类型

      【讨论】:

      • 如果 Contacts.Phones.NUMBER 里面有空格但是 phoneNumber 没有呢?
      • 我在 Contacts.Phones.NUMBER 中有空格,但在@Davide 提到的 phoneNumber 中没有空格。我不能为此使用 SelectionClause。我必须在 do while 循环中进行过滤,这是一个巨大的性能损失。
      • @AMITAVA 我以这种方式解决了:"replace(" + ContactsContract.CommonDataKinds.Phone.NUMBER + ", ' ', '')" + " = '" + phoneNumber + "'" Contacts.Phones.NUMBER + "='" + phoneNumber + "'",使用sqlite提供的替换功能即可
      • 嗨@Davide 非常感谢,一个问题,它是修改原始源ContactsContract 数据还是仅修改从中生成的表(或不修改任何内容,仅在选择子句中)。由于我不想更改源数据,因此我无法检查它。
      • 它做了一个简单的选择。从该表中,它将用空字符替换所有空格,然后与电话号码进行比较。原始持久数据不受影响。在您的情况下,将 ContactsContract.CommonDataKinds.Phone.NUMBER 列与您的列(可能是 Contacts.Phones.NUMBER)
      【解决方案3】:

      您应该能够将合法的 SQLite WHERE 子句作为第三个参数作为 query() 方法的第三个参数,包括 LIKE,但是 SQLite 中没有原生的 REGEXP 函数,Android 似乎不允许您定义自己的函数。因此,根据您的需求有多复杂,一组其他 SQLite 条件和 LIKE 表达式可能会解决问题。

      请参阅 ContentResolver 和 SQLite expressionsquery method 上的文档。

      【讨论】:

        【解决方案4】:

        实际上,带有 Calllog Content Provider 的 REGEXP 可以工作(意味着 regexp() 函数是为该内容提供者的数据库 https://sqlite.org/lang_expr.html#regexp 定义的)!但它非常慢:约 15 秒,约 1750 条记录。

        String regexp = "([\\s\\S]{0,}" + 
        TextUtils.join("||[\\s\\S]{0,}", numbers) + 
        ")";
        
        cursor = context.getContentResolver().query(
        CallLog.Calls.CONTENT_URI, 
        null, 
        CallLog.Calls.NUMBER + " REGEXP ?", 
        new String[]{regexp}, 
        CallLog.Calls.DATE + " DESC"
        );
        

        【讨论】:

          猜你喜欢
          • 1970-01-01
          • 2017-02-10
          • 1970-01-01
          • 2019-01-28
          • 2010-12-24
          • 1970-01-01
          • 2023-04-09
          • 1970-01-01
          • 1970-01-01
          相关资源
          最近更新 更多