智能搜索 android 中的联系人
Smart searching contacts in android
在 android 开发者站点中 This Retrieving a List of Contacts Tutorial 之后,我成功实现了联系人搜索功能。到目前为止,这是我的代码
private void retrieveContactRecord(String phoneNo) {
try {
Log.e("Info", "Input: " + phoneNo);
Uri uri = Uri.withAppendedPath(ContactsContract.PhoneLookup.CONTENT_FILTER_URI,
Uri.encode(phoneNo));
String[] projection = new String[]{ContactsContract.PhoneLookup._ID, ContactsContract.PhoneLookup.DISPLAY_NAME};
String sortOrder = ContactsContract.PhoneLookup.DISPLAY_NAME + " COLLATE LOCALIZED ASC";
ContentResolver cr = getContentResolver();
if (cr != null) {
Cursor resultCur = cr.query(uri, projection, null, null, sortOrder);
if (resultCur != null) {
while (resultCur.moveToNext()) {
String contactId = resultCur.getString(resultCur.getColumnIndex(ContactsContract.PhoneLookup._ID));
String contactName = resultCur.getString(resultCur.getColumnIndexOrThrow(ContactsContract.PhoneLookup.DISPLAY_NAME));
Log.e("Info", "Contact Id : " + contactId);
Log.e("Info", "Contact Display Name : " + contactName);
break;
}
resultCur.close();
}
}
} catch (Exception sfg) {
Log.e("Error", "Error in loadContactRecord : " + sfg.toString());
}
}
关键是,这段代码工作得很好,但我需要在这里实现智能搜索。 我想要 26268 来匹配 Amanu 以及 094 526 2684。 我相信它叫做 T9 字典。
我尝试查看其他项目以寻找线索,但我找不到任何东西。任何指针将不胜感激!
将所有联系人转储到 HashSet
Set<String> contacts = new HashSet<String>();
然后搜索:
List<List<String>> results = new ArrayList<List<String>>();
// start the search, pass empty stack to represent words found so far
search(input, dictionary, new Stack<String>(), results);
搜索方法(from @WhiteFang34)
public static void search(String input, Set<String> contacts,
Stack<String> words, List<List<String>> results) {
for (int i = 0; i < input.length(); i++) {
// take the first i characters of the input and see if it is a word
String substring = input.substring(0, i + 1);
if (contacts.contains(substring)) {
// the beginning of the input matches a word, store on stack
words.push(substring);
if (i == input.length() - 1) {
// there's no input left, copy the words stack to results
results.add(new ArrayList<String>(words));
} else {
// there's more input left, search the remaining part
search(input.substring(i + 1), contacts, words, results);
}
// pop the matched word back off so we can move onto the next i
words.pop();
}
}
}
T9 搜索可以使用 trie data structure. You can see an example here - Trie dict 实现。
在实现类似的东西后,您将能够将搜索输入转换为其可能的 T9 解码变体,并比较它是否与名称匹配。
联系人的 ContentProvider
不支持。所以我所做的是将所有联系人转储到 List
中,然后使用 RegEx
来匹配姓名。
public static String[] values = new String[]{" 0", "1", "ABC2", "DEF3", "GHI4", "JKL5", "MNO6", "PQRS7", "TUV8", "WXYZ9"};
/**
* Get the possible pattern
* You'll get something like ["2ABC","4GHI"] for input "14"
*/
public static List<String> possibleValues(String in) {
if (in.length() >= 1) {
List<String> p = possibleValues(in.substring(1));
String s = "" + in.charAt(0);
if (s.matches("[0-9]")) {
int n = Integer.parseInt(s);
p.add(0, values[n]);
} else {
// It is a character, use it as it is
p.add(s);
}
return p;
}
return new ArrayList<>();
}
... 然后编译模式。我使用 (?i)
使其不区分大小写
List<String> values = Utils.possibleValues(query);
StringBuilder sb = new StringBuilder();
for (String value : values) {
sb.append("[");
sb.append(value);
sb.append("]");
if (values.get(values.size() - 1) != value) {
sb.append("\s*");
}
}
Log.e("Utils", "Pattern = " + sb.toString());
Pattern queryPattern = Pattern.compile("(?i)(" + sb.toString() + ")");
之后你就会知道该怎么做了。
在 android 开发者站点中 This Retrieving a List of Contacts Tutorial 之后,我成功实现了联系人搜索功能。到目前为止,这是我的代码
private void retrieveContactRecord(String phoneNo) {
try {
Log.e("Info", "Input: " + phoneNo);
Uri uri = Uri.withAppendedPath(ContactsContract.PhoneLookup.CONTENT_FILTER_URI,
Uri.encode(phoneNo));
String[] projection = new String[]{ContactsContract.PhoneLookup._ID, ContactsContract.PhoneLookup.DISPLAY_NAME};
String sortOrder = ContactsContract.PhoneLookup.DISPLAY_NAME + " COLLATE LOCALIZED ASC";
ContentResolver cr = getContentResolver();
if (cr != null) {
Cursor resultCur = cr.query(uri, projection, null, null, sortOrder);
if (resultCur != null) {
while (resultCur.moveToNext()) {
String contactId = resultCur.getString(resultCur.getColumnIndex(ContactsContract.PhoneLookup._ID));
String contactName = resultCur.getString(resultCur.getColumnIndexOrThrow(ContactsContract.PhoneLookup.DISPLAY_NAME));
Log.e("Info", "Contact Id : " + contactId);
Log.e("Info", "Contact Display Name : " + contactName);
break;
}
resultCur.close();
}
}
} catch (Exception sfg) {
Log.e("Error", "Error in loadContactRecord : " + sfg.toString());
}
}
关键是,这段代码工作得很好,但我需要在这里实现智能搜索。 我想要 26268 来匹配 Amanu 以及 094 526 2684。 我相信它叫做 T9 字典。
我尝试查看其他项目以寻找线索,但我找不到任何东西。任何指针将不胜感激!
将所有联系人转储到 HashSet
Set<String> contacts = new HashSet<String>();
然后搜索:
List<List<String>> results = new ArrayList<List<String>>();
// start the search, pass empty stack to represent words found so far
search(input, dictionary, new Stack<String>(), results);
搜索方法(from @WhiteFang34)
public static void search(String input, Set<String> contacts,
Stack<String> words, List<List<String>> results) {
for (int i = 0; i < input.length(); i++) {
// take the first i characters of the input and see if it is a word
String substring = input.substring(0, i + 1);
if (contacts.contains(substring)) {
// the beginning of the input matches a word, store on stack
words.push(substring);
if (i == input.length() - 1) {
// there's no input left, copy the words stack to results
results.add(new ArrayList<String>(words));
} else {
// there's more input left, search the remaining part
search(input.substring(i + 1), contacts, words, results);
}
// pop the matched word back off so we can move onto the next i
words.pop();
}
}
}
T9 搜索可以使用 trie data structure. You can see an example here - Trie dict 实现。 在实现类似的东西后,您将能够将搜索输入转换为其可能的 T9 解码变体,并比较它是否与名称匹配。
联系人的 ContentProvider
不支持。所以我所做的是将所有联系人转储到 List
中,然后使用 RegEx
来匹配姓名。
public static String[] values = new String[]{" 0", "1", "ABC2", "DEF3", "GHI4", "JKL5", "MNO6", "PQRS7", "TUV8", "WXYZ9"};
/**
* Get the possible pattern
* You'll get something like ["2ABC","4GHI"] for input "14"
*/
public static List<String> possibleValues(String in) {
if (in.length() >= 1) {
List<String> p = possibleValues(in.substring(1));
String s = "" + in.charAt(0);
if (s.matches("[0-9]")) {
int n = Integer.parseInt(s);
p.add(0, values[n]);
} else {
// It is a character, use it as it is
p.add(s);
}
return p;
}
return new ArrayList<>();
}
... 然后编译模式。我使用 (?i)
使其不区分大小写
List<String> values = Utils.possibleValues(query);
StringBuilder sb = new StringBuilder();
for (String value : values) {
sb.append("[");
sb.append(value);
sb.append("]");
if (values.get(values.size() - 1) != value) {
sb.append("\s*");
}
}
Log.e("Utils", "Pattern = " + sb.toString());
Pattern queryPattern = Pattern.compile("(?i)(" + sb.toString() + ")");
之后你就会知道该怎么做了。