#import <Foundation/Foundation.h>
@interface RKNetConnect: NSObject
@property(nonatomic,strong)NSString *oBytes; //上行流量
@property(nonatomic,strong)NSString *oBytesOfRate;
@property(nonatomic,strong)NSString *iBytes; //下行流量
@property(nonatomic,strong)NSString *iBytesOfRate;
+(instancetype)shareInstance;
@end
@interface RKNetMonitor : NSObject
@property(nonatomic,strong)RKNetConnect *connectObj;
+(instancetype)shareInstance;
- (RKNetConnect *)getInterfaceBytes:(int)interval;
@end
#import "RKNetMonitor.h"
#include <ifaddrs.h>
#include <arpa/inet.h>
#include <net/if.h>
#import "AppDelegate.h"
@implementation RKNetConnect
static RKNetConnect *_connect = nil;
+(instancetype)shareInstance {
static dispatch_once_t onceToken;
dispatch_once(&onceToken, ^{
_connect = [[super allocWithZone:NULL]init];
});
return _connect;
}
+ (instancetype)allocWithZone:(struct _NSZone *)zone {
return [self shareInstance];;
}
@end
@interface RKNetMonitor()
@property (nonatomic, assign)long long int lastoBytes; //上一次上行
@property (nonatomic, assign)long long int lastiBytes; //上一次下行
@end
@implementation RKNetMonitor
static RKNetMonitor *_monitor = nil;
+(instancetype)shareInstance {
static dispatch_once_t onceToken;
dispatch_once(&onceToken, ^{
_monitor = [[super allocWithZone:NULL]init];
});
return _monitor;
}
+ (instancetype)allocWithZone:(struct _NSZone *)zone{
return [self shareInstance];;
}
- (RKNetConnect *)getInterfaceBytes:(int)interval {
if (!interval) {
interval = 1;
}
_connectObj = [RKNetConnect shareInstance];
struct ifaddrs *ifa_list = 0, *ifa;
if (getifaddrs(&ifa_list) == -1) {
_connect.oBytes = 0;
_connect.iBytes = 0;
return 0;
}
uint32_t iBytes = 0;//下行
uint32_t oBytes = 0;//上行
for (ifa = ifa_list; ifa; ifa = ifa->ifa_next){
if (AF_LINK != ifa->ifa_addr->sa_family)
continue;
if (!(ifa->ifa_flags & IFF_UP) && !(ifa->ifa_flags & IFF_RUNNING))
continue;
if (ifa->ifa_data == 0)
continue;
/* Not a loopback device. */
if (strncmp(ifa->ifa_name, "lo", 2)){
struct if_data *if_data = (struct if_data *)ifa->ifa_data;
iBytes += if_data->ifi_ibytes;
oBytes += if_data->ifi_obytes;
}
}
//计算
long long int rateOfoBytes = 0; //上行速率
long long int rateOfiBytes = 0; //下行速率
if (self.lastoBytes) {
//用当前的上行总流量 减去 上次的上行流量 达到上行速录
rateOfoBytes = oBytes - self.lastoBytes;
}
if(self.lastiBytes) {
rateOfiBytes = iBytes - self.lastiBytes;
}
//保存上一秒的
self.lastoBytes = oBytes;
self.lastiBytes = iBytes;
NSLog(@"\n[getInterfaceBytes-Total]%d,%d",iBytes,oBytes);
_connectObj.oBytes = [self formatNetWork:oBytes];
_connectObj.iBytes = [self formatNetWork:iBytes];
_connectObj.oBytesOfRate = [self formatNetWork:(rateOfoBytes/interval)];
_connectObj.iBytesOfRate = [self formatNetWork:(rateOfiBytes/interval)];
freeifaddrs(ifa_list);
return _connectObj;
}
- (NSString*)formatNetWork:(long long int)rate {
if(rate <1024) {
return[NSString stringWithFormat:@"%lldB", rate];
}else if(rate >=1024&& rate <1024*1024) {
return[NSString stringWithFormat:@"%.1fKB", (double)rate /1024];
}else if(rate >=1024*1024 && rate <1024*1024*1024){
return[NSString stringWithFormat:@"%.2fMB", (double)rate / (1024*1024)];
}else{
return@"10Kb";
};
}
@end
[[RKNetMonitor shareInstance] getInterfaceBytes:5];
NSString *rateShowStr = [NSString stringWithFormat:@"上:%@ R:%@/S\n下:%@ R:%@/S",[RKNetMonitor shareInstance].connectObj.oBytes,[RKNetMonitor shareInstance].connectObj.oBytesOfRate,[RKNetMonitor shareInstance].connectObj.iBytes,[RKNetMonitor shareInstance].connectObj.iBytesOfRate];
//_rateBtn显示网速的 按钮
[_rateBtn setTitle:rateShowStr forState:0];
+ (NSInteger)getDeviceType;{
struct utsname systemInfo;
uname(&systemInfo);
NSString *platform = [NSString stringWithCString:systemInfo.machine encoding:NSUTF8StringEncoding];
NSArray *symbols = [platform componentsSeparatedByString:@","];
NSInteger number = 0;
if (symbols.count > 0){
NSCharacterSet *characterSet = [[NSCharacterSet decimalDigitCharacterSet] invertedSet];
number = [[[symbols[0] componentsSeparatedByCharactersInSet:characterSet] componentsJoinedByString:@""] integerValue];
}
return number;
}
+ (NSString *)getNetworkType {
UIApplication *app = [UIApplication sharedApplication];
id statusBar = nil;
NSString *network = @"";
if (@available(iOS 13.0, *)) {
UIStatusBarManager *statusBarManager = [UIApplication sharedApplication].keyWindow.windowScene.statusBarManager;
#pragma clang diagnostic push
#pragma clang diagnostic ignored "-Wundeclared-selector"
if ([statusBarManager respondsToSelector:@selector(createLocalStatusBar)]) {
UIView *localStatusBar = [statusBarManager performSelector:@selector(createLocalStatusBar)];
if ([localStatusBar respondsToSelector:@selector(statusBar)]) {
statusBar = [localStatusBar performSelector:@selector(statusBar)];
}
}
#pragma clang diagnostic pop
if (statusBar) {
//UIStatusBarDataCellularEntry
id currentData = [[statusBar valueForKeyPath:@"_statusBar"] valueForKeyPath:@"currentData"];
id _wifiEntry = [currentData valueForKeyPath:@"wifiEntry"];
id _cellularEntry = [currentData valueForKeyPath:@"cellularEntry"];
if (_wifiEntry && [[_wifiEntry valueForKeyPath:@"isEnabled"] boolValue]) {
//If wifiEntry is enabled, is WiFi.
network = @"WIFI";
} else if (_cellularEntry && [[_cellularEntry valueForKeyPath:@"isEnabled"] boolValue]) {
NSNumber *type = [_cellularEntry valueForKeyPath:@"type"];
if (type) {
switch (type.integerValue) {
case 0:
//无sim卡
network = @"NONE";
break;
case 1:
network = @"1G";
break;
case 4:
network = @"3G";
break;
case 5:
network = @"4G";
break;
default:
//默认WWAN类型
network = @"WWAN";
break;
}
}
}
}
}else {
statusBar = [app valueForKeyPath:@"statusBar"];
if (IS_IPHONE_X== 1) {
//刘海屏
id statusBarView = [statusBar valueForKeyPath:@"statusBar"];
UIView *foregroundView = [statusBarView valueForKeyPath:@"foregroundView"];
NSArray *subviews = [[foregroundView subviews][2] subviews];
if (subviews.count == 0) {
//iOS 12
id currentData = [statusBarView valueForKeyPath:@"currentData"];
id wifiEntry = [currentData valueForKey:@"wifiEntry"];
if ([[wifiEntry valueForKey:@"_enabled"] boolValue]) {
network = @"WIFI";
}else {
//卡1:
id cellularEntry = [currentData valueForKey:@"cellularEntry"];
//卡2:
id secondaryCellularEntry = [currentData valueForKey:@"secondaryCellularEntry"];
if (([[cellularEntry valueForKey:@"_enabled"] boolValue]|[[secondaryCellularEntry valueForKey:@"_enabled"] boolValue]) == NO) {
//无卡情况
network = @"NONE";
}else {
//判断卡1还是卡2
BOOL isCardOne = [[cellularEntry valueForKey:@"_enabled"] boolValue];
int networkType = isCardOne ? [[cellularEntry valueForKey:@"type"] intValue] : [[secondaryCellularEntry valueForKey:@"type"] intValue];
switch (networkType) {
case 0://无服务
network = [NSString stringWithFormat:@"%@-%@", isCardOne ? @"Card 1" : @"Card 2", @"NONE"];
break;
case 3:
network = [NSString stringWithFormat:@"%@-%@", isCardOne ? @"Card 1" : @"Card 2", @"2G/E"];
break;
case 4:
network = [NSString stringWithFormat:@"%@-%@", isCardOne ? @"Card 1" : @"Card 2", @"3G"];
break;
case 5:
network = [NSString stringWithFormat:@"%@-%@", isCardOne ? @"Card 1" : @"Card 2", @"4G"];
break;
default:
break;
}
}
}
}else {
for (id subview in subviews) {
if ([subview isKindOfClass:NSClassFromString(@"_UIStatusBarWifiSignalView")]) {
network = @"WIFI";
}else if ([subview isKindOfClass:NSClassFromString(@"_UIStatusBarStringView")]) {
network = [subview valueForKeyPath:@"originalText"];
}
}
}
}else {
//非刘海屏
UIView *foregroundView = [statusBar valueForKeyPath:@"foregroundView"];
NSArray *subviews = [foregroundView subviews];
for (id subview in subviews) {
if ([subview isKindOfClass:NSClassFromString(@"UIStatusBarDataNetworkItemView")]) {
int networkType = [[subview valueForKeyPath:@"dataNetworkType"] intValue];
switch (networkType) {
case 0:
network = @"NONE";
break;
case 1:
network = @"2G";
break;
case 2:
network = @"3G";
break;
case 3:
network = @"4G";
break;
case 5:
network = @"WIFI";
break;
default:
break;
}
}
}
}
}
if ([network isEqualToString:@""]) {
network = @"NO DISPLAY";
}
return network;
}
+ (int)getSignalStrength {
int signalStrength = 0;
if (@available(iOS 13.0, *)) {
UIStatusBarManager *statusBarManager = [UIApplication sharedApplication].keyWindow.windowScene.statusBarManager;
id statusBar = nil;
#pragma clang diagnostic push
#pragma clang diagnostic ignored "-Wundeclared-selector"
if ([statusBarManager respondsToSelector:@selector(createLocalStatusBar)]) {
UIView *localStatusBar = [statusBarManager performSelector:@selector(createLocalStatusBar)];
if ([localStatusBar respondsToSelector:@selector(statusBar)]) {
statusBar = [localStatusBar performSelector:@selector(statusBar)];
}
}
#pragma clang diagnostic pop
if (statusBar) {
id currentData = [[statusBar valueForKeyPath:@"_statusBar"] valueForKeyPath:@"currentData"];
id _wifiEntry = [currentData valueForKeyPath:@"wifiEntry"];
id _cellularEntry = [currentData valueForKeyPath:@"cellularEntry"];
if (_wifiEntry && [[_wifiEntry valueForKeyPath:@"isEnabled"] boolValue]) {
// If wifiEntry is enabled, is WiFi.
if ([_wifiEntry isKindOfClass:NSClassFromString(@"_UIStatusBarDataIntegerEntry")]) {
// 层级:_UIStatusBarDataNetworkEntry、_UIStatusBarDataIntegerEntry、_UIStatusBarDataEntry
signalStrength = [[_wifiEntry valueForKey:@"displayValue"] intValue];
}
} else if (_cellularEntry && [[_cellularEntry valueForKeyPath:@"isEnabled"] boolValue]) {
if ([_cellularEntry isKindOfClass:NSClassFromString(@"_UIStatusBarDataIntegerEntry")]) {
// 层级:_UIStatusBarDataNetworkEntry、_UIStatusBarDataIntegerEntry、_UIStatusBarDataEntry
signalStrength = [[_cellularEntry valueForKey:@"displayValue"] intValue];
}
}
}
}else {
if (IS_IPHONE_X == 1) {
id statusBar = [[UIApplication sharedApplication] valueForKeyPath:@"statusBar"];
id statusBarView = [statusBar valueForKeyPath:@"statusBar"];
UIView *foregroundView = [statusBarView valueForKeyPath:@"foregroundView"];
int signalStrength = 0;
NSArray *subviews = [[foregroundView subviews][2] subviews];
for (id subview in subviews) {
if ([subview isKindOfClass:NSClassFromString(@"_UIStatusBarWifiSignalView")]) {
signalStrength = [[subview valueForKey:@"numberOfActiveBars"] intValue];
break;
}else if ([subview isKindOfClass:NSClassFromString(@"_UIStatusBarPersistentAnimationView")]) {//_UIStatusBarStringView
signalStrength = [[subview valueForKey:@"numberOfActiveBars"] intValue];
break;
}
}
return signalStrength;
} else {
UIApplication *app = [UIApplication sharedApplication];
NSArray *subviews = [[[app valueForKey:@"statusBar"] valueForKey:@"foregroundView"] subviews];
NSString *dataNetworkItemView = nil;
int signalStrength = 0;
for (id subview in subviews) {
if([subview isKindOfClass:[NSClassFromString(@"UIStatusBarDataNetworkItemView") class]] && [[self getNetworkType] isEqualToString:@"WIFI"] && ![[self getNetworkType] isEqualToString:@"NONE"]) {
dataNetworkItemView = subview;
signalStrength = [[dataNetworkItemView valueForKey:@"_wifiStrengthBars"] intValue];
break;
}
if ([subview isKindOfClass:[NSClassFromString(@"UIStatusBarSignalStrengthItemView") class]] && ![[self getNetworkType] isEqualToString:@"WIFI"] && ![[self getNetworkType] isEqualToString:@"NONE"]) {
dataNetworkItemView = subview;
//signalStrength = [[dataNetworkItemView valueForKey:@"_signalStrengthRaw"] intValue];
signalStrength = [[dataNetworkItemView valueForKey:@"_signalStrengthBars"] intValue];
break;
}
}
return signalStrength;
}
}
return signalStrength;
}