How can we validate the length of a mobile number by COUNTRY?
(Knowing that the country code might or might not be part of the number)
Length may vary per country, meaning there should be a length range or pattern validator.
Example:
+1 222 2222 222 (13 digits) Valid ✔️
222 2222 222 (12 digits) Valid only if chosen in corresponding Locale ✔️
+1 222 2222 2222222 (17 digits) Invalid ❌
+1 222 2222 (8 digits) Invalid ❌
Note: Any idea where can I find each country's mobile number length range.
Thank you!
Given the mobile number and the country code, you can use libphonenumeer which is a Google library for validating phone numbers; it checks the number length and catches NumberParseException exception if it is not a right number.
This is their sample in how to use it
String swissNumberStr = "044 668 18 00";
PhoneNumberUtil phoneUtil = PhoneNumberUtil.getInstance();
try {
PhoneNumber swissNumberProto = phoneUtil.parse(swissNumberStr, "CH");
} catch (NumberParseException e) {
System.err.println("NumberParseException was thrown: " + e.toString());
}
Adding to #Zain 's answer.
String swissNumberStr = "044 668 18 00";
PhoneNumberUtil phoneUtil = PhoneNumberUtil.getInstance();
try {
PhoneNumber swissNumberProto = phoneUtil.parse(swissNumberStr, "CH");
// This will check if the phone number is real and its length is valid.
boolean isPossible = phoneUtil.isPossibleNumber(swissNumberProto);
} catch (NumberParseException e) {
System.err.println("NumberParseException was thrown: " + e.toString());
}
Related
I am working on a inventory management system where it's required to write asset ids (with length of maximum 17) in to an RFID tag.
First the problem was that when I write on a tag an ID with shorter length than the already written one, it keeps the non overridden characters in the tag.
for ex: if the tag has the ID "123456789" written on it and I write id "abc" on the tag. The tag's asset id becomes abc456789. I tried killing and erasing the tag before writing but it didn't work.
After that, I though of appending zeros before the target ID until it reaches the maximum length (17) so that this way no asset id with shorter length will be written on the tag and after reading I remove all preceding zero's. This worked well with a certain tag but not with another one, I figured out that the other tag can't be written on with more than 12 characters but I don't get why and the problem isn't in the RFID tag since it works well in another application and can be written on with more than 12 characters.
I would be really thankful if anyone could help me identify why this tag has only 12 characters written on it and the rest of the asset ID is neglected even though the same code works with another RFID tag.
Here's the write tag method:
fun writeTag(sourceEPC: String?, targetData: String): TagData? {
errorMessage = ""
try {
val tagData = TagData()
val tagAccess = TagAccess()
val writeAccessParams = tagAccess.WriteAccessParams()
writeAccessParams.accessPassword = 0
writeAccessParams.memoryBank = MEMORY_BANK.MEMORY_BANK_EPC
writeAccessParams.offset = 2
var paddedTargetData = padLeftZeros(targetData,17)
val targetDataInHex = HexStringConverter.getHexStringConverterInstance().stringToHex(if (paddedTargetData.length % 2 != 0) "0$paddedTargetData" else paddedTargetData)//if ODD
val padded = targetDataInHex + RFID_ADDED_VALUE
writeAccessParams.setWriteData(padded)
writeAccessParams.writeRetries = 1
writeAccessParams.writeDataLength = padded.length / 4 // WORD EQUALS 4 HEX
reader!!.Actions.TagAccess.writeWait(sourceEPC, writeAccessParams, null, tagData)
return tagData
} catch (e: InvalidUsageException) {
errorMessage = "InvalidUsageException=" + e.vendorMessage + " " + e.info
println(errorMessage)
return null
} catch (e: OperationFailureException) {
errorMessage = "InvalidUsageException=" + e.vendorMessage + " " + e.results
println(errorMessage)
return null
} catch (e: UnsupportedEncodingException) {
errorMessage = if (e.message == null) "" else e.message!!
println(errorMessage)
return null
}
}
Read Full Tag method:
fun readFullTag(sourceEPC: String): TagData? {
errorMessage = ""
try {
val tagAccess = TagAccess()
val readAccessParams = tagAccess.ReadAccessParams()
readAccessParams.accessPassword = 0
readAccessParams.memoryBank = MEMORY_BANK.MEMORY_BANK_TID
readAccessParams.offset = 0
return reader?.Actions?.TagAccess?.readWait(sourceEPC, readAccessParams, null, false)
} catch (e: InvalidUsageException) {
errorMessage = "InvalidUsageException=" + e.vendorMessage + " " + e.info
println(errorMessage)
return null
} catch (e: OperationFailureException) {
errorMessage = "InvalidUsageException=" + e.vendorMessage + " " + e.results
println(errorMessage)
return null
}
}
Handle Tag Data method:
override fun handleTagData(tagData: Array<TagData?>?) {
var readValue = ""
if (!tagData.isNullOrEmpty()) readValue = tagData[0]!!.tagID.trimIndent().replace("\n", "")
if (isWritingRFID) {
isWritingRFID = false
if (currentRFIDAssetCode.isNotEmpty())
writeRFID(readValue, currentRFIDAssetCode)
} else {
CoroutineScope(Dispatchers.Main).launch {
if (!pDialog.isShowing) readFullRFID(readValue)
}
}
}
Feel free to ask for any additional code or info.
Another way to solve this problem instead of padding with zeros is use a technique used a lot in NFC and the first byte of your data is the value of the length of the data (in Hex).
Therefore it does not matter if the old data is not zero'd out and you won't have a problem detecting if it is a zero for blanking or a real zero
e.g.
0A 31 32 33 34 35 36 37 38 39 30
or in text
10 1 2 3 4 5 6 7 8 9 0
would be overwritten with
03 41 42 43
or in text
3 A B C
resulting in text in memory of
3 A B C 4 5 6 7 8 9 0
But you would read the first byte to get the length of 3 and then read 3 more bytes to get in text
A B C
I'm trying to format a previously E164 formatted phone number into National format without the National Prefix number, I'm using PhoneNumberUtils to do it:
public static String getNationalPhone(String phoneE164Formatted) {
PhoneNumberUtil phoneUtil = PhoneNumberUtil.getInstance();
String phoneNumber = phoneE164Formatted;
try {
Phonenumber.PhoneNumber numberProto = phoneUtil.parseAndKeepRawInput(phoneE164Formatted, "");
phoneNumber = phoneUtil.format(numberProto, PhoneNumberUtil.PhoneNumberFormat.NATIONAL);
} catch (NumberParseException e) {
e.printStackTrace();
}
return phoneNumber;
}
With that code I'm getting the national prefix I don't want. For example, formatting this number "+526143342293" into national format gave me this result: "01 614 334 22 93", where "01" it's what I want to suppress.
https://github.com/brick/phonenumber/blob/master/src/PhoneNumber.php
These answer in php, you can convert into your own.
public function getCountryCode()
{
return (string) $this->phoneNumber->getCountryCode();
}
Convert above code will get the national number in desired format.
I have an app which contain mobile number edit text in which user can edit mobile number and I have to send two request to server like:- mobile number and mssdn,mobile number(which is full lenghth ) and mssdn(which contain mobile number last 4 digit).How can I do that
Try this. Check for length greater than 4 before calling subString to avoid IndexOutOfBounds Exception.
EditText mEdtPhoneNumber = (EditText) findViewById(R.id.edtPhoneNumber);
String phoneNumber = mEdtPhoneNumber.getText().toString().trim();
String strLastFourDi = phoneNumber.length() >= 4 ? phoneNumber.substring(phoneNumber.length() - 4): "";
Also what is mssdn?? Is it msisdn??
Use the modulus (%) operator:
To get the last digit: use number % 10
To get the last 2 digits: use number % 100
and so on
For example:
42455%10000 = 2455
You could do something like this:
EditText phoneNumberEditText = (EditText) findViewById(R.id.phoneNumberEditText);
String phoneNumber = phoneNumberEditText.getText().toString();
String lastFourDigits = phoneNumber.substring(phoneNumber.length() - 4);
you should use regex because this will only give you result if the last four letters are actually numbers on the other hand the substring function simply give you last four letters no matter they are numbers or characters. e.g 4344sdsdss4 will give you dss4 which is clearly not a part of phone number
String str="4444ntrjntkr555566";
Pattern p = Pattern.compile("(\\d{4})$");
Matcher m = p.matcher(str);
if (m.find()) {
System.out.println(m.group(m.groupCount()));
}
this will produce 5566
Working
//d mean digits
{4} for fix length as 4
$ mean at the end
List<Integer> f(String str){
ArrayList<Integer> digits = new ArrayList<>();
if (null == str || str.length() < 4){
Log.i(LOG_TAG, "there are less than 4 digits");
return digits;
}
String digitsStr = str.substring(str.length() - 4);
for (char c : digitsStr.toCharArray()){
try {
Integer digit = Integer.parseInt(String.valueOf(c));
digits.add(digit);
} catch (Exception e){
continue;
}
}
return digits;
}
We can also use a new method introduced in kotlin: takeLast(n)
fun getLastDigit(data: String, n:Int): String {
return if(data.length > n){
data.takeLast(n)
}else {
""
}
}
I am allowing the user to choose a phone number from their address book. I need the number to always be in the international format, however sometimes people store a local number without the country code in their contacts (ex. 555-555-5555 instead of +1-555-555-5555).
Is there an easy way to find out what country code the local number implies so I can add it manually?
This is what you need
https://code.google.com/p/libphonenumber/
String numberString = "044 668 18 00"
PhoneNumberUtil phoneUtil = PhoneNumberUtil.getInstance();
try {
PhoneNumber numberProto = phoneUtil.parse(numberString, "BH"); // Where BH is the user's iso country code
String finalNumber = phoneUtil.format(numberProto, PhoneNumberFormat.E164);
} catch (NumberParseException e) {
System.err.println("NumberParseException was thrown: " + e.toString());
}
I have a string like this : +33123456789 (french phone number). I want to extract the country code (+33) without knowing the country. For example, it should work if i have another phone from another country. I use the google library https://code.google.com/p/libphonenumber/.
If I know the country, it is cool I can find the country code :
PhoneNumberUtil phoneUtil = PhoneNumberUtil.getInstance();
int countryCode = phoneUtil.getCountryCodeForRegion(locale.getCountry());
but I don't find a way to parse a string without to know the country.
Okay, so I've joined the google group of libphonenumber ( https://groups.google.com/forum/?hl=en&fromgroups#!forum/libphonenumber-discuss ) and I've asked a question.
I don't need to set the country in parameter if my phone number begins with "+". Here is an example :
PhoneNumberUtil phoneUtil = PhoneNumberUtil.getInstance();
try {
// phone must begin with '+'
PhoneNumber numberProto = phoneUtil.parse(phone, "");
int countryCode = numberProto.getCountryCode();
} catch (NumberParseException e) {
System.err.println("NumberParseException was thrown: " + e.toString());
}
I have got kept a handy helper method to take care of this based on one answer posted above:
Imports:
import com.google.i18n.phonenumbers.NumberParseException
import com.google.i18n.phonenumbers.PhoneNumberUtil
Function:
fun parseCountryCode( phoneNumberStr: String?): String {
val phoneUtil = PhoneNumberUtil.getInstance()
return try {
// phone must begin with '+'
val numberProto = phoneUtil.parse(phoneNumberStr, "")
numberProto.countryCode.toString()
} catch (e: NumberParseException) {
""
}
}
In here you can save the phone number as international formatted phone number
internationalFormatPhoneNumber = phoneUtil.format(givenPhoneNumber, PhoneNumberFormat.INTERNATIONAL);
it return the phone number as
International format +94 71 560 4888
so now I have get country code as this
String countryCode = internationalFormatPhoneNumber.substring(0,internationalFormatPhoneNumber.indexOf('')).replace('+', ' ').trim();
Hope this will help you
Here is a solution to get the country based on an international phone number without using the Google library.
Let me explain first why it is so difficult to figure out the country. The country code of few countries is 1 digit, 2, 3 or 4 digits. That would be simple enough. But the country code 1 is not just used for US, but also for Canada and some smaller places:
1339 USA
1340 Virgin Islands (Caribbean Islands)
1341 USA
1342 not used
1343 Canada
Digits 2..4 decide, if it is US or Canada or ... There is no easy way to figure out the country, like the first xxx are Canada, the rest US.
For my code, I defined a class which holds information for ever digit:
public class DigitInfo {
public char Digit;
public Country? Country;
public DigitInfo?[]? Digits;
}
A first array holds the DigitInfos for the first digit in the number. The second digit is used as an index into DigitInfo.Digits. One travels down that Digits chain, until Digits is empty. If Country is defined (i.e. not null) that value gets returned, otherwise any Country defined earlier gets returned:
country code 1: byPhone[1].Country is US
country code 1236: byPhone[1].Digits[2].Digits[3].Digits[6].Country is Canada
country code 1235: byPhone[1].Digits[2].Digits[3].Digits[5].Country is null. Since
byPhone[1].Country is US, also 1235 is US, because no other
country was found in the later digits
Here is the method which returns the country based on the phone number:
/// <summary>
/// Returns the Country based on an international dialing code.
/// </summary>
public static Country? GetCountry(ReadOnlySpan<char> phoneNumber) {
if (phoneNumber.Length==0) return null;
var isFirstDigit = true;
DigitInfo? digitInfo = null;
Country? country = null;
foreach (var digitChar in phoneNumber) {
var digitIndex = digitChar - '0';
if (isFirstDigit) {
isFirstDigit = false;
digitInfo = ByPhone[digitIndex];
} else {
if (digitInfo!.Digits is null) return country;
digitInfo = digitInfo.Digits[digitIndex];
}
if (digitInfo is null) return country;
country = digitInfo.Country??country;
}
return country;
}
The rest of the code (digitInfos for every country of the world, test code, ...) is too big to be posted here, but it can be found on Github:
https://github.com/PeterHuberSg/WpfWindowsLib/blob/master/WpfWindowsHelperLib/CountryCode.cs
The code is part of a WPF TextBox and the library contains also other controls for email addresses, etc. A more detailed description is on CodeProject: International Phone Number Validation Explained in Detail
Change 23.1.23: I moved CountryCode.cs to WpfWindowsHelperLib, which doesn't have any WPF dependencies, despite it's name.
Use a try catch block like below:
try {
const phoneNumber = this.phoneUtil.parseAndKeepRawInput(value, this.countryCode);
}catch(e){}
If the string containing the phone number will always start this way (+33 or another country code) you should use regex to parse and get the country code and then use the library to get the country associated to the number.
Here's a an answer how to find country calling code without using third-party libraries (as real developer does):
Get list of all available country codes, Wikipedia can help here:
https://en.wikipedia.org/wiki/List_of_country_calling_codes
Parse data in a tree structure where each digit is a branch.
Traverse your tree digit by digit until you are at the last branch - that's your country code.