Jump to content
qubits

MakeDWordIntoIPv4Address backwards result on Android

Recommended Posts

GStack,LocalAddress does not work on Android.

 

I am already getting WifiManager to obtain a lock, so I pulled the ip out of it.

 

    info := fWifiManager.getConnectionInfo;
    ip := MakeDWordIntoIPv4Address(info.getIpAddress);
    fIp:=ip;

 

works perfect but all backwards.

looked but, is there another routine i can run the longword thru before converting to a string or something??

 

sorry, thanks..

 

q

Share this post


Link to post
14 minutes ago, qubits said:

GStack,LocalAddress does not work on Android.

You're welcome to use the code from here:

 

https://github.com/DelphiWorlds/Multicaster/blob/master/MC.LocalAddresses.Android.pas

 

Code repeated here in case that repo ever "disappears":
 

unit MC.LocalAddresses.Android;

interface

uses
  IdStack;

procedure GetLocalAddressList(const AAddresses: TIdStackLocalAddressList);

implementation

uses
  // RTL
  System.SysUtils,
  // Android
  Androidapi.JNI.Java.Net, Androidapi.JNI.JavaTypes, Androidapi.Helpers, Androidapi.JNIBridge,
  // Indy
  IdGlobal;

procedure GetLocalAddressList(const AAddresses: TIdStackLocalAddressList);
var
  LInterfaces, LAddresses: JEnumeration;
  LInterface: JNetworkInterface;
  LAddress: JInetAddress;
  LName, LHostAddress: string;
begin
  AAddresses.Clear;
  LInterfaces := TJNetworkInterface.JavaClass.getNetworkInterfaces;
  while LInterfaces.hasMoreElements do
  begin
    LInterface := TJNetworkInterface.Wrap(JObjectToID(LInterfaces.nextElement));
    LAddresses := LInterface.getInetAddresses;
    while LAddresses.hasMoreElements do
    begin
      LAddress := TJInetAddress.Wrap(JObjectToID(LAddresses.nextElement));
      if LAddress.isLoopbackAddress then
        Continue;
      // Hack until I can find out how to check properly
      LName := JStringToString(LAddress.getClass.getName);
      LHostAddress := JStringToString(LAddress.getHostAddress);
      // Trim excess stuff
      if LHostAddress.IndexOf('%') > -1 then
        LHostAddress := LHostAddress.Substring(0, LHostAddress.IndexOf('%'));
      if LName.Contains('Inet4Address') then
        TIdStackLocalAddressIPv4.Create(AAddresses, LHostAddress, '')
      else if LName.Contains('Inet6Address') then
        TIdStackLocalAddressIPv6.Create(AAddresses, LHostAddress);
    end;
  end;
end;

end.

Note: this code hasn't been changed in some time. The "hack" can probably be done another way, and I'm pretty sure Yaroslav has told me JObjectToID isn't necessary

  • Like 1

Share this post


Link to post
Posted (edited)

flipped it around just now..

with this..

 

function SwapBytes(Value: LongWord): LongWord;
type
  Bytes = packed array[0..3] of Byte;

begin
  Bytes(Result)[0]:= Bytes(Value)[3];
  Bytes(Result)[1]:= Bytes(Value)[2];
  Bytes(Result)[2]:= Bytes(Value)[1];
  Bytes(Result)[3]:= Bytes(Value)[0];
end;

 

 

    info := fWifiManager.getConnectionInfo;
    lw:=info.getIpAddress;
    lw:=SwapBytes(lw);
    ip := MakeDWordIntoIPv4Address(lw);
    fIp:=ip;

 

 

fixed me up nicely..

 

i have already seen that getting ip from wifimanager is no longer appreciated..

so yes, i'll give that example a testing too, thanks!!

 

Indy Packet Server - work in progress

 

~q

Edited by qubits

Share this post


Link to post
Posted (edited)
15 hours ago, qubits said:

GStack,LocalAddress does not work on Android.

GStack.LocalAddress is deprecated, you should be using GStack.GetLocalAddressList() instead.

Quote

I am already getting WifiManager to obtain a lock, so I pulled the ip out of it.

Indy does not currently use WifiManager, that operates at the Android Java layer, but since Indy operates at the native layer then it uses Linux APIs instead to enumerate local IPs, namely gethostname()+getaddrinfo() (there is a TODO in IdStackVCLPosix.pas to use getifaddrs() instead, or Android's NetworkInterface or WifiManager).

Quote

 


    info := fWifiManager.getConnectionInfo;
    ip := MakeDWordIntoIPv4Address(info.getIpAddress);
    fIp:=ip;

works perfect but all backwards.

MakeDWordIntoIPv4Address() is deprecated, use MakeUInt32IntoIPv4Address() instead.  Alternatively, have a look at TIdIPAddress.IPv4(AsString) (which uses MakeUInt32IntoIPv4Address() internally).

 

But in any case, the input value is expected to be in network byte order, aka big endian, but WifiInfo.getIpAddress() returns an IPv4 address in host byte order, which may be either little endian or big endian, depending on the device.  You can use Integer.reverseBytes() to swap the IP's endian if ByteOrder.nativeOrder() is LITTLE_ENDIAN.

 

Seems Indy's own use of MakeUInt32IntoIPv4Address() may be inconsistent, some places use host byte order, some don't.

 

Also, WifiInfo.getIpAddress() is deprecated since Android 12. You should use LinkProperties now.

Edited by Remy Lebeau

Share this post


Link to post

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now
×