Как отфильтровать результаты поиска контента в андроиде?
Я хотел бы получить пользовательские контакты, а затем добавить какое-то регулярное выражение и добавить их в список. В настоящее время я могу получить все контакты через
getContentResolver().query(People.CONTENT_URI, null, null, null, null);
а затем передать их в пользовательский класс, который расширяет SimpleCursorAdapter
.
Итак, я хотел бы знать, как получить только контакты, которые соответствуют регулярному выражению, а не всем контактам пользователей.
Ответы
Ответ 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);
Обратите внимание, что вместо null у меня есть параметры, которые создают инструкцию sql.
RequestColumns - это данные, которые я хочу вернуть, и Contacts.Phones.NUMBER + "= '" + phoneNumber + "" - это предложение Where, поэтому я получаю имя и тип, где номер телефона соответствует
Ответ 3
В качестве третьего аргумента метода query(), в том числе LIKE, вы должны иметь правовое предложение SQLite WHERE, но нет никакой собственной функции REGEXP в SQLite и Android, похоже, не позволяет вам определять свои собственные. Таким образом, в зависимости от того, насколько сложны ваши потребности, множество других условий SQLite и выражения LIKE могут сделать трюк.
См. документацию по методу в разделе ContentResolver и SQLite выражения.
Ответ 4
Фактически 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"
);