FileDocCategorySizeDatePackage
PhoneNumberUtils.javaAPI DocAndroid 1.5 API39036Wed May 06 22:42:00 BST 2009android.telephony

PhoneNumberUtils

public class PhoneNumberUtils extends Object
Various utilities for dealing with phone number strings.

Fields Summary
public static final char
PAUSE
public static final char
WAIT
public static final char
WILD
public static final int
TOA_International
public static final int
TOA_Unknown
private static final Pattern
GLOBAL_PHONE_NUMBER_PATTERN
public static final int
FORMAT_UNKNOWN
The current locale is unknown, look for a country code or don't format
public static final int
FORMAT_NANP
NANP formatting
public static final int
FORMAT_JAPAN
Japanese formatting
private static final String[]
NANP_COUNTRIES
List of country codes for countries that use the NANP
private static final int
NANP_STATE_DIGIT
private static final int
NANP_STATE_PLUS
private static final int
NANP_STATE_ONE
private static final int
NANP_STATE_DASH
static final int
MIN_MATCH
private static final android.util.SparseIntArray
KEYPAD_MAP
The phone keypad letter mapping (see ITU E.161 or ISO/IEC 9995-8.) TODO: This should come from a resource.
Constructors Summary
Methods Summary
private static charbcdToChar(byte b)
returns 0 on invalid value

        if (b < 0xa) {
            return (char)('0" + b);
        } else switch (b) {
            case 0xa: return '*";
            case 0xb: return '#";
            case 0xc: return PAUSE;
            case 0xd: return WILD;

            default: return 0;
        }
    
public static java.lang.StringcalledPartyBCDFragmentToString(byte[] bytes, int offset, int length)
Like calledPartyBCDToString, but field does not start with a TOA byte. For example: SIM ADN extension fields

        StringBuilder ret = new StringBuilder(length * 2);

        internalCalledPartyBCDFragmentToString(ret, bytes, offset, length);

        return ret.toString();
    
public static java.lang.StringcalledPartyBCDToString(byte[] bytes, int offset, int length)
3GPP TS 24.008 10.5.4.7 Called Party BCD Number See Also TS 51.011 10.5.1 "dialing number/ssc string" and TS 11.11 "10.3.1 EF adn (Abbreviated dialing numbers)"

param
bytes the data buffer
param
offset should point to the TOA (aka. TON/NPI) octet after the length byte
param
length is the number of bytes including TOA byte and must be at least 2
return
partial string on invalid decode FIXME(mkf) support alphanumeric address type currently implemented in SMSMessage.getAddress()

        boolean prependPlus = false;
        StringBuilder ret = new StringBuilder(1 + length * 2);

        if (length < 2) {
            return "";
        }

        if ((bytes[offset] & 0xff) == TOA_International) {
            prependPlus = true;
        }

        internalCalledPartyBCDFragmentToString(
                ret, bytes, offset + 1, length - 1);

        if (prependPlus && ret.length() == 0) {
            // If the only thing there is a prepended plus, return ""
            return "";
        }

        if (prependPlus) {
            // This is an "international number" and should have
            // a plus prepended to the dialing number. But there
            // can also be Gsm MMI codes as defined in TS 22.030 6.5.2
            // so we need to handle those also.
            //
            // http://web.telia.com/~u47904776/gsmkode.htm is a
            // has a nice list of some of these GSM codes.
            //
            // Examples are:
            //   **21*+886988171479#
            //   **21*8311234567#
            //   *21#
            //   #21#
            //   *#21#
            //   *31#+11234567890
            //   #31#+18311234567
            //   #31#8311234567
            //   18311234567
            //   +18311234567#
            //   +18311234567
            // Odd ball cases that some phones handled
            // where there is no dialing number so they
            // append the "+"
            //   *21#+
            //   **21#+
            String retString = ret.toString();
            Pattern p = Pattern.compile("(^[#*])(.*)([#*])(.*)(#)$");
            Matcher m = p.matcher(retString);
            if (m.matches()) {
                if ("".equals(m.group(2))) {
                    // Started with two [#*] ends with #
                    // So no dialing number and we'll just
                    // append a +, this handles **21#+
                    ret = new StringBuilder();
                    ret.append(m.group(1));
                    ret.append(m.group(3));
                    ret.append(m.group(4));
                    ret.append(m.group(5));
                    ret.append("+");
                } else {
                    // Starts with [#*] and ends with #
                    // Assume group 4 is a dialing number
                    // such as *21*+1234554#
                    ret = new StringBuilder();
                    ret.append(m.group(1));
                    ret.append(m.group(2));
                    ret.append(m.group(3));
                    ret.append("+");
                    ret.append(m.group(4));
                    ret.append(m.group(5));
                }
            } else {
                p = Pattern.compile("(^[#*])(.*)([#*])(.*)");
                m = p.matcher(retString);
                if (m.matches()) {
                    // Starts with [#*] and only one other [#*]
                    // Assume the data after last [#*] is dialing
                    // number (i.e. group 4) such as *31#+11234567890.
                    // This also includes the odd ball *21#+
                    ret = new StringBuilder();
                    ret.append(m.group(1));
                    ret.append(m.group(2));
                    ret.append(m.group(3));
                    ret.append("+");
                    ret.append(m.group(4));
                } else {
                    // Does NOT start with [#*] just prepend '+'
                    ret = new StringBuilder();
                    ret.append('+");
                    ret.append(retString);
                }
            }
        }

        return ret.toString();
    
private static intcharToBCD(char c)

        if (c >= '0" && c <= '9") {
            return c - '0";
        } else if (c == '*") {
            return 0xa;
        } else if (c == '#") {
            return 0xb;
        } else if (c == PAUSE) {
            return 0xc;
        } else if (c == WILD) {
            return 0xd;
        } else {
            throw new RuntimeException ("invalid char for BCD " + c);
        }
    
public static booleancompare(java.lang.String a, java.lang.String b)
Compare phone numbers a and b, return true if they're identical enough for caller ID purposes. - Compares from right to left - requires MIN_MATCH (5) characters to match - handles common trunk prefixes and international prefixes (basically, everything except the Russian trunk prefix) Tolerates nulls

        int ia, ib;
        int matched;

        if (a == null || b == null) return a == b;

        if (a.length() == 0 || b.length() == 0) {
            return false;
        }

        ia = indexOfLastNetworkChar (a);
        ib = indexOfLastNetworkChar (b);
        matched = 0;

        while (ia >= 0 && ib >=0) {
            char ca, cb;
            boolean skipCmp = false;

            ca = a.charAt(ia);

            if (!isDialable(ca)) {
                ia--;
                skipCmp = true;
            }

            cb = b.charAt(ib);

            if (!isDialable(cb)) {
                ib--;
                skipCmp = true;
            }

            if (!skipCmp) {
                if (cb != ca && ca != WILD && cb != WILD) {
                    break;
                }
                ia--; ib--; matched++;
            }
        }

        if (matched < MIN_MATCH) {
            int aLen = a.length();

            // if the input strings match, but their lengths < MIN_MATCH,
            // treat them as equal.
            if (aLen == b.length() && aLen == matched) {
                return true;
            }
            return false;
        }

        // At least one string has matched completely;
        if (matched >= MIN_MATCH && (ia < 0 || ib < 0)) {
            return true;
        }

        /*
         * Now, what remains must be one of the following for a
         * match:
         *
         *  - a '+' on one and a '00' or a '011' on the other
         *  - a '0' on one and a (+,00)<country code> on the other
         *     (for this, a '0' and a '00' prefix would have succeeded above)
         */

        if (matchIntlPrefix(a, ia + 1)
            && matchIntlPrefix (b, ib +1)
        ) {
            return true;
        }

        if (matchTrunkPrefix(a, ia + 1)
            && matchIntlPrefixAndCC(b, ib +1)
        ) {
            return true;
        }

        if (matchTrunkPrefix(b, ib + 1)
            && matchIntlPrefixAndCC(a, ia +1)
        ) {
            return true;
        }

        return false;
    
public static java.lang.StringconvertKeypadLettersToDigits(java.lang.String input)
Translates any alphabetic letters (i.e. [A-Za-z]) in the specified phone number into the equivalent numeric digits, according to the phone keypad letter mapping described in ITU E.161 and ISO/IEC 9995-8.

return
the input string, with alpha letters converted to numeric digits using the phone keypad letter mapping. For example, an input of "1-800-GOOG-411" will return "1-800-4664-411".

        if (input == null) {
            return input;
        }
        int len = input.length();
        if (len == 0) {
            return input;
        }

        char[] out = input.toCharArray();

        for (int i = 0; i < len; i++) {
            char c = out[i];
            // If this char isn't in KEYPAD_MAP at all, just leave it alone.
            out[i] = (char) KEYPAD_MAP.get(c, c);
        }

        return new String(out);
    
public static java.lang.StringextractNetworkPortion(java.lang.String phoneNumber)
Extracts the network address portion and canonicalizes (filters out separators.) Network address portion is everything up to DTMF control digit separators (pause or wait), but without non-dialable characters. Please note that the GSM wild character is allowed in the result. This must be resolved before dialing. Allows + only in the first position in the result string. Returns null if phoneNumber == null

        if (phoneNumber == null) {
            return null;
        }

        int len = phoneNumber.length();
        StringBuilder ret = new StringBuilder(len);
        boolean firstCharAdded = false;

        for (int i = 0; i < len; i++) {
            char c = phoneNumber.charAt(i);
            if (isDialable(c) && (c != '+" || !firstCharAdded)) {
                firstCharAdded = true;
                ret.append(c);
            } else if (isStartsPostDial (c)) {
                break;
            }
        }

        return ret.toString();
    
public static java.lang.StringextractPostDialPortion(java.lang.String phoneNumber)
Extracts the post-dial sequence of DTMF control digits, pauses, and waits. Strips separators. This string may be empty, but will not be null unless phoneNumber == null. Returns null if phoneNumber == null

        if (phoneNumber == null) return null;

        int trimIndex;
        StringBuilder ret = new StringBuilder();

        trimIndex = indexOfLastNetworkChar (phoneNumber);

        for (int i = trimIndex + 1, s = phoneNumber.length()
                ; i < s; i++
        ) {
            char c = phoneNumber.charAt(i);
            if (isNonSeparator(c)) {
                ret.append(c);
            }
        }

        return ret.toString();
    
public static voidformatJapaneseNumber(android.text.Editable text)
Formats a phone number in-place using the Japanese formatting rules. Numbers will be formatted as:

03-xxxx-xxxx 090-xxxx-xxxx 0120-xxx-xxx +81-3-xxxx-xxxx +81-90-xxxx-xxxx

param
text the number to be formatted, will be modified with the formatting

        JapanesePhoneNumberFormatter.format(text);
    
public static voidformatNanpNumber(android.text.Editable text)
Formats a phone number in-place using the NANP formatting rules. Numbers will be formatted as:

xxx-xxxx xxx-xxx-xxxx 1-xxx-xxx-xxxx +1-xxx-xxx-xxxx

param
text the number to be formatted, will be modified with the formatting


                                           
         
        int length = text.length();
        if (length > "+1-nnn-nnn-nnnn".length()) {
            // The string is too long to be formatted
            return;
        }
        CharSequence saved = text.subSequence(0, length);

        // Strip the dashes first, as we're going to add them back
        int p = 0;
        while (p < text.length()) {
            if (text.charAt(p) == '-") {
                text.delete(p, p + 1);
            } else {
                p++;
            }
        }
        length = text.length();

        // When scanning the number we record where dashes need to be added,
        // if they're non-0 at the end of the scan the dashes will be added in
        // the proper places.
        int dashPositions[] = new int[3];
        int numDashes = 0;

        int state = NANP_STATE_DIGIT;
        int numDigits = 0;
        for (int i = 0; i < length; i++) {
            char c = text.charAt(i);
            switch (c) {
                case '1":
                    if (numDigits == 0 || state == NANP_STATE_PLUS) {
                        state = NANP_STATE_ONE;
                        break;
                    }
                    // fall through
                case '2":
                case '3":
                case '4":
                case '5":
                case '6":
                case '7":
                case '8":
                case '9":
                case '0":
                    if (state == NANP_STATE_PLUS) {
                        // Only NANP number supported for now
                        text.replace(0, length, saved);
                        return;
                    } else if (state == NANP_STATE_ONE) {
                        // Found either +1 or 1, follow it up with a dash
                        dashPositions[numDashes++] = i;
                    } else if (state != NANP_STATE_DASH && (numDigits == 3 || numDigits == 6)) {
                        // Found a digit that should be after a dash that isn't
                        dashPositions[numDashes++] = i;
                    }
                    state = NANP_STATE_DIGIT;
                    numDigits++;
                    break;

                case '-":
                    state = NANP_STATE_DASH;
                    break;

                case '+":
                    if (i == 0) {
                        // Plus is only allowed as the first character
                        state = NANP_STATE_PLUS;
                        break;
                    }
                    // Fall through
                default:
                    // Unknown character, bail on formatting
                    text.replace(0, length, saved);
                    return;
            }
        }

        if (numDigits == 7) {
            // With 7 digits we want xxx-xxxx, not xxx-xxx-x
            numDashes--;
        }

        // Actually put the dashes in place
        for (int i = 0; i < numDashes; i++) {
            int pos = dashPositions[i];
            text.replace(pos + i, pos + i, "-");
        }

        // Remove trailing dashes
        int len = text.length();
        while (len > 0) {
            if (text.charAt(len - 1) == '-") {
                text.delete(len - 1, len);
                len--;
            } else {
                break;
            }
        }
    
public static java.lang.StringformatNumber(java.lang.String source)
Breaks the given number down and formats it according to the rules for the country the number is from.

param
source the phone number to format
return
a locally acceptable formatting of the input, or the raw input if formatting rules aren't known for the number


                                                        
         
        SpannableStringBuilder text = new SpannableStringBuilder(source);
        formatNumber(text, getFormatTypeForLocale(Locale.getDefault()));
        return text.toString();
    
public static voidformatNumber(android.text.Editable text, int defaultFormattingType)
Formats a phone number in-place. Currently only supports NANP formatting.

param
text The number to be formatted, will be modified with the formatting
param
defaultFormattingType The default formatting rules to apply if the number does not begin with +

        int formatType = defaultFormattingType;

        if (text.length() > 2 && text.charAt(0) == '+") {
            if (text.charAt(1) == '1") {
                formatType = FORMAT_NANP;
            } else if (text.length() >= 3 && text.charAt(1) == '8"
                && text.charAt(2) == '1") {
                formatType = FORMAT_JAPAN;
            } else {
                return;
            }
        }

        switch (formatType) {
            case FORMAT_NANP:
                formatNanpNumber(text);
                return;
            case FORMAT_JAPAN:
                formatJapaneseNumber(text);
                return;
        }
    
public static intgetFormatTypeForLocale(java.util.Locale locale)
Returns the phone number formatting type for the given locale.

param
locale The locale of interest, usually {@link Locale#getDefault()}
return
the formatting type for the given locale, or FORMAT_UNKNOWN if the formatting rules are not known for the given locale

        String country = locale.getCountry();

        // Check for the NANP countries
        int length = NANP_COUNTRIES.length;
        for (int i = 0; i < length; i++) {
            if (NANP_COUNTRIES[i].equals(country)) {
                return FORMAT_NANP;
            }
        }
        if (locale.equals(Locale.JAPAN)) {
            return FORMAT_JAPAN;
        }
        return FORMAT_UNKNOWN;
    
public static java.lang.StringgetNumberFromIntent(android.content.Intent intent, android.content.Context context)
Extracts the phone number from an Intent.

param
intent the intent to get the number of
param
context a context to use for database access
return
the phone number that would be called by the intent, or null if the number cannot be found.

        String number = null;

        Uri uri = intent.getData();
        String scheme = uri.getScheme();

        if (scheme.equals("tel")) {
            return uri.getSchemeSpecificPart();
        }

        if (scheme.equals("voicemail")) {
            return TelephonyManager.getDefault().getVoiceMailNumber();
        }

        if (context == null) {
            return null;
        }

        String type = intent.resolveType(context);

        Cursor c = context.getContentResolver().query(
                uri, new String[]{ Contacts.People.Phones.NUMBER },
                null, null, null);
        if (c != null) {
            try {
                if (c.moveToFirst()) {
                    number = c.getString(
                            c.getColumnIndex(Contacts.People.Phones.NUMBER));
                }
            } finally {
                c.close();
            }
        }

        return number;
    
public static java.lang.StringgetStrippedReversed(java.lang.String phoneNumber)
Returns the network portion reversed. This string is intended to go into an index column for a database lookup. Returns null if phoneNumber == null

        String np = extractNetworkPortion(phoneNumber);

        if (np == null) return null;

        return internalGetStrippedReversed(np, np.length());
    
private static booleanhasPlus(java.lang.String s)

      return s.indexOf('+") >= 0;
    
private static intindexOfLastNetworkChar(java.lang.String a)
index of the last character of the network portion (eg anything after is a post-dial string)

        int pIndex, wIndex;
        int origLength;
        int trimIndex;

        origLength = a.length();

        pIndex = a.indexOf(PAUSE);
        wIndex = a.indexOf(WAIT);

        trimIndex = minPositive(pIndex, wIndex);

        if (trimIndex < 0) {
            return origLength - 1;
        } else {
            return trimIndex - 1;
        }
    
private static voidinternalCalledPartyBCDFragmentToString(java.lang.StringBuilder sb, byte[] bytes, int offset, int length)

        for (int i = offset ; i < length + offset ; i++) {
            byte b;
            char c;

            c = bcdToChar((byte)(bytes[i] & 0xf));

            if (c == 0) {
                return;
            }
            sb.append(c);

            // FIXME(mkf) TS 23.040 9.1.2.3 says
            // "if a mobile receives 1111 in a position prior to
            // the last semi-octet then processing shall commense with
            // the next semi-octet and the intervening
            // semi-octet shall be ignored"
            // How does this jive with 24,008 10.5.4.7

            b = (byte)((bytes[i] >> 4) & 0xf);

            if (b == 0xf && i + 1 == length + offset) {
                //ignore final 0xf
                break;
            }

            c = bcdToChar(b);
            if (c == 0) {
                return;
            }

            sb.append(c);
        }

    
private static java.lang.StringinternalGetStrippedReversed(java.lang.String np, int numDigits)
Returns the last numDigits of the reversed phone number Returns null if np == null

        if (np == null) return null;

        StringBuilder ret = new StringBuilder(numDigits);
        int length = np.length();

        for (int i = length - 1, s = length
            ; i >= 0 && (s - i) <= numDigits ; i--
        ) {
            char c = np.charAt(i);

            ret.append(c);
        }

        return ret.toString();
    
public static final booleanis12Key(char c)
True if c is ISO-LATIN characters 0-9, *, #

        return (c >= '0" && c <= '9") || c == '*" || c == '#";
    
private static booleanisDialable(java.lang.String address)

        for (int i = 0, count = address.length(); i < count; i++) {
            if (!isDialable(address.charAt(i))) {
                return false;
            }
        }
        return true;
    
public static final booleanisDialable(char c)
True if c is ISO-LATIN characters 0-9, *, # , +, WILD

        return (c >= '0" && c <= '9") || c == '*" || c == '#" || c == '+" || c == WILD;
    
public static booleanisEmergencyNumber(java.lang.String number)
isEmergencyNumber: checks a given number against the list of emergency numbers provided by the RIL and SIM card.

param
number the number to look up.
return
if the number is in the list of emergency numbers listed in the ril / sim, then return true, otherwise false.


                                                          
         
        // Strip the separators from the number before comparing it
        // to the list.
        number = extractNetworkPortion(number);

        // retrieve the list of emergency numbers
        String numbers = SystemProperties.get("ro.ril.ecclist");

        if (!TextUtils.isEmpty(numbers)) {
            // searches through the comma-separated list for a match,
            // return true if one is found.
            for (String emergencyNum : numbers.split(",")) {
                if (emergencyNum.equals(number)) {
                    return true;
                }
            }
            // no matches found against the list!
            return false;
        }

        //no ecclist system property, so use our own list.
        return (number.equals("112") || number.equals("911"));
    
public static booleanisGlobalPhoneNumber(java.lang.String phoneNumber)

        if (TextUtils.isEmpty(phoneNumber)) {
            return false;
        }

        Matcher match = GLOBAL_PHONE_NUMBER_PATTERN.matcher(phoneNumber);
        return match.matches();
    
public static booleanisISODigit(char c)
True if c is ISO-LATIN characters 0-9


            
      
       
        return c >= '0" && c <= '9";
    
public static final booleanisNonSeparator(char c)
True if c is ISO-LATIN characters 0-9, *, # , +, WILD, WAIT, PAUSE

        return (c >= '0" && c <= '9") || c == '*" || c == '#" || c == '+"
                || c == WILD || c == WAIT || c == PAUSE;
    
public static final booleanisReallyDialable(char c)
True if c is ISO-LATIN characters 0-9, *, # , + (no WILD)

        return (c >= '0" && c <= '9") || c == '*" || c == '#" || c == '+";
    
public static final booleanisStartsPostDial(char c)
This any anything to the right of this char is part of the post-dial string (eg this is PAUSE or WAIT)

        return c == PAUSE || c == WAIT;
    
public static booleanisWellFormedSmsAddress(java.lang.String address)
Return true iff the network portion of address is, as far as we can tell on the device, suitable for use as an SMS destination address.

        String networkPortion =
                PhoneNumberUtils.extractNetworkPortion(address);

        return (!(networkPortion.equals("+")
                  || TextUtils.isEmpty(networkPortion)))
               && isDialable(networkPortion);
    
private static booleanmatchIntlPrefix(java.lang.String a, int len)
all of a up to len must be an international prefix or separators/non-dialing digits

        /* '([^0-9*#+pwn]\+[^0-9*#+pwn] | [^0-9*#+pwn]0(0|11)[^0-9*#+pwn] )$' */
        /*        0       1                           2 3 45               */

        int state = 0;
        for (int i = 0 ; i < len ; i++) {
            char c = a.charAt(i);

            switch (state) {
                case 0:
                    if      (c == '+") state = 1;
                    else if (c == '0") state = 2;
                    else if (isNonSeparator(c)) return false;
                break;

                case 2:
                    if      (c == '0") state = 3;
                    else if (c == '1") state = 4;
                    else if (isNonSeparator(c)) return false;
                break;

                case 4:
                    if      (c == '1") state = 5;
                    else if (isNonSeparator(c)) return false;
                break;

                default:
                    if (isNonSeparator(c)) return false;
                break;

            }
        }

        return state == 1 || state == 3 || state == 5;
    
private static booleanmatchIntlPrefixAndCC(java.lang.String a, int len)
all of 'a' up to len must be a (+|00|011)country code) We're fast and loose with the country code. Any \d{1,3} matches

        /*  [^0-9*#+pwn]*(\+|0(0|11)\d\d?\d? [^0-9*#+pwn] $ */
        /*      0          1 2 3 45  6 7  8                 */

        int state = 0;
        for (int i = 0 ; i < len ; i++ ) {
            char c = a.charAt(i);

            switch (state) {
                case 0:
                    if      (c == '+") state = 1;
                    else if (c == '0") state = 2;
                    else if (isNonSeparator(c)) return false;
                break;

                case 2:
                    if      (c == '0") state = 3;
                    else if (c == '1") state = 4;
                    else if (isNonSeparator(c)) return false;
                break;

                case 4:
                    if      (c == '1") state = 5;
                    else if (isNonSeparator(c)) return false;
                break;

                case 1:
                case 3:
                case 5:
                    if      (isISODigit(c)) state = 6;
                    else if (isNonSeparator(c)) return false;
                break;

                case 6:
                case 7:
                    if      (isISODigit(c)) state++;
                    else if (isNonSeparator(c)) return false;
                break;

                default:
                    if (isNonSeparator(c)) return false;
            }
        }

        return state == 6 || state == 7 || state == 8;
    
private static booleanmatchTrunkPrefix(java.lang.String a, int len)
all of 'a' up to len must match non-US trunk prefix ('0')

        boolean found;

        found = false;

        for (int i = 0 ; i < len ; i++) {
            char c = a.charAt(i);

            if (c == '0" && !found) {
                found = true;
            } else if (isNonSeparator(c)) {
                return false;
            }
        }

        return found;
    
private static intminPositive(int a, int b)
or -1 if both are negative

        if (a >= 0 && b >= 0) {
            return (a < b) ? a : b;
        } else if (a >= 0) { /* && b < 0 */
            return a;
        } else if (b >= 0) { /* && a < 0 */
            return b;
        } else { /* a < 0 && b < 0 */
            return -1;
        }
    
public static byte[]networkPortionToCalledPartyBCD(java.lang.String s)
Note: calls extractNetworkPortion(), so do not use for SIM EF[ADN] style records Exceptions thrown if extractNetworkPortion(s).length() == 0

        return numberToCalledPartyBCD(extractNetworkPortion(s));
    
public static byte[]networkPortionToCalledPartyBCDWithLength(java.lang.String s)
Same as {@link #networkPortionToCalledPartyBCD}, but includes a one-byte length prefix.

        return numberToCalledPartyBCDWithLength(extractNetworkPortion(s));
    
public static byte[]numberToCalledPartyBCD(java.lang.String number)
Convert a dialing number to BCD byte array

param
number dialing number string if the dialing number starts with '+', set to internationl TOA
return
BCD byte array

        // The extra byte required for '+' is taken into consideration while calculating
        // length of ret.
        int size = (hasPlus(number) ? number.length() - 1 : number.length());
        byte[] ret = new byte[(size + 1) / 2 + 1];

        return numberToCalledPartyBCDHelper(ret, 0, number);
    
private static byte[]numberToCalledPartyBCDHelper(byte[] ret, int offset, java.lang.String number)

        if (hasPlus(number)) {
            number = number.replaceAll("\\+", "");
            ret[offset] = (byte) TOA_International;
        } else {
            ret[offset] = (byte) TOA_Unknown;
        }

        int size = number.length();
        int curChar = 0;
        int countFullBytes = ret.length - offset - 1 - ((size - curChar) & 1);
        for (int i = 1; i < 1 + countFullBytes; i++) {
            ret[offset + i]
                    = (byte) ((charToBCD(number.charAt(curChar++)))
                              | (charToBCD(number.charAt(curChar++))) << 4);
        }

        // The left-over octet for odd-length phone numbers should be
        // filled with 0xf.
        if (countFullBytes + offset < ret.length - 1) {
            ret[ret.length - 1]
                    = (byte) (charToBCD(number.charAt(curChar))
                              | (0xf << 4));
        }
        return ret;
    
private static byte[]numberToCalledPartyBCDWithLength(java.lang.String number)
Same as {@link #numberToCalledPartyBCD}, but includes a one-byte length prefix.

        // The extra byte required for '+' is taken into consideration while calculating
        // length of ret.
        int size = (hasPlus(number) ? number.length() - 1 : number.length());
        int length = (size + 1) / 2 + 1;
        byte[] ret = new byte[length + 1];

        ret[0] = (byte) (length & 0xff);
        return numberToCalledPartyBCDHelper(ret, 1, number);
    
public static java.lang.StringstringFromStringAndTOA(java.lang.String s, int TOA)
Basically: makes sure there's a + in front of a TOA_International number Returns null if s == null

        if (s == null) return null;

        if (TOA == TOA_International && s.length() > 0 && s.charAt(0) != '+") {
            return "+" + s;
        }

        return s;
    
public static java.lang.StringstripSeparators(java.lang.String phoneNumber)
Strips separators from a phone number string.

param
phoneNumber phone number to strip.
return
phone string stripped of separators.

        if (phoneNumber == null) {
            return null;
        }
        int len = phoneNumber.length();
        StringBuilder ret = new StringBuilder(len);

        for (int i = 0; i < len; i++) {
            char c = phoneNumber.charAt(i);
            if (isNonSeparator(c)) {
                ret.append(c);
            }
        }

        return ret.toString();
    
public static java.lang.StringtoCallerIDMinMatch(java.lang.String phoneNumber)
Returns the rightmost MIN_MATCH (5) characters in the network portion in *reversed* order This can be used to do a database lookup against the column that stores getStrippedReversed() Returns null if phoneNumber == null

        String np = extractNetworkPortion(phoneNumber);
        return internalGetStrippedReversed(np, MIN_MATCH);
    
public static inttoaFromString(java.lang.String s)
Returns the TOA for the given dial string Basically, returns TOA_International if there's a + prefix

        if (s != null && s.length() > 0 && s.charAt(0) == '+") {
            return TOA_International;
        }

        return TOA_Unknown;