YH_Device.m 6.21 KB
//
//  YH_Device.m
//  YHEventReport
//
//  Created by 孙凯 on 2017/9/21.
//  Copyright © 2017年 YOHO. All rights reserved.
//

#import "YH_Device.h"
#include <net/if.h>
#include <net/if_dl.h>
#include <sys/sysctl.h>
#include <sys/param.h>
#include <sys/file.h>
#include <sys/socket.h>
#import <UIKit/UIKit.h>
#import "OpenUDID.h"
#import "JTSHardwareInfo.h"
#import "YHEventReport.h"

static NSString *const kAppFingerPrint = @"com.yoho.appfingerprint";

@interface YH_Device ()

@property (copy, nonatomic) NSString *sv;   // 采集数据sdk的版本
@property (copy, nonatomic) NSString *os;   // 操作系统
@property (copy, nonatomic) NSString *osv;  // 操作系统版本
@property (copy, nonatomic) NSString *dm;   // 设备型号
@property (copy, nonatomic) NSString *udid; // 设备标识
@property (copy, nonatomic) NSString *ifa;  // idfa
@property (copy, nonatomic) NSString *ifv;  // ifv
@property (copy, nonatomic) NSString *res;  // 分辨率
@property (copy, nonatomic) NSString *mac;  // Mac地址
@property (copy, nonatomic) NSString *afp;  // app安装指纹(40位随机数)

@end

@implementation YH_Device

- (id)init
{
    self = [super init];
    if (self) {
        self.sv = YOHOAppReportKeykYHAnalyticsSDKVersion;
        self.ch = [[YHEventReport sharedInstance] channelId];
        self.ak = YOHOAppReportKeykYohobuyAppKey;
        
        NSString *os = [[UIDevice currentDevice] systemName];
        if (os) {
            self.os = os;
            self.osv = [[UIDevice currentDevice] systemVersion];
        } else {
            // 在模拟器上,有时会出现未知系统的情况
            self.os = @"Unknown";
            self.osv = @"Unknown";
        }
        
        self.dm = [JTSHardwareInfo hardwareIdentifier];
        
        CGRect rect = [[UIScreen mainScreen] bounds];
        CGFloat scale = [[UIScreen mainScreen] scale];
        NSString *screenResolution = [NSString stringWithFormat:@"%ldx%ld",(long)(rect.size.width * scale), (long)(rect.size.height * scale)];
        self.res = screenResolution;
        self.udid = [OpenUDID value];
        
        //Vendor标示符
        self.ifv = [[[UIDevice currentDevice] identifierForVendor] UUIDString];
        
        self.mac = [YH_Device getMacAddress];
        
        self.afp = [YH_Device getAppFingerPrint];
        
        self.ps = @"0";
    }
    
    return self;
}

- (NSDictionary *)jsonDictionary
{
    
    return @{
             YOHOAppReportKeyJsonKeyDeviceSV : self.sv ? self.sv : @"",
             YOHOAppReportKeyJsonKeyDeviceAK : self.ak ? self.ak : @"",
             YOHOAppReportKeyJsonKeyDeviceCH : self.ch ? self.ch : @"",
             YOHOAppReportKeyJsonKeyDeviceOS : self.os ? self.os : @"",
             YOHOAppReportKeyJsonKeyDeviceOSV : self.osv ? self.osv : @"",
             YOHOAppReportKeyJsonKeyDeviceDM : self.dm ? self.dm : @"",
             YOHOAppReportKeyJsonKeyDeviceUDID : self.udid ? self.udid : @"",
             YOHOAppReportKeyJsonKeyDeviceIFA : @"",
             YOHOAppReportKeyJsonKeyDeviceIFV : self.ifv ? self.ifv : @"",
             YOHOAppReportKeyJsonKeyDeviceRES : self.res ? self.res : @"",
             YOHOAppReportKeyJsonKeyDeviceMAC : self.mac ? self.mac : @"",
             YOHOAppReportKeyJsonKeyDeviceAFP : self.afp ? self.afp : @"",
             YOHOAppReportKeyJsonKeyDeviceTDID : self.tdid ? self.tdid : @"",
             YOHOAppReportKeyJsonKeyDevicePS : self.ps ?self.ps: @""
             };
}


#pragma mark - method
+ (NSString *)getMacAddress
{
    int                 mgmtInfoBase[6];
    char                *msgBuffer = NULL;
    size_t              length;
    unsigned char       macAddress[6];
    struct if_msghdr    *interfaceMsgStruct;
    struct sockaddr_dl  *socketStruct;
    NSString            *errorFlag = NULL;
    
    // Setup the management Information Base (mib)
    mgmtInfoBase[0] = CTL_NET;        // Request network subsystem
    mgmtInfoBase[1] = AF_ROUTE;       // Routing table info
    mgmtInfoBase[2] = 0;
    mgmtInfoBase[3] = AF_LINK;        // Request link layer information
    mgmtInfoBase[4] = NET_RT_IFLIST;  // Request all configured interfaces
    
    // With all configured interfaces requested, get handle index
    if ((mgmtInfoBase[5] = if_nametoindex("en0")) == 0) {
        errorFlag = @"if_nametoindex failure";
    } else if (sysctl(mgmtInfoBase, 6, NULL, &length, NULL, 0) < 0) {
        // Get the size of the data available (store in len)
        errorFlag = @"sysctl mgmtInfoBase failure";
    } else if ((msgBuffer = malloc(length)) == NULL) {
        // Alloc memory based on above call
        errorFlag = @"buffer allocation failure";
    } else if (sysctl(mgmtInfoBase, 6, msgBuffer, &length, NULL, 0) < 0) {
        // Get system information, store in buffer
        errorFlag = @"sysctl msgBuffer failure";
    }
    
    // Befor going any further...
    if (errorFlag != NULL) {
        if (msgBuffer) {
            free(msgBuffer);
            msgBuffer = NULL;
        }
        
        return errorFlag;
    }
    
    // Map msgbuffer to interface message structure
    interfaceMsgStruct = (struct if_msghdr *) msgBuffer;
    
    // Map to link-level socket structure
    socketStruct = (struct sockaddr_dl *) (interfaceMsgStruct + 1);
    
    // Copy link layer address data in socket structure to an array
    memcpy(&macAddress, socketStruct->sdl_data + socketStruct->sdl_nlen, 6);
    
    // Read from char array into a string object, into traditional Mac address format
    NSString *macAddressString = [NSString stringWithFormat:@"%02X:%02X:%02X:%02X:%02X:%02X",
                                  macAddress[0], macAddress[1], macAddress[2],
                                  macAddress[3], macAddress[4], macAddress[5]];
    
    // Release the buffer memory
    free(msgBuffer);
    msgBuffer = NULL;
    
    return macAddressString;
}

+ (NSString *)getAppFingerPrint
{
    NSUserDefaults *defaults = [NSUserDefaults standardUserDefaults];
    NSString *fpString = [defaults objectForKey:kAppFingerPrint];
    if (fpString == nil || ![fpString isKindOfClass:[NSString class]] || fpString.length != 40) {
        fpString = [OpenUDID _generateFreshOpenUDID];
        [defaults setObject:fpString forKey:kAppFingerPrint];
        [defaults synchronize];
    }
    return fpString;
}

@end