0

I am having some major problems with my new project. I have a client app on my PC that is sending a simple String of data to the phone over the WiFi LAN connection. When recieved it should be split to its component parts and then an SMS sent.

I'll be honest, this is my first Android project but I'm determined to get this working.

When I send the command from my client, the app is failing and being caught in the catch labeled with Log.w("ServerRunnable", "Exception 2"); below. Id really appreciate some advice on this? I don't know why it won't work!

public class ListeningService extends Service {

private int iNotificationIcon = 1;
Handler hHandler;
Thread thServerThread = null;
private ServerSocket oServerSocket = null;

private static final String _S_DELIMITER = "##t2tDELIMITER##";
private static final int _I_SERVER_PORT = 50001;

@Override
public IBinder onBind(Intent arg0) {
    Toast.makeText(this, "Service Bound", Toast.LENGTH_LONG).show();
    return null;
}

@Override
public int onStartCommand(Intent oIntent, int iFlags, int iStartID) {
    addNotification(getString(R.string.app_name), "Server listening on xxx.xxx.xxx.xxx:ppppp", iNotificationIcon, true);

    /* Server Threading */      
    /*hHandler = new Handler() {
        @Override
        public void handleMessage(Message mMsg) {
            // TODO Auto-generated method stub
            showMessageBox(mMsg.getData().toString(), "Data Bundle", true);
            super.handleMessage(mMsg);
        }
    };*/

    this.thServerThread = new Thread(new ServerRunnable());
    //showToast("Thread Created but not started yet", false);
    this.thServerThread.start();

    return START_STICKY;
}
public class ServerRunnable implements Runnable  {
    public ServerRunnable() {
        /**/
    }

    public void run() {
        Socket oSocket;
        try {
            oServerSocket = new ServerSocket(_I_SERVER_PORT);
            Log.w("ServerRunnable", "oServerSocket created");
        } catch (Exception e) {
            e.printStackTrace();
            Log.w("ServerRunnable", "Exception 1");
        }
        while (!Thread.currentThread().isInterrupted()) {
            try {
                oSocket = oServerSocket.accept();
                CommsThread commThread = new CommsThread(oSocket);
                new Thread(commThread).start();
                Log.w("ServerRunnable", "oSocket created");
            } catch (Exception e) {
                e.printStackTrace();
                Log.w("ServerRunnable", "Exception 2");
            }
        }
    }       
}

public class CommsThread implements Runnable {

    private Socket oClientSocket;
    private BufferedReader brInput;

    public CommsThread(Socket oSocket) {
        this.oClientSocket = oSocket;
        try {
            this.brInput = new BufferedReader(new InputStreamReader(this.oClientSocket.getInputStream()));
        } catch (IOException e) {
            e.printStackTrace();
        }
    }

    public void run() {
        while (!Thread.currentThread().isInterrupted()) {
            try {
                String sRead = brInput.readLine();
                //hHandler.post(new SendSMSThread(sRead));
            } catch (IOException e) {
                e.printStackTrace();
            } catch (Exception e) {
                e.printStackTrace();
            }
        }
    }
}

public class SendSMSThread implements Runnable {

    String sPhoneNumber = "";
    String sTextMessage = "";
    int iMessageLength = 0;

    public SendSMSThread(String sRead) {

        /* Received */
        //showMessageBox(sRead, "Raw Data", true);

        int iDelimiterStart = sRead.indexOf(_S_DELIMITER);
        int iDelimiterLen = _S_DELIMITER.length();

        /* Split the input */
        sPhoneNumber = sRead.substring(0, (iDelimiterStart+1));
        sTextMessage = sRead.substring((iDelimiterStart + iDelimiterLen));

        //showMessageBox(sTextMessage, sPhoneNumber, true);
    }

    public void run() {
        if ((sPhoneNumber.length() == 11) && (sTextMessage.length() > 0)) {
            sendSMS(sPhoneNumber, sTextMessage, true);
        }
    }
}

StackTrace:

01-23 23:48:42.673: W/ServerRunnable(15567): Exception 2
01-23 23:48:42.673: W/StackTrace(15567): java.lang.NullPointerException
01-23 23:48:42.673: W/StackTrace(15567):    at uk.co.tip2tail.wintextserver.ListeningService$ServerRunnable.run(ListeningService.java:78)
01-23 23:48:42.673: W/StackTrace(15567):    at java.lang.Thread.run(Thread.java)

This only seems to be occuring after I have stopped and restarted the service. The initial running of the service seems to be ok, although it still does nothing when the data is recieved! Im totally lost. Every book ive read has code like i do but this just wont work!

Any help appreciated.

tip2tail
  • 463
  • 1
  • 6
  • 23
  • 1
    Can you include the stack trace please? – Andrew Fielden Jan 23 '14 at 23:30
  • Hi @AndrewFielden updated above :) – tip2tail Jan 23 '14 at 23:52
  • Err, and which is line 78? Obviously you are dereferencing a null reference at that line. Probably because of your strange practice of catching exceptions and then letting the code proceed as though they didn't happen. Was there a prior exception? Creating the ServerSocket for example? – user207421 Jan 24 '14 at 00:06
  • OMG, you're starting 4 (if I'm not wrong) new Threads in your app. Are you using the Deep Blue Android device or something? :) You could easily get rid of `CommsThread`, for example, it's perfectly fine to read the lines out of clientSocket within the same thread. Also I'm not sure if you really need to re-invent the wheel in your app. Maybe it's worth lookting at GCM - starndard async messaging for Android? – injecteer Jan 24 '14 at 00:21
  • @injecteer No it isn't, unless you're only expecting to handle one client. Multiple clients require multiple threads. – user207421 Jan 24 '14 at 00:24
  • it is. It's perfectly fine with multiple clientSockets, because `accept()` returns a fresh new Socket instance for each incoming connection. The problem with the code above, is that the same field `oSocket' gets overwritten each time. – injecteer Jan 24 '14 at 00:30
  • @injecteer No it isn't. One thread can only service one client at a time. If you process client I/O in the accept thread, the other clients don't get any service until the first one disconnects. Have you ever tried it? – user207421 Jan 24 '14 at 00:36
  • In general you're right... for high-load server environment. But do you really expect, that an android app will have to be able to handle lots of big client requests simultaneously, or will those be rather small data chunks (the guy wants to send SMS á 160 letters long) which come not too often? In that case I don't see the potential blocking by response processing as a critical issue. The time of socket creation (which IS blocking) should be greater than that, and you can not do anything here. – injecteer Jan 24 '14 at 00:57
  • @injecteer I don't know what to expect, and neither do you. TCP servers are almost invariably written to be concurrent when handling clients, and for you to state otherwise without knowing anything about the actual application is just plain wrong, as well as completely irrelevant to the actual question. NB The 'time of socket creation' is insignificant compared to a TCP session time that could extend into hours, or weeks. You don't seem to know much about it frankly. – user207421 Jan 24 '14 at 01:06
  • 1
    Anyway, back to the original question. Best thing to do here, is to set a breakpoint at line 78, and run your app in debug mode. This will help you determine why the null pointer exception is happening. – Andrew Fielden Jan 24 '14 at 10:58
  • @AndrewFielden et all Thanks for this so far. Im still a bit confused. Am I going about this the right way of have I over complicated things? – tip2tail Jan 24 '14 at 19:28
  • You're ignoring the question I asked. Which is line 78? What happens when you fixed your exception handling as I suggested yesterday? – user207421 Jan 24 '14 at 21:34
  • Sorry @EJP I'm not ignoring the question but I have not been back on my development system sice last night. Line 78 is `oServerSocket = new ServerSocket(_I_SERVER_PORT);`. I don't really know how to adjust the error handling so I have done nothing with that yet. – tip2tail Jan 24 '14 at 22:14
  • It can't be. Recompile and retest. What you have to do with the exception handling is move all code that's after a catch block into the try block that belongs to the catch. Repeat until closure. – user207421 Jan 25 '14 at 02:25

1 Answers1

0

I had over complicated things.

I have since went back and completely changed the code for the Service, only running 2 Threads.

And it now works!

Thank you for the constructive comments above. :)

tip2tail
  • 463
  • 1
  • 6
  • 23