Delphi For Android 使用Posix函数获取网络信息,MAC, IP...

安卓中获取系统当前活动的网卡MAC地址和IP地址时,需要使用到java.net.networkinterface库,在Delphi中虽然可以调用java库,

但是如果没有现成的java库(jar、class等),也会比较麻烦,这里使用posix函数实现获取MAC和IP地址,不需要root权限,

但理论上应该需要设置查询网络状态和WIFI状态权限:

<!-- 获取网络状态的权限 -->
<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />
<uses-permission android:name="android.permission.ACCESS_WIFI_STATE" />

delphi的话在工程属性中勾选就好了。

使用posix函数的方法,理论上支持android、ios、mac、linux...好处是很多的,而在android的NDK开发中也是使用这种方法实现,网上找一下就有代码。

unit uNetWorkInfo;

interface
//注: posix的网络操作可参看indy控件的底层,如IdStackVCLPosix.pas
//     posix大部分操作可参看linux相关代码,搜索linux代码即可翻译成pascal

function getLocalMac(var sIP: string): string;

implementation
uses
  Posix.Base,
  Posix.ArpaInet,
  Posix.Errno,
  Posix.NetDB,
  Posix.NetIf,
  Posix.NetinetIn,
  Posix.StrOpts,
  Posix.SysTypes,
  Posix.SysUio,
  Posix.Unistd,
  Posix.SysSelect,
  Posix.SysSocket,
  Posix.SysTime,
  Posix.Stdio,
  Sockios,
  SysUtils;


type
  TSunB = packed record
    s_b1, s_b2, s_b3, s_b4: Byte;
  end;

  TSunW = packed record
    s_w1, s_w2: Word;
  end;

  PIn4Addr = ^TIn4Addr;
  TIn4Addr = packed record
    case integer of
        0: (S_un_b: TSunB);
        1: (S_un_w: TSunW);
        2: (S_addr: LongWord);
  end;

  PIn6Addr = ^TIn6Addr;
  TIn6Addr = packed record
    case Integer of
    0: (s6_addr: packed array [0..16-1] of Byte);
    1: (s6_addr16: packed array [0..8-1] of Word);
  end;

function IPv4AddrToString(const aInAddr: TIn4Addr): string;
begin
  Result := IntToStr(TIn4Addr(AInAddr).S_un_b.s_b1) + '.'   {Do not Localize}
            + IntToStr(TIn4Addr(AInAddr).S_un_b.s_b2) + '.' {Do not Localize}
            + IntToStr(TIn4Addr(AInAddr).S_un_b.s_b3) + '.' {Do not Localize}
            + IntToStr(TIn4Addr(AInAddr).S_un_b.s_b4);
end;

// 获取本地mac
function getLocalMac(var sIP: string): string;
{$IFDEF POSIX}
const
  MAXINTERFACES = 15;
var
  sock_fd: integer;
  buf: array[0..MAXINTERFACES-1] of ifreq;
  ifc: ifconf;
  interface_num: integer;
  //M: TMarshaller;
  //sEn: string;
{$ENDIF}
begin
  {$IFDEF POSIX}
  sIP := '';
  Result := '';

  sock_fd := socket(AF_INET,
    SOCK_DGRAM, //SOCK_STREAM,
    0);
  if (sock_fd = -1) then
  begin
        //perror('create socket falise...mac\n');
    Exit;
  end;

  FillChar(buf, SizeOf(buf), 0);
  ifc.ifc_len := sizeof(buf);
  ifc.ifc_ifcu.ifcu_req := @buf[0];

  (*
  //sEn := 'eth0';
  sEn := 'en0';
    Move(M.AsAnsi(sEn).ToPointer^, ifr_mac.ifrn_name, 4);
  *)

  if(ioctl(sock_fd, SIOCGIFCONF, @ifc) < 0) then
  begin
    Exit;
  end;
  interface_num := ifc.ifc_len div sizeof(ifreq);

  while interface_num>0 do
  begin
    Dec(interface_num);

    sIP := '';
    Result := '';

    if (ioctl(sock_fd, SIOCGIFFLAGS, @buf[interface_num])<0) then
    begin
      Continue;
    end;
    (*
        if(buf[interface_num].ifr_flags & IFF_PROMISC)
            printf("Interface is in promiscuous mode\n");
    *)
    if ((buf[interface_num].ifr_ifru.ifru_flags and IFF_UP)<>0) and
       ((buf[interface_num].ifr_ifru.ifru_flags and IFF_RUNNING)<>0)and
       ((buf[interface_num].ifr_ifru.ifru_flags and IFF_LOOPBACK)=0) then
        //printf("Interface is running\n");
    else
       Continue; //printf("Interface is not running\n");

    //IP地址
    if (ioctl(sock_fd, SIOCGIFADDR, @buf[interface_num])<0) then
    begin
      Continue;
    end;
    if buf[interface_num].ifr_ifru.ifru_addr.sa_family<>AF_INET then //AF_INET6
      Continue;
    sIP := IPv4AddrToString(
      TIn4Addr(sockaddr_in(buf[interface_num].ifr_ifru.ifru_addr).sin_addr));

    //MAC地址
    if ((ioctl(sock_fd, SIOCGIFHWADDR, @buf[interface_num])) < 0) then
    begin
      //printf('mac ioctl error\n');
      Result := '';
      Continue;
    end;

    Result := Format('%02X:%02X:%02X:%02X:%02X:%02X',
      [buf[interface_num].ifr_ifru.ifru_hwaddr.sa_data[0],
       buf[interface_num].ifr_ifru.ifru_hwaddr.sa_data[1],
       buf[interface_num].ifr_ifru.ifru_hwaddr.sa_data[2],
       buf[interface_num].ifr_ifru.ifru_hwaddr.sa_data[3],
       buf[interface_num].ifr_ifru.ifru_hwaddr.sa_data[4],
       buf[interface_num].ifr_ifru.ifru_hwaddr.sa_data[5]]
    );
    Break;
  end;
    FileClose(sock_fd);
  {$ELSE}
  //其他平台(如Windows,网上已经有很多代码了,可自行补充)
sIP := '0.0.0.0'; Result := '00:00:00:00:00:00'; {$ENDIF} end; end.

由于delphi XE5/XE7...没有翻译sockios.h文件,因此此文件中的常量定义需要补充,Sockios.pas如下:

unit Sockios;

interface

const
  FIOSETOWN =$8901;
  SIOCSPGRP =$8902;
  FIOGETOWN =$8903;
  SIOCGPGRP =$8904;
  SIOCATMARK =$8905;
  SIOCGSTAMP =$8906;

  //SIOCINQ = FIONREAD;
  //SIOCOUTQ = TIOCOUTQ;

  SIOCADDRT =$890B;
  SIOCDELRT =$890C;
  SIOCRTMSG =$890D;

  SIOCGIFNAME =$8910;
  SIOCSIFLINK =$8911;
  SIOCGIFCONF =$8912;
  SIOCGIFFLAGS =$8913;
  SIOCSIFFLAGS =$8914;
  SIOCGIFADDR =$8915;
  SIOCSIFADDR =$8916;
  SIOCGIFDSTADDR =$8917;
  SIOCSIFDSTADDR =$8918;
  SIOCGIFBRDADDR =$8919;
  SIOCSIFBRDADDR =$891a;
  SIOCGIFNETMASK =$891b;
  SIOCSIFNETMASK =$891c;
  SIOCGIFMETRIC =$891d;
  SIOCSIFMETRIC =$891e;
  SIOCGIFMEM =$891f;
  SIOCSIFMEM =$8920;
  SIOCGIFMTU =$8921;
  SIOCSIFMTU =$8922;
  SIOCSIFNAME =$8923;
  SIOCSIFHWADDR =$8924;
  SIOCGIFENCAP =$8925;
  SIOCSIFENCAP =$8926;
  SIOCGIFHWADDR =$8927;
  SIOCGIFSLAVE =$8929;
  SIOCSIFSLAVE =$8930;
  SIOCADDMULTI =$8931;
  SIOCDELMULTI =$8932;
  SIOCGIFINDEX =$8933;
  SIOGIFINDEX =SIOCGIFINDEX;
  SIOCSIFPFLAGS =$8934;
  SIOCGIFPFLAGS =$8935;
  SIOCDIFADDR =$8936;
  SIOCSIFHWBROADCAST =$8937;
  SIOCGIFCOUNT =$8938;
  SIOCKILLADDR =$8939;

  SIOCGIFBR =$8940;
  SIOCSIFBR =$8941;

  SIOCGIFTXQLEN =$8942;
  SIOCSIFTXQLEN =$8943;

  SIOCETHTOOL =$8946;

  SIOCGMIIPHY =$8947;
  SIOCGMIIREG =$8948;
  SIOCSMIIREG =$8949;

  SIOCWANDEV =$894A;

  SIOCDARP =$8953;
  SIOCGARP =$8954;
  SIOCSARP =$8955;

  SIOCDRARP =$8960;
  SIOCGRARP =$8961;
  SIOCSRARP =$8962;

  SIOCGIFMAP =$8970;
  SIOCSIFMAP =$8971;

  SIOCADDDLCI =$8980;
  SIOCDELDLCI =$8981;

  SIOCGIFVLAN =$8982;
  SIOCSIFVLAN =$8983;

  SIOCBONDENSLAVE =$8990;
  SIOCBONDRELEASE =$8991;
  SIOCBONDSETHWADDR =$899;
  SIOCBONDSLAVEINFOQUERY =$8993;
  SIOCBONDINFOQUERY =$8994;
  SIOCBONDCHANGEACTIVE =$8995;

  SIOCBRADDBR =$89a0;
  SIOCBRDELBR =$89a1;
  SIOCBRADDIF =$89a2;
  SIOCBRDELIF =$89a3;

  SIOCDEVPRIVATE =$89F0;

  SIOCPROTOPRIVATE =$89E0;

implementation

end.