什么是号码匹配,个人理解,即判断两组号码是否属于同一个号码。在实际使用过程中,接触到的号码会涉及到区号,国家编码以及IP号码等,这个时候就用到了号码匹配。两个内容不一样的号码,如+86***和17951***,是不是同一个号码。就需要软件判断是否同一个号码。手机里面涉及号码匹配的场景很多,打电话发短信都要用到。和前面的+86***和17951***两个号码所示,号码匹配是从后往前进行比较的,可以猜测一个标准号码的附加号码都是加在前面的。
根据匹配数据来源可以将号码匹配分为一下两种:
1.同一个应用内的号码匹配:在一个应用内判断两个号码是否是同一个号码,根据结果将记录合并或者分开。典型场景如:通话记录是否合并,新发送或者新接收的短信是新建会话还是存入已知会话。
2.同联系人应用进行号码匹配:一个应用去联系人数据库里面查询,获取号码的其他数据。一般每个涉及号码的应用都会有一个自己的数据库的表,用来存储号码上的信息。应用第一次收到号码都会查询联系人的数据库,获得这个号码的详细信息:如姓名等。典型的场景有:发短信和打电话时候输入了号码自动匹配上了号码对应的联系人姓名,一段文字里面的号码是否在当前手机中有。
在android原生系统上,大致可以根据前面介绍,将其号码匹配的实现方案分为两种:
1.在数据库增加PHONE_NUMBERS_EQUAL方法,进行SQL级别的匹配查询,这个方法有三个参数,两个是号码,还有一个是否是严格匹配。查看2.3.5的android源码,这个严格匹配和泰国有关系……所以一般这个参数都是false,即不执行严格号码匹配。
2.在构建数据库的查询语句上,进行号码匹配。一般这种情况都会进行号码的从后往前的截断,直接判断截断的数据是否相等。
号码匹配是后往前匹配的,如果后面连续N个数字相等的话,就认为是同一个号码。这里的N,即是N位号码匹配。google自带的两个号码匹配都是7位号码匹配。下面来根据实例进行讲解。先说说数据库上的PHONE_NUMBERS_EQUAL方法,直接去看telephonyprovider里面的一个方法:
private long getSingleAddressId(String address) { …… if (!isPhoneNumber) { selectionArgs = new String[] { refinedAddress }; } else { selection += " OR PHONE_NUMBERS_EQUAL(address, ?, " + (mUseStrictPhoneNumberComparation ? 1 : 0) + ")"; selectionArgs = new String[] { refinedAddress, refinedAddress }; }
如代码所示,构建SQL语句时候直接使用了PHONE_NUMBERS_EQUAL方法,进行数据库级别的比较,这里的号码匹配位数是7位,在OldPhoneNumberUtils.cpp文件中,定义语句是static int MIN_MATCH = 7。另外这里还有一个严格模式:mUseStrictPhoneNumberComparation。关于严格模式可以直接去OldPhoneNumberUtils.cpp所在目录查看PHONE_NUMBERS_EQUAL方法实现。自己看了下严格模式仅仅和泰国有关系,意义不是很大,android本身也基本都是关闭的,大多数场景下都没有使用严格模式。
再说说构建数据库语句时候的号码匹配。这个号码匹配位数是在PhoneNumberUtils.java文件里面。定义代码如下:static final int MIN_MATCH = 7。查看PhoneNumberUtils.java的公有方法public static String toCallerIDMinMatch(String)在contact数据库里面的调用,就可以看到:联系人数据库在每次新增加一个号码的时候,都会增加一个字段,即后7位号码,用来帮助查询。在构建查询的SQL语句时候,也会调用public static String toCallerIDMinMatch(String)方法,截取查询号码的后7位。典型代码如下:
public void buildPhoneLookupAndContactQuery( SQLiteQueryBuilder qb, String normalizedNumber, String numberE164) { String minMatch = PhoneNumberUtils.toCallerIDMinMatch(normalizedNumber); StringBuilder sb = new StringBuilder(); appendPhoneLookupTables(sb, minMatch, true); qb.setTables(sb.toString()); sb = new StringBuilder(); appendPhoneLookupSelection(sb, normalizedNumber, numberE164); qb.appendWhere(sb.toString()); }
到这里google原生的号码匹配基本介绍结束。原生的是7位号码匹配,考虑到我国固定电话长度是8位,手机号码长度是11位,7位一般是不够用的,各开发者可以根据自己的需要进行修改。