I have spent quite some time debugging an issue where a phone number that was entered, formatted and validated on an Android device was rejected by the backend server because it could not be used to send an SMS.
It turns out formatting and validating phone numbers can be a bit tricky, depending on the phone number and the specific locale of the device.
What was happening?
The user enters his phone number into an EditText that has TextWatcher attached to it.
The TextWatcher is a standard Android
PhoneNumberFormattingTextWatcher and automatically formats the phone number while typing.
When the user is done, the number is reformatted in the international E164 format using
PhoneNumberUtils.formatNumberToE164 before it is sent to the backend.
Note that both the
PhoneNumberUtils.formatNumberToE164() require a country code to figure out if a phone number is valid and how it should be formatted.
When a Belgian user types the phone number 0475873235, he will see 0475 87 32 35, and the backend will receive the full E164 number +32475873235. This is a valid mobile number in Belgium and can be used to send an SMS.
This example works fine when the locale of the user’s device is set to the Belgian locale
Unfortunately things start to go wrong when the user has set his phone to
nl_NL instead of
Both locales are largely the same (e.g. the UI is shown in Dutch, date and amounts are formatted the same way,…) but they do phone number formatting differently.
nl_NL device, when the user types the phone number 0475873235, he will still see 0475 87 32 35 because that phone number is also valid in the Netherlands.
But this time the backend will receive the full E164 number +31475873235, with the international prefix for the Netherlands: 31.
Even though this is a valid number in the Netherlands, it is not a valid mobile number and can not be used to send an SMS. The server encounters a problem and returns an error.
|Locale||User types||User sees||Backend gets||Backend sends SMS|
|nl_BE||0475873235||0475 87 32 35||+32475873235||Success|
|nl_NL||0475873235||0475 87 32 35||+31475873235||Failure|
Since quite a few people in Belgium have set up their phone as
nl_NL instead of
nl_BE, it’s best to avoid
Instead I decided to use the country code provided by
TelephonyManager.getNetworkCountryIso(). This returns the country code of the current registered operator of the cell tower nearby.
Note that this code has a fallback to
Locale.getDefault().getCountry() when the operator’s country code is not available.