Android:ContactsContract查询,需要更高级的选择字符串

时间:2011-06-15 17:22:03

标签: java android contacts android-contentprovider

我正在尝试查询ContactContract ContentProvider并获取以下算法将获得的数据:

given a phone number (input), return record...:
if(recordNumber has 7 digits) {
    if('%recordNumber' LIKE 'inputNumber') {
        return recordDisplayName;
    }
} else if(recordNumber has 10 digits) {
    if('recordNumber' LIKE '%inputNumber') {
        return recordDisplayName;
    }
} else if(recordNumber == inputNumber) {
    return recordDisplayName;
}

这适用于查询调用:

ContactsContract.CommonDataKinds.Phone.NUMBER+" LIKE ?"

但我需要更像这样的东西:

"('%" + ContactsContract.CommonDataKinds.Phone.NUMBER+"' LIKE '?' AND LENGTH("+ContactsContract.CommonDataKinds.Phone.NUMBER+")=7) OR ('" + ContactsContract.CommonDataKinds.Phone.NUMBER+"' LIKE '%?' AND LENGTH("+ContactsContract.CommonDataKinds.Phone.NUMBER+")=10)"

但每次我使用带单引号的查询时都会遇到运行时错误。例如,改变:

ContactsContract.CommonDataKinds.Phone.NUMBER+" LIKE ?"

为:

ContactsContract.CommonDataKinds.Phone.NUMBER+" LIKE '?'"

导致运行时错误“绑定或列索引超出范围...”。所以这必须是一些语法错误......对吗?什么是ContentProvider查询的正确语法和/或我如何从ContactsContract获得结果集?

2 个答案:

答案 0 :(得分:8)

对ContentProviders的查询有点不同,并且对格式化无法容忍。对于ContentProviders,如果要使用'%'作为通配符,则'%'必须连接到WHERE子句中的参数,而不是作为子句本身的一部分。

正确的:

Cursor cursor = getContentResolver().query(
    ContactsContract.Data.CONTENT_URI, 
    null, 
    ContactsContract.CommonDataKinds.Phone.NUMBER+" LIKE ?",
    new String[] { "%"+number },
    null);

不正确的:

Cursor cursor = getContentResolver().query(
    ContactsContract.Data.CONTENT_URI, 
    null, 
    ContactsContract.CommonDataKinds.Phone.NUMBER+" LIKE %?", 
    new String[] { number }, 
    null);

上面的“不正确”声明对于SQLite查询实际上是完全合法的,而不是针对ContentProvider查询。

此外,单引号是ContentProvider查询的WHERE子句中的语法错误(或连接到所述子句中的args)。

最终代码:

if(number.length()==7) {
    cursor = getContentResolver().query(ContactsContract.Data.CONTENT_URI, null, 
        ContactsContract.CommonDataKinds.Phone.NUMBER+" LIKE ?",
        //"('%" + ContactsContract.CommonDataKinds.Phone.NUMBER+"' LIKE '?' AND LENGTH("+ContactsContract.CommonDataKinds.Phone.NUMBER+")=7) OR ('" + ContactsContract.CommonDataKinds.Phone.NUMBER+"' LIKE '%?' AND LENGTH("+ContactsContract.CommonDataKinds.Phone.NUMBER+")=10)",
        new String[] { "%"+number },
        null);
} else if(number.length()==10) {
    cursor = getContentResolver().query(ContactsContract.Data.CONTENT_URI, null, 
        "("+ContactsContract.CommonDataKinds.Phone.NUMBER+"=? AND LENGTH("+ContactsContract.CommonDataKinds.Phone.NUMBER+")=7) OR ("+ContactsContract.CommonDataKinds.Phone.NUMBER+"=? AND LENGTH("+ContactsContract.CommonDataKinds.Phone.NUMBER+")=10)",
        new String[] { number.substring(3), number },
        null);
} else {
    cursor = getContentResolver().query(ContactsContract.Data.CONTENT_URI, null, 
        ContactsContract.CommonDataKinds.Phone.NUMBER+"=?",
        new String[] { number },
        null);
}

此代码将检索与相关号码匹配的电话号码的匹配显示名称 - 如果号码是7位数字,我们检索任何电话号码最后7位数的记录(短划线和特殊字符剥离,除了“*”和“#”,因为它们是有效的电话字符)匹配数字的7位数字问题。
- 如果数字是10位数字,则返回任何包含7位数字并与最后7位字符匹配的记录,或者在记录包含10位数字时包含完全匹配的记录。
- 如果有问题的数字既没有7位也没有10位数,则必须进行完全匹配。

答案 1 :(得分:0)

使用ContactsContract.CommonDataKinds.Phone.NORMALIZED_NUMBER代替ContactsContract.CommonDataKinds.Phone.NUMBER