题记

自研的电话应用中,有两处使用了号码归属地,一处是通话记录页,一处是通话界面;那么它们是如何实现的呢?下面进行一步一步的分析。

Dialer使用号码归属地

通话记录页的号码归属地

通过查询calls表中的Calls.GEOCODED_LOCATION字段,来进行获取号码的归属地。

相关代码如下:

查询:

startQuery(token, null, uri, CallLogQuery._PROJECTION, selection, selectionArgs.toArray(

new String[selectionArgs.size()]), Calls.DEFAULT_SORT_ORDER);

获取号码归属地

details.geocode = c.getString(CallLogQuery.GEOCODED_LOCATION);

既然是通过查询数据库而得,那么数据是何时及如何更新的呢?

熟悉通话流程框架就会知道,添加一个通话需要经过APP->Telecom->framework->modem几层进行。那么通话记录的更新就是在Telecom的CallLogManager.java进行管理;

源码地址:packages/services/Telecomm/src/com/android/server/telecom/CallLogManager

主要流程是:onCallAdd->onCallStateChanged->logCall;logCall方法到最后就是向calls表中插入该通电话的各个信息;

该文只对location(号码归属地)进行详细分析。

查看logCall的实现:

logCall(call.getCallerInfo(), logNumber, call.getPostDialDigits(), formattedViaNumber,

call.getHandlePresentation(), callLogType, callFeatures, accountHandle,

creationTime, age, callDataUsage, call.isEmergencyCall(), call.getInitiatingUser(),

logCallCompletedListener,

call.getConferenceCallLogId() /* M: For Volte Conference call */);

发现位置等信息的是存储在call.getCallerInfo()中,那么call.getCallerInfo()得到的mCallerInfo,又是怎么获取到location(号码归属地)的呢?

查看CallerInfo类,发现updateGeoDescription方法就是为了获取号码归属地;代码如下:

public void updateGeoDescription(Context context, String fallbackNumber) {

String number = TextUtils.isEmpty(phoneNumber) ? fallbackNumber : phoneNumber;

geoDescription = getGeoDescription(context, number);

}

getGeoDescription方法实现如下:

需引用如下包:

import com.android.i18n.phonenumbers.geocoding.PhoneNumberOfflineGeocoder;

import com.android.i18n.phonenumbers.NumberParseException;

import com.android.i18n.phonenumbers.PhoneNumberUtil;

import com.android.i18n.phonenumbers.Phonenumber.PhoneNumber;

private static String getGeoDescription(Context context, String number) {

if (VDBG) Rlog.v(TAG, "getGeoDescription('" + number + "')...");

if (TextUtils.isEmpty(number)) {

return null;

}

// MTK新增逻辑,7.0以后geoCodingQuery实现为空,即已舍弃新增的逻辑实现。

/// M: CC: Query city name via GeoCodingQuery @{

// [ALPS00286530]Query Geocoding description

if (SystemProperties.get("ro.mtk_phone_number_geo").equals("1")) {

GeoCodingQuery geoCodingQuery = GeoCodingQuery.getInstance(context);

String cityName = geoCodingQuery.queryByNumber(number);

Rlog.v(TAG, "[GeoCodingQuery] cityName = " + cityName);

if ((cityName != null) && (!cityName.equals(""))) {

return cityName;

}

}

/// @}

PhoneNumberUtil util = PhoneNumberUtil.getInstance();

PhoneNumberOfflineGeocoder geocoder = PhoneNumberOfflineGeocoder.getInstance();

Locale locale = context.getResources().getConfiguration().locale;

String countryIso = getCurrentCountryIso(context, locale);

PhoneNumber pn = null;

try {

if (VDBG) Rlog.v(TAG, "parsing '" + number

+ "' for countryIso '" + countryIso + "'...");

pn = util.parse(number, countryIso);

if (VDBG) Rlog.v(TAG, "- parsed number: " + pn);

} catch (NumberParseException e) {

Rlog.d(TAG, "getGeoDescription: NumberParseException for incoming number '"

+ number + "'");

}

if (pn != null) {

String description = geocoder.getDescriptionForNumber(pn, locale);

if (VDBG) Rlog.v(TAG, "- got description: '" + description + "'");

return description;

} else {

return null;

}

}

通过getGeoDescription的实现我们可以知道获取号码归属地的核心为:

//获取PhoneNumberUtil、PhoneNumberOfflineGeocoder 实例

PhoneNumberUtil util = PhoneNumberUtil.getInstance();

PhoneNumberOfflineGeocoder geocoder = PhoneNumberOfflineGeocoder.getInstance();

//获取国家码,此处会转换为two letters country code,如(86等)

Locale locale = context.getResources().getConfiguration().locale;

String countryIso = getCurrentCountryIso(context, locale);

//libphonenumber库中定义的号码“结构”,包含国家码和号码

PhoneNumber pn = null;

try {

if (VDBG) Rlog.v(TAG, "parsing '" + number

+ "' for countryIso '" + countryIso + "'...");

pn = util.parse(number, countryIso);

if (VDBG) Rlog.v(TAG, "- parsed number: " + pn);

} catch (NumberParseException e) {

Rlog.d(TAG, "getGeoDescription: NumberParseException for incoming number '"

+ number + "'");

}

if (pn != null) {

//真正解析,筛选的方法

String description = geocoder.getDescriptionForNumber(pn, locale);

if (VDBG) Rlog.v(TAG, "- got description: '" + description + "'");

return description;

} else {

return null;

}

总结就是使用phonenumbers的方法进行实现。

通话界面中的号码归属地

使用phonenumbers的方法直接对号码进行处理得到号码归属地:

通话界面调用代码:

String location=GeoUtil.getGeocodedLocationFor(getActivity(), number);

GeoUtil是ContactCommon的一个类,实现如下

import com.google.i18n.phonenumbers.geocoding.PhoneNumberOfflineGeocoder;

import com.google.i18n.phonenumbers.NumberParseException;

import com.google.i18n.phonenumbers.PhoneNumberUtil;

import com.google.i18n.phonenumbers.Phonenumber;

import java.util.Locale;

/** * Static methods related to Geo. */

public class GeoUtil {

/** * Returns the country code of the country the user is currently in. Before calling this * method, make sure that {@link CountryDetector#initialize(Context)} has already been called * in {@link Application#onCreate()}. *@return The ISO 3166-1 two letters country code of the country the user * is in. */

public static String getCurrentCountryIso(Context context) {

// The {@link CountryDetector} should never return null so this is safe to return as-is.

return CountryDetector.getInstance(context).getCurrentCountryIso();

}

public static String getGeocodedLocationFor(Context context, String phoneNumber) {

final PhoneNumberOfflineGeocoder geocoder = PhoneNumberOfflineGeocoder.getInstance();

final PhoneNumberUtil phoneNumberUtil = PhoneNumberUtil.getInstance();

try {

final Phonenumber.PhoneNumber structuredPhoneNumber =

phoneNumberUtil.parse(phoneNumber, getCurrentCountryIso(context));

final Locale locale = context.getResources().getConfiguration().locale;

return geocoder.getDescriptionForNumber(structuredPhoneNumber, locale);

} catch (NumberParseException e) {

return null;

}

}

}

我们发现也是使用geocoder.getDescriptionForNumber(structuredPhoneNumber, locale)进行获取号码归属地。

总结

号码归属地使用com.google.i18n.phonenumbers下的方法进行获取:核心代码如下:

final PhoneNumberOfflineGeocoder geocoder = PhoneNumberOfflineGeocoder.getInstance();

final PhoneNumberUtil phoneNumberUtil = PhoneNumberUtil.getInstance();

try {

final Phonenumber.PhoneNumber structuredPhoneNumber =

phoneNumberUtil.parse(phoneNumber, getCurrentCountryIso(context));

final Locale locale = context.getResources().getConfiguration().locale;

return geocoder.getDescriptionForNumber(structuredPhoneNumber, locale);

} catch (NumberParseException e) {

return null;

}

Libphonenumber -号码归属地核心

分析了电话应用两处使用号码归属地的实现发现号码归属地是使用google源码自带的库-Libphonenumber。这里就大致介绍下这个库的原理

源码地址:external/libphonenumber/

号码归属地主要是使用如下地址的代码:

external/libphonenumber/libphonenumber/src/com/google/i18n/phonenumbers

主要涉及:PhoneNumberOfflineGeocoder、PhoneNumberUtil、MetadataLoader、prefixFileReader、

android号码查询归属地,号码归属地识别-Android电话应用相关推荐

  1. adb 51 android.rules,使用51-android-rules解决ubuntu上不识别 android手机的问题

    此文系转载:http://blog.sina.com.cn/s/blog_96a11ddf0101t56b.html 首先我们在编译完一个项目后,在项目的输出档中将会有一个adb文件 /out/hos ...

  2. android sdk 官网说明,神目人脸识别Android SDK Demo说明

    Demo使用说明 SDK Demo主界面如图1-1所示,主要功能有:1:1,1:N,人脸库管理,设置选项四大功能.具体说明如下: (1)1:1,即图片1与图片2进行人脸比对,得出两者的相似度分数.界面 ...

  3. android用于查询数据的方法,android: SQLite查询数据

    掌握了查询数据的方法之后,你也就将数据库的 CRUD 操 作全部学完了.不过千万不要因此而放松,因为查询数据也是在 CRUD 中最复杂的一种 操作. 我们都知道 SQL 的全称是 Structured ...

  4. Android 号码, 来电归属地 Jni 使用C++对二进制文件查询(一) 理论篇

    1.效果图 左边的是应用程序界面,只是做个测试.右边的是应用程序信息,你会发现数据这块很小,只有420KB,要知道里面有近280,000记录. 2.尝试使用sqlite数据库, 用db格式文件. 随便 ...

  5. [android] 手机卫士来电显示号码归属地

    继续N天前的项目 开启服务监听手机来电,查询数据库,显示归属地 详细内容可以参考这篇博文:http://www.cnblogs.com/taoshihan/p/5331232.html Address ...

  6. Android 身份证号码查询、手机号码查询、天气查询

    1.基本信息 身份证号码查询: http://apistore.baidu.com/apiworks/servicedetail/113.html 手机号码: http://apistore.baid ...

  7. Android 简单几步实现手机号码归属地查询,可监听文本框的变化自动查询

    2019独角兽企业重金招聘Python工程师标准>>> 手机号码归属地查询需要用到一个数据库文件,我们可以用小米公司的数据库文件 第一步:数据库文件存储在 data/data/包名/ ...

  8. 安卓开发之使用第三方的聚合数据API,QQ测吉凶案、身份证号码查询。

    在安卓开发中,肯定需要很多API接口, 比如天气获.快递实时信息.身份证号码查询和基本的短信验证码. API(Application Programming Interface,应用程序编程接口)是一 ...

  9. 「SAP技术」SAP WM 如何根据TR号码查询TO号码?

    「SAP技术」SAP WM 如何根据TR号码查询TO号码? 今日下午,收到K项目的仓库部门用户的提问,如何通过TR号码查找TO单号码.笔者想到了LT22 & LT23等TO查询的报表里,是可以 ...

  10. SAP HUM 如何查询一个HU号码是否被软分配给了某个销售订单 ?

    SAP HUM 如何查询一个HU号码是否被软分配给了某个销售订单 ? 1, SE16 + VERP, 输入HU号码,查询到internal HU no. 2, Se16 + HURES, 输入Inte ...

最新文章

  1. C++与.net的编译方式
  2. java中block类6_Java 实现区块链中的区块,BLOCK的实现
  3. Andorid之bitmap里面的压缩总结
  4. java蝇量模式_Head First设计模式——蝇量和解释器模式
  5. 【渝粤题库】国家开放大学2021春2227物业设备设施管理题目
  6. SAP JCo的Server/Client编程实例
  7. Spyder清除Variable Explorer手动安装protobuf3.0(为了配置windows的python接口)
  8. 以太坊服务器是什么_OKEX区块链60讲 | 第33集:什么是以太坊?
  9. Android Studio 复制粘贴图片到drawable文件夹没有效果 - 解决方法
  10. MySQL中使用SQL语句对字段进行重命名
  11. HTML与XML数据的结合小总结
  12. 数据库中的内连接、自然连接、和外连接的区别
  13. 全民一起玩Python提高篇第十五课:函数式编程初步(下)
  14. 复习Python爬取必应的壁纸
  15. 海门中学2021高考成绩查询入口,海门中学举行2020—2021学年度第一学期优秀学生表彰大会,附名单...
  16. 纯HTML+CSS+js实现大型企业站小米商城官网之注册页面
  17. 看完这篇iOS面试题,一天3offer!!!
  18. windows版微信Hook开发SDK之C#版-微信二次开发
  19. 使用电脑微信扫描二维码
  20. uva 10306(完全背包)

热门文章

  1. 安装Visio2010 64bit时提示不能安装32位版本的Office 2010 ,因为您当前已经安装了64位Office产品的解决方法(亲测可行)
  2. 《tcpip详解卷一》:150行代码拉开协议栈实现的篇章
  3. 斗鱼直播分享html代码,用纯javascript实现斗鱼直播弹幕效果,代码也才这么点-优酷弹幕怎么设置...
  4. 引文工具的全球与中国市场2022-2028年:技术、参与者、趋势、市场规模及占有率研究报告
  5. 计算机组成与体系结构
  6. c语言的编程特点,c语言编程是什么?C语言编程的特点和应用
  7. linux hasp的加密狗驱动程序,hasp加密狗驱动下载-hasp加密狗驱动(圣天诺加密狗驱动) win7/8/10 官方通用版 - 河东下载站...
  8. Linux下虚拟打印机CUPS-PDF教程
  9. java 加密\解密工具类
  10. Wannacry勒索病毒样本分析