iOS开发中WiFi相关功能总结

本文总结了iOS开发中与WiFi相关的功能,包括使用SimplePing进行Ping测试、获取WiFi信息、获取WiFi名称、获取网关地址以及获取本机在WiFi环境下的IP地址。通过示例代码和第三方库,详细介绍了实现这些功能的步骤和注意事项。
摘要由CSDN通过智能技术生成




支持在iOS9以上

在 Capabilities 找到 Wireless Accessory Configuration

权限 EFNEHotspotHelperDemo.entitlements  ++  ExternalAccessory.framework

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
	<key>com.apple.external-accessory.wireless-configuration</key>
	<true/>

	<key>com.apple.developer.networking.HotspotHelper</key>
	<true/>

</dict>
</plist>


懒人模式开启,直接copy运行:

#import "ViewController.h"
#import <NetworkExtension/NetworkExtension.h>

@interface ViewController ()

@property (nonatomic, strong) UITextView *outputLabel;
@property (nonatomic, strong) UIButton *settingButton;
@property (nonatomic, copy) NSString *infoString;

@end

@implementation ViewController

- (void)viewDidLoad {
    [super viewDidLoad];

    // 添加控件
    [self addControl];

    // 根据扫描任务添加结果设置按钮状态
    [self.settingButton setEnabled: [self scanWifiInfo]];

    // 添加进入前台时的刷新
    [self observeApplicationNotifications];
}

- (void)viewWillAppear:(BOOL)animated {
    [super viewWillAppear: animated];

    [self refresh];
}

- (void)addControl {
    CGSize screenSize = [UIScreen mainScreen].bounds.size;

    self.outputLabel = [[UITextView alloc] initWithFrame: CGRectMake(3, 23, screenSize.width - 6, screenSize.height - 89)];
    self.outputLabel.font = [UIFont systemFontOfSize: 13];
    self.outputLabel.layer.borderWidth = 1;
    self.outputLabel.editable = NO;
    self.outputLabel.layer.borderColor = [[UIColor blackColor] CGColor];
    [self.view addSubview: self.outputLabel];

    self.settingButton = [[UIButton alloc] initWithFrame: CGRectMake(3, screenSize.height - 64, screenSize.width - 6, 60)];
    self.settingButton.titleLabel.font = [UIFont systemFontOfSize: 20];
    [self.settingButton setTitle: @"Open WiFi Setting" forState: UIControlStateNormal];
    [self.settingButton setTitleColor: [UIColor blackColor] forState: UIControlStateNormal];
    self.settingButton.layer.borderWidth = 1;
    self.settingButton.layer.borderColor = [[UIColor blackColor] CGColor];
    [self.settingButton addTarget: self action:@selector(openWiFiSetting) forControlEvents: UIControlEventTouchUpInside];
    [self.view addSubview: self.settingButton];
}

- (BOOL)scanWifiInfo {
    NSLog(@"1.Start");
    self.outputLabel.text = @"1.Start";

    NSMutableDictionary* options = [[NSMutableDictionary alloc] init];
    [options setObject:@"EFNEHotspotHelperDemo" forKey: kNEHotspotHelperOptionDisplayName];
    dispatch_queue_t queue = dispatch_queue_create("EFNEHotspotHelperDemo", NULL);

    NSLog(@"2.Try");
    self.outputLabel.text = @"2.Try";

    __weak typeof(self) weakself = self;
    BOOL returnType = [NEHotspotHelper registerWithOptions: options queue: queue handler: ^(NEHotspotHelperCommand * cmd) {

        NSLog(@"4.Finish");

        NSMutableString* resultString = [[NSMutableString alloc] initWithString: @""];

        NEHotspotNetwork* network;
        if (cmd.commandType == kNEHotspotHelperCommandTypeEvaluate || cmd.commandType == kNEHotspotHelperCommandTypeFilterScanList) {
            // 遍历 WiFi 列表,打印基本信息
            for (network in cmd.networkList) {
                NSString* wifiInfoString = [[NSString alloc] initWithFormat: @"SSID: %@\nMac地址: %@\n信号强度: %f\nCommandType:%ld\n\n",
                                            network.SSID, network.BSSID, network.signalStrength, (long)cmd.commandType];
                NSLog(@"%@", wifiInfoString);
                [resultString appendString: wifiInfoString];

                // 检测到指定 WiFi 可设定密码直接连接
                if ([network.SSID isEqualToString: @"测试 WiFi"]) {
                    [network setConfidence: kNEHotspotHelperConfidenceHigh];
                    [network setPassword: @"123456789"];
                    NEHotspotHelperResponse *response = [cmd createResponse: kNEHotspotHelperResultSuccess];
                    NSLog(@"Response CMD: %@", response);
                    [response setNetworkList: @[network]];
                    [response setNetwork: network];
                    [response deliver];
                }
            }
        }

        weakself.infoString = resultString;
    }];

    // 注册成功 returnType 会返回一个 Yes 值,否则 No
    NSString* logString = [[NSString alloc] initWithFormat: @"3.Result: %@", returnType == YES ? @"Yes" : @"No"];
    NSLog(@"%@", logString);
    self.outputLabel.text = logString;

    return returnType;
}

// 打开 无线局域网设置
- (void)openWiFiSetting {
    NSURL* urlCheck1 = [NSURL URLWithString: @"App-Prefs:root=WIFI"];
    NSURL* urlCheck2 = [NSURL URLWithString: @"prefs:root=WIFI"];
    NSURL* urlCheck3 = [NSURL URLWithString: UIApplicationOpenSettingsURLString];

    NSLog(@"Try to open WiFi Setting, waiting...");
    self.outputLabel.text = @"Try to open WiFi Setting, waiting...";

    if ([[UIApplication sharedApplication] canOpenURL: urlCheck1]) {
        [[UIApplication sharedApplication] openURL: urlCheck1];
    } else if ([[UIApplication sharedApplication] canOpenURL: urlCheck2]) {
        [[UIApplication sharedApplication] openURL: urlCheck2];
    } else if ([[UIApplication sharedApplication] canOpenURL: urlCheck3]) {
        [[UIApplication sharedApplication] openURL: urlCheck3];
    } else {
        NSLog(@"Unable to open WiFi Setting!");
        self.outputLabel.text = @"Unable to open WiFi Setting!";

        return;
    }
    NSLog(@"Open WiFi Setting successful.");
    self.outputLabel.text = @"Open WiFi Setting successful.";
}

// 从设置页或者其他地方回来刷新
- (void)observeApplicationNotifications {
    [[NSNotificationCenter defaultCenter] removeObserver: self];

    [[NSNotificationCenter defaultCenter] addObserver: self
                                             selector: @selector(refresh)
                                                 name: UIApplicationWillEnterForegroundNotification
                                               object: nil];

    [[NSNotificationCenter defaultCenter] addObserver: self
                                             selector: @selector(refresh)
                                                 name: UIApplicationDidBecomeActiveNotification
                                               object: nil];
}

// 刷新获取到的 WiFi 信息
- (void)refresh {
    if (self.infoString != nil && ![self.infoString isEqual: @""]) {
        self.outputLabel.text = self.infoString;
    }
}








1.Ping域名、Ping某IP

有时候可能会遇到ping 某个域名或者ip通不通,再做下一步操作。这里的ping与传统的做get或者post请求还是有很大区别的。比如我们连接了某个WiFi,测试ping www.baidu.com,如果能ping 通,基本可以断定可以上网了,但是如果我们做了一个get 请求(url 是www.baidu.com),路由器可能重定向这个WiFi内的某网页了,依然没有错误返回,就会误认为可以正常上网。

这里有关于ping命令的详细解释:百度百科Ping

iOS中想要ping域名或者ip,苹果提供了一个官方例子SimplePing

在例子中,有一个苹果已经封装过的类【SimplePing.h】和【SimplePing.m】

使用起来也相当的简单:

首先创建一个Ping对象:

1
2
3
4
5
  SimplePing *pinger = [[SimplePing alloc] initWithHostName:self.hostName];
  self.pinger = pinger;
  pinger.delegate = self;
  pinger.addressStyle = SimplePingAddressStyleICMPv4;
  [pinger start];

然后在start成功的代理方法中,发送数据报文:

1
2
3
4
5
6
7
8
9
10
11
12
13
/**
  *  start成功,也就是准备工作做完后的回调
  */
- (void)simplePing:(SimplePing *)pinger didStartWithAddress:(NSData *)address
{
     // 发送测试报文数据
     [self.pinger sendPingWithData:nil];
}
- (void)simplePing:(SimplePing *)pinger didFailWithError:(NSError *)error
{
     NSLog(@ "didFailWithError" );
     [self.pinger stop];
}

其他几个代理方法也非常简单,就简单记录一下:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
// 发送测试报文成功的回调方法
- (void)simplePing:(SimplePing *)pinger didSendPacket:(NSData *)packet sequenceNumber:(uint16_t)sequenceNumber
{
     NSLog(@ "#%u sent" , sequenceNumber);
}
//发送测试报文失败的回调方法
- (void)simplePing:(SimplePing *)pinger didFailToSendPacket:(NSData *)packet sequenceNumber:(uint16_t)sequenceNumber error:(NSError *)error
{
     NSLog(@ "#%u send failed: %@" , sequenceNumber, error);
}
// 接收到ping的地址所返回的数据报文回调方法
- (void)simplePing:(SimplePing *)pinger didReceivePingResponsePacket:(NSData *)packet sequenceNumber:(uint16_t)sequenceNumber
{
     NSLog(@ "#%u received, size=%zu" , sequenceNumber, packet.length);
}
- (void)simplePing:(SimplePing *)pinger didReceiveUnexpectedPacket:(NSData *)packet
{
     NSLog(@ "#%s" ,__func__);
}

注意点:

iOS 中 ping失败后(即发送测试报文成功后,一直没后收到响应的报文),不会有任何回调方法告知我们。而一般ping 一次的结果也不太准确,ping 花费的时间也非常短,所以我们一般会ping多次,发送一次ping 测试报文0.5s后检测一下这一次ping是否已经收到响应。0.5s后检测时,如果已经收到响应,则可以ping 通;如果没有收到响应,则视为超时。

做法也有很多种,可以用NSTimer或者 {- (void)performSelector: withObject:afterDelay:}

这里有一个别人写的工程:https://github.com/lovesunstar/STPingTest

727768-ff8ab7124905812e.jpg

PingTest效果图

727768-6d4c781945dd1334.jpg

终端ping效果图

2.获取WiFi信息

以前物联网刚火的时候,出现过很多一体式无线路由,所以App里难免会遇到要判断当前所连接的WiFi,以及获取WiFi信息的功能。13年的时候查过一些关于WiFi的方法,后面渐渐都忘记了。惭愧!!!

需要添加SystemConfiguration.framework 并在当前类中添加代码

#import arpa/inet.h>
#import netinet/in.h>
#import ifaddrs.h>

1
2
3
4
5
6
7
8
9
10
11
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值