Bagaimana saya bisa mendapatkan alamat MAC dari iphone secara terprogram

144

Bagaimana secara terprogram mendapatkan alamat MAC dan alamat IP iPhone?

Cur
sumber
saya ingin mendapatkan alamat MAC dan alamat IP secara terprogram dalam aplikasi iPhone.
Alamat MAC Wifi? atau BlueTooth? Ada banyak alamat Mac.
mskw
11
Mulai dari iOS 7, sistem selalu mengembalikan nilai 02:00:00:00:00:00ketika Anda meminta alamat MAC pada perangkat apa pun. Periksa jawaban saya di bawah ini.
Hejazi
Untuk ios dan yang lebih tinggi (hingga hari ini) lihat stackoverflow.com/questions/11836225/…
rptwsthi

Jawaban:

114

CATATAN Pada iOS7, Anda tidak lagi dapat mengambil perangkat alamat MAC. Nilai tetap akan dikembalikan daripada MAC yang sebenarnya


Sesuatu yang saya temui beberapa waktu lalu. Awalnya dari sini saya memodifikasinya sedikit dan membersihkannya.

IPAddress.h
IPAddress.c

Dan untuk menggunakannya

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

Nama adaptor bervariasi tergantung pada simulator / perangkat serta wifi atau sel pada perangkat.

PyjamaSam
sumber
saya hanya ingin tahu apakah ini berbeda dari pendekatan generik OS X (aku bertanya karena aku seorang n00b mac)
Tamas Czinege
2
@ abc: Saya sarankan Anda memposting pertanyaan lain tentang itu. Lebih baik menguburnya dalam komentar untuk pertanyaan yang berbeda.
PyjamaSam
1
tapi bagaimana dengan panggilan ke ether_ntoa? ini API pribadi bukan?
stigi
1
@NicTesla Saya tidak bisa berkomentar pasti, tapi karena itu hanya melakukan panggilan jaringan dasar saya tidak bisa melihat masalah. Meskipun itu dikatakan dengan penghapusan UDID dari iOS5 mendapatkan alamat mac dan menggunakannya untuk mengembangkan beberapa jenis pengidentifikasi unik alternatif mungkin akan diteliti oleh apel di beberapa titik di masa depan.
PyjamaSam
1
Mengenai ether_ntoaperingatan, periksa: stackoverflow.com/a/13412265/88597
ohho
45

Pembaruan: ini tidak akan berfungsi di iOS 7. Anda harus menggunakan ASIdentifierManager .


Lebih banyak solusi bersih di situs web 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;
}
ArtFeel
sumber
ubah tautan ke mobiledevelopertips alih-alih iphonedevelopertips
SEG
Apple sangat mungkin untuk memecahkan ini di iOS7 ... dan kami tidak akan dapat mengomentari ini secara publik sampai dikirimkan kecuali di Forum resmi Apple Dev.
Gabe
3
Ini tidak berfungsi pada iPhone5 saya dengan iOS7. Ini memberi saya: 02: 00: 00: 00: 00 yang tidak benar.
Sjoerd Perfors
3
@ Brenden Anda tidak bisa mendapatkan alamat MAC jaringan menggunakan PublicAPI di iOS7 lagi. Jadi, jika Anda memerlukan id unik, Anda harus menggunakanIdentifierManager
ArtFeel
2
@SjoerdPerfors Di bawah iOS 7 Anda memang akan selalu mendapatkan dari alamat yang sama 02:00:00:00:00:00sebagai tindakan pencegahan privasi oleh Apple.
Basil Bourque
31

Saya ingin sesuatu mengembalikan alamat terlepas dari apakah wifi diaktifkan atau tidak, jadi solusi yang dipilih tidak bekerja untuk saya. Saya menggunakan panggilan lain yang saya temukan di beberapa forum setelah beberapa penyesuaian. Saya berakhir dengan yang berikut ini (permisi C yang berkarat):

#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;
}

Dan kemudian saya akan menyebutnya meminta en0 , sebagai berikut:

char* macAddressString= (char*)malloc(18);
NSString* macAddress= [[NSString alloc] initWithCString:getMacAddress(macAddressString, "en0")
                                              encoding:NSMacOSRomanStringEncoding];
free(macAddressString);
kepala kapal
sumber
9
Saya harus menambahkan #define IFT_ETHER 0x6
teedyay
Yang ini tidak berfungsi untuk saya ... mengatakan ifName tidak dideklarasikan juga sebagai variabel macaddress.
bugfixr
Kode panggilan di atas akan bocor. gratis (macAddressString); sebelum kembali dari metode panggilan di atas. Juga, macAddress harus autoreleased jika kode panggilan di atas adalah dalam metode lain.
4
untuk menjadi jelas, kode itu sendiri tidak akan bocor, komentator berbicara tentang cuplikan panggilan di akhir, di mana saya mengalokasikan dua string tanpa membebaskan mereka.
kepala kapal
1
Saya memasukkan ini ke dalam metode objektif-c yang bagus dan membuatnya jadi tidak memerlukan parameter: gist.github.com/wsidell/5069159
wsidell
23

Mulai dari iOS 7, sistem selalu mengembalikan nilai 02:00:00:00:00:00ketika Anda meminta alamat MAC pada perangkat apa pun.

Di iOS 7 dan yang lebih baru, jika Anda meminta alamat MAC perangkat iOS, sistem mengembalikan nilai 02: 00: 00: 00: 00: 00: 00. Jika Anda perlu mengidentifikasi perangkat, gunakan properti identifierForVendor dari UIDevice sebagai gantinya. (Aplikasi yang membutuhkan pengidentifikasi untuk tujuan periklanan mereka sendiri harus mempertimbangkan untuk menggunakan properti advertisingIdentifier dari ASIdentifierManager.) "

Referensi: releasenotes

Hejazi
sumber
Apa yang benar-benar baik tentang penghentian API ini adalah bahwa ia masih bekerja pada simulator dengan benar, dan hanya pada perangkat keras saat ini.
John Nye
12

Ada beragam solusi tentang ini, tetapi saya tidak dapat menemukan semuanya. Jadi saya membuat solusi sendiri untuk:

nicinfo

Cara Penggunaan :

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
sumber
Kelas yang sangat bagus & bermanfaat! Kerja bagus! Namun, Anda melewatkan [super dealloc] di kedua kelas & lupa menyertakan perpustakaan, yang mengarah ke peringatan di xCode. Versi tambalan dapat ditemukan di sini: raptor.hk/download/NICInfo_raptor_patched.zip
Raptor
mendapatkan hasil ini Alamat Mac: 02: 00: 00: 00: 00
Stalin Pusparaj
1
Iya. Apple memblokir ini sejak iOS 7 :( ... developer.apple.com/library/content/releasenotes/General/…
Kenial
5

Ini terlihat seperti solusi yang cukup bersih: 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 Mengunyah
sumber
1
Saya menggunakan solusi Anda, 99% kasus berfungsi dengan baik seperti yang diharapkan, tetapi tingkat 1% tidak bisa mendapatkan alamat mac, mengembalikan NULL, dilaporkan oleh pengguna di AppStore. Masih belum mendapatkan langkah-langkah yang dapat direproduksi, sudahkah Anda mendapatkannya? Terima kasih.
jianhua
Saya belum melihat masalah apa pun, tapi saya akan tetap melihat keluar!
Grantland Chew
Menindaklanjuti komentar @ jianhua: kami baru saja menerima laporan dari pengguna yang pada dasarnya tidak dapat menggunakan aplikasi karena kode ini mengembalikan null untuk perangkatnya (kami menggunakan pengidentifikasi untuk mengotentikasi setiap panggilan server).
samvermette
Kasing yang gagal adalah pada iPhone 4S dengan iOS versi 5.0.1, tentu saja hanya pada beberapa kesempatan khusus.
jianhua
5

Sekarang perangkat iOS 7 - selalu mengembalikan alamat MAC 02: 00: 00: 00: 00: 00

Jadi lebih baik gunakan [UIDevice identifierForVendor].

jadi lebih baik memanggil metode ini untuk mendapatkan kunci unik khusus aplikasi

Kategori akan lebih cocok

impor "UIDevice + Identifier.h"

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

Sekarang panggil metode di atas untuk mendapatkan alamat unik

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

NSLog(@"%@",like_UDID);
Nagendra Tripathi
sumber
apakah pengidentifikasi ini konsisten per perangkat dibandingkan beberapa pemasangan aplikasi yang sama?
samsam
4

@Grantland "Solusi yang cukup bersih" ini terlihat mirip dengan peningkatan saya sendiri atas solusi iPhoneDeveloperTips.

Anda dapat melihat langkah saya di sini: 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;
}
Cur
sumber
dan saya tidak mengerti mengapa saya bisa menambahkan komentar untuk jawaban saya sendiri tetapi tidak untuk jawaban orang lain? : /
Cœur
1
Karena reputasi Anda tidak cukup tinggi.
honus
Terima kasih, sepertinya beberapa orang telah menghadirkan varian mereka sendiri dari solusi ini: ios.biomsoft.com/2011/11/07/determine-mac-address
josh-fuggle
1

Itu tidak mungkin lagi pada perangkat yang menjalankan iOS 7.0 atau yang lebih baru, sehingga tidak tersedia untuk mendapatkan alamat MAC di Swift.

Seperti yang dikatakan Apple:

Di iOS 7 dan yang lebih baru, jika Anda meminta alamat MAC perangkat iOS, sistem mengembalikan nilai 02: 00: 00: 00: 00: 00: 00. Jika Anda perlu mengidentifikasi perangkat, gunakan properti identifierForVendor dari UIDevice sebagai gantinya. (Aplikasi yang membutuhkan pengidentifikasi untuk tujuan periklanan mereka sendiri harus mempertimbangkan untuk menggunakan properti advertisingIdentifier dari ASIdentifierManager.)

pedrouan
sumber
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
sumber
0

Untuk membuat Strtring unik berdasarkan pengidentifikasi unik perangkat di iOS 6:

#import <AdSupport/ASIdentifierManager.h>

NSString *uniqueString = [[[ASIdentifierManager sharedManager] advertisingIdentifier] UUIDString];
NSLog(@"uniqueString: %@", uniqueString);
Denis Kutlubaev
sumber
1
bagaimana ini berhubungan dengan pertanyaan yang diajukan?
Valeriy Van
1
Alamat Mac diperlukan untuk mengidentifikasi perangkat secara unik dalam banyak kasus. Sebagai gantinya, Anda dapat menggunakan solusi ini.
Denis Kutlubaev
0

Banyak dari pertanyaan ini hanya membahas alamat Mac. Jika Anda juga memerlukan alamat IP yang baru saya tulis ini, mungkin perlu beberapa pekerjaan tetapi tampaknya berfungsi dengan baik pada mesin saya ...

- (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
sumber