Google's phone number handling library, powering Android and more
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).

This project provides a C# port of Google's libphonenumber

Google's libphonenumber: Link
Based on: Version 5.8 (r606)

Highlights of functionality

  • Parsing/formatting/validating phone numbers for all countries/regions of the world.
  • getNumberType - gets the type of the number based on the number itself; able to distinguish Fixed-line, Mobile, Toll-free, Premium Rate, Shared Cost, VoIP and Personal Numbers (whenever feasible).
  • isNumberMatch - gets a confidence level on whether two numbers could be the same.
  • getExampleNumber/getExampleNumberByType - provides valid example numbers for all countries/regions, with the option of specifying which type of example phone number is needed.
  • isPossibleNumber - quickly guessing whether a number is a possible phonenumber by using only the length information, much faster than a full validation.
  • isValidNumber - full validation of a phone number for a region using length and prefix information.
  • AsYouTypeFormatter - formats phone numbers on-the-fly when users enter each digit.
  • findNumbers - finds numbers in text input.
  • PhoneNumberOfflineGeocoder - provides geographical information related to a phone number.
(Source: http://code.google.com/p/libphonenumber/)
 

Examples

using libphonenumber;
...

string germanNumberStr = "089123456";
PhoneNumber number;
try
{
	number = PhoneNumberUtil.Instance.Parse(germanNumberStr, "DE");
}
catch (NumberParseException e)
{
	throw;
}

if (number.IsValidNumber)
{
	// Produces "+49 89 123456"
	Debug.WriteLine(number.Format(PhoneNumberUtil.PhoneNumberFormat.INTERNATIONAL));
	// Produces "089 123456"
	Debug.WriteLine(number.Format(PhoneNumberUtil.PhoneNumberFormat.NATIONAL));
	// Produces "+4989123456"
	Debug.WriteLine(number.Format(PhoneNumberUtil.PhoneNumberFormat.E164));

	// Produces "011 49 89 123456", the number when it is dialed in the United States.
	Debug.WriteLine(number.FormatOutOfCountryCallingNumber("US"));
}

// Outputs "Munich"
Debug.WriteLine(number.GetDescriptionForNumber(Locale.ENGLISH));
// Outputs "München"
Debug.WriteLine(number.GetDescriptionForNumber(Locale.GERMAN));
// Outputs "Munich"
Debug.WriteLine(number.GetDescriptionForNumber(Locale.ITALIAN));

AsYouTypeFormatter formatter = PhoneNumberUtil.Instance.GetAsYouTypeFormatter("DE");
Debug.WriteLine(formatter.InputDigit('0'));  // Outputs "0"
Debug.WriteLine(formatter.InputDigit('8'));  // Outputs "08"
Debug.WriteLine(formatter.InputDigit('9'));  // Outputs "089"
Debug.WriteLine(formatter.InputDigit('1'));  // Outputs "089 1"
Debug.WriteLine(formatter.InputDigit('2'));  // Outputs "089 12"
Debug.WriteLine(formatter.InputDigit('3'));  // Outputs "089 123"
Debug.WriteLine(formatter.InputDigit('4'));  // Outputs "089 1234"
Debug.WriteLine(formatter.InputDigit('5'));  // Outputs "089 12345"
Debug.WriteLine(formatter.InputDigit('6'));  // Outputs "089 123456"

Concept

There are two options to get the Java-libphonenumber working under C#:
  1. Translate all the libphonenumber's sourcecode to C# and replace all Java-API calls to its C# equivalent.
    • concept1.png
    • [+] libphonenumber is not that CPU intensive, but if its methods are used very extensive this option might be faster because the C# API is used directly.
    • [−] Regex are handled slightly differently by Java and C#. This is a big Problem because libphonenumber depends very much on Regular Expressions. Not only in the source code, but also in the Metadata files.
  2. Leave the Java source as it is (only the necessary changes) and implement the parts of the Java-API with are used by libphonenumber.
    • concept2.png
    • [+] Source code strays as it is, so updating future changes is much easier.
    • [+] The existing binary Metadata files can be used.
    • [+] If the original Java-Regex implementation is used, there should not be any problem in using the Regular Expressions from the Source code or the Metadata files.
    • [−] It might be more work to implement Java instate of just translating libphonenumber's source code. :)
So for this project I've decided to use the second option.

Necessary changes

Java C# Note
final readonly, const, sealed Depending on the Context
package x.y.z; namespace x.y.z { ... }
int test[]; int[] test; Different syntax
test.length test.Length Different syntax
for(x : y) foreach(x in y) Different syntax
i >>> 4 (int)((uint)i >> 4) Workaround
void someMethod() {} internal void someMethod() {} Different default visability
enum with code class with code Workaround
switch (x) { case 1: default: ... } Rewrite Code fallthrough not suported
int in, out; int @in, @out; Different keywords
synchronized lock Different keywords
super(...) : base(...) Different syntax
class x extends y implements z class x : y, z Different syntax
static { ... } static ClassName { ... } Different syntax

Apart from this changes the original java source code staied almost the same.

Unit Tests

Also all the original tests have been tranalated to C#

tests.png

And of course all passed!

Last edited Sep 9, 2013 at 8:01 PM by bepe, version 72