经常有朋友来问这个问题。
每次都去解释这个问题也浪费不少时间,
所以还是开一篇文章,
把这个问题说清楚吧。
先纠正一个误区吧:
有同学可以通过ionic natvie的device插件获取。
我们在文档里可以找到有serial这个属性。
通过这个属性,我们的确获取到一串字符串。
但是我们也会发现,当我们卸载app之后,这串数值会变,所以这个不能作为我们的唯一设备id。
回归到ios。
我们列举一下可以想到的办法。
ios获取设备id的方法
UUID
设备的唯一标识符,然而在ios6以后就已经被废弃了,现在试图获取这一数值的app会被禁止上架。
MAC
设备的mac地址具备唯一性。然后ios7之后,所有获取的设备mac地址为:02:00:00:00:00:00。
IDFV
相同vendor下(即相同包前缀下)获取的值是一样的,卸载或重装app后,此值会变化。
IDFA
广告id,同一个设备下不同APP都相同且唯一。当然,如果用户在设备里手动重置或禁用广告追踪,这一数值可能会变化或者无法取到。
UUID
这个方法的思路是使用uuid生成一段随机数(重复概率极低),然后使用ios的keychain保存到钥匙链里,这样即使app重新安装和卸载后也不会改变,除非系统刷机和重装系统。
纵观上面所列的方法,我们发现只有最终只有后2种方法接近我们的答案,当然还有一些不完美,但是已经基本符合我们的需求了。
最终的方案:
如果你的工程可以支持adsupport
IDFA+KeyChain
如果你的工程不支持adsupport
UUID+KeyChain
如何实现?
IDFA+KeyChain
1、引入adsupport.fraemwrok
2、获取idfa
NSString *adId = [[[ASIdentifierManager sharedManager] advertisingIdentifier] UUIDString];
3、存储到keychian里。
+ (void)setValue:(NSString *)value forKey:(NSString *)key inService:(NSString *)service {
NSMutableDictionary *keychainItem = [[NSMutableDictionary alloc] init];
keychainItem[(__bridge id)kSecClass] = (__bridge id)kSecClassGenericPassword;
keychainItem[(__bridge id)kSecAttrAccessible] = (__bridge id)kSecAttrAccessibleAlways;
keychainItem[(__bridge id)kSecAttrAccount] = key;
keychainItem[(__bridge id)kSecAttrService] = service;
keychainItem[(__bridge id)kSecValueData] = [value dataUsingEncoding:NSUTF8StringEncoding];
SecItemAdd((__bridge CFDictionaryRef)keychainItem, NULL);
}
特别说明:
由于引入了Adsupport, 所以当你的应用提交到appstore的时候,如果没有接入广告的话,需要正确的选择广告接入选项,否则有被拒的风险。具体参考如下:
UUID+KeyChain
1、生成UUID
+ (NSString *)randomUUID {
if(NSClassFromString(@"NSUUID")) { // only available in iOS >= 6.0
return [[NSUUID UUID] UUIDString];
}
CFUUIDRef uuidRef = CFUUIDCreate(kCFAllocatorDefault);
CFStringRef cfuuid = CFUUIDCreateString(kCFAllocatorDefault, uuidRef);
CFRelease(uuidRef);
NSString *uuid = [((__bridge NSString *) cfuuid) copy];
CFRelease(cfuuid);
return uuid;
2、写入到keychain
代码同上。
特别说明:
由于Keychain默认是存放在当前app的私有域下的,所以如果想要在app之间共享uuid数据的话,需要开启keychain sharing
,具体操作方法:xcode--capabililties--keychain sharing,然后填写相同的group名字
讲了半天,大家可能会说,这些都是原生的方法,怎么在js里调用啊。
那么cordova其实就是干这个事情的。
为了方便大家使用,我封装成插件,直接安装即可调用。
IDFA+KEYCHAIN
https://github.com/jasonz1987/cordova-plugin-keychain-idfa
UUID+KEYCHAIN