Pergunta

I made one android application that needs to connect one local database provided by wamp server. First using the android virtual device (AVD) my IP to connect the server first time used to be: 10.0.2.2. My AVD was connecting fine, but when I tried to connect direct on my device he wasn't finding the local server with this 10.0.2.2 IP. At this point I've changed IP to 192.168.1.5 which was my LAN cable IP, both device and AVD were running without problems... but sometimes I need to change my connection to wifi, which changes the IP..also, I realized that fix one IP in my source code will be a problem to release the android app, since other people will have other LAN IP address.

To solve this problem, I've started to look for a solution, such as acquire the LAN IP dynamically. For this purpose I built this Java application as test:

public class test {
    public static void main(String[] args) throws Exception
    {
        String roundHost = null;
        Enumeration<NetworkInterface> n = NetworkInterface.getNetworkInterfaces();
        for (; n.hasMoreElements();)
        {
            NetworkInterface e = n.nextElement();

            Enumeration<InetAddress> a = e.getInetAddresses();
            for (; a.hasMoreElements();)
            {
                InetAddress addr = a.nextElement();
                if (addr.isSiteLocalAddress()){
                    String pureHost = addr.getByName(addr.getHostName()).toString();
                    roundHost = addr.getHostAddress();
                    pureHost = pureHost.substring(addr.getHostName().length()+1);

                    if(!roundHost.equals(pureHost))
                        break;
                }
            }
        }
        System.out.println(roundHost);
    }
}

As output, this java application gives me my correct LAN wifi IP or even my LAN cable IP which is 192.168.1.3 or 192.168.1.7. From here I made one "IPParser" to use on my android app:

public class IPParser {

    String pureHost, roundHost = null;

    public IPParser() throws UnknownHostException{

        Enumeration<NetworkInterface> n = null;
        try {
            n = NetworkInterface.getNetworkInterfaces();
        } catch (SocketException e1) {
            e1.printStackTrace();
        }
        for (; n.hasMoreElements();)
        {
            NetworkInterface e = n.nextElement();

            Enumeration<InetAddress> a = e.getInetAddresses();
            for (; a.hasMoreElements();)
            {
                InetAddress addr = a.nextElement();
                if (addr.isSiteLocalAddress()){
                    pureHost = addr.getByName(addr.getHostName()).toString();
                    roundHost = addr.getHostAddress();
                    pureHost = pureHost.substring(addr.getHostName().length()+1);

                    if(!roundHost.equals(pureHost))
                        break;
                }
            }
        }
     }

     public String returnIp() {
         return roundHost;
     }
}

As you can see it's pretty similar; the difference is just some structural changes to adapt the needed syntax. And now comes the real problem: When I try to run this parser inside my AVD, my ip is 10.0.2.15 and running directly in my device the ip return is 192.168.1.6 - Obviously the android app is crashing because it can't find the local server to connect.

My IP config information: My IP config information

I'm not an expert in network, so I ask, take it easy and if I said something technically wrong or adjacents please edit and correct me..finally I ask:

Why this is happening and what's possible to do to solve this problem?

Foi útil?

Solução

The IPs you mention (10.0.2.2 and 192.168.1.5) are from two different networks, which makes sense since the documentation states that:

Each instance of the emulator runs behind a virtual router/firewall service that isolates it from your development machine's network interfaces and settings and from the internet. An emulated device can not see your development machine or other emulator instances on the network. Instead, it sees only that it is connected through Ethernet to a router/firewall.

The virtual router for each instance manages the 10.0.2/24 network address space — all addresses managed by the router are in the form of 10.0.2., where is a number. Addresses within this space are pre-allocated by the emulator/router as follows:

What this means is that when using the AVD there is a virtual network that is created which the device and the computer are part of. In your case your local machine takes the address 10.0.2.2 in this virtual network and the AVD 10.0.2.15. But when you connect directly through your device, the computer's IP (as well as the device's) is in the LAN's address space (i.e. 192.168.1.5 and 192.168.1.6).

The code you posted resolves the IP address of the host, but if you want the device to resolve automatically the server's IP address and you can guarantee they will always be both connected to the same LAN, then you can use multicast UDP messages (I didn't find a really good source but you can start here, here and here). This type of communication sends a UDP datagram to the network to a specific multicast IP address and port, to which other devices in the network are listening. I've used this scheme in an Android application that needed to find a computer in the network so I know for a fact that it works. I can share some code if you need to.


EDIT

The following snippets of code are the ones that implement the search of computers in the network. The Android application this was used in could control the mouse and keyboard of any computer in the network that had the server application running.

Android Client

public void findComputers(View v) {
    try {
        int port = 4444;
        String multicastAddr = "224.168.1.0";

        DatagramSocket socket = new DatagramSocket(port);
        socket.setSoTimeout(300);
        InetAddress group = InetAddress
                .getByName(multicastAddr);
        DatagramPacket packet = new DatagramPacket(new byte[] { 1 }, 1,
                group, port);
        socket.send(packet);

        // Give time to the servers to respond
        Thread.sleep(100);

        while (true) {
            try {
                // Listen for the servers responses
                byte[] buffer = new byte[256];
                packet = new DatagramPacket(buffer, buffer.length);
                socket.receive(packet);
                String data = new String(packet.getData());
                // Information sent from servers include the host's name
                // and IP addres separated by a semicolon.
                String[] parts = data.split(";");

                // Add a server to the result list.
                Computer computer = new Computer(parts[1].trim(),
                        parts[0].trim());
                this.computers.put(computer.getName(), computer);
            } catch (InterruptedIOException ex) {
                break;
            }
        }
        socket.close();
    } catch (SocketException e) {
        e.printStackTrace();
    } catch (IOException e) {
        e.printStackTrace();
    } catch (InterruptedException e) {
        e.printStackTrace();
    }

    String output = "No computers found.";

    if (this.computers.size() > 0) {
        output = this.computers.size() + " computer(s) found.";
        this.fillComputers();
    }

    Toast.makeText(this, output, Toast.LENGTH_SHORT).show();
}

Server

import java.io.IOException;
import java.net.DatagramPacket;
import java.net.InetAddress;
import java.net.MulticastSocket;

/**
 * Receives UDP broadcast packets in the default port requesting for server name
 * and IP, broadcasting the information in return.
 * 
 * @author jfacorro
 * 
 */
public class NameResolverService extends Thread {

    private InetAddress localAddress = null;
    private byte[] localAddressData = null;
    private MulticastSocket socket = null;
    private boolean exit = false;

    public NameResolverService() {
    }

    public void exit() {
        this.exit = true;
        this.socket.close();
    }

    @Override
    public void run() {
        try {
            int port = 4444;
            String multicastAddr = "224.168.1.0";

            // Get current address
            this.localAddress = InetAddress.getLocalHost();

            this.socket = new MulticastSocket(port);
            InetAddress group = InetAddress.getByName(multicastAddr);
            this.socket.joinGroup(group);
            this.localAddressData = (this.localAddress.getHostAddress() + ";" + this.localAddress
                    .getHostName()).getBytes();

        } catch (IOException ex) {
            this.notified.notified(ex.getMessage());
            ex.printStackTrace();
        }

        while (!this.exit) {
            try {
                byte[] buffer = new byte[1];
                DatagramPacket packet = new DatagramPacket(buffer,
                        buffer.length);

                socket.receive(packet);

                InetAddress address = packet.getAddress();
                int port = packet.getPort();
                packet = new DatagramPacket(this.localAddressData,
                        this.localAddressData.length, address, port);

                socket.send(packet);

            } catch (IOException e) {
                if(!this.exit)
                    e.printStackTrace();
            }
        }

        this.socket.close();
    }
}
Licenciado em: CC-BY-SA com atribuição
Não afiliado a StackOverflow
scroll top