Android: How do I get GSM signal strength for all available network operators

I am working on a little app to check the signal strength of various network operators in my area. My current operators signal is quite unstable and I want to look into the strength of other GSM operators.

Sofar I've been using the TelephonyManager and a PhoneStateListener with the onSignalStrengthsChanged call back to get the GSM Signal strength of the current network operator, but it seems that this class only gives me info on the signal strength of the network attached to my SIM card.

I'm interested in measurement of GSM signal strength of ALL available operators. Searching the net has given vague hints on using internal android classes, but I've not yet found any good examples on this.

Any answer that can move me on to get a list of all available network operators and their signal strength are appreaciated.


Maybe these quotes and links can help you code your own solution:

1.- To get a list of available network providers (quoting How to get a list of available network providers? in full):

Since Android is open source I had a look at the sources and finally found something called INetworkQueryService. I guess you can do the same as the android settings implementation and interact with this service. Some guidance through NetworkSettings.java:

  • onCreate starts the NetworkQueryService and binds it.
  • loadNetworksList() tells the service to query for network operators.
  • INetworkQueryServiceCallback is evaluated and if the event "EVENT_NETWORK_SCAN_COMPLETED" was raised, networksListLoaded will be called to iterate over the available Networks.

2.- Even a quick read to NetworkSetting.java and INetworkQueryService interface, gives us an idea to achieve your goal.

  • Connect the service in declaration.
/**
 * Service connection code for the NetworkQueryService.
 * Handles the work of binding to a local object so that we can make
 * the appropriate service calls.
 */

/** Local service interface */
private INetworkQueryService mNetworkQueryService = null;

/** Service connection */
private final ServiceConnection mNetworkQueryServiceConnection = new ServiceConnection() {

    /** Handle the task of binding the local object to the service */
    public void onServiceConnected(ComponentName className, IBinder service) {
        if (DBG) log("connection created, binding local service.");
        mNetworkQueryService = ((NetworkQueryService.LocalBinder) service).getService();
        // as soon as it is bound, run a query.
        loadNetworksList();
    }

    /** Handle the task of cleaning up the local binding */
    public void onServiceDisconnected(ComponentName className) {
        if (DBG) log("connection disconnected, cleaning local binding.");
        mNetworkQueryService = null;
    }
};
  • onCreate starts the NetworkQueryService and binds it.
Intent intent = new Intent(this, NetworkQueryService.class);
...
startService (intent);
bindService (new Intent(this, NetworkQueryService.class), mNetworkQueryServiceConnection,
                        Context.BIND_AUTO_CREATE);
  • loadNetworksList() tells the service to query for network operators.
private void loadNetworksList() {
...    
// delegate query request to the service.
try {
    mNetworkQueryService.startNetworkQuery(mCallback);
} catch (RemoteException e) {
}

displayEmptyNetworkList(false); 
}
  • INetworkQueryServiceCallback is evaluated:
/**
 * This implementation of INetworkQueryServiceCallback is used to receive
 * callback notifications from the network query service.
 */
private final INetworkQueryServiceCallback mCallback = new INetworkQueryServiceCallback.Stub() {

    /** place the message on the looper queue upon query completion. */
    public void onQueryComplete(List<OperatorInfo> networkInfoArray, int status) {
        if (DBG) log("notifying message loop of query completion.");
        Message msg = mHandler.obtainMessage(EVENT_NETWORK_SCAN_COMPLETED,
                status, 0, networkInfoArray);
        msg.sendToTarget();
    }
};
  • If the event "EVENT_NETWORK_SCAN_COMPLETED" was raised, networksListLoaded will be called to iterate over the available Networks.
private void networksListLoaded(List<OperatorInfo> result, int status) {
    ...

    if (status != NetworkQueryService.QUERY_OK) {
        ...
        displayNetworkQueryFailed(status);
        displayEmptyNetworkList(true);
    } else {
        if (result != null){
            displayEmptyNetworkList(false);
            ...
        } else {
            displayEmptyNetworkList(true);
        }
    }
}

I hope it helps. I think it's an interesting challenge so maybe I'll give it a try next time I have some spare time. Good luck!


private final PhoneStateListener phoneStateListener = new PhoneStateListener() {
    @Override
    public void onCallForwardingIndicatorChanged(boolean cfi) {

        super.onCallForwardingIndicatorChanged(cfi);
    }

    @Override
    public void onCallStateChanged(int state, String incomingNumber) {
        //checkInternetConnection();
        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;
        }

        Log.i("Phone Stats", "onCallStateChanged " + callState);

        super.onCallStateChanged(state, incomingNumber);
    }

    @Override
    public void onCellLocationChanged(CellLocation location) {
        String cellLocationString = location.toString();

        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;
        }

        Log.i("Phone Stats", "onDataActivity " + directionString);

        super.onDataActivity(direction);
    }

    @Override
    public void onDataConnectionStateChanged(int state,int networktype) {
        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;
        }

        super.onDataConnectionStateChanged(state);


        Log.i("Phone Stats", "onDataConnectionStateChanged "
                + connectionState);


    }

    @Override
    public void onMessageWaitingIndicatorChanged(boolean 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;
        }

        Log.i("Phone Stats", "onServiceStateChanged " + serviceStateString);

        super.onServiceStateChanged(serviceState);
    }

    @Override
    public void onSignalStrengthChanged(int asu) {

        Log.i("Phone Stats", "onSignalStrengthChanged " + asu);
        setSignalLevel( asu);
        super.onSignalStrengthChanged(asu);
    }
    private void setSignalLevel(int level) {
        int sLevel = (int) ((level / 31.0) * 100);


        Log.i("signalLevel ", "" + sLevel);
    }

};