You might already have noticed that Ice Cream Sandwich does a really good job in auto formatting phone numbers while you type them in. But unfortunately, when you use the formatNumber method from the PhoneNumberUtils class, you will quickly notice that you don't achieve the same level of formatting. And this especially for non-US numbers.
This all because the dialer in ICS isn't using the same methods. The logic behind the number formatting in ICS is based on libphonenumber. libphonenumber is described as "Google's common Java, C++ and Javascript library for parsing, formatting, storing and validating international phone numbers. The Java version is optimized for running on smartphones, and is used by the Android framework since 4.0 (Ice Cream Sandwich)."
What you need to do to get this working is simply including the jar of libphonenumber on your classpath and your set to go. As an extra you can also create a basic version of the PhoneNumberUtils class which can be found in the ICS sources and gives you some extra validation.
/*
* Copyright (C) 2006 The Android Open Source Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.example.phonenumber;
import android.text.TextUtils;
import com.google.i18n.phonenumbers.NumberParseException;
import com.google.i18n.phonenumbers.PhoneNumberUtil;
import com.google.i18n.phonenumbers.PhoneNumberUtil.PhoneNumberType;
import com.google.i18n.phonenumbers.Phonenumber.PhoneNumber;
public class PhoneNumberUtils {
/*
* Special characters
*
* (See "What is a phone number?" doc)
* 'p' --- GSM pause character, same as comma
* 'n' --- GSM wild character
* 'w' --- GSM wait character
*/
public static final char PAUSE = ',';
public static final char WAIT = ';';
public static final char WILD = 'N';
/** True if c is ISO-LATIN characters 0-9, *, # , +, WILD */
public final static boolean isDialable(char c) {
return (c >= '0' && c <= '9') || c == '*' || c == '#' || c == '+' || c == WILD;
}
/**
* Format a phone number.
* <p>
* If the given number doesn't have the country code, the phone will be
* formatted to the default country's convention.
*
* @param phoneNumber
* the number to be formatted.
* @param defaultCountryIso
* the ISO 3166-1 two letters country code whose convention will
* be used if the given number doesn't have the country code.
* @return the formatted number, or null if the given number is not valid.
*
* @hide
*/
public static String formatNumber(String phoneNumber, String defaultCountryIso) {
// Do not attempt to format numbers that start with a hash or star
// symbol.
if (phoneNumber.startsWith("#") || phoneNumber.startsWith("*")) {
return phoneNumber;
}
PhoneNumberUtil util = PhoneNumberUtil.getInstance();
String result = null;
try {
PhoneNumber pn = util.parseAndKeepRawInput(phoneNumber, defaultCountryIso);
result = util.formatInOriginalFormat(pn, defaultCountryIso);
} catch (NumberParseException e) {
}
return result;
}
/**
* Format the phone number only if the given number hasn't been formatted.
* <p>
* The number which has only dailable character is treated as not being
* formatted.
*
* @param phoneNumber
* the number to be formatted.
* @param phoneNumberE164
* the E164 format number whose country code is used if the given
* phoneNumber doesn't have the country code.
* @param defaultCountryIso
* the ISO 3166-1 two letters country code whose convention will
* be used if the phoneNumberE164 is null or invalid.
* @return the formatted number if the given number has been formatted,
* otherwise, return the given number.
*
* @hide
*/
public static String formatNumber(String phoneNumber, String phoneNumberE164, String defaultCountryIso) {
int len = phoneNumber.length();
for (int i = 0; i < len; i++) {
if (!isDialable(phoneNumber.charAt(i))) {
return phoneNumber;
}
}
PhoneNumberUtil util = PhoneNumberUtil.getInstance();
// Get the country code from phoneNumberE164
if (phoneNumberE164 != null && phoneNumberE164.length() >= 2 && phoneNumberE164.charAt(0) == '+') {
try {
PhoneNumber pn = util.parse(phoneNumberE164, defaultCountryIso);
String regionCode = util.getRegionCodeForNumber(pn);
if (!TextUtils.isEmpty(regionCode)) {
defaultCountryIso = regionCode;
}
} catch (NumberParseException e) {
}
}
String result = formatNumber(phoneNumber, defaultCountryIso);
return result != null ? result : phoneNumber;
}
}
To see it in action you can testdrive the Java version or the Javascript version.







