libphonenumber:Google的公共電話號碼解析庫
前言
以前在專案中碰到一個問題,測試提了個需求:接聽接話使,皮套介面要能解析號碼的來源地,並且要和系統的語言保持一致。這個問題說難不難,但是也不簡單,一般情況下,我們可能會想到建立一個數據庫,然後寫一個ContentPrivoder,然後在專案中使用提供的URI來解析電話號碼。
如果你真的這麼想,那麼你這個任務就是無盡的任務了。因為你需要適配各種語言,需要收集這個國家的地名,這簡直是不可能完成的任務!
好了,大家稍安勿躁,我不是來吐槽的,我是來提供解決方法的,大家接著看下去。
我認為最好的辦法就是用Google的公共電話號碼解析庫—libphonenumber
這個庫Android原始碼的路徑是:
external/libphonenumber/
當然了,github上面也有,地址是:
[libphonenumber](https://github.com/googlei18n/libphonenumber)
由於我本人是直接使用Android原始碼下的庫,所以我接下來用它來舉例子。
首先用使用這個庫,有兩個方法:
- 將libphonenumber作為module放到你的工程裡
- 將libphonenumber作為jar放到Android工程的libs目錄下
步驟
在這裡我們使用第二種,至於第一種方法不會使用的,可以問度娘,接來我說說使用步驟:
編譯libphonenumber
使用mmm external/libphonenumber/,之後在終端下看到這個:
找到對應的jar包
看圖可以知道,out下生成了很多jar包,我們選倒數第二個。為了便於識別我們把classes.jar改名為libphonenumber.jar。
匯入到工程裡
我用的是Android Studio,也希望也用這個工具,畢竟谷歌推薦用這款軟體。
首先,複製到libs下:
接著配置app那級的build.gradle,在dependencies裡面新增一行:
compile files('libs/libphonenumber.jar')
如圖:
當然了,如果你的dependencies有下面這麼一句程式碼,那就不用在手動新增,它會自動包含libs目錄下面所有的jar。
compile fileTree(dir: 'libs', include: ['*.jar'])
4.在程式碼裡面使用該庫的介面
可以仿照原始碼InCallUI模組下面CallerInfo.java類下面的getGeoDescription方法:
/**
* @return a geographical description string for the specified number.
* @see com.android.i18n.phonenumbers.PhoneNumberOfflineGeocoder
*/
private static String getGeoDescription(Context context, String number) {
Log.v(TAG, "getGeoDescription('" + number + "')...");
if (TextUtils.isEmpty(number)) {
return null;
}
PhoneNumberUtil util = PhoneNumberUtil.getInstance();
PhoneNumberOfflineGeocoder geocoder = PhoneNumberOfflineGeocoder.getInstance();
Locale locale = context.getResources().getConfiguration().locale;
String countryIso = TelephonyManagerUtils.getCurrentCountryIso(context, locale);
PhoneNumber pn = null;
try {
Log.v(TAG, "parsing '" + number
+ "' for countryIso '" + countryIso + "'...");
pn = util.parse(number, countryIso);
Log.v(TAG, "- parsed number: " + pn);
} catch (NumberParseException e) {
Log.v(TAG, "getGeoDescription: NumberParseException for incoming number '" +
number + "'");
}
if (pn != null) {
String description = geocoder.getDescriptionForNumber(pn, locale);
Log.v(TAG, "- got description: '" + description + "'");
return description;
}
return null;
}
這是我自己為了呼叫該介面,建立的一個類:
import android.content.Context;
import android.telephony.TelephonyManager;
import android.text.TextUtils;
import android.util.Log;
import com.google.i18n.phonenumbers.NumberParseException;
import com.google.i18n.phonenumbers.PhoneNumberUtil;
import com.google.i18n.phonenumbers.Phonenumber;
import com.google.i18n.phonenumbers.geocoding.PhoneNumberOfflineGeocoder;
import java.util.Locale;
/**
* Created by neal on 9/6/16.
*/
public class CallerInfo {
private static final String TAG = "CallerInfo";
/**
* @return a geographical description string for the specified number.
* @see com.android.i18n.phonenumbers.PhoneNumberOfflineGeocoder
*/
public static String getGeoDescription(Context context, String number) {
android.util.Log.d(TAG, "getGeoDescription('" + number + "')...");
if (TextUtils.isEmpty(number)) {
return null;
}
PhoneNumberUtil util = PhoneNumberUtil.getInstance();
PhoneNumberOfflineGeocoder geocoder = PhoneNumberOfflineGeocoder.getInstance();
Locale locale = context.getResources().getConfiguration().locale;
final TelephonyManager telephonyManager =
(TelephonyManager) context.getSystemService(Context.TELEPHONY_SERVICE);
String countryIso = telephonyManager.getNetworkCountryIso().toUpperCase();
if (countryIso == null) {
countryIso = locale.getCountry();
Log.w(TAG, "No CountryDetector; falling back to countryIso based on locale: "
+ countryIso);
}
Phonenumber.PhoneNumber pn = null;
try {
android.util.Log.d(TAG, "parsing '" + number
+ "' for countryIso '" + countryIso + "'...");
pn = util.parse(number, countryIso);
android.util.Log.d(TAG, "- parsed number: " + pn);
} catch (NumberParseException e) {
android.util.Log.d(TAG, "getGeoDescription: NumberParseException for incoming number '" +
number + "'");
}
if (pn != null) {
String description = geocoder.getDescriptionForNumber(pn, locale);
android.util.Log.d(TAG, "- got description: '" + description + "'");
return description;
}
return null;
}
}
最後你在需要獲取地名的地方呼叫:
String address = CallerInfo.getGeoDescription(mContext,number);