Using Private API To read WiFi RSSI value

I'm working on something that doesn't have to be in the app store, so I have no problem using private APIs to meet my needs. I'm trying to use MobileWiFi. framework to read the RSSI value for the wireless network the phone is currently connected to. I've included the headers MobileWiFi. framework to read the RSSI value for the wireless network the phone is currently connected to. I've included the MobileWiFi. framework to read the RSSI value for the wireless network the phone is currently connected to. I've included the MobileWiFi. framework to read the RSSI value for the wireless network the phone is currently connected to. I've included the https://github.com/Cykey/ios-reversed-headers/tree/c613e45f3ee5ad9f85ec7d43906cf69ee812ec6a/MobileWiFi `and used the bridge header to include them in my quick project and wrote the code as follows. Please excuse me, I'm new.

 import SystemConfiguration.CaptiveNetwork typealias _WiFiManagerClientCreate = @convention(c) (CFAllocator, CInt) -> UnsafeRawPointer typealias _WiFiManagerClientCopyDevices = @convention(c) (UnsafeRawPointer) -> CFArray typealias _WiFiDeviceClientCopyProperty = @convention(c) (UnsafeRawPointer, CFString) -> CFPropertyList if let libHandle = dlopen (Paths.ipConfiguration, RTLD_LAZY) { result = libHandle.debugDescription let _createManagerPtr = dlsym(libHandle, "WiFiManagerClientCreate") let _clientCopyDevicesPtr = dlsym(libHandle, "WiFiManagerClientCopyDevices") let _clientCopyPropertyPtr = dlsym(libHandle, "WiFiDeviceClientCopyProperty") if (_createManagerPtr != nil) && (_clientCopyDevicesPtr != nil) && (_clientCopyPropertyPtr != nil) { let _createManager = unsafeBitCast(_createManagerPtr, to: _WiFiManagerClientCreate.self) let _clientCopyDevices = unsafeBitCast(_clientCopyDevicesPtr, to: _WiFiManagerClientCopyDevices.self) let _clientCopyProperty = unsafeBitCast(_clientCopyPropertyPtr, to: _WiFiDeviceClientCopyProperty.self) let manager = _createManager(kCFAllocatorDefault, 0) let devices = _clientCopyDevices(manager) let client = CFArrayGetValueAtIndex(devices, 0) let data = _clientCopyProperty(client!, "RSSI" as CFString) let rssi = CFDictionaryGetValue(data as! CFDictionary, "RSSI_CTL_AGR") NSLog("RSSI: \(rssi)") } dlclose(libHandle) } 

Which gives the error fatal error: unexpectedly found nil while unwrapping an Optional value which stems from trying to call _createManager

+7
ios swift
source share
3 answers

I ended up using this workaround:

 + (int) wifiStrength { UIApplication *app = [UIApplication sharedApplication]; NSArray *subviews = [[[app valueForKey:@"statusBar"] valueForKey:@"foregroundView"] subviews]; NSString *dataNetworkItemView = nil; for (id subview in subviews) { if([subview isKindOfClass:[NSClassFromString(@"UIStatusBarDataNetworkItemView") class]]) { dataNetworkItemView = subview; break; } } return[[dataNetworkItemView valueForKey:@"wifiStrengthRaw"] intValue]; } 

Works without any rights or jailbreaks

+6
source share

Since the status bar on the iPhone X is different from other iPhones, the way you get WiFi information is different.

Here is a workaround on how to get it through undocumented properties, "which means that Apple may change these properties in the future without informing us. The application will crash if Apple changes the undocumented properties , but we have not adjusted our code accordingly. Therefore we must handle NSException in Swift.

Create a header file and add it to your Bridging-Header.h. You can find the file here: https://gist.github.com/zhihuitang/6d3de0963d96a552d47721a598ca79c8

 // // OCCatch.h // // #ifndef OCCatch_h #define OCCatch_h // add the code below to your -Bridging-Header.h /** #import "OCCatch.h" */ // How to use it in Swift? /** let exception = tryBlock { let statusBar = UIApplication.shared.value(forKey: "statusBar") as? UIView //...... } if let exception = exception { print("exception: \(exception)") } */ #import <Foundation/Foundation.h> NS_INLINE NSException * _Nullable tryBlock(void(^_Nonnull tryBlock)(void)) { @try { tryBlock(); } @catch (NSException *exception) { return exception; } return nil; } #endif /* OCCatch_h */ 

On iPhoneX, we can get WiFi numberOfActiveBars , which ranges from 0 to 3. On other iPhones, except iPhoneX, we can get WiFi RSSI.

On iPhoneX, use getWiFiNumberOfActiveBars() :

  private func getWiFiNumberOfActiveBars() -> Int? { let app = UIApplication.shared var numberOfActiveBars: Int? let exception = tryBlock { guard let containerBar = app.value(forKey: "statusBar") as? UIView else { return } guard let statusBarMorden = NSClassFromString("UIStatusBar_Modern"), containerBar .isKind(of: statusBarMorden), let statusBar = containerBar.value(forKey: "statusBar") as? UIView else { return } guard let foregroundView = statusBar.value(forKey: "foregroundView") as? UIView else { return } for view in foregroundView.subviews { for v in view.subviews { if let statusBarWifiSignalView = NSClassFromString("_UIStatusBarWifiSignalView"), v .isKind(of: statusBarWifiSignalView) { if let val = v.value(forKey: "numberOfActiveBars") as? Int { numberOfActiveBars = val break } } } if let _ = numberOfActiveBars { break } } } if let exception = exception { print("getWiFiNumberOfActiveBars exception: \(exception)") } return numberOfActiveBars } 

On iPhone devices other than iPhoneX, use getWiFiRSSI() :

 private func getWiFiRSSI() -> Int? { let app = UIApplication.shared var rssi: Int? let exception = tryBlock { guard let statusBar = app.value(forKey: "statusBar") as? UIView else { return } if let statusBarMorden = NSClassFromString("UIStatusBar_Modern"), statusBar .isKind(of: statusBarMorden) { return } guard let foregroundView = statusBar.value(forKey: "foregroundView") as? UIView else { return } for view in foregroundView.subviews { if let statusBarDataNetworkItemView = NSClassFromString("UIStatusBarDataNetworkItemView"), view .isKind(of: statusBarDataNetworkItemView) { if let val = view.value(forKey: "wifiStrengthRaw") as? Int { rssi = val break } } } } if let exception = exception { print("getWiFiRSSI exception: \(exception)") } return rssi } 

So far, I have not found a way to get WiFi RSSI on iPhoneX. If you guys know how to do this, please let me know. thanks.

here is a demo project on github

+3
source share

I think this is not possible for the latest version of iOS. This is only possible for iOS4.

0
source share

All Articles