iOS应用开发中的设备标识

对于iOS应用开发者来说,苹果所提供的官方后台系统实际上就是iTunes Connect了。通过iTunes Connect我们创建应用记录,提交应用给苹果审核,发布应用,通过iTunes Connect我们可以配置银行卡收钱( 这个很重要:) ),我们可以看到应用的下载量和收据数据报表。

但总体来说iTunes Connect提供的功能还比较有限,而且基本不能定制(除非你能说服苹果)。

对于应用发布后的跟踪和数据收集,很多时候是iTunes Connect之外的事情,甚至有些开发者对于闪退日志收集等也抛弃了iTunes Connect的crash report。那么一个识别具体设备的标志,或者说能够区分不同设备的方法就显得很重要。这篇文章我简要整理一下。

大家可以明确一点,为了保护用户隐私,苹果并没开放太多API给开发者,使得设备的数据追踪变得越来越难。

IMEI、IMSI、ICCID这类在iTunes Mac客户端可以直接看到的东西,现在都不要想着能通过API在程序中获取到。

0. UDID

在iOS6.1及之前,我们可以再UIKit.framework的UIDevice类中看到一个属性,那就是uniqueIdentifier,也就是我们通常所提到的UDID。

但这个属性的声明后面,有NS_DEPRECATED_IOS(2_0, 5_0),意思就是5.0开始就是deprecated的了,是过时的,不建议再继续使用。

到了iOS SDK的7.0版本,在UIDevice类中,就再也找不到这个uniqueIdentifier属性了。而且苹果方面明确表示在2013年5月份之后不再对此支持。即使使用老版本的SDK,也不一定能通过苹果审核,听说有人还尝到过Rejected的苦头。

1. identifierForVendor (IDFV)

貌似也有人简略为IDFV,这是苹果安抚大家的一个UDID的替代品,也是UIDevice类的属性。

按照苹果的文档说明,这个IDFV在同一设备上的所有同Vendor应用得到的ID是相同的,而不同的设备就有不同的IDFV。当这个设备上,同Vendor的所有应用都被卸载掉之后,不能保证同一设备再次安装这个Vendor的应用时,得到同样的ID。

简单来说,如果一个设备上只装了你一个应用,卸载掉再装ID也许就不同了。这样,对于唯一设备的定义就和原来UDID的很不同。这点并不令广大开发者感到满意。

2. MAC地址

如上所述,identifierForVendor不是很令大家满意,于是各种民间方法就出现了。一个方案就是用MAC地址。

学过计算机网络课程的同学们应该了解,要先完成底层网络通信实现MAC地址是必须有的,而这个在网卡制造时要保证全球唯一的,一个设备通常一个网卡就够用了,所以这个在一定程度上可以作为设备标识。

于是乎,拿出了各种底层库,做各种计算,拿到一个MAC地址字符串。

下面这段是网络上比较流行的:


1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

22

23

24

25

26

27

28

29

30

31

32

33

34

35

36

37

38

39

40

41

42

43

44

45

46

-
(
NSString

*) macAddress

{

    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

*outstring = [
NSString

stringWithFormat:
@"%02X:%02X:%02X:%02X:%02X:%02X",

                           *ptr,
*(ptr+1), *(ptr+2), *(ptr+3), *(ptr+4), *(ptr+5)];

    free(buf);

    return

outstring;

}

而这段需要引入几个系统库:


1

2

3

4

#include
<sys/socket.h>

#include
<sys/sysctl.h>

#include
<net/if.h>

#include
<net/if_dl.h>

嗯,不错,这样貌似就可以获取比较有意义的设备标识了。如果这个时候,你沾沾自喜了,那你还是不了解苹果为了保护用户隐私,下了多大力气。

很遗憾第告诉大家,在装有iOS7的设备上,这段代码计算出的值,永远是一个恒定的:

02:00:00:00:00:00

所以,梦又碎了。。

3. advertisingIdentifier (IDFA)

苹果为了完善自己的生态圈,在2010年前后推出了iAd广告网络。那么这个advertisingIdentifier和这个iAd的关系就不言自喻了。如果不了解广告也没关系,简单来讲,现在的互联网广告精准投放需要了解用户数据,基于这些信息是的广告更有效率,唯一标识就很重要,就用到了IDFA。

advertisingIdentifier在AdSupport.framework的ASIdentifierManager类中,是其中两个属性中的一个。

可以说,用这个IDFA标识设备应该还是很精准的(不然iAd就彻底不用玩了),很多开发者还在使用。

但再次,非常遗憾地说,貌似最近苹果对这个的要求也越来越严格了。

我这里收到过的一次拒审原因是:

PLA 3.3.12

In addition, we found your app uses the iOS Advertising Identifier for purposes other than to serve ads. This does not comply with the terms of the iOS Developer Program License Agreement, as required by the App Store Review Guidelines.

Specifically, section 3.3.12 of the iOS Developer Program License Agreement states:

"You and Your Applications (and any third party with whom you have contracted to serve advertising) may use the Advertising Identifier, and any information obtained through the use of the Advertising Identifier, only for the purpose of serving advertising. If a user resets the Advertising Identifier, then You agree not to combine, correlate, link or otherwise associate, either directly or indirectly, the prior Advertising Identifier and any derived information with the reset Advertising Identifier."

Please check your code - including any third-party libraries - to remove inappropriate uses of:

class: ASIdentifierManager
selector: advertisingIdentifier
framework: AdSupport.framework

所以,还在“滥用”IDFA标识设备的朋友们要小心了。

4. 接下来怎么办?

“这是个很好的问题”一般演讲者觉得提问者的问题很难回答的时候会这么说,然后接下来绕弯子兜圈子。。。当然这里我不会。

原则上来说,iOS的开发者是生长在苹果的生态圈,需要与苹果合作,尊重其理念。所以这里的结论是,最好的办法,就是不去标识设备ID。

但人是活的,所以这里有一个比较俗套的办法:

前面讲到IDFV不能令人满意,很大程度上是因为卸载之后重装ID就变了。我们在卸载一个应用的时候,其沙箱内的数据应该会一起不见,那有没有沙箱之外的地方呢?答案自然是肯定的,不过按照苹果的说法,沙箱之外需要系统的API协助。一个比较直观的选择就是Key Chain。所以通俗的方案就是自己生成可见范围内的唯一ID,存入Key Chain,下次再来重装依然可以读到。

在苹果对各种ID封杀后,很多民间的做法就是这种思路。这个做法对于一般条件下的数据收集应该足够了,但如果考虑到设备黑名单等安全识别,还差得远。

后面有机会我们再来讨论这个问题,设备标识的事儿就整理到这里。欢迎大家给出更好的方案来唯一标识设备,欢迎跟帖。

附一张转自Cocoachina的图片,不考虑现今实际的可用情况,对比一下这些ID们的差异:

各类Device ID相关标识的比较

时间: 2024-07-30 14:37:10

iOS应用开发中的设备标识的相关文章

有关 iOS 的开发证书、应用标识、设备标识、配置文件以及密钥 #DF

iOS开发过程中如果需要进行真机调试.发布需要注册申请很多证书, 以下是对iOS开发的常用证书和密钥等的逐一简单说明: 证书 iOS常用的证书包括开发证书和发布证书,无论是真机调试还是最终发布应用到App Store这两个证书都是必须的,它是iOS开发的基本证书. 1. 开发证书:开发证书又分为普通开发证书和推送证书,如果仅仅是一般的应用则前者即可满足,但是如果开发推送应用则必须使用推送证书. 2. 发布证书:发布证书又可以分为普通发布证书.推送证书.Pass Type ID证书.站点发布证书.

iOS项目开发中的知识点与问题收集整理(Part 一)

前言部分 注:本文并非绝对原创 大部分内容摘自 http://blog.csdn.net/hengshujiyi/article/details/20943045 文中有些方法可能已过时并不适用于现在的开发环境. 1.Search Bar 怎样去掉背景的颜色(storyboard里只能设置background颜色,可是发现clear Color无法使用). 其实在代码里还是可以设置的,那就是删除背景view  [[self.searchBar.subviews objectAtIndex:0]

iOS项目开发中的知识点与问题收集整理

注:本文并非绝对原创 大部分内容摘自 http://blog.csdn.net/hengshujiyi/article/details/20943045 文中有些方法可能已过时并不适用于现在的开发环境. 1,Search Bar 怎样去掉背景的颜色(storyboard里只能设置background颜色,可是发现clear Color无法使用). 其实在代码里还是可以设置的,那就是删除背景view  [[self.searchBar.subviews objectAtIndex:0] remov

ios 界面开发中的常见元素

界面开发中的 CGPoint.CGSize.CGRect.CGRectMake.window(窗口).视图(view)简单记录 定义 /* Points. */ struct CGPoint { CGFloat x; CGFloat y; }; typedef struct CGPoint CGPoint; /* Sizes. */ struct CGSize { CGFloat width; CGFloat height; }; typedef struct CGSize CGSize; /*

Hybrid App Development: 二、关于造轮子以及在Xcode iOS应用开发中加入Cordova

转载请注明出处:http://www.cnblogs.com/xdxer/p/4111552.html [ctrl+左键点击图片可以查看原图] 在上一篇关于Hybrid App Development的文章中,我讨论了一下在iOS下UIWebView的使用方法.但是光使用一个UIWebView所提供的功能还是完全不能满足我们的需求.   关于造轮子的思考: 在UIKit中的UIWebView虽然已经提供了很多功能了,比如JavaScript和Objc之间的通信.但是考虑到一个问题,如果在Hybr

iOS 应用开发中的断点续传实践总结

断点续传概述 断点续传就是从文件上次中断的地方开始重新下载或上传数据,而不是从文件开头.(本文的断点续传仅涉及下载,上传不在讨论之内)当下载大文件的时候,如果没有实现断点续传功能,那么每次出现异常或者用户主动的暂停,都会去重头下载,这样很浪费时间.所以项目中要实现大文件下载,断点续传功能就必不可少了.当然,断点续传有一种特殊的情况,就是 iOS 应用被用户 kill 掉或者应用 crash,要实现应用重启之后的断点续传.这种特殊情况是本文要解决的问题. 断点续传原理 要实现断点续传 , 服务器必

ios app 开发中ipa重新签名步骤介绍

作为一个app应用程序开发者,在app应用程序在苹果商店上架前总需要将安装包安装到ios机器上进行测试,这个时候我们就需要打包in house版本的ipa了,打包in house实际上是一个将ipa应用程序重新签名的一个过程.一般来说打包in house需要以下东西:MAC机器,一般打包ipa都是在MAC机上打包的,一个后缀名为.mobileprovision概要配置文件,一个后缀名为P12的证书,还有一个后缀名为.cer的证书,还有就是你想重新签名的ipa. 如何给ipa重新签名 步骤1 : 

iOS——Swift开发中的单例设计模式(摘译,非原创)

最近在开发一个小的应用,遇到了一些Objective-c上面常用的单例模式,但是swift上面还是有一定区别的,反复倒来倒去发现不能按常理(正常的oc to swift的方式)出牌,因此搜索了一些帖子.可能是xcode或者sdk的问题吧(我相信他们不会把未经测试的代码展示,吧?...),一些帖子中的代码犯了明显的错误,编译失败.于是有了这篇文章,分享给大家. 原作者实现了一种单例,但是红色代码导致非线程安全: 1 class var sharedInstance:TPScopeManager {

持续更新中 --- IOS移动开发中的优质资源

在我们做IOS APP的开发过程中, 需要很多设计, 产品, 技术, 运营等方面的技巧和资源. 现将其整理汇总, 本文会一直持续更新. 敬请关注. 设计 Dribbble Dribbble是一个面向创作家.艺术工作者.设计师等创意类作品的人群,提供作品在线服务,供网友在线查看已经完成的作品或者正在创作的作品的交流网站. 其作品整体质量非常高,许多摄影师.设计师和其他创意产业人士都喜欢在这里展示其未完成的设计,通过与其他设计师的共同探讨来激发自己的灵感. Dribbble还针对手机推出了相应的软件