Wie kann ich programmgesteuert die MAC-Adresse eines iPhones abrufen?

144

Wie erhalte ich programmgesteuert die MAC-Adresse und IP-Adresse eines iPhones?

Cœur
quelle
Ich möchte MAC-Adresse und IP-Adresse programmgesteuert in einer iPhone-Anwendung erhalten.
Wifi MAC-Adresse? oder BlueTooth? Es gibt viele Mac-Adressen.
mskw
11
Ab iOS 7 gibt das System den Wert immer zurück, 02:00:00:00:00:00wenn Sie auf einem Gerät nach der MAC-Adresse fragen. Überprüfen Sie meine Antwort unten.
Hejazi
Für ios und bis (bis heute) siehe stackoverflow.com/questions/11836225/…
rptwsthi

Antworten:

114

HINWEIS Ab iOS7 können Sie keine Geräte-MAC-Adressen mehr abrufen. Es wird ein fester Wert anstelle des tatsächlichen MAC zurückgegeben


Etwas, über das ich vor einiger Zeit gestolpert bin. Ursprünglich von hier aus habe ich es ein wenig modifiziert und aufgeräumt.

IPAddress.h
IPAddress.c

Und um es zu benutzen

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

Die Adapternamen variieren je nach Simulator / Gerät sowie WLAN oder Zelle auf dem Gerät.

PyjamaSam
quelle
Ich frage mich nur, ob dies etwas anderes ist als ein generischer OS X-Ansatz (ich frage, weil ich ein Mac n00b bin)
Tamas Czinege
2
@abc: Ich empfehle dir eine weitere Frage dazu zu stellen. Sei besser, als es in Kommentaren für eine andere Frage zu vergraben.
PyjamaSam
1
aber was ist mit dem Aufruf von ether_ntoa? Das ist eine private API, nicht wahr?
Stigi
1
@NicTesla Ich kann nicht sicher kommentieren, aber da es nur grundlegende Netzwerkanrufe macht, kann ich kein Problem sehen. Obwohl das Entfernen der UDID von iOS5, wenn die Mac-Adresse abgerufen und zur Entwicklung einer alternativen eindeutigen Kennung verwendet wird, möglicherweise irgendwann in der Zukunft von Apple überprüft wird.
PyjamaSam
1
In Bezug auf ether_ntoaWarnung Besuche: stackoverflow.com/a/13412265/88597
ohho
45

Update: Dies funktioniert nicht unter iOS 7. Sie sollten ASIdentifierManager verwenden .


Sauberere Lösung auf der MobileDeveloperTips-Website:

#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;
}
ArtFeel
quelle
Ändern Sie den Link zu mobiledevelopertips anstelle von iphonedevelopertips
SEG
Apple wird dies in iOS7 SEHR wahrscheinlich brechen ... und wir könnten dies erst öffentlich kommentieren, wenn es ausgeliefert wird, außer in den offiziellen Apple Dev-Foren.
Gabe
3
Dies funktionierte auf meinem iPhone5 mit iOS7 nicht. Es gibt mir: 02: 00: 00: 00: 00: 00, was nicht richtig ist.
Sjoerd Perfors
3
@Brenden Mit PublicAPI unter iOS7 können Sie keine Netzwerk-MAC-Adresse mehr abrufen. Wenn Sie also eine eindeutige ID benötigen, sollten SieIdentifierManager
ArtFeel
2
@SjoerdPerfors Unter iOS 7 erhalten Sie in der Tat immer die gleiche Adresse 02:00:00:00:00:00wie eine Datenschutzmaßnahme von Apple.
Basil Bourque
31

Ich wollte, dass etwas die Adresse zurückgibt, unabhängig davon, ob WLAN aktiviert ist oder nicht, daher funktionierte die gewählte Lösung für mich nicht. Ich habe einen anderen Anruf verwendet, den ich nach einigen Optimierungen in einem Forum gefunden habe. Am Ende hatte ich Folgendes (entschuldigen Sie mein rostiges 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;
}

Und dann würde ich es so nennen und nach en0 fragen :

char* macAddressString= (char*)malloc(18);
NSString* macAddress= [[NSString alloc] initWithCString:getMacAddress(macAddressString, "en0")
                                              encoding:NSMacOSRomanStringEncoding];
free(macAddressString);
Schiffsführer
quelle
9
Ich musste #define IFT_ETHER 0x6
teedyay
Dieser funktioniert bei mir nicht ... sagt, dass ifName nicht so deklariert ist wie die Variable macaddress.
Bugfixr
Der obige Aufrufcode leckt. kostenlos (macAddressString); bevor Sie von der obigen aufrufenden Methode zurückkehren. Außerdem sollte macAddress automatisch freigegeben werden, wenn sich der obige Aufrufcode in einer anderen Methode befindet.
4
Um klar zu sein, der Code selbst wird nicht auslaufen. Der Kommentator hat am Ende über das aufrufende Snippet gesprochen, bei dem ich zwei Zeichenfolgen zugewiesen habe, ohne sie freizugeben.
Schiffsführer
1
Ich habe dies in eine nette Objective-C-Methode eingefügt
wsidell
23

Ab iOS 7 gibt das System den Wert immer zurück, 02:00:00:00:00:00wenn Sie auf einem Gerät nach der MAC-Adresse fragen.

Wenn Sie in iOS 7 und höher nach der MAC-Adresse eines iOS-Geräts fragen, gibt das System den Wert 02: 00: 00: 00: 00: 00 zurück. Wenn Sie das Gerät identifizieren müssen, verwenden Sie stattdessen die Eigenschaft identifierForVendor von UIDevice. (Apps, die eine Kennung für ihre eigenen Werbezwecke benötigen, sollten stattdessen die Eigenschaft "AdvertisingIdentifier" von ASIdentifierManager verwenden.) "

Referenz: Releasenoten

Hejazi
quelle
Das Schöne an dieser Ablehnung in der API ist, dass sie auf dem Simulator immer noch korrekt funktioniert und derzeit nur auf Hardware.
John Nye
12

Es gibt verschiedene Lösungen dafür, aber ich konnte keine ganze Sache finden. Also habe ich meine eigene Lösung gemacht für:

nicinfo

Wie benutzt man :

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!");
}
Kenial
quelle
Sehr schöne und nützliche Klasse! Gute Arbeit! Sie haben jedoch beide Klassen [super dealloc] verpasst und vergessen, eine Bibliothek einzuschließen, was zu Warnungen in xCode führt. Die gepatchte Version finden Sie hier: raptor.hk/download/NICInfo_raptor_patched.zip
Raptor
Erhalten dieses Ergebnisses Mac-Adresse: 02: 00: 00: 00: 00: 00
Stalin Pusparaj
1
Ja. Apple hat dies seit iOS 7 blockiert :( ... developer.apple.com/library/content/releasenotes/General/…
Kenial
5

Dies sieht nach einer ziemlich sauberen Lösung aus: 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;
}
Grantland Chew
quelle
1
Ich verwende Ihre Lösung. 99% der Fälle funktionieren wie erwartet, aber 1% kann die Mac-Adresse nicht abrufen. Geben Sie NULL zurück, wie von den Benutzern im AppStore gemeldet. Immer noch keine reproduzierbaren Schritte, hast du es? Danke dir.
Jianhua
Ich habe noch keine Probleme bemerkt, aber ich werde aufpassen!
Grantland Chew
Weiterverfolgung des Kommentars von @ jianhua: Wir haben gerade Berichte von einem Benutzer erhalten, der die App grundsätzlich nicht verwenden kann, da dieser Code für sein Gerät null zurückgibt (wir verwenden die Kennung, um jeden Serveranruf zu authentifizieren).
Samvermette
Der fehlgeschlagene Fall ist auf dem iPhone 4S mit IOS Version 5.0.1, natürlich nur zu besonderen Anlässen.
Jianhua
5

Jetzt geben iOS 7-Geräte - immer eine MAC-Adresse von 02: 00: 00: 00: 00: 00 zurück.

Verwenden Sie daher besser [UIDevice identifierForVendor].

Rufen Sie diese Methode besser auf, um einen app-spezifischen eindeutigen Schlüssel zu erhalten

Kategorie wird besser geeignet

importiere "UIDevice + Identifier.h"

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

Rufen Sie nun die obige Methode auf, um eine eindeutige Adresse zu erhalten

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

NSLog(@"%@",like_UDID);
Nagendra Tripathi
quelle
Wäre diese Kennung pro Gerät über mehrere Installationen derselben App hinweg konsistent?
Samsam
4

@Grantland Diese "ziemlich saubere Lösung" ähnelt meiner eigenen Verbesserung gegenüber der iPhoneDeveloperTips-Lösung.

Sie können meinen Schritt hier sehen: 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;
}
Cœur
quelle
und ich verstehe nicht, warum ich Kommentare für meine eigenen Antworten hinzufügen kann, aber nicht für die Antworten anderer? : /
Cœur
1
Weil dein Ruf nicht hoch genug ist.
Honus
Vielen Dank, es sieht so aus, als hätten sich einige Leute ihre eigenen Varianten dieser Lösung ausgedacht
josh-fuggle
1

Auf Geräten mit iOS 7.0 oder höher ist dies nicht mehr möglich. Daher ist es nicht möglich , die MAC-Adresse in Swift abzurufen.

Wie Apple sagte:

Wenn Sie in iOS 7 und höher nach der MAC-Adresse eines iOS-Geräts fragen, gibt das System den Wert 02: 00: 00: 00: 00: 00 zurück. Wenn Sie das Gerät identifizieren müssen, verwenden Sie stattdessen die Eigenschaft identifierForVendor von UIDevice. (Apps, die eine Kennung für ihre eigenen Werbezwecke benötigen, sollten stattdessen die Eigenschaft "AdvertisingIdentifier" von ASIdentifierManager verwenden.)

pedrouan
quelle
0
#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;
}
Valentin Shamardin
quelle
0

So erstellen Sie einen uniqueString basierend auf der eindeutigen Kennung des Geräts in iOS 6:

#import <AdSupport/ASIdentifierManager.h>

NSString *uniqueString = [[[ASIdentifierManager sharedManager] advertisingIdentifier] UUIDString];
NSLog(@"uniqueString: %@", uniqueString);
Denis Kutlubaev
quelle
1
Wie hängt das mit der gestellten Frage zusammen?
Valeriy Van
1
In den meisten Fällen wird eine Mac-Adresse benötigt, um das Gerät eindeutig zu identifizieren. Stattdessen können Sie diese Lösung verwenden.
Denis Kutlubaev
0

Viele dieser Fragen beziehen sich nur auf die Mac-Adresse. Wenn Sie auch die IP-Adresse benötigen, die ich gerade geschrieben habe, müssen Sie möglicherweise etwas arbeiten, scheinen aber auf meinem Computer gut zu funktionieren ...

- (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 @"?.?.?.?";
}
Oliver Pearmain
quelle