libphonenumber:Google的公共電話號碼解析庫

前言

以前在項目中碰到一個問題,測試提了個需求:接聽接話使,皮套界面要能解析號碼的來源地,並且要和系統的語言保持一致。這個問題說難不難,但是也不簡單,一般情況下,我們可能會想到建立一個數據庫,然後寫一個ContentPrivoder,然後在項目中使用提供的URI來解析電話號碼。

如果你真的這麼想,那麼你這個任務就是無盡的任務了。因爲你需要適配各種語言,需要收集這個國家的地名,這簡直是不可能完成的任務!

好了,大家稍安勿躁,我不是來吐槽的,我是來提供解決方法的,大家接着看下去。


我認爲最好的辦法就是用Google的公共電話號碼解析庫—libphonenumber

這個庫Android源碼的路徑是:

    external/libphonenumber/
    當然了,github上面也有,地址是:
    [libphonenumber](https://github.com/googlei18n/libphonenumber)

由於我本人是直接使用Android源碼下的庫,所以我接下來用它來舉例子。

首先用使用這個庫,有兩個方法:

  • 將libphonenumber作爲module放到你的工程裏
  • 將libphonenumber作爲jar放到Android工程的libs目錄下

步驟

在這裏我們使用第二種,至於第一種方法不會使用的,可以問度娘,接來我說說使用步驟:

  1. 編譯libphonenumber
    使用mmm external/libphonenumber/,之後在終端下看到這個:
    生成jar包

  2. 找到對應的jar包

    看圖可以知道,out下生成了很多jar包,我們選倒數第二個。爲了便於識別我們把classes.jar改名爲libphonenumber.jar。

  3. 導入到工程裏

    我用的是Android Studio,也希望也用這個工具,畢竟谷歌推薦用這款軟件。
    首先,複製到libs下:
    複製到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);
發佈了27 篇原創文章 · 獲贊 28 · 訪問量 18萬+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章