iOS - 获取设备标识符UUID/UDID/IMEI等

本文详细介绍了iOS设备的各种标识符,包括IDFA、IDFV、IMEI等,并提供了获取这些标识符的具体方法。文中还探讨了不同标识符的特点及其适用场景。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

关于获取设备各种标识符,最近整理了一下。基本上有IDFA、IDFV、IMEI、IMSI、UUID、UDID、MAC地址; 想要获取系统唯一标识符的话,比如说不管用户卸载还是重新安装都可以唯一标识的可以直接滑动到底部查看

先将各种实现的方法列出来,可能你需要的只是获取的方式:
Git 标识符工具类Demo链接 —》 DYDeviceInfo 传送门
如果有帮到你的话,点个Star就是最好的肯定!

  • IDFA:
    广告标示符,它是由系统存储着的,iOS6及以后使用。但是如果用户还原位置与隐私的话这个广告标识符就会重新生成(设置程序 -》 通用 -》 还原 -》还原位置与隐私) 。或者用户更明确的将设置中的广告还原掉(设置程序 -》 通用-》 关于本机 -》广告 -》 还原广告标示符) ,IDFA也会重新生成。而且用户可以在设置-》隐私 -》广告里面限制IDFA获取,一般用户都不知道有这个,哈哈,不过还是不能用来做唯一标识的id呦。
#import <AdSupport/ASIdentifierManager.h>
ASIdentifierManager *asIM = [[ASIdentifierManager alloc] init];
NSString *idfa = [asIM.advertisingIdentifier UUIDString];
  • IDFV:
    iOS6.0及以后使用,是给Vendor标识用户用的,vendor:卖主,小贩。经过测试发现com.test.app1和com.test.app2具有相同的idfv,而如果是com.app1和com.app2则是两个不同的idfv。准确点说,就是通过BundleID的反转的前两部分进行匹配,如果相同就是同一个Vender,共享同一个idfv的值。
NSString *idfv = [[UIDevice currentDevice].identifierForVendor UUIDString];
  • IMEI,IMSI:
    IMEI(International Mobile Equipment Identity)是国际移动设备身份码的缩写,国际移动装备辨识码,是由15位数字组成的”电子串号”,它与每台手机一一对应,而且该码是全世界唯一的。每一部手机在组装完成后都将被赋予一个全球唯一的一组号码,这个号码从生产到交付使用都将被制造生产的厂商所记录。手机用户可以在手机中查到自己手机的IMEI码。
    重点来了 !iOS5以后不能再获取了,但通过私有Api能获取,这是在网上能查到的。Git上的erica的UIDevice扩展文件,以前可用但由于IOKit framework没有公开,所以也无法使用。就算手动导入,依旧无法使用,看来获取IMEI要失败了,同时失败的还有IMSI。不过还存在另外一种可能,Stack Overflow上有人提供采用com.apple.coretelephony.Identity.get entitlement方法,but device must be jailbroken;在此附上链接,供大家参考:http://stackoverflow.com/questions/16667988/how-to-get-imei-on-iphone-5/16677043#16677043
    如果实现了,自己拿来玩就行,别上架,这是会被拒掉的。

  • Mac地址,这个是做IDFA的时候,从友盟收集到的方法:
    要导入一堆头文件:

#include <sys/sysctl.h>
#include <sys/socket.h>
#include <net/if.h>
#include <net/if_dl.h>
    int mib[6];
    size_t len;
    char *buf;
    unsigned char *ptr;
    struct if_msghdr *ifm;
    struct sockaddr_dl *sdl;

    mib[0] = CTL_NET;
    mib[1] = AF_ROUTE;
    mib[2] = 0;
    mib[3] = AF_LINK;
    mib[4] = NET_RT_IFLIST;

    if ((mib[5] = if_nametoindex("en0")) == 0) {
        printf("Error: if_nametoindex error\n");
        return NULL;
    }

    if (sysctl(mib, 6, NULL, &len, NULL, 0) < 0) {
        printf("Error: sysctl, take 1\n");
        return NULL;
    }

    if ((buf = malloc(len)) == NULL) {
        printf("Could not allocate memory. error!\n");
        return NULL;
    }

    if (sysctl(mib, 6, buf, &len, NULL, 0) < 0) {
        printf("Error: sysctl, take 2");
        free(buf);
        return NULL;
    }

    ifm = (struct if_msghdr *)buf;
    sdl = (struct sockaddr_dl *)(ifm + 1);
    ptr = (unsigned char *)LLADDR(sdl);
    NSString *macStr = [NSString stringWithFormat:@"%02X:%02X:%02X:%02X:%02X:%02X",*ptr, *(ptr+1), *(ptr+2), *(ptr+3), *(ptr+4), *(ptr+5)];
    free(buf);

- UUID ,获取唯一标识符

每次运行都会发生变化,最理想的就是保存在keychain里面,以此作为标识用户设备的唯一标识符

    CFUUIDRef uuid = CFUUIDCreate(NULL);
    assert(uuid != NULL);
    CFStringRef uuidStr = CFUUIDCreateString(NULL, uuid);

    DYLog(@"uuidStr------》%@",uuidStr);

之前使用了Git上的一个第三方库,SSKeychain,将UUID保存在keychain里面,每次调用先检查钥匙串里面有没有,有则使用,没有则写进去,保证其唯一性,具体使用如下:

CFUUIDRef uuid = CFUUIDCreate(NULL);
assert(uuid != NULL);
CFStringRef uuidStr = CFUUIDCreateString(NULL, uuid);
NSString *identifierNumber = [SSKeychain passwordForService:@"com.test.app1"account:@"user"];

if (!identifierNumber){
   [SSKeychain setPassword: [NSString stringWithFormat:@"%@", uuidStr] forService:@"com.test.app1"account:@"user"];
   identifierNumber = [SSKeychain passwordForService:@"com.test.app1"account:@"user"];
}

Git 标识符工具类Demo链接 —》 DYDeviceInfo 传送门

### 获取唯一设备ID的挑战 在开发过程中,获取一个能够唯一标识设备的ID是一个常见的需求。然而,在Android和iOS平台上,由于隐私政策和技术限制的影响,这一目标变得愈发困难。 #### Android 平台上的解决方案 在Android平台上,虽然存在多种可能用于识别设备的方式,但由于系统更新以及对用户隐私保护的要求日益严格,许多传统方法已经不再适用[^1]。例如,IMEIMAC地址和Android ID曾被广泛使用,但这些方式要么受到权限限制,要么无法满足跨应用的一致性和稳定性要求[^2]。 一种推荐的做法是创建并存储自定义的应用级UUID作为设备标识符。这种方法可以确保即使操作系统版本发生变化或者硬件特性不可访问的情况下仍然有效: ```java public class DeviceIdManager { private static final String PREFS_FILE = "device_id.xml"; private static final String PREFS_DEVICE_ID = "device_id"; public static String getDeviceId(Context context) { SharedPreferences prefs = context.getSharedPreferences(PREFS_FILE, Context.MODE_PRIVATE); String deviceId = prefs.getString(PREFS_DEVICE_ID, null); if (deviceId == null) { deviceId = UUID.randomUUID().toString(); SharedPreferences.Editor editor = prefs.edit(); editor.putString(PREFS_DEVICE_ID, deviceId); editor.apply(); } return deviceId; } } ``` 此代码片段展示了如何利用SharedPreferences保存一个随机生成的UUID,并将其作为设备ID返回。 #### iOS 平台上的解决方案 对于iOS来说,苹果公司出于隐私考虑早已停止支持UDID等可以直接追踪用户的标识方案。目前官方建议使用的Identifier For Vendor(IDFV),它由App Store分配给同一供应商下的所有应用程序共享同一个值直到卸载最后一个关联程序为止;还有Advertising Identifier(IDFA),主要用于广告目的且允许用户重置或禁用其跟踪功能。 如果需要更持久可靠的解决办法,则可以通过Keychain服务来储存自行产生的GUID形式的数据串当作专属标志码: ```swift import UIKit import Security func save(key: String, data: Data) -> OSStatus { let query: [String : Any] = [ kSecClass as String : kSecClassGenericPassword, kSecAttrAccount as String : key, kSecValueData as String : data ] SecItemDelete(query as CFDictionary) return SecItemAdd(query as CFDictionary, nil) } func load(key: String) -> Data? { let query: [String : Any] = [ kSecClass as String : kSecClassGenericPassword, kSecAttrAccount as String : key, kSecReturnData as String : true, kSecMatchLimit as String : kSecMatchLimitOne ] var result: AnyObject? SecItemCopyMatching(query as CFDictionary, &result) return result as? Data } let deviceIDKey = "com.example.deviceid" if let storedData = load(key: deviceIDKey), let id = NSString(data:storedData, encoding:String.Encoding.utf8.rawValue){ print(id) } else{ let newID = NSUUID().uuidString.data(using:.utf8)! _ = save(key: deviceIDKey, data:newID) print(String(data:newID,encoding:.utf8)!) } ``` 上述Swift代码实现了基于Keychain的安全数据存取机制,从而达到长期保留特定字符串的目的。 ### 结论 综上所述,在当前环境下无论是Android还是iOS都无法简单直接地获得完全意义上的永久型物理装置编号。因此采用软件层面构建逻辑实体号成为主流趋势之一。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值