Logo Icon Logo
A Crowd-sourced Cookbook on Writing Great Android® Apps
GitHub logo Twitter logo OReilly Book Cover Art

Using Android's TelephonyManager to Obtain Device Information

Published? true
FormatLanguage: WikiFormat

Problem:

I want to obtain network related and telephonic information on my phone. How to do this?

Solution:

Android TelephonyManager can be used to obtain the different statistics about network status and telephonic information.

Discussion:

Android TelephonyManager provides information about the android telephony system. It assists in collecting different information like Cell Location, IMEI Number, Network Provider Information and more.

Below code covers many of the facilities provided by the android TelephonyManager:

import java.util.List;
import android.app.Activity;
import android.os.Bundle;
import android.telephony.CellLocation;
import android.telephony.NeighboringCellInfo;
import android.telephony.PhoneStateListener;
import android.telephony.ServiceState;
import android.telephony.TelephonyManager;
import android.telephony.gsm.GsmCellLocation;
import android.util.Log;
import android.widget.ImageView;
import android.widget.ProgressBar;
import android.widget.TextView;

public class PhoneStateSample extends Activity {
        
        private static final String APP_NAME = "SignalLevelSample";
        private static final int EXCELLENT_LEVEL = 75;
        private static final int GOOD_LEVEL = 50;
        private static final int MODERATE_LEVEL = 25;
        private static final int WEAK_LEVEL = 0;
        
        private static final int INFO_SERVICE_STATE_INDEX = 0;
        private static final int INFO_CELL_LOCATION_INDEX = 1;
        private static final int INFO_CALL_STATE_INDEX = 2;
        private static final int INFO_CONNECTION_STATE_INDEX = 3;
        private static final int INFO_SIGNAL_LEVEL_INDEX = 4;
        private static final int INFO_SIGNAL_LEVEL_INFO_INDEX = 5;
        private static final int INFO_DATA_DIRECTION_INDEX = 6;
        private static final int INFO_DEVICE_INFO_INDEX = 7;
        
        private static final int[] info_ids= {
                R.id.serviceState_info,
                R.id.cellLocation_info,
                R.id.callState_info,
                R.id.connectionState_info,
                R.id.signalLevel,
                R.id.signalLevelInfo,
                R.id.dataDirection,
                R.id.device_info
        };
    
    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.main);
        startSignalLevelListener();
        displayTelephonyInfo();
    }
    
    @Override
        protected void onPause()
        {
                super.onPause();
                stopListening();
        }

        @Override
        protected void onResume()
        {
                super.onResume();
                startSignalLevelListener();
        }
        
        @Override
        protected void onDestroy()
        {
                stopListening();
                super.onDestroy();
        }

        private void setTextViewText(int id,String text) {
                ((TextView)findViewById(id)).setText(text);
        }
        private void setSignalLevel(int id,int infoid,int level){
                int progress = (int) ((((float)level)/31.0) * 100);
                String signalLevelString =getSignalLevelString(progress);
                ((ProgressBar)findViewById(id)).setProgress(progress);
                ((TextView)findViewById(infoid)).setText(signalLevelString);
                Log.i("signalLevel ","" + progress);
        }

        private String getSignalLevelString(int level) {
                String signalLevelString = "Weak";
                if(level > EXCELLENT_LEVEL)     signalLevelString = "Excellent";
                else if(level > GOOD_LEVEL)     signalLevelString = "Good";
                else if(level > MODERATE_LEVEL) signalLevelString = "Moderate";
                else if(level > WEAK_LEVEL)     signalLevelString= "Weak";    
                return signalLevelString;
        }

        private void stopListening(){
                TelephonyManager tm = (TelephonyManager) 
getSystemService(TELEPHONY_SERVICE);
                tm.listen(phoneStateListener, 
PhoneStateListener.LISTEN_NONE);
        }

        private void setDataDirection(int id, int direction){
                int resid = getDataDirectionRes(direction);
                ((ImageView)findViewById(id)).setImageResource(resid);
        }
        private int getDataDirectionRes(int direction){
                int resid = R.drawable.data_none;

                switch(direction)
                {
                        case TelephonyManager.DATA_ACTIVITY_IN:    
resid = R.drawable.data_in; break;
                        case TelephonyManager.DATA_ACTIVITY_OUT:   
resid = R.drawable.data_out; break;
                        case TelephonyManager.DATA_ACTIVITY_INOUT: 
resid = R.drawable.data_both; break;
                        case TelephonyManager.DATA_ACTIVITY_NONE: 
resid = R.drawable.data_none; break;
                        default: resid = R.drawable.data_none; break;
                }
                return resid;
        }
        private void startSignalLevelListener() {
        TelephonyManager tm = (TelephonyManager) 
getSystemService(TELEPHONY_SERVICE);
        int events = PhoneStateListener.LISTEN_SIGNAL_STRENGTH | PhoneStateListener.LISTEN_DATA_ACTIVITY | 
PhoneStateListener.LISTEN_CELL_LOCATION|PhoneStateListener.LISTEN_CALL_STATE |
PhoneStateListener.LISTEN_CALL_FORWARDING_INDICATOR |
PhoneStateListener.LISTEN_DATA_CONNECTION_STATE |
PhoneStateListener.LISTEN_MESSAGE_WAITING_INDICATOR |
                                 PhoneStateListener.LISTEN_SERVICE_STATE;
        tm.listen(phoneStateListener, events);
    }
        private void displayTelephonyInfo(){
                TelephonyManager tm = (TelephonyManager) 
getSystemService(TELEPHONY_SERVICE);
                GsmCellLocation loc = (GsmCellLocation)tm.getCellLocation();
                int cellid = loc.getCid();
                int lac = loc.getLac();
                String deviceid = tm.getDeviceId();
                String phonenumber = tm.getLine1Number();
                String softwareversion = tm.getDeviceSoftwareVersion();
                String operatorname = tm.getNetworkOperatorName();
                String simcountrycode = tm.getSimCountryIso();
                String simoperator = tm.getSimOperatorName();
                String simserialno = tm.getSimSerialNumber();
                String subscriberid = tm.getSubscriberId();
                String networktype = getNetworkTypeString(tm.getNetworkType());
                String phonetype = getPhoneTypeString(tm.getPhoneType());
                logString("CellID: " + cellid);
                logString("LAC: " + lac);
                logString("Device ID: " + deviceid);
                logString("Phone Number: " + phonenumber);
                logString("Software Version: " + softwareversion);
                logString("Operator Name: " + operatorname);
                logString("SIM Country Code: " + simcountrycode);
                logString("SIM Operator: " + simoperator);
                logString("SIM Serial No.: " + simserialno);
                logString("Sibscriber ID: " + subscriberid);
                String deviceinfo = "";    
                deviceinfo += ("CellID: " + cellid + "\n");
                deviceinfo += ("LAC: " + lac + "\n");
                deviceinfo += ("Device ID: " + deviceid + "\n");
                deviceinfo += ("Phone Number: " + phonenumber + "\n");
                deviceinfo += ("Software Version: " + softwareversion + "\n");
                deviceinfo += ("Operator Name: " + operatorname + "\n");
                deviceinfo += ("SIM Country Code: " + simcountrycode + "\n");
                deviceinfo += ("SIM Operator: " + simoperator + "\n");
                deviceinfo += ("SIM Serial No.: " + simserialno + "\n");
                deviceinfo += ("Subscriber ID: " + subscriberid + "\n");
                deviceinfo += ("Network Type: " + networktype + "\n");
                deviceinfo += ("Phone Type: " + phonetype + "\n");   
                List<NeighboringCellInfo> cellinfo =tm.getNeighboringCellInfo();
                if(null != cellinfo){
                        for(NeighboringCellInfo info: cellinfo){
                                deviceinfo += ("\tCellID: " + info.getCid() +", RSSI: " + info.getRssi() + "\n");
                        }
                }
setTextViewText(info_ids[INFO_DEVICE_INFO_INDEX],deviceinfo);
        }
        private String getNetworkTypeString(int type){
                String typeString = "Unknown";
                switch(type)
                {
                        case TelephonyManager.NETWORK_TYPE_EDGE:typeString = "EDGE"; break;
                        case TelephonyManager.NETWORK_TYPE_GPRS:typeString = "GPRS"; break;
                        case TelephonyManager.NETWORK_TYPE_UMTS:typeString = "UMTS"; break;
                        default:                                          
                              typeString = "UNKNOWN"; break;
                }
                return typeString;
        }
        private String getPhoneTypeString(int type){
                String typeString = "Unknown";
                switch(type)
                {
                        case TelephonyManager.PHONE_TYPE_GSM: typeString = GSM"; break;
                        case TelephonyManager.PHONE_TYPE_NONE: typeString = UNKNOWN"; break;
                        default:typeString = "UNKNOWN"; break;
                }
                return typeString;
        }
        private int logString(String message) {
                return Log.i(APP_NAME,message);
        }
  
    private final PhoneStateListener phoneStateListener = new PhoneStateListener(){

                @Override
                public void onCallForwardingIndicatorChanged(boolean cfi)
                {
                        Log.i(APP_NAME, "onCallForwardingIndicatorChanged " +cfi); 
                        super.onCallForwardingIndicatorChanged(cfi);
                }

                @Override
                public void onCallStateChanged(int state, String incomingNumber)
                {
                        String callState = "UNKNOWN";
                        switch(state)
                        {
                                case TelephonyManager.CALL_STATE_IDLE:callState = "IDLE"; break;
                                case TelephonyManager.CALL_STATE_RINGING:callState = "Ringing (" + incomingNumber + ")"; break;
                                case TelephonyManager.CALL_STATE_OFFHOOK:       callState = "Offhook"; break;
                        }
setTextViewText(info_ids[INFO_CALL_STATE_INDEX],callState);                    
                        Log.i(APP_NAME, "onCallStateChanged " + callState);
                        super.onCallStateChanged(state, incomingNumber);
                }
                @Override
                public void onCellLocationChanged(CellLocation location)
                {
                        String locationString = location.toString();
setTextViewText(info_ids[INFO_CELL_LOCATION_INDEX],locationString);
                        
                        Log.i(APP_NAME, "onCellLocationChanged " + 
locationString);        
                        super.onCellLocationChanged(location);
                }

                @Override
                public void onDataActivity(int direction)
                {
                        String directionString = "none";
                        switch(direction)
                        {
                                case TelephonyManager.DATA_ACTIVITY_IN:
      directionString = "IN"; break;
                                case TelephonyManager.DATA_ACTIVITY_OUT:
      directionString = "OUT"; break;
                                case 
TelephonyManager.DATA_ACTIVITY_INOUT:      directionString = "INOUT"; 
break;
                                case TelephonyManager.DATA_ACTIVITY_NONE: 
      directionString = "NONE"; break;
                                default: directionString = "UNKNOWN: " + 
direction; break;
                        }

setDataDirection(info_ids[INFO_DATA_DIRECTION_INDEX],direction);              
                        Log.i(APP_NAME, "onDataActivity " + 
directionString);            
                        super.onDataActivity(direction);
                }

                @Override
                public void onDataConnectionStateChanged(int state)
                {
                        String connectionState = "Unknown";    
                        switch(state)
                        {
                                case TelephonyManager.DATA_CONNECTED:     
      connectionState = "Connected"; break;
                                case TelephonyManager.DATA_CONNECTING:    
      connectionState = "Connecting"; break;
                                case TelephonyManager.DATA_DISCONNECTED:  
      connectionState = "Disconnected"; break;
                                case TelephonyManager.DATA_SUSPENDED:     
      connectionState = "Suspended"; break;
                                default:                                  

                                      connectionState = "Unknown: " + 
state; break;
                        }
                        
                        

setTextViewText(info_ids[INFO_CONNECTION_STATE_INDEX],connectionState);
                        
                        Log.i(APP_NAME, "onDataConnectionStateChanged " + 
connectionState);
                        
                        super.onDataConnectionStateChanged(state);
                }

                @Override
                public void onMessageWaitingIndicatorChanged(boolean mwi)
                {
                        Log.i(APP_NAME, "onMessageWaitingIndicatorChanged 
" + mwi);             
                        super.onMessageWaitingIndicatorChanged(mwi);
                }

                @Override
                public void onServiceStateChanged(ServiceState 
serviceState)
                {
                        String serviceStateString = "UNKNOWN";         
                        switch(serviceState.getState())
                        {
                                case ServiceState.STATE_IN_SERVICE:       
      serviceStateString = "IN SERVICE"; break;
                                case ServiceState.STATE_EMERGENCY_ONLY:   
      serviceStateString = "EMERGENCY ONLY"; break;
                                case ServiceState.STATE_OUT_OF_SERVICE:   
      serviceStateString = "OUT OF SERVICE"; break;
                                case ServiceState.STATE_POWER_OFF:        
              serviceStateString = "POWER OFF"; break;
                                default:                                  

                                      serviceStateString = "UNKNOWN"; 
break;
                        }
                        
                        

setTextViewText(info_ids[INFO_SERVICE_STATE_INDEX],serviceStateString);
                        
                        Log.i(APP_NAME, "onServiceStateChanged " + 
serviceStateString);
                        
                        super.onServiceStateChanged(serviceState);
                }

                @Override
                public void onSignalStrengthChanged(int asu)
                {
                        Log.i(APP_NAME, "onSignalStrengthChanged " + 
asu);
setSignalLevel(info_ids[INFO_SIGNAL_LEVEL_INDEX],info_ids[INFO_SIGNAL_LEV
EL_INFO_INDEX],asu);                    
                        super.onSignalStrengthChanged(asu);
                }
    };
}

Below code goes in 'main.xml' file:

<?xml version="1.0" encoding="utf-8"?>
<ScrollView xmlns:android="http://schemas.android.com/apk/res/android"
        android:layout_width="fill_parent"
        android:layout_height="wrap_content"
        android:orientation="vertical"
        android:scrollbarStyle="insideOverlay"
        android:scrollbarAlwaysDrawVerticalTrack="false">
        <LinearLayout
        android:orientation="vertical"
        android:layout_width="fill_parent"
        android:layout_height="fill_parent">
                <LinearLayout
                        android:layout_width="fill_parent"
                        android:layout_height="wrap_content"
                        android:orientation="horizontal">          
                        <TextView android:text="Serivice State" 
style="@style/labelStyleRight"/>
                        <TextView android:id="@+id/serviceState_info" 
style="@style/textStyle"/>
                </LinearLayout> 
                <LinearLayout
                        android:layout_width="fill_parent"
                        android:layout_height="wrap_content"
                        android:orientation="horizontal">                
                        <TextView android:text="Cell Location" 
style="@style/labelStyleRight"/>
                        <TextView android:id="@+id/cellLocation_info" 
style="@style/textStyle"/>
                </LinearLayout>              
                <LinearLayout
                        android:layout_width="fill_parent"
                        android:layout_height="wrap_content"
                        android:orientation="horizontal">                
                        <TextView android:text="Call State" 
style="@style/labelStyleRight"/>
                        <TextView android:id="@+id/callState_info" 
style="@style/textStyle"/>
                </LinearLayout>            
                <LinearLayout
                        android:layout_width="fill_parent"
                        android:layout_height="wrap_content"
                        android:orientation="horizontal">                    
                        <TextView android:text="Connection State" 
style="@style/labelStyleRight"/>
                        <TextView android:id="@+id/connectionState_info" 
style="@style/textStyle"/>
                </LinearLayout>      
                <LinearLayout
                        android:layout_width="fill_parent"
                        android:layout_height="wrap_content"
                        android:orientation="horizontal">                
                        <TextView android:text="Signal Level" 
style="@style/labelStyleRight"/>             
                        <LinearLayout
                                android:layout_width="fill_parent"
                                android:layout_height="wrap_content"
                                android:layout_weight="0.5"
                                android:orientation="horizontal">
                                <ProgressBar 
android:id="@+id/signalLevel" style="@style/progressStyle"/>
                                <TextView 
android:id="@+id/signalLevelInfo" style="@style/textSmallStyle"/>
                        </LinearLayout>
                </LinearLayout>
                <LinearLayout
                        android:layout_width="fill_parent"
                        android:layout_height="wrap_content"
                        android:orientation="horizontal">            
                        <TextView android:text="Data" 
style="@style/labelStyleRight"/>
                        <ImageView android:id="@+id/dataDirection" 
style="@style/imageStyle"/>
                </LinearLayout>
                <TextView android:id="@+id/device_info" 
style="@style/labelStyleLeft"/>
        </LinearLayout>
</ScrollView>

Our code uses some UI styles which are declared in this file named

'styles.xml':

<?xml version="1.0" encoding="utf-8"?>
<resources>
        <style name="labelStyleRight">
                <item name="android:layout_width">fill_parent</item>
                <item name="android:layout_height">wrap_content</item>
                <item name="android:layout_weight">0.5</item>
                <item name="android:textSize">15dip</item>
                <item name="android:textStyle">bold</item>
                <item name="android:layout_margin">10dip</item>
                <item name="android:gravity">center_vertical|right</item>
        </style>
       
        <style name="labelStyleLeft">
                <item name="android:layout_width">fill_parent</item>
                <item name="android:layout_height">wrap_content</item>
                <item name="android:layout_weight">0.5</item>
                <item name="android:textSize">15dip</item>
                <item name="android:textStyle">bold</item>
                <item name="android:layout_margin">10dip</item>
                <item name="android:gravity">center_vertical|left</item>
        </style>
       
        <style name="textStyle">
                <item name="android:layout_width">fill_parent</item>
                <item name="android:layout_height">wrap_content</item>
                <item name="android:layout_weight">0.5</item>
                <item name="android:textSize">15dip</item>
                <item name="android:textStyle">bold</item>
                <item name="android:layout_margin">10dip</item>
                <item name="android:gravity">center_vertical|left</item>
        </style>
       
        <style name="textSmallStyle">
                <item name="android:layout_width">fill_parent</item>
                <item name="android:layout_height">fill_parent</item>
                <item name="android:layout_weight">0.5</item>
                <item name="android:textSize">10dip</item>
                <item name="android:layout_margin">10dip</item>
                <item name="android:gravity">center_vertical|left</item>
        </style>
       
        <style name="progressStyle">
                <item name="android:layout_width">fill_parent</item>
                <item name="android:layout_height">wrap_content</item>
                <item name="android:layout_margin">10dip</item>
                <item name="android:layout_weight">0.5</item>
                <item name="android:indeterminateOnly">false</item>
                <item name="android:minHeight">20dip</item>
                <item name="android:maxHeight">20dip</item>
                <item name="android:progress">15</item>
                <item name="android:max">100</item>
                <item name="android:gravity">center_vertical|left</item>
                <item name="android:progressDrawable">@android:drawable/progress_horizontal</it

em>
                <item 

name="android:indeterminateDrawable">@android:drawable/progress_indetermi

nate_horizontal</item>
        </style>
       
        <style name="imageStyle">
                <item name="android:layout_width">fill_parent</item>
                <item name="android:layout_height">wrap_content</item>
                <item name="android:layout_weight">0.5</item>
                <item name="android:src">@drawable/icon</item>
                <item name="android:scaleType">fitStart</item>
                <item name="android:layout_margin">10dip</item>
                <item name="android:gravity">center_vertical|left</item>
        </style>
</resources>

The application uses following android permission which needs to be added in 'AndroidManifest.xml' file of your project.

<uses-permission android:name="android.permission.ACCESS_COARSE_LOCATION" />

The application also uses some images for indicating the data communication state as no data communication, incoming data communication, outgoing data communication and both ways data communication. These images are respectively named as 'data_none.png','data_in.png', 'data_out.png' and 'data_both.png'. Please add some icons with above names in 'res/drawable' folder of your project structure.

Download:

The source code for this project is in the Android Cookbook repository, http://github.com/IanDarwin/Android-Cookbook-Examples/,in the subdirectory TelephonyManager.