Как программно получить MAC-адрес iphone

Как программно получить MAC-адрес и IP-адрес iPhone?


person Community    schedule 24.03.2009    source источник
comment
Я хочу получить MAC-адрес и IP-адрес программно в приложении для iPhone.   -  person    schedule 24.03.2009
comment
MAC-адрес Wi-Fi? или BlueTooth? Есть много Mac-адресов.   -  person mskw    schedule 08.06.2013
comment
Начиная с iOS 7, система всегда возвращает значение 02:00:00:00:00:00, когда вы запрашиваете MAC-адрес на любом устройстве. Проверьте мой ответ ниже.   -  person Hejazi    schedule 12.06.2013
comment
Для iOS и более поздних версий (до сегодняшнего дня) см. stackoverflow.com/questions/11836225/   -  person rptwsthi    schedule 05.07.2013


Ответы (11)



ПРИМЕЧАНИЕ. Начиная с iOS7, вы больше не можете получать MAC-адреса устройств. Будет возвращено фиксированное значение, а не фактический MAC


Что-то, на что я наткнулся некоторое время назад. Исходя из здесь, я изменил это немного и прибрано.

IPAddress.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]);
    }
}

Имена адаптеров различаются в зависимости от симулятора / устройства, а также от Wi-Fi или сотовой сети на устройстве.

person PyjamaSam    schedule 24.03.2009
comment
Мне просто интересно, отличается ли это от общего подхода OS X (я спрашиваю, потому что я Mac n00b) - person Tamas Czinege; 24.03.2009
comment
@DrJokepu Я думаю, что это базовые вещи для OSX. На самом деле это базовый материал BSD. Тот же подход, скорее всего, будет работать и в Linux (даже, возможно, в окнах с небольшой настройкой) - person PyjamaSam; 24.03.2009
comment
@abc: Я рекомендую вам задать еще один вопрос по этому поводу. Лучше закопайте это в комментариях для другого вопроса. - person PyjamaSam; 24.03.2009
comment
а как насчет вызова ether_ntoa? это частный API, не так ли? - person stigi; 04.11.2009
comment
Я не верю, что какой-либо из методов, используемых в этой реализации, считается частью частного API. Все они являются базовыми вызовами BSD. Вы можете узнать больше о ether_ntoa здесь: developer.apple.com/Mac/library/documentation/Darwin/Reference/ Это просто преобразование двоичного представления адреса Ethernet в строковую форму. - person PyjamaSam; 14.11.2009
comment
Изменится ли MAC-адрес, когда устройство перейдет с Wi-Fi на сотовую передачу данных? - person xanadont; 20.08.2011
comment
@xanadont: Поскольку интерфейсы WIFI и Cellular - это разные физические устройства, я предполагаю, что это так. Я давно не запускал этот код, поэтому точно не знаю, но его будет легко проверить. - person PyjamaSam; 31.08.2011
comment
Когда вы получаете MAC-адрес iphone, это доказательство itunesstore? (Можете ли вы загрузить его в itunesstore, и будет ли он принят Apple, или можно получить адрес Mac только с взломанного iphone?) - person NicTesla; 21.09.2011
comment
@NicTesla Я не могу комментировать наверняка, но, поскольку он просто выполняет базовые сетевые вызовы, я не вижу проблемы. Хотя это, как говорится, с удалением UDID из iOS5, получение MAC-адреса и его использование для разработки какого-то альтернативного уникального идентификатора может в какой-то момент в будущем подвергнуться проверке со стороны Apple. - person PyjamaSam; 22.09.2011
comment
Можно ли получить MAC-адрес интерфейса Wi-Fi, даже если Wi-Fi отключен? - person neilvillareal; 10.05.2012
comment
Что касается предупреждения ether_ntoa, проверьте: stackoverflow.com/a/13412265/88597 - person ohho; 16.11.2012
comment
К вашему сведению, в декларации об авторских правах на код C указано, что все права защищены. - person jeff7091; 11.10.2013

Обновление: это не будет работать на iOS 7. Вам следует использовать 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;
}
person ArtFeel    schedule 07.11.2011
comment
измените ссылку на mobiledevelopertips вместо iphonedevelopertips - person SEG; 10.05.2012
comment
Apple ОЧЕНЬ вероятно нарушит это в iOS7 ... и мы не сможем публично комментировать это, пока она не будет выпущена, за исключением официальных форумов Apple Dev. - person Gabe; 22.07.2013
comment
Да, вам следует использовать ASIdentifierManager. - person ArtFeel; 23.07.2013
comment
Это не сработало на моем iPhone5 с iOS7. Это дает мне: 02: 00: 00: 00: 00: 00, что неправильно. - person Sjoerd Perfors; 27.09.2013
comment
Посмотрите мой комментарий выше. - person ArtFeel; 27.09.2013
comment
@ArtFeel ASIdentifierManager не предоставляет сетевой MAC-адрес - person Brenden; 02.10.2013
comment
@Brenden Вы больше не можете получить сетевой MAC-адрес с помощью PublicAPI на iOS7. Итак, если вам нужен уникальный идентификатор, вы должны использовать IdentifierManager - person ArtFeel; 03.10.2013
comment
@SjoerdPerfors В iOS 7 вы действительно всегда будете получать тот же адрес 02:00:00:00:00:00 в качестве меры предосторожности Apple. - person Basil Bourque; 22.05.2014

Я хотел, чтобы что-то возвращало адрес независимо от того, был ли включен Wi-Fi, поэтому выбранное решение у меня не сработало. Я использовал другой звонок, который нашел на каком-то форуме после некоторой настройки. У меня получилось следующее (простите мой ржавый 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;
}

Затем я бы назвал это запросом en0 следующим образом:

char* macAddressString= (char*)malloc(18);
NSString* macAddress= [[NSString alloc] initWithCString:getMacAddress(macAddressString, "en0")
                                              encoding:NSMacOSRomanStringEncoding];
free(macAddressString);
person shipmaster    schedule 23.05.2011
comment
Мне пришлось добавить #define IFT_ETHER 0x6 - person teedyay; 09.08.2011
comment
Это не работает для меня ... говорит, что ifName не объявлено, а также переменная macaddress. - person bugfixr; 29.08.2011
comment
Приведенный выше код вызова будет протекать. бесплатно (macAddressString); перед возвратом из вышеуказанного метода вызова. Кроме того, macAddress должен автоматически выпускаться, если приведенный выше код вызова находится в другом методе. - person ; 11.10.2011
comment
@ Veera.s.Vasan, вы правы. Фрагмент не был задуман как полный код, просто чтобы показать вам, как использовать указанную выше функцию. - person shipmaster; 11.10.2011
comment
для ясности, сам код не просочится, комментатор говорил о вызывающем сниппете в конце, где я выделяю две строки, не освобождая их. - person shipmaster; 21.12.2011
comment
Я поместил это в красивый метод objective-c и сделал так, чтобы он не требовал параметров: gist.github.com / wsidell / 5069159 - person wsidell; 02.03.2013

Начиная с iOS 7, система всегда возвращает значение 02:00:00:00:00:00, когда вы запрашиваете MAC-адрес на любом устройстве.

В iOS 7 и более поздних версиях, если вы запрашиваете MAC-адрес устройства iOS, система возвращает значение 02: 00: 00: 00: 00: 00. Если вам нужно идентифицировать устройство, используйте вместо этого свойство identifierForVendor UIDevice. (Приложениям, которым требуется идентификатор для их собственных рекламных целей, следует рассмотреть возможность использования вместо этого свойства AdvertisingIdentifier ASIdentifierManager.) "

Ссылка: примечания к выпуску < / а>

person Hejazi    schedule 11.06.2013
comment
Что действительно приятно в этой устаревшей версии API, так это то, что она по-прежнему корректно работает на симуляторе, и на данный момент только на оборудовании. - person John Nye; 13.06.2013

Есть разные решения по этому поводу, но я не смог найти всего. Итак, я сделал собственное решение для:

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!");
}
person Kenial    schedule 21.11.2011
comment
Очень красивый и полезный класс! Хорошая работа! Однако вы пропустили [super dealloc] в обоих классах и забыли включить библиотеку, что приводит к предупреждениям в xCode. Исправленную версию можно найти здесь: raptor.hk/download/NICInfo_raptor_patched.zip - person Raptor; 30.12.2011
comment
получение этого результата Mac Address: 02: 00: 00: 00: 00: 00 - person Stalin Pusparaj; 02.02.2017
comment
да. Apple заблокировала это с iOS 7 :( ... developer.apple.com/library/content/releasenotes/General/ - person Kenial; 02.02.2017

Это выглядит довольно чистым решением: UIDevice 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;
}
person Grantland Chew    schedule 27.03.2012
comment
Я использую ваше решение, 99% случаев работают, как ожидалось, но 1% случаев не может получить MAC-адрес, вернуть NULL, о чем сообщили пользователи в AppStore. По-прежнему нет воспроизводимых шагов, у вас это есть? Спасибо. - person jianhua; 15.10.2012
comment
Я еще не заметил никаких проблем, но буду следить! - person Grantland Chew; 15.10.2012
comment
Продолжая комментарий @ jianhua: мы только что получили отчеты от пользователя, который в основном не может использовать приложение, потому что этот код возвращает null для его устройства (мы используем идентификатор для аутентификации каждого вызова сервера). - person samvermette; 16.10.2012
comment
Неудачный случай есть на iPhone 4S с версией IOS 5.0.1, конечно, только в некоторых особых случаях. - person jianhua; 16.10.2012

Теперь устройства iOS 7 - всегда возвращают MAC-адрес 02: 00: 00: 00: 00: 00.

Так что лучше использовать [UIDevice identifierForVendor].

поэтому лучше вызвать этот метод, чтобы получить уникальный ключ для конкретного приложения

Категория подойдет больше

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);
person Nagendra Tripathi    schedule 24.09.2013
comment
будет ли этот идентификатор согласованным для каждого устройства при нескольких установках одного и того же приложения? - person samsam; 06.08.2015

@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;
}
person Cœur    schedule 27.03.2012
comment
и я не понимаю, почему я могу добавлять комментарии к своим ответам, но не к ответам других? : / - person Cœur; 27.03.2012
comment
Потому что ваша репутация недостаточно высока. - person honus; 11.05.2012
comment
Спасибо, похоже, несколько человек придумали свои варианты этого решения: ios.biomsoft.com/2011/11/07/determine-mac-address - person josh-fuggle; 25.02.2013

Это больше невозможно на устройствах под управлением iOS 7.0 или новее, поэтому получить MAC-адрес в Swift невозможно.

Как заявила Apple:

В iOS 7 и более поздних версиях, если вы запрашиваете MAC-адрес устройства iOS, система возвращает значение 02: 00: 00: 00: 00: 00. Если вам нужно идентифицировать устройство, используйте вместо этого свойство identifierForVendor UIDevice. (Приложениям, которым требуется идентификатор для их собственных рекламных целей, следует рассмотреть возможность использования вместо этого свойства AdvertisingIdentifier ASIdentifierManager.)

person pedrouan    schedule 04.09.2016

Чтобы создать uniqueString на основе уникального идентификатора устройства в iOS 6:

#import <AdSupport/ASIdentifierManager.h>

NSString *uniqueString = [[[ASIdentifierManager sharedManager] advertisingIdentifier] UUIDString];
NSLog(@"uniqueString: %@", uniqueString);
person Denis Kutlubaev    schedule 27.07.2013
comment
как это связано с заданным вопросом? - person Valeriy Van; 23.08.2013
comment
Mac-адрес необходим для однозначной идентификации устройства в большинстве случаев. Вместо этого вы можете использовать это решение. - person Denis Kutlubaev; 04.09.2013

Многие из этих вопросов касаются только 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 @"?.?.?.?";
}
person Oliver Pearmain    schedule 17.12.2014