iOS 获取手机 唯一标识

本文介绍了一个iOS应用程序中实现用户行为统计的方法,包括如何利用Keychain进行安全的数据存储,采集用户设备信息,并通过API记录用户的登录信息。

存贮在keychainQuery 可以统计用户使用情况

-(void)gatherMessage{


    //采集用户设备信息


    NSUserDefaults *userDefaults=[NSUserDefaults standardUserDefaults];


    NSDate *loadDate=[NSDate date];


    NSDate *lastData=[userDefaults valueForKey:@"loadForDay"];


    NSDateFormatter *dateFormatter=[[NSDateFormatter alloc]init];


    [dateFormatter setDateFormat:@"YYYY/MM/dd"];


    NSString *lastd=[dateFormatter stringFromDate:lastData];


    NSString *nowd=[dateFormatter stringFromDate:loadDate];


    if (![lastd isEqualToString:nowd]) {


        [userDefaults setObject:loadDate forKey:@"loadForDay"];


        //获取设备型号


        NSString *deviceModel=[CommenData getCurrentDeviceModel];


    


        //identifierForVendor 作为唯一标识


        NSString *identifierStr = [[[UIDevice currentDevice] identifierForVendor] UUIDString];


        NSString * const KEY_USERNAME_PASSWORD = @"com.int-yt.kyks.usernamepassword";


        NSString * const KEY_PASSWORD = @"com.int-yt.kyks.password";


        NSMutableDictionary *usernamepasswordKVPairs = [NSMutableDictionary dictionary];


        [usernamepasswordKVPairs setObject:identifierStr forKey:KEY_PASSWORD];


    


        NSMutableDictionary *readUserPwd = (NSMutableDictionary *)[CommenData load:KEY_USERNAME_PASSWORD];


        if(readUserPwd==nil){


            //


            [CommenData save:KEY_USERNAME_PASSWORD data:usernamepasswordKVPairs];


            readUserPwd = (NSMutableDictionary *)[CommenData load:KEY_USERNAME_PASSWORD];


          


        }


        //调用接口纪录登陆信息


        


        NSString *string= [NSString stringWithFormat:@"%@cdpt/api/uselog?access_token=123&imeiid=%@&mtype=%@&device_platform=2",BaseURLString, [readUserPwd objectForKey:KEY_PASSWORD],deviceModel];


        


        NSURL *url = [NSURL URLWithString:string];


        NSURLRequest *request = [NSURLRequest requestWithURL:url];


        NSLog(@"%@",string);


        AFHTTPRequestOperation *operation = [[AFHTTPRequestOperation alloc] initWithRequest:request];


        operation.responseSerializer = [AFJSONResponseSerializer serializer];


        [operation setCompletionBlockWithSuccess:^(AFHTTPRequestOperation *operation, id responseObject) {




        } failure:^(AFHTTPRequestOperation *operation, NSError *error) {




        }];


        [operation start];


    }


}


//


+ (void)save:(NSString *)service data:(id)data {


    //Get search dictionary


    NSMutableDictionary *keychainQuery = [self getKeychainQuery:service];


    //Delete old item before add new item


    SecItemDelete((__bridge CFDictionaryRef)keychainQuery);


    //Add new object to search dictionary(Attention:the data format)


    [keychainQuery setObject:[NSKeyedArchiver archivedDataWithRootObject:data] forKey:(__bridge id)kSecValueData];


    //Add item to keychain with the search dictionary


    SecItemAdd((__bridge CFDictionaryRef)keychainQuery, NULL);


}




+ (NSMutableDictionary *)getKeychainQuery:(NSString *)service {


    return [NSMutableDictionary dictionaryWithObjectsAndKeys:


            (__bridge id)kSecClassGenericPassword,(__bridge id)kSecClass,


            service, (__bridge id)kSecAttrService,


            service, (__bridge id)kSecAttrAccount,


            (__bridge id)kSecAttrAccessibleAfterFirstUnlock,(__bridge id)kSecAttrAccessible,


            nil];


}




//


+ (id)load:(NSString *)service {


    id ret = nil;


    NSMutableDictionary *keychainQuery = [self getKeychainQuery:service];


    //Configure the search setting


    //Since in our simple case we are expecting only a single attribute to be returned (the password) we can set the attribute kSecReturnData to kCFBooleanTrue


    [keychainQuery setObject:(__bridge id)kCFBooleanTrue forKey:(__bridge id)kSecReturnData];


    [keychainQuery setObject:(__bridge id)kSecMatchLimitOne forKey:(__bridge id)kSecMatchLimit];


    CFDataRef keyData = NULL;


    if (SecItemCopyMatching((__bridge CFDictionaryRef)keychainQuery, (CFTypeRef *)&keyData) == noErr) {


        @try {


            ret = [NSKeyedUnarchiver unarchiveObjectWithData:(__bridge NSData *)keyData];


        } @catch (NSException *e) {


            NSLog(@"Unarchive of %@ failed: %@", service, e);


        } @finally {


        }


    }


    if (keyData)


        CFRelease(keyData);


    return ret;


}






+ (void)delete:(NSString *)service {


    NSMutableDictionary *keychainQuery = [self getKeychainQuery:service];


    SecItemDelete((__bridge CFDictionaryRef)keychainQuery);


}




//获得设备型号


+ (NSString *)getCurrentDeviceModel


{


    int mib[2];


    size_t len;


    char *machine;


    mib[0] = CTL_HW;


    mib[1] = HW_MACHINE;


    sysctl(mib, 2, NULL, &len, NULL, 0);


    machine = malloc(len);


    sysctl(mib, 2, machine, &len, NULL, 0);


    NSString *platform = [NSString stringWithCString:machine encoding:NSUTF8StringEncoding];


    free(machine);


    return platform;


}



### 获取设备唯一标识的方法与代码示例 在UniApp中,获取安卓和iOS设备的唯一标识可以通过多种方式实现。以下是详细的方法和代码示例。 #### 1. 使用 `Ba-IdCode` 插件 `Ba-IdCode` 是一款插件,支持获取国内各大手机厂商的 OAID(开放匿名设备标识)及海外手机平台的 AAID(安卓广告标识)。此外,它还支持 IMEI/MEID、AndroidID、WidevineID、PseudoID、GUID 等常见的设备标识[^1]。 以下是一个使用 `Ba-IdCode` 插件的代码示例: ```javascript const baIdCode = uni.requireNativePlugin('Ba-IdCode'); baIdCode.getOAID({}, (res) => { console.log("OAID:", res); }); baIdCode.getAAID({}, (res) => { console.log("AAID:", res); }); baIdCode.getIMEI({}, (res) => { console.log("IMEI:", res); }); ``` #### 2. 使用 `uni-device-id` 插件 `uni-device-id` 插件可以用于获取设备唯一ID,支持安卓、iOS 和鸿蒙系统。对于安卓设备,它可以获取 AndroidId、OAID、IMEI、MEID 等;对于 iOS 设备,它可以获取 Identifier 和 UUID;对于鸿蒙设备,它可以获取 AAID 和 ODID[^2]。 以下是一个使用 `uni-device-id` 插件的代码示例: ```javascript import device from 'uni-device-id'; device.getUniqueId().then(res => { console.log("设备唯一ID:", res); }).catch(err => { console.error("获取设备唯一ID失败:", err); }); device.getAndroidId().then(res => { console.log("Android ID:", res); }).catch(err => { console.error("获取Android ID失败:", err); }); device.getOAID().then(res => { console.log("OAID:", res); }).catch(err => { console.error("获取OAID失败:", err); }); ``` #### 3. 注意事项 从 Android 10(API级别29)开始,Google 加强了对设备标识符的管理,许多传统的设备唯一标识(例如 IMEI、MAC 地址等)无法直接通过应用程序访问,除非用户明确授予相关权限[^3]。因此,在开发过程中需要特别注意权限管理。 #### 4. 蓝牙设备标识问题 在蓝牙通信中,安卓和 iOS 平台对设备标识的处理方式不同。安卓通常使用 `deviceId`,而 iOS 使用 `uuid` 字符串来标识设备。这是因为苹果官方认为透露 `deviceId`(MAC 地址)会有安全问题,因此进行了屏蔽[^4]。 以下是一个解决蓝牙设备标识差异的代码示例: ```javascript uni.onBluetoothDeviceFound((devices) => { devices.devices.forEach(device => { if (uni.getSystemInfoSync().platform === 'ios') { console.log("iOS设备UUID:", device.uuids); } else { console.log("安卓设备ID:", device.deviceId); } }); }); ``` ###
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值