2017-05-24 78 views
7

我正在研究一些不需要在App Store上的東西,所以我沒有使用私有API來滿足我的需求的問題 我正在嘗試使用MobileWiFi. framework to read the RSSI value for the wireless network the phone is currently connected to. I've included thehttps://github.com/Cykey/ios-reversed-headers/tree/c613e45f3ee5ad9f85ec7d43906cf69ee812ec6a/MobileWiFi`標題並使用橋接標題將它們包含在我的swift項目中,並按如下所示編寫代碼。請原諒我,我是一個新手。使用私有API讀取WiFi RSSI值

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

回答

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

工作沒有任何權利或越獄

0

我認爲這是不可能的iOS的最新版本。只有iOS4纔有可能。

+0

我設法讓代碼來構建的,但現在看來似乎不起作用,因爲的權利需要,應該一個越獄的手機 –

+0

上工作,它在非工作越獄設備? – user2323838

+0

不,因爲您無法獲得運行所需的權利 –

3

由於iPhone X狀態欄是從其他的iPhone不同,得到的WiFi信息的方式是不同的。

這裏是解決方法1:通過「無證文件屬性」獲取它,這意味着Apple可能會在未告訴我們將來更改這些屬性。 如果Apple更改了未記錄的屬性,該應用程序將崩潰,但我們沒有相應地調整我們的代碼。所以我們必須在Swift中處理NSException。

創建一個頭文件,並將其添加到您的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,我們可以得到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 
} 

到目前爲止,我還沒有找到一種方式來獲得無線RSSI在iPhoneX上使用。如果你們知道如何去做,請告訴我。謝謝。

這裏是在Github上demo project