iOS 获取设备唯一标示符的方法详解
在开发中会遇到应用需要记录设备标示,即使应用卸载后再安装也可重新识别的情况,在这写一种实现方式——读取设备的uuid(universally unique identifier)并通过keychain记录。
首先ios中获取设备唯一标示符的方法一直随版本的更新而变化。ios 2.0版本以后uidevice提供一个获取设备唯一标识符的方法uniqueidentifier,通过该方法我们可以获取设备的序列号,这个也是目前为止唯一可以确认唯一的标示符。好景不长,因为该唯一标识符与手机一一对应,苹果觉得可能会泄露用户隐私,所以在 ios 5.0之后该方法就被废弃掉了;ios 6.0系统新增了两个用于替换uniqueidentifier的接口,分别是:identifierforvendor,advertisingidentifier,但这两个接口会在应用重新安装时改变数值,并不是唯一的标示符,所以开发者改为使用wifi的mac地址来取代;ios 7中苹果又封杀mac地址,所以开发者再次改变思路使用keychain来保存获取到的udid,这样以后即使app删了再装回来,也可以从keychain中读取回来。
首先保存设备的uuid,可以使用类方法+ (id)uuid 是一个类方法,调用该方法可以获得一个uuid。通过下面的代码可以获得一个uuid字符串:
nsstring *uuid = [[nsuuid uuid] uuidstring];
也可以保存在ios 6中新增的vindor标示符 (idfv-identifierforvendor),获取这个idfv的新方法被添加在已有的uidevice类中。跟advertisingidentifier一样,该方法返回的是一个nsuuid对象。
nsstring *idfv = [[[uidevice currentdevice] identifierforvendor] uuidstring];
如果用户卸载了同一个vendor对应的所有程序,然后在重新安装同一个vendor提供的程序,此时identifierforvendor会被重置,所以这里要用到keychain来保存。
keychain(钥匙串)是使用苹果设备经常使用的,通常要调试的话,都得安装证书之类的,这些证书就是保存在keychain中,还有我们平时浏览网页记录的账号密码也都是记录在keychain中。ios中的keychain相比os x比较简单,整个系统只有一个keychain,每个程序都可以往keychain中记录数据,而且只能读取到自己程序记录在keychain中的数据。ios中security.framework框架提供了四个主要的方法来操作keychain:
- secitemcopymatching(cfdictionaryref query, cftyperef *result);//查询osstatus
- secitemadd(cfdictionaryref attributes, cftyperef *result); //添加osstatus
- secitemupdate(cfdictionaryref query, cfdictionaryref attributestoupdate);//更新keychain中的itemosstatus
- secitemdelete(cfdictionaryref query)//删除keychain中的itemosstatus
这四个方法参数比较复杂,一旦传错就会导致操作keychain失败,文档中介绍的比较详细,大家可以查查官方文档。而苹果提供的keychain使用起来略麻烦,所以这里推荐一个第三方库samkeychains.samkeychains对苹果安全框架api进行了简单封装,支持对存储在钥匙串中密码、账户进行访问,包括读取、删除和设置。samkeychains使用简单,通过实例代码便可掌握。
//保存一个uuid字符串到钥匙串: cfuuidref uuid = cfuuidcreate(null); assert(uuid != null); cfstringref uuidstr = cfuuidcreatestring(null, uuid); [samkeychain setpassword: [nsstring stringwithformat:@"%@", uuidstr] forservice:@"com.yourapp.yourcompany"account:@"user"]; //从钥匙串读取uuid: nsstring *retrieveuuid = [samkeychain passwordforservice:@"com.yourapp.yourcompany"account:@"user"];
**注意: setpassword和passwordforsevice方法中的**services 和 accounts 参数应该是一致的。
更多详细用法说明可以看samkeychains documentation
基本的实现思路便是这样,下面是具体的一种具体实现代码,仅供参考。
+ (nsstring *)getdeviceid { nsstring * currentdeviceuuidstr = [samkeychain passwordforservice:@" "account:@"uuid"]; if (currentdeviceuuidstr == nil || [currentdeviceuuidstr isequaltostring:@""]) { nsuuid * currentdeviceuuid = [uidevice currentdevice].identifierforvendor; currentdeviceuuidstr = currentdeviceuuid.uuidstring; currentdeviceuuidstr = [currentdeviceuuidstr stringbyreplacingoccurrencesofstring:@"-" withstring:@""]; currentdeviceuuidstr = [currentdeviceuuidstr lowercasestring]; [samkeychain setpassword: currentdeviceuuidstr forservice:@" "account:@"uuid"]; } return currentdeviceuuidstr; }
以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持。、