我正在开发一些不需要在App Store上的东西,所以我在使用私有API来满足我的需求方面没有任何问题
我正在尝试使用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`标头并使用桥接头将它们包含在我的swift项目中,并按如下方式编写代码。请原谅,我是新手。
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)
}
会产生错误fatal error: unexpectedly found nil while unwrapping an Optional value which stems from trying to call _createManager
答案 0 :(得分:6)
我最终使用了这种解决方法:
+ (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];
}
没有任何权利或越狱的作品
答案 1 :(得分:5)
由于iPhone X中的状态栏与其他iPhone不同,因此获取WiFi信息的方式也不同。
以下是解决方法如何通过“未记录的属性”获取它,这意味着Apple可能会在未来不知情的情况下更改这些属性。 如果Apple更改未记录的属性,应用程序将崩溃但我们没有相应地调整我们的代码。所以我们必须在Swift中处理NSException。
创建一个Header文件,并将其添加到Bridging-Header.h中。 您可以找到文件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 */
在iPhoneX中,我们可以获得WiFi的 numberOfActiveBars ,范围从0到3。 在iPhoneX以外的其他iPhone中,我们可以获得WiFi RSSI。
在iPhoneX上,请使用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
}
在iPhoneX以外的iPhone设备上,请使用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
}
到目前为止,我还没有找到在iPhoneX上获得WiFi RSSI 的方法。如果你们知道怎么做,请告诉我。感谢。
这是Github中的demo project
答案 2 :(得分:0)
我认为最新版本的iOS不可能。只有iOS4才有可能。
答案 3 :(得分:0)
Apple并不喜欢这种方法并且威胁app review rejection