Identifying Unknown/Private/Restricted calls in my Android app - android

I use a simple projection in my contentObserver to detect missed calls.
String[] projection = new String[] {Calls.NUMBER, Calls.DATE};
and later ...
String number = cursor.getString(0);
I would like to be able to identify calls with no caller ID. A quick experiment showed that the number returned was "-2" for a "Restricted" call (from a real phone, using #31#). On the emulator using "#" as phone number, shows up as a call from "-1", reported as "Unknown".
I cannot find any documentation to confirm this. Is simply looking for a negative number or a "-" prefix a reliable way of identifying such calls?

You can use another colum: Calls.NUMBER_PRESENTATION that have the following possible values:
PRESENTATION_ALLOWED
Number is allowed to display for caller id. Constant Value: 1 (0x00000001)
PRESENTATION_RESTRICTED
Number is blocked by user. Constant Value: 2 (0x00000002)
PRESENTATION_UNKNOWN
Number is not specified or unknown by network. Constant Value: 3 (0x00000003)
PRESENTATION_PAYPHONE
Number is a pay phone. Constant Value: 4 (0x00000004)
A call from a restricted ou unknown number the field value will be 2 or 3. So you can do something like that:
String[] projection = new String[] {
Calls.NUMBER,
Calls.DATE,
Calls.NUMBER_PRESENTATION
};
and later ...
String number = cursor.getString(0);
String type = cursor.getString(2);
if(type == "2" || type == "3") {
number = "RESTICTED OR UNKNOWN";
}

Related

Sending USSD code with alphabetic characters

In my android app, I am sending USSD codes (#144#73#) using below Intent :
String baseUssd = Uri.encode("#") + "144" + Uri.encode("#");
StringBuilder builder = new StringBuilder();
builder.append(baseUssd);
builder.append("73");
builder.append(Uri.encode("#"));
Intent intent = new Intent(Intent.ACTION_CALL, Uri.parse("tel:" + builder.toString()));
It's working well.
What I want now is to send this code :
#144#73MA#
I run this using the dial pad, following the Operator USSD menu, that worked.
But if I try to do this programmatically using the above Intent that didn't work.
I know that alphabetic characters can't be used when typing code with the Dial Pad, but I though that It can be possible programmatically !!
Any Idea please !
Edit
When I try to send this programmatically : #144#73MA# I noticed that the Dialer application changes the alphabetic characters to their corresponding digit in the dial pad. Meaning that the dialer transform this : #144#73MA#
to this #144#7362# : why ?
Because :
the M matches the digit 6
the A matches the digit 2
Meaning that the dialer transform this : #144#73MA#
to this #144#7362# : why ?
I will try to answer only the why part.
Intent.ACTION_CALL is handled by OutgoingCallBroadcaster class. If you look at processIntent() method, there is this piece of code (lines 438~448 as of this writing):
String number = PhoneNumberUtils.getNumberFromIntent(intent, this);
// Check the number, don't convert for sip uri
// TODO put uriNumber under PhoneNumberUtils
if (number != null) {
if (!PhoneNumberUtils.isUriNumber(number)) {
number = PhoneNumberUtils.convertKeypadLettersToDigits(number);
number = PhoneNumberUtils.stripSeparators(number);
}
} else {
Log.w(TAG, "The number obtained from Intent is null.");
}
There PhoneNumberUtils.convertKeypadLettersToDigits() converts the letters into the equivalent numeric digits:
public static String convertKeypadLettersToDigits (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.
Returns
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".
Hope this helps.

Extract code country from phone number [libphonenumber]

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.

How to determine if two phone numbers are the same?

If we have a phone number like 358541321 without a country code, sometimes when phone rings it says (+56 - 358541321) or +56358541321.
How to detect whether the ringed number is first number?
The number is not saved in phone memory in order to phone lookup.
https://developer.android.com/reference/android/telephony/PhoneNumberUtils.html
provides a neat solution:
import android.telephony.PhoneNumberUtils;
...
String one = "+51 - 3245678";
String two = "+513245678";
boolean isSame = PhoneNumberUtils.compare(one, two);
The usual solution to this problem is just to compare the last X (e.g. 7 or 8, depending on your country) digits of the number. In rare cases, this can lead to false positives, but usually it's a good approximation and it avoids the problem of different or missing country or area codes.
Java regular expression and String function replaceAll can do this easily.
this way,
String one = "+51 - 3245678";
String two = "+513245678";
one = one.replaceAll("[^0-9]","");
two = two.replaceAll("[^0-9]","");
Toast.makeText(this, one+" -- "+two, Toast.LENGTH_LONG).show();
if(one.equalsIgnoreCase(two))
{
Toast.makeText(this, "Both Are Equal", Toast.LENGTH_LONG).show();
}
else
{
Toast.makeText(this, "Different", Toast.LENGTH_LONG).show();
}

Check Value from mysql using android

I have a table which has a field called Sold , in that field i store 0 and 1.
So 1 means sold and 0 mean Available.
K, my problem is that ,I want to change 0 to available and 1 to sold when i diplay information into my emulator , here what i tried but it returning sold even though i have 0 in my database :
if (sold.length()==0){
Log.d("checking","Inside = 0");
val = "Available";}
else if (sold.length()>0)
Log.d("checking","Inside = 1");
val = "Sold
And sold contains a value from a database.
please help to change 0 to Available and 1 to Sold.
if(sold.equalIgnoreCase("0"))
{
Log.d("checking","Inside = 0");
}else
{
Log.d("checking","Inside = 1");
}
The sold.length you have there is the actual length of the String representation "sold" that you are using. Meaning that if you have the word "some" this .length() equals 4.
So in your snippet the sold variable is the "0" or "1" respectively so the sold.length() always equals to 1. Try to cast the String variable into an Integer and make the comparison or even better try to make the variable into Integer from the beginning.

Get phone number without country code for the purpose of comparing numbers

I can obtain the phone number from an incoming call or from a sms message. unfortunately, in case of the SMS there might be the country code in it. So, basically I need to obtain the plain phone number, without country code, in order to compare it with existing numbers in Contacts.
If you want to compare phone numbers you can always use the
PhoneNumberUtils.compare(number1, number2);
or
PhoneNumberUtils.compare(context, number1, number2);
Then you don't have to worry about the country code, it will just compare the numbers from the reversed order and see if they match (enough for callerID purposes at least).
fast untested approach (AFAIK phone numbers have 10 digits):
// As I said, AFAIK phone numbers have 10 digits... (at least here in Mexico this is true)
int digits = 10;
// the char + is always at first.
int plus_sign_pos = 0;
// Always send the number to this function to remove the first n digits (+1,+52, +520, etc)
private String removeCountryCode(String number) {
if (hasCountryCode(number)) {
// +52 for MEX +526441122345, 13-10 = 3, so we need to remove 3 characters
int country_digits = number.length() - digits;
number = number.substring(country_digits);
}
return number;
}
// Every country code starts with + right?
private boolean hasCountryCode(String number) {
return number.charAt(plus_sign_pos) == '+'; // Didn't String had contains() method?...
}
then you just call these functions

Categories

Resources