I need to determine the national carrier code (not the carrier name) of any phone number, using libphonenumber Java SDK. How can I do this? I can find only method how to retrieve carrier name:
Locale.PhoneNumberUtil phoneUtil = PhoneNumberUtil.getInstance();
PhoneNumberToCarrierMapper carrierMapper = PhoneNumberToCarrierMapper.getInstance();
Phonenumber.PhoneNumber numberProto = phoneUtil.parse( 375445111111, "");
String name = carrierMapper.getNameForValidNumber(numberProto, Locale.US);
System.out.println(name);//Velcome, but I need just number like 44, or 37544, or 375445
CodePudding user response:
You can't. Not every country has phone numbers that are split up like that between carriers, so not every country even has carrier codes.
Especially in the EU it is impossible to derive the carrier from the phone number as the EU mandates that people can switch carrier without changing their phone number. While each carrier may have specific series of numbers they get assigned for handing out to customers by national authorities (rather than just getting them sequentially or randomly as needed), those numbers are in no way guaranteed to stay with any specific carrier.
I don't know how libphonenumber tries to find out the carrier name, maybe it queries databases or makes an educated guess. If it's open source you may be able to find out yourself and go from there.
CodePudding user response:
My final dirty solution. Code partially copy-pasted from com.google.i18n.phonenumbers
class should sit in package com.google.i18n.phonenumbers.prefixmapper;
, otherwise no access to classes methods, fields or variables.
package com.google.i18n.phonenumbers.prefixmapper;
import com.google.i18n.phonenumbers.NumberParseException;
import com.google.i18n.phonenumbers.PhoneNumberToCarrierMapper;
import com.google.i18n.phonenumbers.PhoneNumberUtil;
import com.google.i18n.phonenumbers.Phonenumber;
import lombok.extern.slf4j.Slf4j;
import java.io.IOException;
import java.io.InputStream;
import java.io.ObjectInputStream;
import java.util.ArrayList;
import java.util.SortedSet;
@Slf4j
public class Mapper {
public static final String[] EMPTY = new String[]{null, null, null};
public static void main(String ... args) {
Mapper mapper = new Mapper();
new ArrayList<String>(){{
add("375-44-111-12-22");
add(" 3754411112233");
add("995-593111222");
add(" 995593111222");
}}.forEach(phone -> {
try {
String[] result = mapper.parsePhone(phone);
System.out.print("input: " phone " country code: " result[0]);
System.out.print(" carrier: " result[1] " ");
System.out.println(" phone: " result[2]);
} catch (IOException e) {
throw new RuntimeException(e);
}
});
}
private PhonePrefixMapStorageStrategy phonePrefixMapStorage;
public String[] parsePhone(String phone) throws IOException {
if(phone == null || phone.isEmpty()) {
return EMPTY;
}
int countryCode;
PhoneNumberUtil phoneUtil = PhoneNumberUtil.getInstance();
Long phoneNumber;
try {
if(phone.indexOf(" ") != 0) {
phone = " " phone;
}
Phonenumber.PhoneNumber numberProto = phoneUtil.parse(phone, "");
countryCode = numberProto.getCountryCode();
phoneNumber = Long.parseLong(countryCode String.valueOf(numberProto.getNationalNumber()));
} catch (NumberParseException e) {
log.error("fail to parse phone number {}.", phone, e);
return EMPTY;
}
String carrier;
try (InputStream inputStream = Mapper.class.getResourceAsStream("/com/google/i18n/phonenumbers/carrier/data/" countryCode "_en")) {
try (ObjectInputStream streamReader = new ObjectInputStream(inputStream)) {
boolean useFlyweightMapStorage = streamReader.readBoolean();
if (useFlyweightMapStorage) {
this.phonePrefixMapStorage = new FlyweightMapStorage();
} else {
this.phonePrefixMapStorage = new DefaultMapStorage();
}
phonePrefixMapStorage.readExternal(streamReader);
String result = lookup(phoneNumber);
carrier = result == null ? null : result.substring(String.valueOf(countryCode).length());
}
}
String prefix = " " countryCode (carrier == null ? "" : carrier);
return new String[]{String.valueOf(countryCode), carrier, String.valueOf(phoneNumber).substring(prefix.length() - 1)};
}
private int binarySearch(int start, int end, long value) {
int current = 0;
while(start <= end) {
current = start end >>> 1;
int currentValue = this.phonePrefixMapStorage.getPrefix(current);
if ((long)currentValue == value) {
return current;
}
if ((long)currentValue > value) {
--current;
end = current;
} else {
start = current 1;
}
}
return current;
}
private String lookup(long number) {
int numOfEntries = this.phonePrefixMapStorage.getNumOfEntries();
if (numOfEntries == 0) {
return null;
} else {
long phonePrefix = number;
int currentIndex = numOfEntries - 1;
Integer possibleLength;
for(SortedSet<Integer> currentSetOfLengths = this.phonePrefixMapStorage.getPossibleLengths(); ((SortedSet)currentSetOfLengths).size() > 0; currentSetOfLengths = ((SortedSet)currentSetOfLengths).headSet(possibleLength)) {
possibleLength = (Integer)((SortedSet)currentSetOfLengths).last();
String phonePrefixStr = String.valueOf(phonePrefix);
if (phonePrefixStr.length() > possibleLength) {
phonePrefix = Long.parseLong(phonePrefixStr.substring(0, possibleLength));
}
currentIndex = this.binarySearch(0, currentIndex, phonePrefix);
if (currentIndex < 0) {
return null;
}
int currentPrefix = this.phonePrefixMapStorage.getPrefix(currentIndex);
if (phonePrefix == (long)currentPrefix) {
return String.valueOf(currentPrefix);
}
}
return null;
}
}
}