如何以编程方式获取 iphone 的 MAC 地址

如何通过编程获得 iPhone 的 MAC 地址和 IP 地址?

141653 次浏览

在 iOS7中,你不能再检索设备的 MAC 地址。将返回一个固定值,而不是实际的 MAC


一些我前段时间偶然发现的东西。原来从 给你我修改了一点,清理的东西。

IP 地址 h
IPAddress. c

并利用它

InitAddresses();
GetIPAddresses();
GetHWAddresses();


int i;
NSString *deviceIP = nil;
for (i=0; i<MAXADDRS; ++i)
{
static unsigned long localHost = 0x7F000001;        // 127.0.0.1
unsigned long theAddr;


theAddr = ip_addrs[i];


if (theAddr == 0) break;
if (theAddr == localHost) continue;


NSLog(@"Name: %s MAC: %s IP: %s\n", if_names[i], hw_addrs[i], ip_names[i]);


//decided what adapter you want details for
if (strncmp(if_names[i], "en", 2) == 0)
{
NSLog(@"Adapter en has a IP of %s", ip_names[i]);
}
}

适配器名称因模拟器/设备以及设备上的 wifi 或单元而异。

无论是否启用 wifi,我都希望有东西返回地址,所以选择的解决方案对我来说不起作用。我使用了另一个电话,我发现在一些论坛后,一些调整。最后我得到了以下结论(原谅我生疏的 C) :

#include <sys/types.h>
#include <stdio.h>
#include <string.h>
#include <sys/socket.h>
#include <net/if_dl.h>
#include <ifaddrs.h>




char*  getMacAddress(char* macAddress, char* ifName) {


int  success;
struct ifaddrs * addrs;
struct ifaddrs * cursor;
const struct sockaddr_dl * dlAddr;
const unsigned char* base;
int i;


success = getifaddrs(&addrs) == 0;
if (success) {
cursor = addrs;
while (cursor != 0) {
if ( (cursor->ifa_addr->sa_family == AF_LINK)
&& (((const struct sockaddr_dl *) cursor->ifa_addr)->sdl_type == IFT_ETHER) && strcmp(ifName,  cursor->ifa_name)==0 ) {
dlAddr = (const struct sockaddr_dl *) cursor->ifa_addr;
base = (const unsigned char*) &dlAddr->sdl_data[dlAddr->sdl_nlen];
strcpy(macAddress, "");
for (i = 0; i < dlAddr->sdl_alen; i++) {
if (i != 0) {
strcat(macAddress, ":");
}
char partialAddr[3];
sprintf(partialAddr, "%02X", base[i]);
strcat(macAddress, partialAddr);


}
}
cursor = cursor->ifa_next;
}


freeifaddrs(addrs);
}
return macAddress;
}

然后我把它叫做求 10,如下所示:

char* macAddressString= (char*)malloc(18);
NSString* macAddress= [[NSString alloc] initWithCString:getMacAddress(macAddressString, "en0")
encoding:NSMacOSRomanStringEncoding];
free(macAddressString);

更新: 这在 iOS7上不起作用。你应该使用 ASIdentifierManager


更多清洁解决方案 在 MobileDeveloperTips 网站:

#include <sys/socket.h>
#include <sys/sysctl.h>
#include <net/if.h>
#include <net/if_dl.h>


...


- (NSString *)getMacAddress
{
int                 mgmtInfoBase[6];
char                *msgBuffer = NULL;
size_t              length;
unsigned char       macAddress[6];
struct if_msghdr    *interfaceMsgStruct;
struct sockaddr_dl  *socketStruct;
NSString            *errorFlag = NULL;


// Setup the management Information Base (mib)
mgmtInfoBase[0] = CTL_NET;        // Request network subsystem
mgmtInfoBase[1] = AF_ROUTE;       // Routing table info
mgmtInfoBase[2] = 0;
mgmtInfoBase[3] = AF_LINK;        // Request link layer information
mgmtInfoBase[4] = NET_RT_IFLIST;  // Request all configured interfaces


// With all configured interfaces requested, get handle index
if ((mgmtInfoBase[5] = if_nametoindex("en0")) == 0)
errorFlag = @"if_nametoindex failure";
else
{
// Get the size of the data available (store in len)
if (sysctl(mgmtInfoBase, 6, NULL, &length, NULL, 0) < 0)
errorFlag = @"sysctl mgmtInfoBase failure";
else
{
// Alloc memory based on above call
if ((msgBuffer = malloc(length)) == NULL)
errorFlag = @"buffer allocation failure";
else
{
// Get system information, store in buffer
if (sysctl(mgmtInfoBase, 6, msgBuffer, &length, NULL, 0) < 0)
errorFlag = @"sysctl msgBuffer failure";
}
}
}


// Befor going any further...
if (errorFlag != NULL)
{
NSLog(@"Error: %@", errorFlag);
return errorFlag;
}


// Map msgbuffer to interface message structure
interfaceMsgStruct = (struct if_msghdr *) msgBuffer;


// Map to link-level socket structure
socketStruct = (struct sockaddr_dl *) (interfaceMsgStruct + 1);


// Copy link layer address data in socket structure to an array
memcpy(&macAddress, socketStruct->sdl_data + socketStruct->sdl_nlen, 6);


// Read from char array into a string object, into traditional Mac address format
NSString *macAddressString = [NSString stringWithFormat:@"%02X:%02X:%02X:%02X:%02X:%02X",
macAddress[0], macAddress[1], macAddress[2],
macAddress[3], macAddress[4], macAddress[5]];
NSLog(@"Mac Address: %@", macAddressString);


// Release the buffer memory
free(msgBuffer);


return macAddressString;
}

关于这个问题有各种各样的解决方案,但是我找不到一个完整的解决方案。 所以我想出了自己的解决方案:

Nicinfo

使用方法:

NICInfoSummary* summary = [[[NICInfoSummary alloc] init] autorelease];


// en0 is for WiFi
NICInfo* wifi_info = [summary findNICInfo:@"en0"];


// you can get mac address in 'XX-XX-XX-XX-XX-XX' form
NSString* mac_address = [wifi_info getMacAddressWithSeparator:@"-"];


// ip can be multiple
if(wifi_info.nicIPInfos.count > 0)
{
NICIPInfo* ip_info = [wifi_info.nicIPInfos objectAtIndex:0];
NSString* ip = ip_info.ip;
NSString* netmask = ip_info.netmask;
NSString* broadcast_ip = ip_info.broadcastIP;
}
else
{
NSLog(@"WiFi not connected!");
}

这看起来是一个相当干净的解决方案: UIDdevice BIdentifier

// Return the local MAC addy
// Courtesy of FreeBSD hackers email list
// Accidentally munged during previous update. Fixed thanks to erica sadun & mlamb.
- (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;
}

@ Grantland 这个“相当干净的解决方案”看起来类似于我自己对 iPhoneDeveloperTips 解决方案的改进。

你可以看到我的脚步: Https://gist.github.com/1409855/

/* Original source code courtesy John from iOSDeveloperTips.com */


#include <sys/socket.h>
#include <sys/sysctl.h>
#include <net/if.h>
#include <net/if_dl.h>


+ (NSString *)getMacAddress
{
int                 mgmtInfoBase[6];
char                *msgBuffer = NULL;
NSString            *errorFlag = NULL;
size_t              length;


// Setup the management Information Base (mib)
mgmtInfoBase[0] = CTL_NET;        // Request network subsystem
mgmtInfoBase[1] = AF_ROUTE;       // Routing table info
mgmtInfoBase[2] = 0;
mgmtInfoBase[3] = AF_LINK;        // Request link layer information
mgmtInfoBase[4] = NET_RT_IFLIST;  // Request all configured interfaces


// With all configured interfaces requested, get handle index
if ((mgmtInfoBase[5] = if_nametoindex("en0")) == 0)
errorFlag = @"if_nametoindex failure";
// Get the size of the data available (store in len)
else if (sysctl(mgmtInfoBase, 6, NULL, &length, NULL, 0) < 0)
errorFlag = @"sysctl mgmtInfoBase failure";
// Alloc memory based on above call
else if ((msgBuffer = malloc(length)) == NULL)
errorFlag = @"buffer allocation failure";
// Get system information, store in buffer
else if (sysctl(mgmtInfoBase, 6, msgBuffer, &length, NULL, 0) < 0)
{
free(msgBuffer);
errorFlag = @"sysctl msgBuffer failure";
}
else
{
// Map msgbuffer to interface message structure
struct if_msghdr *interfaceMsgStruct = (struct if_msghdr *) msgBuffer;


// Map to link-level socket structure
struct sockaddr_dl *socketStruct = (struct sockaddr_dl *) (interfaceMsgStruct + 1);


// Copy link layer address data in socket structure to an array
unsigned char macAddress[6];
memcpy(&macAddress, socketStruct->sdl_data + socketStruct->sdl_nlen, 6);


// Read from char array into a string object, into traditional Mac address format
NSString *macAddressString = [NSString stringWithFormat:@"%02X:%02X:%02X:%02X:%02X:%02X",
macAddress[0], macAddress[1], macAddress[2], macAddress[3], macAddress[4], macAddress[5]];
NSLog(@"Mac Address: %@", macAddressString);


// Release the buffer memory
free(msgBuffer);


return macAddressString;
}


// Error...
NSLog(@"Error: %@", errorFlag);


return nil;
}
#import <sys/socket.h>
#import <net/if_dl.h>
#import <ifaddrs.h>
#import <sys/xattr.h>
#define IFT_ETHER 0x6

...

- (NSString*)macAddress
{
NSString* result = nil;


char* macAddressString = (char*)malloc(18);
if (macAddressString != NULL)
{
strcpy(macAddressString, "");


struct ifaddrs* addrs = NULL;
struct ifaddrs* cursor;


if (getifaddrs(&addrs) == 0)
{
cursor = addrs;


while (cursor != NULL)
{
if ((cursor->ifa_addr->sa_family == AF_LINK) && (((const struct sockaddr_dl*)cursor->ifa_addr)->sdl_type == IFT_ETHER) && strcmp("en0", cursor->ifa_name) == 0)
{
const struct sockaddr_dl* dlAddr = (const struct sockaddr_dl*) cursor->ifa_addr;
const unsigned char* base = (const unsigned char*)&dlAddr->sdl_data[dlAddr->sdl_nlen];


for (NSInteger index = 0; index < dlAddr->sdl_alen; index++)
{
char partialAddr[3];


sprintf(partialAddr, "%02X", base[index]);
strcat(macAddressString, partialAddr);
}
}


cursor = cursor->ifa_next;
}


}


result = [[[NSString alloc] initWithUTF8String:macAddressString] autorelease];


free(macAddressString);
}


return result;
}

从 iOS7开始,当你询问任何设备的 MAC 地址时,系统总是返回值 02:00:00:00:00:00

在 iOS7以及更高版本中,如果你要求一个 iOS 设备的 MAC 地址,系统会返回值02:00:00:00:00:00:00:00:00。如果需要标识设备,请改为使用 UIDdevice 的 IdentifierForVendor 属性。(为了自己的广告目的,需要标识符的应用程序应该考虑使用 ASIdentifierManager 的 AdversingIdentifier 属性。)

参考资料: 释放

在 ios6中创建基于设备唯一标识符的 uniqueString:

#import <AdSupport/ASIdentifierManager.h>


NSString *uniqueString = [[[ASIdentifierManager sharedManager] advertisingIdentifier] UUIDString];
NSLog(@"uniqueString: %@", uniqueString);

现在 iOS7设备-总是返回一个 MAC 地址02:00:00:00:00:00。

所以最好使用[ UIDeviceIdentifierForVendor ]。

所以最好调用这个方法来获取应用程序特定的唯一键

分类比较合适

Import“ UIDevice + Identifier.h”

- (NSString *) identifierForVendor1
{
if ([[UIDevice currentDevice] respondsToSelector:@selector(identifierForVendor)]) {
return [[[UIDevice currentDevice] identifierForVendor] UUIDString];
}
return @"";
}

现在调用上面的方法来获得唯一地址

NSString *like_UDID=[NSString stringWithFormat:@"%@",
[[UIDevice currentDevice] identifierForVendor1]];


NSLog(@"%@",like_UDID);

许多这样的问题只涉及 Mac 地址。如果你也需要的 IP 地址,我刚写的这个,可能需要一些工作,但似乎工作在我的机器..。

- (NSString *)getLocalIPAddress
{
NSArray *ipAddresses = [[NSHost currentHost] addresses];
NSArray *sortedIPAddresses = [ipAddresses sortedArrayUsingSelector:@selector(localizedCaseInsensitiveCompare:)];


NSNumberFormatter *numberFormatter = [[NSNumberFormatter alloc] init];
numberFormatter.allowsFloats = NO;


for (NSString *potentialIPAddress in sortedIPAddresses)
{
if ([potentialIPAddress isEqualToString:@"127.0.0.1"]) {
continue;
}


NSArray *ipParts = [potentialIPAddress componentsSeparatedByString:@"."];


BOOL isMatch = YES;


for (NSString *ipPart in ipParts) {
if (![numberFormatter numberFromString:ipPart]) {
isMatch = NO;
break;
}
}
if (isMatch) {
return potentialIPAddress;
}
}


// No IP found
return @"?.?.?.?";
}

在运行 iOS 7.0或更高版本的设备上再也不可能 了,因此在 Swift 中无法获得 MAC 地址。

正如苹果所言:

在 iOS7以及更高版本中,如果你要求一个 iOS 设备的 MAC 地址,系统会返回值02:00:00:00:00:00:00:00:00。如果需要标识设备,请改为使用 UIDdevice 的 IdentifierForVendor 属性。(为了自己的广告目的,需要标识符的应用程序应该考虑改为使用 ASIdentifierManager 的 AdversingIdentifier 属性。)