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.
好不容易活着

浙公网安备 33010602011771号