美文网首页iOS 精美收藏
iOS 判断是否连接VPN

iOS 判断是否连接VPN

作者: F森 | 来源:发表于2017-04-12 13:09 被阅读1432次

由于项目测试当中需要外网测试人员连到内网进行测试,有时候因为测试人员大意,没有连接到VPN环境,导致反馈过来的测试结果不正确,因此需要在打包测试安装包的时候先判断是否已经连接上VPN。

网上找到的blog都是判断当前网络状态,但是判断的结果却不准确,满足不了需求。在一次跟 @黄二百万 聊天中获得灵感,可以根据状态栏中的的图标进行判断,判断当前的状态栏是否有VPN标志。
</br>
</br>方案一:起初想通获取状态栏UIStatusBar的方式,将UIView转成UIImage,然后通过图片文字识别,是否包含“VPN”字样,但是系统的UIStatusBar“直接”获取是获取不到的,该方案行不通。(勘误:可以通过方案三中的方式得到)
</br>
</br>方案二:将整个屏幕截图包括状态栏,然后截取

[UIApplication sharedApplication].statusBarFrame 

这个size下的context再转成UIImage,然后通过图片文字识别,是否包含“VPN”字样。但是通过代码截图的方式获取不到带状态栏的截图,因此该方案也行不通(如果谁知道如何获取带状态栏的截图,麻烦留言区告知,谢谢!!!)
</br>
</br> 方案三:偶然看到一篇博客里面可以通过UIApplication的:

- (nullable id)valueForKey:(NSString *)key;

的方式获取到 UIStatusBar!

将手机连上VPN, 尝试打印:

 UIApplication *app = [UIApplication sharedApplication];
 UIView *statusView = [app valueForKey:@"statusBar"];
 NSArray *subViews = [[statusView valueForKey:@"foregroundView"] subviews];
 
 NSLog(@"%@",subViews);

结果如下是:

Printing description of subViews:
<__NSArrayM 0x170258780>(
<UIStatusBarSignalStrengthItemView: 0x100306110; frame = (6 0; 35 20); userInteractionEnabled = NO; layer = <CALayer: 0x17403a0e0>> [Item = <UIStatusBarItem: 0x17403a0c0> [UIStatusBarSignalStrengthItemView (Left)]],
<UIStatusBarServiceItemView: 0x1002015d0; frame = (44 0; 50 20); userInteractionEnabled = NO; layer = <CALayer: 0x17003e520>> [Item = <UIStatusBarItem: 0x17003e560> [UIStatusBarServiceItemView (Left)]],
<UIStatusBarDataNetworkItemView: 0x100209210; frame = (99 0; 13 20); userInteractionEnabled = NO; layer = <CALayer: 0x17003e180>> [Item = <UIStatusBarItem: 0x17003e2e0> [UIStatusBarDataNetworkItemView (Left)]],
<UIStatusBarIndicatorItemView: 0x1002099b0; frame = (118 0; 20 20); userInteractionEnabled = NO; layer = <CALayer: 0x1702204e0>> [Item = <UIStatusBarItem: 0x170220500> [UIStatusBarIndicatorItemView:VPN (Left/Right)]],
<UIStatusBarBatteryItemView: 0x10020a140; frame = (337 0; 33 20); userInteractionEnabled = NO; layer = <CALayer: 0x170220320>> [Item = <UIStatusBarItem: 0x170220580> [UIStatusBarBatteryItemView (Right)]],
<UIStatusBarBatteryPercentItemView: 0x10020bbd0; frame = (303 0; 31 20); userInteractionEnabled = NO; layer = <CALayer: 0x170220c20>> [Item = <UIStatusBarItem: 0x170220560> [UIStatusBarBatteryPercentItemView (Right)]],
<UIStatusBarIndicatorItemView: 0x100209420; frame = (287 0; 10 20); userInteractionEnabled = NO; layer = <CALayer: 0x170220c60>> [Item = <UIStatusBarItem: 0x170220540> [UIStatusBarIndicatorItemView:Alarm (Right)]],
<UIStatusBarIndicatorItemView: 0x10020aaf0; frame = (261 0; 20 20); alpha = 0; userInteractionEnabled = NO; layer = <CALayer: 0x170220d80>> [Item = <UIStatusBarItem: 0x170220500> [UIStatusBarIndicatorItemView:VPN (Left/Right)]],
<UIStatusBarIndicatorItemView: 0x10020a370; frame = (269 0; 12 20); userInteractionEnabled = NO; layer = <CALayer: 0x170220d00>> [Item = <UIStatusBarItem: 0x170220520> [UIStatusBarIndicatorItemView:RotationLock (Right)]],
<UIStatusBarTimeItemView: 0x100204470; frame = (161 0; 56 20); userInteractionEnabled = NO; layer = <CALayer: 0x170220f40>> [Item = <UIStatusBarItem: 0x17403a0a0> [UIStatusBarTimeItemView (Center)]]
)

可以看到description打印结果中有暴露“VPN”相关的信息,证明通过访问私有属性是可以做到的。

方法一:因此可以通过遍历UIStatusBar的子view,打印子view的description,通过判断description中是否包含“VPN”这个子字符串的方式达到文章开头提到的目的!

上代码:

- (BOOL)isVPNConnected {
    UIApplication *app = [UIApplication sharedApplication];
    UIView *statusView = [app valueForKey:@"statusBar"];
    NSArray *subViews = [[statusView valueForKey:@"foregroundView"] subviews];
    
    Class StatusBarIndicatorItemViewClass = NSClassFromString(@"UIStatusBarIndicatorItemView");
    for (UIView *subView in subViews) {
        Class SubStatusBarIndicatorItemViewClass = [subView class];
        if ([SubStatusBarIndicatorItemViewClass isSubclassOfClass:StatusBarIndicatorItemViewClass]) {
            return [[subView description] containsString:@"VPN"];
        }
    }
    return NO;
}

方法二:访问UIStatusBarIndicatorItemView的私有属性_visible判断是否开启了VPN
上代码:

- (BOOL)isVPNConnected {
    UIApplication *app = [UIApplication sharedApplication];
    UIView *statusView = [app valueForKey:@"statusBar"];
    NSArray *subViews = [[statusView valueForKey:@"foregroundView"] subviews];
    
    Class StatusBarIndicatorItemViewClass = NSClassFromString(@"UIStatusBarIndicatorItemView");
    for (UIView *subView in subViews) {
        Class SubStatusBarIndicatorItemViewClass = [subView class];
        if ([SubStatusBarIndicatorItemViewClass isSubclassOfClass:StatusBarIndicatorItemViewClass]) {
            return [[subView valueForKey:@"_visible"] boolValue];
        }
    }
    return NO;
}

相关文章

网友评论

  • 8f72a97287bc:- (BOOL)fetchHttpProxy {
    CFDictionaryRef dicRef = CFNetworkCopySystemProxySettings();
    const CFStringRef proxyCFstr = (const CFStringRef)CFDictionaryGetValue(dicRef,
    (const void*)kCFNetworkProxiesHTTPProxy);
    NSString* proxy = (__bridge NSString *)proxyCFstr;
    if (proxy != nil) {
    return YES;
    }else if ( proxy != nil || proxy == NULL) {
    return NO;
    }
    return NO;
    }
    用这个方法来判断是否使用了代理,效果一样的
  • 天下林子:大神威武
  • yuanweiphone:检测vpn会出问题,判断vpn时,先关闭vpn,进入应用后,再开启vpn,点击按钮打印出来还是未开启
  • 程序猿马国玺:思路奇特
  • rockyMJ:大神方法二不灵啦,连上vpn < _visible >也是false
  • 80369a0b377b:iPhoneX的用此法不行了。有好的办法吗。楼主
    大爱无声2016:在iphonex 下你解决了吗? 看到了麻烦回复我一下,谢谢 377121930@qq.com
    F森:没有iPhoneX设备 没办法做测试 你解决了没?
  • 表情_:大神 两个方法都不能用了
    80369a0b377b:是啥意思呀?使用这方法的话,上传苹果的时候会被拒绝吗?
    表情_:@F森 好的 谢谢大神
    F森:@表情_ 是属于私有api,测试时网络环境判断用的

本文标题:iOS 判断是否连接VPN

本文链接:https://www.haomeiwen.com/subject/ouqmattx.html