Accurately reading of iPhone signal strength
Asked Answered
P

2

10

There are a few questions on this already, but nothing in them seems to provide accurate results. I need to determine simply if the phone is connected to a cell network at a given moment.

http://developer.apple.com/library/ios/#documentation/NetworkingInternet/Reference/CTCarrier/Reference/Reference.html

This class seems to be documented incorrectly, returning values for mobileCountryCode, isoCountryCode and mobileNetworkCode where no SIM is installed to the phone. carrierName indicates a 'home' network or a previous home network if the phone has been unlocked.

I also looked up and found some people claiming the following to work, which uses an undocumented method of the CoreTelephony framework, but the results have been useless to me, reporting seemingly random figures, where perhaps it is not itself updating consistently.

-(int) getSignalStrength
{
    void *libHandle = dlopen("/System/Library/Frameworks/CoreTelephony.framework/CoreTelephony", RTLD_LAZY);
    int (*CTGetSignalStrength)();
    CTGetSignalStrength = dlsym(libHandle, "CTGetSignalStrength");
    if( CTGetSignalStrength == NULL) NSLog(@"Could not find CTGetSignalStrength");
    int result CTGetSignalStrength();
    dlclose(libHandle);
    return result;
}

Thanks.

Edit: The app is connected to an internal wifi and must remain so, making a reachability check more difficult.

Pyromorphite answered 30/1, 2013 at 12:41 Comment(2)
It not run IOS 8.3 help help meDominickdominie
It is not working in iOS 8.4 too, Is there any other way?Subtilize
P
5

Ok I think I have the correct solution now, which was a bit simpler in the end.

The issue with the CTGetSignalStrength() method is that it works normally, but if you remove a sim, it reports the last signal before the removal. I found another method in the same framework called CTSIMSupportGetSIMStatus(), also undocumented, which can tell you if a SIM is currently connected. Using both as follows should confirm the current network signal.

First declare the methods:

NSString * CTSIMSupportGetSIMStatus();
int CTGetSignalStrength();

Then check connectivity to cell network like so:

NSString *status = CTSIMSupportGetSIMStatus();
int signalstrength = CTGetSignalStrength();
BOOL connected = ( [status isEqualToString: @"kCTSIMSupportSIMStatusReady"] && signalstrength > 0 );
Pyromorphite answered 31/1, 2013 at 16:29 Comment(5)
Will this work to detect airplane mode? The private APIs are private for a reason.Millham
You could not assume airplane mode using this, because you couldn't differentiate between no signal where a SIM is installed and the mode being set, so you'd have to look at something else. Certain values of the CTCarrier class are supposed to return nil when the phone is in airplane mode, but I expect this will not work unless the phone has been rebooted.Pyromorphite
I've tried your code but do not understand the value. Do you know what does the number actually represent?Joan
You mean signalstrength? This should give you the signal strength. I'm not sure what the range is however 0 is certainly no signal. This is unreliable though and you need to check the SIM status is ready also, hence why I combined it with the other function into a bool to see if we have signal.Pyromorphite
it not run with IOS 8.3 , help me pleaseDominickdominie
M
9

I'm playing with this function and I've noticed you're calling it in an interesting way. I'm calling it by adding CoreTelephony.framework as a compile-time link. For the function itself, you'll want to declare it's prototype somewhere (perhaps immediately above the method you call from):

int CTGetSignalStrength();

This needs to be declared since it isn't in a public header for CoreTelephony.

Now, I built a simple app that prints signal strength every second.

int CTGetSignalStrength();

- (void)viewDidLoad
{
    [super viewDidLoad];

    while (true) {
        printf("signal strength: %d\n", CTGetSignalStrength());
        sleep(1);
    }
}

I ran it on my iPad mini and it shows steady values until I picked it up, where the number went up. Wrapping my iPad in tin foil (tin foil is a debugging tool I have never used before) caused the number to go down. When I put my iPad in airplane mode, it kept repeating the last value, so this will not be an accurate measure for you.

If you want to test if a device currently has a cellular data network connection, you may be more interested in Reachability, specifically kSCNetworkReachabilityFlagsIsWWAN.

Millham answered 30/1, 2013 at 13:3 Comment(2)
Thanks, that reachability side could be a way forward, though I don't have it working straight away. The issue is that we are deploying the app over a restricted wifi which must remain connected, and so lose the ability to check the connectivity of a data connection. iphonedevsdk.com/forum/iphone-sdk-development/… This might help though if I can ask the phones to use the wifi only for certain things.Pyromorphite
@wjl, Thanks for your post, I have one doubt as is it only work for cellular data or we are able to get Wifi strength too? I have to restrict use if connection is weak.Subtilize
P
5

Ok I think I have the correct solution now, which was a bit simpler in the end.

The issue with the CTGetSignalStrength() method is that it works normally, but if you remove a sim, it reports the last signal before the removal. I found another method in the same framework called CTSIMSupportGetSIMStatus(), also undocumented, which can tell you if a SIM is currently connected. Using both as follows should confirm the current network signal.

First declare the methods:

NSString * CTSIMSupportGetSIMStatus();
int CTGetSignalStrength();

Then check connectivity to cell network like so:

NSString *status = CTSIMSupportGetSIMStatus();
int signalstrength = CTGetSignalStrength();
BOOL connected = ( [status isEqualToString: @"kCTSIMSupportSIMStatusReady"] && signalstrength > 0 );
Pyromorphite answered 31/1, 2013 at 16:29 Comment(5)
Will this work to detect airplane mode? The private APIs are private for a reason.Millham
You could not assume airplane mode using this, because you couldn't differentiate between no signal where a SIM is installed and the mode being set, so you'd have to look at something else. Certain values of the CTCarrier class are supposed to return nil when the phone is in airplane mode, but I expect this will not work unless the phone has been rebooted.Pyromorphite
I've tried your code but do not understand the value. Do you know what does the number actually represent?Joan
You mean signalstrength? This should give you the signal strength. I'm not sure what the range is however 0 is certainly no signal. This is unreliable though and you need to check the SIM status is ready also, hence why I combined it with the other function into a bool to see if we have signal.Pyromorphite
it not run with IOS 8.3 , help me pleaseDominickdominie

© 2022 - 2024 — McMap. All rights reserved.