UDID
之前在iOS
开发中广泛使用的一串字符串,用来标示唯一的设备,它本身并不包含用户信息,但是广告商却可以利用他获取到个人信息,从而发送广告,因为他涉及到隐私问题,所以苹果早在2011年就提出了将不再使用它。然而就在前天,苹果的开发者网站,发出新闻:
Starting May 1, the App Store will no longer accept new apps or app updates that access UDIDs. Please update your apps and servers to associate users with the Vendor or Advertising identifiers introduced in iOS 6. You can find more details in the UIDevice Class Reference .
“自5月1日起,App Store将不再接受任何使用UDID的app,苹果建议开发者转用iOS 6 引进的Vendor 或者 Adverstising Identifier(‘广告标识符’)”
这次苹果打出了强制通知,再使用UDID
的话,那么应用将不会审核通过,也就无法发布。
不过俗话说的好“上有政策,下有对策”。虽然苹果自己也给出了替代的方法,但他们都不是最好的,UUID
每次获取都不同,所以使用时必须要把他们存文件,存数据库或者存UserDefault
。当应用被删除重装,那么这个UUID
也就不同了。Vendor
更是同一个设备上的同一个开发商的应用的id
都是相同的,也没有办法使用。Advertising identifier
也并不是固定的。那要如何才能达到我们的需求呢,既能方便获取又能保证唯一呢?
答案就是MAC
地址,MAC
地址在网络上用来区分设备的唯一性,接入网络的设备都有一个MAC
地址,他们肯定都是不同的,是唯一的。一部iPhone
上可能有多个MAC
地址,包括WIFI
的、SIM
的等,但是iTouch
和iPad
上就有一个WIFI
的,因此只需获取WIFI
的MAC
地址就好了,也就是en0
的地址。直接把MAC
地址拿出来使用是不安全的,因此对他们做一次hash
计算,MD5
就是一种哈希算法,对得到的MAC
地址计算一下他的MD5
值就好了,那么这样拿到的就是这个设备唯一的ID
了。有时我们为了区分设备上的应用,也可以获取到应用的bundleID
,在和MAC
地址结合起来计算一下MD5
,那么该值就是可以区分设备上应用的ID了。
首先是MD5
,为NSString
添加MD5
方法:
NSString+MD5
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
//
// NSString+MD5.h
//
// Created by wtlucky on 12-12-2.
//
//
#import <Foundation/Foundation.h>
@interface NSString (MD5)
- ( NSString * ) MD5 ;
+ ( NSString * ) MD5ByAStr: ( NSString * ) aSourceStr ;
@end
#import <CommonCrypto/CommonDigest.h>
@implementation NSString (MD5)
- ( NSString * ) MD5
{
return [ NSString MD5ByAStr: self ];
}
+ ( NSString * ) MD5ByAStr: ( NSString * ) aSourceStr
{
const char * cStr = [ aSourceStr UTF8String ];
unsigned char result [ CC_MD5_DIGEST_LENGTH ];
CC_MD5 ( cStr , strlen ( cStr ), result );
NSMutableString * ret = [ NSMutableString stringWithCapacity: CC_MD5_DIGEST_LENGTH ];
for ( int i = 0 ; i < CC_MD5_DIGEST_LENGTH ; i ++ )
{
[ ret appendFormat: @"%02x" , result [ i ]];
}
return ret ;
}
@end
接下来是获得唯一ID,为UIDevice
添加方法:
UIDevice+UniqueIdentifier
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
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
//
// UIDevice+UniqueIdentifier.h
//
// Created by wtlucky on 13-3-22.
// Copyright (c) 2013年 AlphaStudio. All rights reserved.
//
#import <UIKit/UIKit.h>
@interface UIDevice (UniqueIdentifier)
/**
* 返回针对与一个应用的唯一ID
*
* @return 针对与一个应用的唯一ID
*/
- ( NSString * ) uniqueDeviceIdentifier ;
/**
* 返回设备的唯一ID
*
* @return 设备的唯一ID
*/
- ( NSString * ) uniqueGlobalDeviceIdentifier ;
@end
#import "NSString+MD5.h"
#include <sys/socket.h>
#include <sys/sysctl.h>
#include <net/if.h>
#include <net/if_dl.h>
@interface UIDevice (private)
- ( NSString * ) macAddress ;
@end
@implementation UIDevice (UniqueIdentifier)
- ( 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 ;
}
- ( NSString * ) uniqueDeviceIdentifier
{
NSString * macAddress = [[ UIDevice currentDevice ] macAddress ];
NSString * bundleIdentifier = [[ NSBundle mainBundle ] bundleIdentifier ];
NSString * stringToHash = [ NSString stringWithFormat: @"%@%@" , macAddress , bundleIdentifier ];
NSString * uniqueIdentifier = [ stringToHash MD5 ];
return uniqueIdentifier ;
}
- ( NSString * ) uniqueGlobalDeviceIdentifier
{
NSString * macAddress = [[ UIDevice currentDevice ] macAddress ];
NSString * uniqueGlobalIdentifier = [ macAddress MD5 ];
return uniqueGlobalIdentifier ;
}
@end
如此一来,在使用时就相当方便了。