再談Contacts中姓氏多音字排序錯誤問題,contacts多音字
說到中國人的名字,那就不得不考慮多音字的問題,比如'單',在作為姓氏時應該讀作'shan'而不是'dan'.但是在Contacts程式中卻使用的是'D'來作為bucket label!
這是為什嗎?如何解決這種多音字姓氏的問題?
從4.3版本開始,HanziToPinyin.java(ContactsProvider中)改為直接調用ICU的Transliterator來對漢字進行transliterate(詳見類中mPinyinTransliterator變數的使用).我們知道,ICU中的Han_Latin_Names.txt中儲存了一些漢字在作為姓氏時的讀音,如果在建立Transliterator對象時使用Han-Latin/Names作為id(可參考mPinyinTransliterator變數的初始化),將可以正確的獲得漢字作為姓氏時的讀音(僅限於Han_Latin_Names.txt中包含的漢字).也就是說,HanziToPinyin這個類在處理作為姓氏的多音字時是可以獲得正確獲得其讀音的.如在使用HanziToPinyin擷取'單田芳'的讀音為'shan tian fang'.就算這樣姓名為'單田芳'的連絡人依然被排在'D'下面!這是為什麼呢?
通過解析代碼可以發現,連絡人排在哪個字母下面是由raw_contacts表中的phonebook_label的值來決定的,而資料庫中phonebook_label的值確實是'D',主要是因為在獲得phonebook_label時使用的是AlphabeticIndex$ImmutableIndex的getBucketLabel函數,而這個函數是沒有對姓氏多音字做任何特殊處理的,所以最後得到的是'D'(phonebook_label的處理流程見附一).
目前,如果想比較省力的解決這個問題,可以在擷取phonebook_label時避免通過使用AlphabeticIndex$ImmutableIndex的getBucketLabel函數來擷取,而是改為用HanziToPinyin去獲得sortKeyPrimary的第一個字元的拼音(sortKeyAlternative暫不考慮).
貼一下代碼修改(基於4.4.4_r2)
-----------------------------------------------------------------------------
--- a/src/com/android/providers/contacts/ContactsDatabaseHelper.java
+++ b/src/com/android/providers/contacts/ContactsDatabaseHelper.java
@@ -78,6 +78,7 @@ import android.text.util.Rfc822Tokenizer;
import android.util.Log;
import com.android.common.content.SyncStateContentProviderHelper;
+import com.android.providers.contacts.HanziToPinyin.Token;
import com.android.providers.contacts.aggregation.util.CommonNicknameCache;
import com.android.providers.contacts.database.ContactsTableUtil;
import com.android.providers.contacts.database.DeletedContactsTableUtil;
@@ -85,6 +86,7 @@ import com.android.providers.contacts.database.MoreDatabaseUtils;
import com.android.providers.contacts.util.NeededForTesting;
import com.google.android.collect.Sets;
+import java.util.ArrayList;
import java.util.HashMap;
import java.util.Locale;
import java.util.Set;
@@ -5388,8 +5390,25 @@ public class ContactsDatabaseHelper extends SQLiteOpenHelper {
ContactLocaleUtils localeUtils = ContactLocaleUtils.getInstance();
if (sortKeyPrimary != null) {
- phonebookBucketPrimary = localeUtils.getBucketIndex(sortKeyPrimary);
- phonebookLabelPrimary = localeUtils.getBucketLabel(phonebookBucketPrimary);
+ boolean flag = false;
+ if (displayNameStyle == FullNameStyle.CHINESE
+ && HanziToPinyin.getInstance().hasChineseTransliterator()) {
+ String target = sortKeyPrimary.substring(0, 1);
+ ArrayList<Token> tokens = HanziToPinyin.getInstance().get(target);
+ if (tokens != null && tokens.size() > 0) {
+ char label = tokens.get(0).target.charAt(0);
+ if (label >= 'A' && label <= 'Z') {
+ phonebookLabelPrimary = String.valueOf(label);
+ phonebookBucketPrimary = localeUtils.getBucketIndex(phonebookLabelPrimary);
+ flag = true;
+ }
+ }
+ }
+
+ if (!flag) {
+ phonebookBucketPrimary = localeUtils.getBucketIndex(sortKeyPrimary);
+ phonebookLabelPrimary = localeUtils.getBucketLabel(phonebookBucketPrimary);
+ }
}
if (sortKeyAlternative != null) {
phonebookBucketAlternative = localeUtils.getBucketIndex(sortKeyAlternative);
-----------------------------------------------------------------------------
通過上面的分析可以發現一個問題,那就是在Contacts首頁面用'dan tian fang'搜尋連絡人時是搜不到的,只能用'shan tian fang'來搜尋,但是在顯示時確是將該連絡人放在了'D'分組下面!根本原因就是NameLookupBuilder在調用appendNameShorthandLookup時實際上使用了HanziToPinyin來擷取讀音,這時得到的是作為姓氏時的讀音,而phonebook_label是使用AlphabeticIndex$ImmutableIndex的getBucketLabel函數來擷取的,而它沒有對姓氏多音字做任何特殊處理,這就導致了前面說的問題.
另外,用HanziToPinyin的一個問題是所有的可作為姓氏的漢字的讀音都是姓氏的讀音,如'單位單'的拼音是'shan wei shan'.如何解決這個問題呢?其實現有條件下沒有一個好的辦法(加詞庫的方法除外),只能盡量規避.我的方法是中文情況下名字中的第一個漢字作為姓氏去擷取讀音(使用Han-Latin/Names; Latin-Ascii; Any-Upper建立的Transliterator對象),而其它漢字則作為普通漢字去擷取讀音(使用Han-Latin; Latin-Ascii; Any-Upper建立的Transliterator對象,需在HanziToPinyin中再建立一個Transliterator對象).
附一
raw_contacts表中的phonebook_label的擷取流程:
raw_contacts表中的phonebook_label是通過調用ContactsDatabaseHelper的updateRawContactDisplayName函數來完成插入/更新的.使用的是phonebookLabelPrimary變數的值.而phonebookLabelPrimary是ContactLocaleUtils中getBucketLabel獲得的,getBucketLabel中實際調用的是ICU中ImmutableIndex的getBucketLabel來完成的().
PS:尋強力ROMTeam Dev.本人主要負責Dialer、Contacts相關模組,三年經驗.有意者可以email我: gaojx0809@gmail.com
EXCEL 姓名排序的問題 高分解決辦法
excel預設按多音字中的拼音首字母在A-Z序列中靠前的那個讀音排序
如
長
zhang,chang
會按照chang來參加排序如果只是排序的不論多音字都可以排序的。
如果要區分多音字排序只有自己多加標註區分。
祝你成功!
姓氏中的多音字解答
不好意思.還沒回答完.不小心按了提交
在姓氏中,“樸”讀(piáo)
在姓氏中,“折”讀(zhé)
在姓氏中,“單”讀(shàn )