iPhone在WiFi网络变化时的通知

8
这是针对一个“调整”的应用,所以目标是越狱设备,而不是应用商店。 我已经尝试了钩取SBWiFiManager中的不同方法,但它们要么在wifi信号变化时(因此连续)被调用,要么在网络变化后相当长的延迟之后才被调用。
是否有其他方法可以获得通知(或挂钩另一个方法),以便在wifi网络发生更改时告知?
我知道现在可以使用公共API获取当前SSID,但我需要在其更改时被告知。

写一个越狱插件就加1分! - Anil
2个回答

18

一个方法是监听来自核心基础达尔文通知中心的com.apple.system.config.network_change事件。

注册该事件:

CFNotificationCenterAddObserver(CFNotificationCenterGetDarwinNotifyCenter(), //center
                                NULL, // observer
                                onNotifyCallback, // callback
                                CFSTR("com.apple.system.config.network_change"), // event name
                                NULL, // object
                                CFNotificationSuspensionBehaviorDeliverImmediately);

这是一个示例回调函数:

static void onNotifyCallback(CFNotificationCenterRef center, void *observer, CFStringRef name, const void *object, CFDictionaryRef userInfo)
{
    NSString* notifyName = (NSString*)name;
    // this check should really only be necessary if you reuse this one callback method
    //  for multiple Darwin notification events
    if ([notifyName isEqualToString:@"com.apple.system.config.network_change"]) {
        // use the Captive Network API to get more information at this point
        //  https://dev59.com/L2445IYBdhLWcg3wwc2g#4714842
    } else {
        NSLog(@"intercepted %@", notifyName);
    }
}

请参见我的另一个答案的链接,了解如何使用Captive Network API获取当前SSID。

请注意,尽管我测试的手机已越狱(iOS 6.1),但我认为这不需要越狱即可正常工作。它当然不需要在正常沙盒区域之外安装应用程序(/var/mobile/Applications/*)。

附言:我没有进行充分的测试,无法确定此事件是否会出现任何误报(基于您对网络更改的定义)。不过,只需存储一些状态变量,等于上一个网络的SSID,并在接收到此事件时将其与当前SSID进行比较即可。


谢谢!!!(顺便说一下,我只是加了越狱的那一段话,以防止有人说它会被AppStore拒绝)。出于好奇,你是怎么找到通知的名称的? - Jonathan.
3
@Jonathan,你能否提出一个新问题,询问确定使用哪些通知的常规技术?我提出这个问题不仅仅是为了多得几个声望点,而是因为(a)我的回答无法放在评论中,(b)如果问题的标题、标签和描述得当,对其他人会更加有用(并且可搜索)。评论没有太多用处,只适合短暂回复。你当然可以将此问题作为一个具体示例链接到那个问题中,以说明为何需要这些技术。 - Nate
"com.apple.system.config.network_change" 经常会通知四次。为什么?您有什么想法可以检查或合并吗?谢谢。 - Victor Choy
是的,看起来我们可以保存一些状态,比如bssid。然而,每次重复通知发生时,我们总是得到空的bssid。这很奇怪。 - Victor Choy

3

SWIFT 4.1 版本

我已经扩展了Reachability类,添加了以下函数:

let notificationName = "com.apple.system.config.network_change"

func onNetworkChange(_ name : String) {
    if (name == notificationName) {
        // Do your stuff
        print("Network was changed")
    }
}

func registerObserver() {
    let observer = UnsafeRawPointer(Unmanaged.passUnretained(self).toOpaque())
    CFNotificationCenterAddObserver(CFNotificationCenterGetDarwinNotifyCenter(), observer,
                                    { (nc, observer, name, _, _) -> Swift.Void in
                                        if let observer = observer, let name = name {
                                            let instance = Unmanaged<Reachability>.fromOpaque(observer).takeUnretainedValue()
                                            instance.onNetworkChange(name.rawValue as String)
                                        } },
                                    notificationName as CFString, nil, .deliverImmediately)
}

func removeObserver() {
    let observer = UnsafeRawPointer(Unmanaged.passUnretained(self).toOpaque())
    CFNotificationCenterRemoveObserver(CFNotificationCenterGetDarwinNotifyCenter(), observer, nil, nil)
}

在初始化时注册观察器,在去初始化时移除观察器。很遗憾,没有额外的信息说明具体发生了什么变化,但我们可以尝试测试当前的SSID作为例子。希望这对某些人有所帮助)


在我的情况下,当网络断开或连接时,通知会被多次调用。你也遇到了同样的问题吗? - Dinesh
@Dinesh,我也遇到了“通知被多次调用”的同样问题。你找到解决方案了吗?是否有可能可靠地限制网络更改时只调用一次通知? - Shiva Reddy
@ShivaReddy,我从未找到解决此问题的方法,现在也不再关注它了。 - Dinesh
作为您代码的小改进:您可以使用在<notify_keys.h>中定义的kNotifySCNetworkChange常量,而不是直接使用“com.apple.system.config.network_change”。 - lucianoenrico

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接