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

4

45

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.

Abfarad answered 4/5, 2012 at 18:39 Comment(4)
Nice and easy tutorialGosselin
Hi are you getting the answer of this question?If you got please give some examples? I need the same your requirements..Cf
I know that this is an old thread, but did you finish your app? Can it be downloaded somewhere?Gram
Hello @Schwartz, I am looking for the same requirement. Do you find a solution for it?. Any paid/free API if you can suggest.Selfinsurance
F
24

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!

Frazee answered 26/5, 2013 at 0:21 Comment(7)
How do you import the items like INetworkQueryService? I can't find paths to them that eclipse recognises.Lumbye
Can't try it today, sorry, but if import com.android.phone.INetworkQueryService doesn't work, you could copy the code and create your own solution using the same principles (basically, it's what I try to say in my answer).Frazee
That's exactly what I did: I created an Activity from scratch and used the code you suggest. However, a lot of the classes referred to, for example INetworkQueryService and NetworkQueryService are not recognised, eclipse can't find import for them and obvious guesses (such as import com.android.phone.INetworkQueryService) result in The import com.android.phone cannot be resolved. What would you suggest?Lumbye
Up to where I can imagine, you can't import com.android.phone, but you've got access to the source code. What I suggest in my answer is to create your own solution copying and modifying it to fit your needs.Frazee
Someone tried? It works? I don't see how it could to work fine.Linsk
Does more than a month that I'm trying to do this, I don't know how this assumption was setted like correct answer (or with 175 points). Someone tried? Worked? I can't have the instance of NetworkQueryService because it is a internal class, for do this I should use a object that contains a instance of the class, that by the way I don't know where find it or if is really possible of be found. Please, help me with this search.Linsk
This might allow you to get a list of OperatorInfo structures, but an OperatorInfo only contains a long name, a short name, the numeric ID and whether you are allowed/registered in that network. It does not contain a signal strength or the network type (GSM/3G/4G)!Radiator
M
2
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);
    }

};
Melainemelamed answered 5/5, 2012 at 7:39 Comment(3)
Thanks for the reply, but this code will 'only' give me info on the subscribed network, I 'm also interested inthe signal strength of the other providers in the area.Abfarad
means when you search for network, operator shown in list and you want to know all shown operators network strength..am i right???Melainemelamed
That's right I want to see a list of all possible network operators and their signal strengths where I am currently.Abfarad
P
1

As I have no 50 reputation points, here is the result of my searches about the subject :

The solution of Alejandro Colorado seems to be the good one. But the problem is that the classes used to achieve it are reserved for android system applications, i.e. apps which are signed with the same signature key as the system.

How could it be possible? I found two way to achieve this.

The first one is to ask a job at any manufacturer compagny, and sign their NDA, but eh, that's not a really good solution. Especially as the app implemented and signed with this key will only work on devices from the compagny...

The second one, much more enjoyable, but i warn you, it's not gonna be easy, is to make your own ROM. You'll have to create your application, insert it in the /system/app/ directory of your ROM and recompile it to flash your device with your new system. But there's a question i've not answered yet, is the problem of unrecognised ROM signature. I think the best way to avoid this problem is to add your ROM signing key in the Recovery you'll be using.

That's where i am at this point, maybe you could find these research usefull, i hope so! I'll come back later if i find some more informations for you guys. Bye.

Presa answered 30/1, 2015 at 15:52 Comment(0)
M
0

create a PhoneStateListener and handle the onSignalStrengthChanged callback. When your app is initialized, it should give you an initial notification. This is in 1.x. in 2.x, there's an open issueabout this.

Mendelsohn answered 4/5, 2012 at 18:48 Comment(4)
Thanks for the fast answer. I have tried that as stated above, it only gives me the signal strength of the current network operators' signal. I'm interested in a full list of all available operators and their current signal strength.Abfarad
I never tried these i'll search that and if i found any answer i'll post here.Mendelsohn
whar is the mean of "I'm interested in a full list of all available operators and their current signal strength."?Melainemelamed
A full list means all available network operators at the phones current position.Abfarad

© 2022 - 2024 — McMap. All rights reserved.