Saturday, September 14, 2013

CallUrgency for Android

This app (CallUrgency) solves the use case where your phone is ringing and you want to know if the call is urgent, and what it is about before picking up. Any problems? Any ideas? Leave your comments below.


Get it on Google Play

Friday, July 19, 2013

Java library for retrieving SMS email gateway, mms APN settings

At the time of this post, there is currently no library written in Java for retrieving the SMS email gateways of mobile service providers, or mms APN settings given an mcc/mnc pair, or Country code and operator name. This library uses a comprehensive aggregation of mms APN settings, MCC, MNC, Operator/Carrier names, SMS email gateways, and MMS email gateways from many online sources (xda developers , cm10.1 apns-config, Wikipedia  mobile country code page, and other sms email gateways found online).

Here is the final xml: XML

Here is a download for the library: Droidprism.jar
Javadoc:    Carrier.html    APN.html

Usage:
First add Jsoup to the build path.

import com.droidprism.*;

Carrier c = Carrier.getCarrier("US","Verizon");
if(c != null) {
  String smsemail = c.getsmsemail();  
  String mmsemail = c.getmmsemail();
  System.out.println(smsemail + "   " + mmsemail); 
  //prints vtext.com   vzwpix.com
  com.droidprism.APN apn = c.getAPN();
  if(apn != null) {
     String mmsc = apn.mmsc;
     String mmsproxy = apn.proxy; //"" if none
     String mmsport = apn.port; //0 if none
     System.out.println(mmsc +"  " + mmsproxy + "  " + mmsport); 
     //prints http://mms.vtext.com/servlets/mms   0
    }
}


You can also get the carrier from android with mcc and mnc codes:
TelephonyManager tel = (TelephonyManager) 
                  getSystemService(Context.TELEPHONY_SERVICE);
    String networkOperator = tel.getNetworkOperator();

    if (networkOperator != null) {
        int mcc = Integer.parseInt(
                  networkOperator.substring(0, 3));
        String s = networkOperator.substring(3);
        //remove leading zeroes
        int mnc = Integer.parseInt(
                   s.replaceFirst("^0{1,2}",""));
        Carrier c = Carrier.getCarrier(mcc, mnc);
        c.getsmsemail();
        APN a = c.getAPN(); 
    }

Wednesday, June 26, 2013

Dealing with international numbers in Android, Java

If you are writing an application that needs to use international or national phone numbers, this post will show you how international and national numbers work, and how you can correctly handle any phone number whatsoever with libphonenumber, a Java library.


Here is how international numbers work:


International Access Code  + Country Calling Code +  National Number.

For example, here is a call from the US, dialing outside of the US, into London:


011
International Access Code
44
Country Calling Code
20 1234 5678
National Number

The international access code for the US (011) dials outside of the US, the country calling code for the United Kingdom (44) dials into the United Kingdom, and the national number (2012345678) dials the local London number. Here is a resource with international access codes ( also called international call prefix) for all countries: International Access Codes. Here is a resource with country calling codes for all countries: Country Calling Codes.

Alternatively, you can dial a plus sign (+) into a mobile phone instead of the international access code, and the phone will dial the country specific international access code on its own. The equivalent for the above example with the plus sign is: +442012345678. For international calls, Android phones will display incoming call numbers in this format (the plus sign followed by the country calling code, followed by the national number). Sometimes, depending on the phone, Android uses this format for local/national calls also, and sometimes it will display just the national number.

To parse an international phone number correctly from any of the above formats in Java, use the Java libphonenumber library written by Google. This library has its equivalents in other languages such as Php, .NET, Javascript, and iOS. The Java and Php version were tested here. The only version that can be guaranteed by this post to be reliable is the Java version. If you are dialing the number above:
PhoneNumberUtil p = PhoneNumberUtil.getInstance();
String number = "011442012345678"; //can also be +442012345678
String region = "US"; 
PhoneNumber pn = p.parse(number, region);
String nationalnumber = String.valueOf(pn.getNationalNumber()); //2012345678
String countrycallingcode =  String.valueOf(pn.getCountryCode()); // country code for Great Britain
The "US" string is the ISO country code for the United States. A list of ISO country codes can be found here: ISO codes. To get the ISO country code within Android:
TelephonyManager t = TelephonyManager.getInstance();
String country = t.getNetworkCountryIso();
if(country != null) {
country = country.toUpperCase(); // must be upper case for libphonenumber parse method
}
The reason "US" is used is because the number is being dialed from the US. If you are parsing the incoming call in London, from the US, the number will be handled in Android as +442012345678. If the number starts with a plus sign, the region is ignored. The receiving phone should use its own ISO code ("GB") if the number does not start with a plus sign.

Here is how national numbers work:


Trunk Prefix  +  National Number.
A list of country specific trunk prefixes can be found here: Trunk Prefix , or here . The trunk prefix for most countries outside of North America is 0. The trunk prefix for most countries inside North America is 1. For example, here is a call from one phone inside the UK to another inside the UK:

0
Trunk Prefix
20 1234 5678
National Number

The trunk prefix is sometimes omitted. Parsing a national number is the same as parsing an international number. The libphonenumber will recognize if there is a trunk prefix, and correctly identify the country code:
PhoneNumberUtil p = PhoneNumberUtil.getInstance();
String number = "02012345678"; //can also be 2012345678
String region = "GB"; 
PhoneNumber pn = p.parse(number, region);
String nationalnumber = String.valueOf(pn.getNationalNumber()); //2012345678
String countrycallingcode =  String.valueOf(pn.getCountryCode()); //44

The Php version was tested too, and people reading this may have a different experience. The problem with it was it threw an exception for a number like this: 2122322323 with Iso region code "US".

In conclusion, to parse a number with libphonenumber, remove all non digit characters from the number string, get the ISO code of the region from which the number is being dialed (if it is an outgoing number), or the region in which the number is being received (for incoming numbers). Then call the parse method.