开发MTK平台的机器一般比较幸福,非常友好的支持(对比国外大厂),N多国内运营商的功能支持早有实现,比如T9。但是开发高大上的高通咋办?木有T9啊。不过目前有多种方案可选则。

实现mtk的sqlite方法

mtk的Contact和Dialer添加了很多功能,例如多选联系人号码,群组等,所以不少厂商高通平台的机器照样是移植mtk的代码。如果T9也能实现,那么不同平台基本就是一套代码了,维护就容易多了。但是mtk未开放sqlite自定义函数DIALER_SEARCH_MATCH_FILTER和DIALER_SEARCH_MATCH的源码,虽然mtk的eservice中会有不少单子上提及dialer search的实现,不过mtk的网站是反网络爬虫的,靠百度google搜索引擎是无用的。
在MTK的T9搜索流程分析中我已经详细分析了mtk T9的流程,看懂的话可以实现这两个sqlite方法。
自定义的方法见 SQLite 加入自定义函数,有C++和java两种方法(链接文章中举的java例子是错误的,这个要注意)。不过java层的SQLiteDatabase.CustomFunction是行不通的,原因是CustomFunction没有返回值。其实java的原理实际最后还是和C++一样,只不过多了jni的使用:
frameworks/base/core/jni/android_database_SQLiteConnection.cpp
static void nativeRegisterCustomFunction(JNIEnv* env, jclass clazz, jlong connectionPtr,jobject functionObj) {...int err = sqlite3_create_function_v2(connection->db, name, numArgs, SQLITE_UTF16,reinterpret_cast<void*>(functionObjGlobal),&sqliteCustomFunctionCallback, NULL, NULL, &sqliteCustomFunctionDestructor);...
}

注册方法中使用sqlite3_create_function_v2方法注册custom方法,这个和C++代码的添加方式是基本一样的。

static void sqliteCustomFunctionCallback(sqlite3_context *context,int argc, sqlite3_value **argv) {JNIEnv* env = AndroidRuntime::getJNIEnv();// Get the callback function object.// Create a new local reference to it in case the callback tries to do something// dumb like unregister the function (thereby destroying the global ref) while it is running.jobject functionObjGlobal = reinterpret_cast<jobject>(sqlite3_user_data(context));jobject functionObj = env->NewLocalRef(functionObjGlobal);jobjectArray argsArray = env->NewObjectArray(argc, gStringClassInfo.clazz, NULL);if (argsArray) {for (int i = 0; i < argc; i++) {const jchar* arg = static_cast<const jchar*>(sqlite3_value_text16(argv[i]));if (!arg) {ALOGW("NULL argument in custom_function_callback.  This should not happen.");} else {size_t argLen = sqlite3_value_bytes16(argv[i]) / sizeof(jchar);jstring argStr = env->NewString(arg, argLen);if (!argStr) {goto error; // out of memory error}env->SetObjectArrayElement(argsArray, i, argStr);env->DeleteLocalRef(argStr);}}// TODO: Support functions that return values.env->CallVoidMethod(functionObj,gSQLiteCustomFunctionClassInfo.dispatchCallback, argsArray);error:env->DeleteLocalRef(argsArray);}env->DeleteLocalRef(functionObj);if (env->ExceptionCheck()) {ALOGE("An exception was thrown by custom SQLite function.");LOGE_EX(env);env->ExceptionClear();}
}

上面是java层custom方法回调的代码,可以看出完全没有返回值的相关代码(sqlite中的返回值是通过sqlite3_result_int等方法返回的,并不是通过return语句,sqlite定义的custom方法返回值都是void)。这样java层的代码只能是干些无返回值的活,例如MediaProvider中是在删除数据库的时候删除对应项目的文件。

所以只能是通过C++的方式实现这两个方法。

开源

handsomezhou

https://github.com/handsomezhou/T9Search
csdn上关于Android流传最广的好像就是android T9 搜索联系人分析与实现(支持多音字),这个有完整的代码和demo例子,简直太好用了。看了下作者是90年的,吾辈好羞愧。虽然原理是读取全部联系人,然后for循环一条一条处理的,但是效率比我预想好得多,在2000个联系人的情况下搜索还是很快。

kewenya

https://github.com/kewenya/SearchCoreTest
虽然作者说了Android也能用,不过没有Android的demo,代码中我看到也只有ios的实现。大概看了下代码,联系人数据用了自定义SearchTree的结构,插入数据后可以用二分查找来寻找要匹配的对象,效率理论上要比handsomezhou的好一些。这个拿来给Android用修改的工作就要大一些了,有两种思路:二分查找的思想挪到handsomezhou的项目上;代码是Objective-C,要转成标准的C++,然后实现上节中介绍的sqlite函数,这个初始化数据源的工作很简单,因为就只有一条数据。

oasisfeng

https://github.com/oasisfeng/android-smartdial-chinese
这个并不是完整的T9实现,肯定不能作为商用,但是对爱刷Android原生或者cm版本rom的朋友来说是福音。oasisfeng是开发绿色守护的大神,稍微修改几十行代码就完成了T9搜索80%的功能,是用Xposed插桩往Dialer中添加运行代码的。对Android代码的理解和直觉真是比我等甩了n条街(人家不是专职搞Dialer的呀)。

自己实现

熟悉T9的匹配规则,然后自己实现。这个不少厂商都是这么干的呀,之前遇见过前辈写的,不过那个实现真是反面教材,j、jj、jjj变量命名到处是,for循环好多层,2000个联系人查一次得5秒以上的时间。关键是我看不懂代码流程和算法,不过这个实现还在好多机器上用了........自己查看不少文章后有几个小想法写下供大家参考:

Trie树

百度百科:又称单词查找树,Trie树,是一种树形结构,是一种哈希树的变种。典型应用是用于统计,排序和保存大量的字符串(但不仅限于字符串),所以经常被搜索引擎系统用于文本词频统计。它的优点是:利用字符串的公共前缀来减少查询时间,最大限度地减少无谓的字符串比较,查询效率比哈希树高。
数据结构和算法学的好同学一下就会想到这个,不过网上我没有搜索到使用Trie树的T9实现。扫描所有联系人生成Trie树,这样查询的效率就几乎是常数了。

数据源的更新

不论是什么方法,基本都会生成一份初始的数据集合以便查询,那么就会面临一个问题,如果联系人有变动怎么办。最简单的就是重新生成一份数据集合,但是如果数据量很大那么效率就会很慢,最好是只针对变化的数据做修改就成了。其实这种思想在android源码中已有实现了,见Android拨号搜索机制源码分析(原)。这篇文章中讲解了原生代码中拨号盘搜索的流程(原生的只能匹配号码和英文名称,没有考虑中文),其中2.2小节“数据库的更新”就介绍了数据库是怎么做局部更新的,这个思想可以借鉴到其它地方,即使那种实现方法不使用数据库。

数据源的保存

数据集的建立是比较花时间的,手机用户修改联系人数据库也不是高频的操作,那么可以把数据源以某种方式保存,不用每次都从零开始。
结合这几种想法,建立trie树,trie用于搜索;同时建立联系人列表(每个联系人又包含了trie树中相关节点所组成的集合),用于更新trie树。更新使用局部更新。数据可以序列化存储在内部存储中。不过我等懒人直接用handsomezhou的就可以了

Android非mtk平台T9的实现相关推荐

  1. Android Q MTK平台开关机铃声

    google 默认开机动画代码在framework/base/cmds/bootanimation MTK 开机动画代码在vendor/mediatek/proprietary/operator/fr ...

  2. Android 系统性能优化(57)---MTK 平台开关机、重启时间优化

    MTK 平台开关机.重启时间优化  开关机.重启时间优化   开机性能优化:是用功能和其它因素多方面平衡的结果,片面追求单方面的性能没有太大意义:  有些产品设计开机动画非常酷炫,动画图片过多.高帧率 ...

  3. Android系统定制源码修改 - MTK平台

                                         Android系统定制源码修改 -  MTK平台  1.修改开机弹出欢迎使用SIM MTK工程/mediatek/packag ...

  4. mtk android 5.1 logo,Android ROM DIY之MTK平台手机通用移植

    在之前的文章中,我们讨论过ROM刷机原理,修改ROM包以及如何让ROM包获取root权限.那么接下来,我们谈谈MTK平台手机ROM移植的话题.如果你是ROM小白,那么建议可以先看看之前的文章. ROM ...

  5. Android Camera (13)---MTK平台相机插值修改

    MTK平台相机插值修改 一.注意事项 二.HAL层修改 三.APP层修改 四.部分插值整理 五.快速编译指令 一.注意事项 Camera插值在底层已经做好,我们只需要在中间层和app层添加一个对应的p ...

  6. Android 系统(159)----MTK 平台过CTA时,发生权限未明示问题

    MTK 平台过CTA时,发生权限未明示问题 Background:CTA是针对中国大陆地区的一个安全认证,目的是提高移动智能终端自身的安全防护能力,防范移动智能终端上的各种安全威胁,避免用户的利益受到 ...

  7. Android 系统(138 )---Mtk平台 Android 打包解包*.img ,修改system.img 参数

    Mtk平台 Android 打包解包*.img ,修改system.img 参数 MTK 升级包文件如下: 若存在软件版本号存在错误或需要修改,重新编译则需要几个小时,或者要几天的测试 若可以直接修改 ...

  8. Android 系统(112)---Android系统读取 CPU温度(MTK平台)

    Android系统读取 CPU温度(MTK平台) 一.[MTK 平台]读取温度命令 1.查看类型是否是 CPU adb shell "cat /sys/class/thermal/therm ...

  9. Android 系统(86)---mtk平台上如何开启f2fs

    本文介绍mtk平台上如何开启f2fs 1.  MTK Android O1   SW 版本 2.  F2FS 在下列平台已经做了验证,其他平台没有验证 1)6580/6570   2)6735/53/ ...

最新文章

  1. php pkcs 1格式的公钥,解说--2--微信支付RSA公钥PKCS1格式转化成PKCS8格式的公钥
  2. Android媒体播放框架MediaSessionCompat介绍实践
  3. 白话Elasticsearch61-进阶篇之基于Term Vectors深入探查数据的情况
  4. CEO 赠书 | 对失败的学习,决定了你成功的速度
  5. Extjs 动态生成表格
  6. EasyUI 分页 简洁代码
  7. 串口-TCP调试助手
  8. 阿里的数据同步神器——Canal
  9. 深度学习数据增强方法-内含(亮度增强,对比度增强,旋转图图像,翻转图像,仿射变化扩充图像,错切变化扩充图像,HSV数据增强)七种方式进行增强-每种扩充一张实现7倍扩)+ 图像缩放代码-批量
  10. 237. 删除链表中的节点 (Delete Node in a Linked List)
  11. 两年多工作心得和体会
  12. linux pv修改大小,Linux下扩容系统容量和删除unknown PV
  13. 【Windows】关于Windows Powershell找不到打不开修复方法
  14. 图扑数字孪生军演,构建跨域作战体系
  15. 微信会员注册开发【带源码】:网页授权,得到code后在当前页面获取openid,js+php实现跨域请求
  16. 2021-04-1 芯片74LS161使用总结
  17. python输入年月日输出年月日_【手把手教你】Python金融数据处理
  18. 批处理bat修改文件后缀
  19. SecureFX之激活教程
  20. 酷壳网大神重要文章转载合集

热门文章

  1. 快速掌握SAP BDC数据导入
  2. K-mean 算法代码演示
  3. python函数测试_python绘制评估优化算法性能的测试函数
  4. mark制图软件_VectorWorks(三维设计制图软件) V2019 Mac版
  5. IDEA 打开一片空白
  6. Python验证注册用户名是否正确
  7. DCU Streamer Prefetcher
  8. 随机数抽奖程序 html,半小时撸一个抽奖程序
  9. 如何跑通平头哥RISC-V E902的仿真验证
  10. 【ISP】浅析CCM