再谈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来完成的().
再谈Contacts中姓氏多音字排序错误问题的更多相关文章
- Unity教程之再谈Unity中的优化技术
这是从 Unity教程之再谈Unity中的优化技术 这篇文章里提取出来的一部分,这篇文章让我学到了挺多可能我应该知道却还没知道的知识,写的挺好的 优化几何体 这一步主要是为了针对性能瓶颈中的”顶点 ...
- 再谈c++中的引用
在<从汇编看c++的引用和指针>一文中,虽然谈到了引用,但是只是为了将两者进行比较.这里将对引用做进一步的分析. 1 引用的实现方式 在介绍有关引用的c++书中,很多都说引用只是其引用变量 ...
- NET Core微服务之路:再谈分布式系统中一致性问题分析
前言 一致性:很多时候表现在IT系统中,通常在分布式系统中,必须(或最终)为多个节点的数据保持一致.世间万物,也有存在相同的特征或相似,比如儿时的双胞胎,一批工厂流水线的产品,当然,我们不去讨论非IT ...
- 再谈AR中的图像识别算法
之前在<浅谈移动平台创新玩法>简单的猜测了easyar中使用的图像识别算法,基于图片指纹的哈希算法的图片检索 .后再阿里引商大神的指点下,意识到图片检测只适用于静态图片的识别,只能做AR脱 ...
- 【一次面试】再谈javascript中的继承
前言 面向对象编程是每次面试必问的知识点,而前端js如何实现继承每次命中率高达80% 这不,近两天我们面试时候,同事就问道面试者此问题,但是,不论之前自己做的回答,还是面试者的回答,基本都不太令人满意 ...
- 再谈vim中多窗口的编辑
参考:http://blog.csdn.net/shuangde800/article/details/11430659 很好 鼠标在各个窗口间循环移动: ctrl+w+(小写的 hjkl), &qu ...
- 再谈机器学习中的归一化方法(Normalization Method)
机器学习.数据挖掘工作中,数据前期准备.数据预处理过程.特征提取等几个步骤几乎要花费数据工程师一半的工作时间.同时,数据预处理的效果也直接影响了后续模型能否有效的工作.然而,目前的大部分学术研究主要集 ...
- 再谈vim中多窗口的编辑 ctrl+w+H窗口位置最大化和互换等操作
参考:http://blog.csdn.net/shuangde800/article/details/11430659 很好 鼠标在各个窗口间循环移动: ctrl+w+(小写的 hjkl), &qu ...
- JVM系列之:再谈java中的safepoint
目录 safepoint是什么 safepoint的例子 线程什么时候会进入safepoint safepoint是怎么工作的 总结 safepoint是什么 java程序里面有很多很多的java线程 ...
随机推荐
- Ubuntu 14.04 下 OF-Config安装
参考: Github of-config configure.ac - configure file issue OF-Config安装 1.安装OvS v2.3.1: Releases $ tar ...
- Codeforces Beta Round #95 (Div. 2) D. Subway dfs+bfs
D. Subway A subway scheme, classic for all Berland cities is represented by a set of n stations conn ...
- Codeforces 895C - Square Subsets
895C - Square Subsets 思路:状压dp. 每个数最大到70,1到70有19个质数,给这19个质数标号,与状态中的每一位对应. 状压:一个数含有这个质因子奇数个,那么他状态的这一位是 ...
- Java IO流-File类
2017-10-24 23:50:22 File类 File类:文件和目录路径名的抽象表示形式.该文件或者目录不一定真实存在. * 构造方法 File类有四种构造方法,主要采用的构造方法师第二种,也就 ...
- VMware 怎么判断哪台机子试图用混杂模式且不成功
主要是看个log, 然后推断虚拟端口号 The VMkernel logs at /var/log/vmkernel or /var/log/messages contain entries simi ...
- golang martini 源码阅读笔记之inject
martini是go语言写的一个超级轻量的web开源框架,具体源码可在github搜索找到.13年那会开始接触go语言时有稍微看过这个框架,由于之后没有继续使用go就慢慢忽略了,最近由于手头项目可能会 ...
- 『科学计算_理论』SVD奇异值分解
转载请声明出处 SVD奇异值分解概述 SVD不仅是一个数学问题,在工程应用中的很多地方都有它的身影,比如前面讲的PCA,掌握了SVD原理后再去看PCA那是相当简单的,在推荐系统方面,SVD更是名声大噪 ...
- hdu 1024 最大M子段dp
题目: Max Sum Plus Plus Time Limit: 2000/1000 MS (Java/Others) Memory Limit: 65536/32768 K (Java/Ot ...
- UVA-10127 Ones (数论)
题目大意:给一个数n,找出一个各位全是1的最小的十进制数,使得n能整除这个数.只输出最小位数. 题目分析:纯粹是数论,暴力. 代码如下: # include<iostream> # inc ...
- 写入CSS的3种方式
CSS能让网页制作者有效的定制.改善网页的效果. CSS是对HTML的补充(网页设计师曾经为无法很好的控制页面的显示效果而倍感苦恼,CSS的出现解决了这个问题) CSS实现了网页内容和页面效果的彻底分 ...