经常有朋友来问这个问题。

每次都去解释这个问题也浪费不少时间,

所以还是开一篇文章,

把这个问题说清楚吧。

 

先纠正一个误区吧:

有同学可以通过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

https://github.com/jasonz1987/cordova-plugin-keychain-uuid