Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Android illegalstatexception

I am trying to send UDP packets with Android to a server written in C# on my computer. When I run the app on my phone, I get an illegal state exception. I think it may have something to do with performing network operations on the main activity, but I'm not sure how to resolve that problem. Here is my client:

public class MainActivity extends Activity {

WifiManager wifi;
InetAddress dev_ip;
final int serverPort = 31337;
Thread drawThread = new Thread(new drawer());

@Override
public void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.activity_main);

    //set up wifi and connection
    wifi = (WifiManager) this.getSystemService(Context.WIFI_SERVICE);
    WifiInfo info = wifi.getConnectionInfo();
    int ip = info.getIpAddress();        
    String ipaddr = (ip & 0xff) + "." + (ip >> 8 & 0xff) + "." + (ip >> 16 & 0xff) + "." + (ip >> 24 & 0xff);

    try {
        dev_ip = InetAddress.getByName(ipaddr);
    } catch (UnknownHostException e) {
        Toast.makeText(this, "host error", Toast.LENGTH_LONG).show();
    }

    if (!wifi.isWifiEnabled())
       wifi.setWifiEnabled(true);

    Toast.makeText(this, "IP: " + ipaddr, Toast.LENGTH_LONG).show();     
}

@Override
public boolean onCreateOptionsMenu(Menu menu) {
    getMenuInflater().inflate(R.menu.activity_main, menu);
    return true;
}

public void draw(View view) throws IOException, SocketException
{
    drawThread.start();
}

public class drawer implements Runnable {

    public void run() {

        //transmit data
        try {
            DatagramSocket socket = new DatagramSocket(serverPort, /*myip*/);
            String test_data = "It works!";
            byte btest[] = new byte[50];
            btest = test_data.getBytes();
            DatagramPacket p1 = new DatagramPacket(btest, btest.length, /*myip*/, serverPort);
            socket.send(p1);
            socket.close();
        }   
        catch (IOException e) {
        }
    }
}
}

LogCat:

07-27 00:10:17.155: D/CLIPBOARD(1711): Hide Clipboard dialog at Starting input: 

finished by someone else... !
07-27 00:10:18.020: W/System.err(1711): java.net.BindException: bind failed: EADDRNOTAVAIL (Cannot assign requested address)
07-27 00:10:18.020: W/System.err(1711):     at libcore.io.IoBridge.bind(IoBridge.java:89)
07-27 00:10:18.020: W/System.err(1711):     at java.net.PlainDatagramSocketImpl.bind(PlainDatagramSocketImpl.java:68)
07-27 00:10:18.020: W/System.err(1711):     at java.net.DatagramSocket.createSocket(DatagramSocket.java:133)
07-27 00:10:18.020: W/System.err(1711):     at java.net.DatagramSocket.<init>(DatagramSocket.java:95)
07-27 00:10:18.020: W/System.err(1711):     at com.ls.styloid.MainActivity$drawer.run(MainActivity.java:67)
07-27 00:10:18.025: W/System.err(1711):     at java.lang.Thread.run(Thread.java:856)
07-27 00:10:18.025: W/System.err(1711): Caused by: libcore.io.ErrnoException: bind failed: EADDRNOTAVAIL (Cannot assign requested address)
07-27 00:10:18.025: W/System.err(1711):     at libcore.io.Posix.bind(Native Method)
07-27 00:10:18.025: W/System.err(1711):     at libcore.io.ForwardingOs.bind(ForwardingOs.java:39)
07-27 00:10:18.025: W/System.err(1711):     at libcore.io.IoBridge.bind(IoBridge.java:87)
07-27 00:10:18.025: W/System.err(1711):     ... 5 more
07-27 00:10:42.090: D/CLIPBOARD(1711): Hide Clipboard dialog at Starting input: finished by someone else... !
07-27 00:11:30.150: W/System.err(2535): java.net.BindException: bind failed: EADDRNOTAVAIL (Cannot assign requested address)
07-27 00:11:30.155: W/System.err(2535):     at libcore.io.IoBridge.bind(IoBridge.java:89)
07-27 00:11:30.155: W/System.err(2535):     at java.net.PlainDatagramSocketImpl.bind(PlainDatagramSocketImpl.java:68)
07-27 00:11:30.155: W/System.err(2535):     at java.net.DatagramSocket.createSocket(DatagramSocket.java:133)
07-27 00:11:30.155: W/System.err(2535):     at java.net.DatagramSocket.<init>(DatagramSocket.java:95)
07-27 00:11:30.155: W/System.err(2535):     at com.ls.styloid.MainActivity$drawer.run(MainActivity.java:67)
07-27 00:11:30.155: W/System.err(2535):     at java.lang.Thread.run(Thread.java:856)
07-27 00:11:30.155: W/System.err(2535): Caused by: libcore.io.ErrnoException: bind failed: EADDRNOTAVAIL (Cannot assign requested address)
07-27 00:11:30.155: W/System.err(2535):     at libcore.io.Posix.bind(Native Method)
07-27 00:11:30.155: W/System.err(2535):     at libcore.io.ForwardingOs.bind(ForwardingOs.java:39)
07-27 00:11:30.155: W/System.err(2535):     at libcore.io.IoBridge.bind(IoBridge.java:87)
07-27 00:11:30.155: W/System.err(2535):     ... 5 more
07-27 00:11:36.515: D/CLIPBOARD(2535): Hide Clipboard dialog at Starting input: finished by someone else... !

EDIT: There seem to be numerous problems with the server that I didn't notice before. They started happening when I rewrote the listener according to one of the answers. I sometimes get a "Cannot access a disposed object" error with label3, a socket exception 0x80004005, and still no packets received. However, when checking the socket state it appears to be readable. I probably screwed up the threading, help me fix this please. Server:

public partial class Form1 : Form
    {
        Socket listener;
        Thread udp_listener;

        public Form1()
        {
            InitializeComponent();

            //set up listener thread
            udp_listener = new Thread(listen);
            udp_listener.IsBackground = true;
            udp_listener.Start();
        }

        protected override void OnFormClosing(FormClosingEventArgs e)
        {
            base.OnFormClosing(e);
            listener.Close();
            udp_listener.Join();
        }

        private void listen()
        {
            //set up UDP
            const int serverPort = 31337;
            bool terminate = false;
            IPHostEntry iphost = Dns.GetHostEntry(Dns.GetHostName());
            IPAddress ipaddr = iphost.AddressList[0];
            IPEndPoint endpoint = new IPEndPoint(ipaddr, serverPort);
            listener = new Socket(AddressFamily.InterNetwork, SocketType.Dgram, ProtocolType.Udp);
            label3.Text = ipaddr.ToString();

            try
            {
                do
                {
                    byte[] buffer = new byte[100];
                    listener.Receive(buffer);
                    label3.Text = "Connected";
                    label3.ForeColor = Color.Red;
                    label3.Text = Encoding.UTF8.GetString(buffer);
                }
                while (!terminate);
            }
            catch (Exception e)
            {
                MessageBox.Show(e.ToString());
            }
            finally
            {
                listener.Close();
            }

            listener.Close();
        }
    }

EDIT2:

I tried making a client with C# on my computer. The packet was sent but my server did not receive anything.

EDIT3: Server works fine now, but the android app refuses to run. Here's the code:

   package com.tests.contest;

import java.io.BufferedReader;
import java.io.BufferedWriter;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.OutputStreamWriter;
import java.net.Socket;
import java.net.UnknownHostException;
import android.app.Activity;

public class MainActivity extends Activity {
      private Socket sock;
      private BufferedWriter out;
      private Thread thrd;

      @Override
      public void onResume() {
        super.onResume();
        thrd = new Thread(new Runnable() {
            public void run() {
              while (!Thread.interrupted()) {
                runOnUiThread(new Runnable() {
                  @Override
                  public void run() {
                      try {
                        sock = new Socket("THEIP", 31337);
                    } catch (UnknownHostException e1) {
                        // TODO Auto-generated catch block
                        e1.printStackTrace();
                    } catch (IOException e1) {
                        // TODO Auto-generated catch block
                        e1.printStackTrace();
                    }
                      try {
                        out = new BufferedWriter(new OutputStreamWriter(sock
                              .getOutputStream()));
                        out.write("WORKS");
                    } catch (IOException e) {
                        // TODO Auto-generated catch block
                        e.printStackTrace();
                    }
                  }
                });
              }
            }
          });
          thrd.start();
      }

      @Override
      public void onPause() {
        super.onPause();
        if (thrd != null)
          thrd.interrupt();
        try {
          if (sock != null) {
            sock.getOutputStream().close();
            sock.getInputStream().close();
            sock.close();
          }
        } catch (IOException e) {}
        thrd = null;
      }

      /*private void sendText() {
        String text = "HI";
        try {
          out.write(text + "\n");
          out.flush();
        } catch (IOException e) {}
      }*/
    }

The problem occurs because I'm running network operations on the main thread, which I am clearly not doing.

like image 274
Lockhead Avatar asked Jul 26 '12 19:07

Lockhead


People also ask

How do I handle IllegalStateException on Android?

In order to avoid java. lang. IllegalStateException in Java main Thread we must ensure that any method in our code cannot be called at an illegal or an inappropriate time. In the above example if we call start() method only once on thread t then we will not get any java.

How do I fix IllegalStateException?

To avoid the IllegalStateException in Java, it should be ensured that any method in code is not called at an illegal or inappropriate time. Calling the next() method moves the Iterator position to the next element.

What is the difference between IllegalArgumentException and IllegalStateException?

The IllegalArgumentException is thrown in cases where the type is accepted but not the value, like expecting positive numbers and you give negative numbers. The IllegalStateException is thrown when a method is called when it shouldn't, like calling a method from a dead thread.

What is IllegalStateException Java?

public class IllegalStateException extends RuntimeException. Signals that a method has been invoked at an illegal or inappropriate time. In other words, the Java environment or Java application is not in an appropriate state for the requested operation.


2 Answers

The exception is telling you exactly what to do: create the Socket object in a separate Thread. You can use an AsyncTask for this as well.

The reasoning behind not allowing Sockets on the main UI thread is that it can cause the app to get the dreaded Application Not Responding message from waiting for a Socket.

edit: http://thinkandroid.wordpress.com/2010/03/27/incorporating-socket-programming-into-your-applications/

You can just skip down to the client example since you already have a desktop server.

edit2: Since I happen to also be working on a C# server for my Android app, here is how my desktop app creates a listener Socket:

IPHostEntry ipHostInfo = Dns.GetHostEntry(Dns.GetHostName());
IPAddress ipAddress = ipHostInfo.AddressList[0];
IPEndPoint localEndPoint = new IPEndPoint(ipAddress, 27015); //Port 27015
Socket listener = new Socket(AddressFamily.InterNetwork,
    SocketType.Stream, ProtocolType.Tcp); // Create a TCP/IP socket.

I'm almost certain that the problem lies within your server/network. The Android code to send out a simple UDP packet looks correct. You might also want to try connecting over localhost or 127.0.0.1 by writing a simple C# client program.

edit 3:

  • Copy and paste the code here into a new C# project and run the code: http://msdn.microsoft.com/en-us/library/fx6588te
  • Take this Android code and make a new project: http://pastebin.com/a0veStT0 and http://pastebin.com/Wv93U1FK

With this basic app you should be able to connect to the server after you put the correct IP address in. Pressing Send will send some bytes to the server. Use this to make sure that your connection is working. I've confirmed that it works on my end. If this works, then I would open a new SO question for your server issues, otherwise something is wrong with your network configuration.

like image 90
telkins Avatar answered Oct 04 '22 07:10

telkins


I think that the problem comes from the do while loop because you are attempting to modifiy a UI component ( label3 ) in the loop which is by the way a infinite loop sins the terminate variable is always false. Try getting the code witch modifies the UI ( label3.*) out of the loop.

like image 39
zizoujab Avatar answered Oct 04 '22 06:10

zizoujab