Search code examples
javaandroidandroid-handler

Android not getting response from handler


I am developing an app to communicate with wifi and android and I am able to send but not able to receive any response because my response is not being called.

So, the basic gist is that I am able to send data but not able to receive any response.

Here's the code for more information :-

Wifi terminal

public class wifi_terminal extends AppCompatActivity {

    ListView logListView;
    private static ChatAdapter adapter;
    private ArrayList<ChatMessage> chatHistory;
    Button sendButton;
    EditText editText;

    TCPConversation wifiCommn;
    byte[] resbyts;
    String response;
    boolean aBoolean =false;
    boolean isInDiagstate =false;
    boolean stopLiveParams =false;

    private Context context;
    private final String TAG = "WIFI Terminal Activity";
    Timer timer;
    WifiSemaphoreService wifiSemaphoreService;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_wifi_terminal);

        init();

    }

    @Override
    public void onBackPressed() {
        super.onBackPressed();
        finish();
    }

    private void init(){

        context = wifi_terminal.this;
        wifiSemaphoreService = new WifiSemaphoreService();
        wifiCommn = Singletone.getTcpConversation();
        wifiCommn.AssignHandler(mhandler);
        TCPConversation.responseCase =1;

        logListView= findViewById(R.id.loglistView);
        logListView.setItemsCanFocus(true);
        logListView.setTranscriptMode(ListView.TRANSCRIPT_MODE_ALWAYS_SCROLL);

        loadDummyHistory();

        sendButton = findViewById(R.id.sendTextid);
        editText= findViewById(R.id.editTextid);

        sendButton.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View view) {
                if(wifiCommn!=null && !wifiCommn.CheckConnection())
                {
                    String  message=editText.getText().toString();


                    if(!message.equals(""))
                    {
                        message=message+"\r\n";
                        final String finalMessage = message;
                        Thread thread = new Thread(new Runnable() {
                            @Override
                            public void run() {
                                wifiCommn.responseCase =1;

                                wifiCommn.Send(finalMessage.getBytes());
                                final String finalMessage1 = finalMessage.replace("\r\n","");
                                PrintConv( finalMessage1,true);
                                runOnUiThread(new Runnable() {
                                    @Override
                                    public void run() {
                                        editText.setText("");
                                    }
                                });
                            }
                        });
                        thread.start();

                    }
                    else
                    {
                        Toast.makeText(context, "Enter some command!", Toast.LENGTH_SHORT).show();
                    }
                }
                else
                {
                    PrintConv( "SOCKET CONN LOST",true);
                    Toast.makeText(wifi_terminal.this, "SOCKET CONN LOST", Toast.LENGTH_SHORT).show();
                }
            }
        });


    }


    Handler mhandler = new Handler(new Handler.Callback()
    {
        @Override
        public boolean handleMessage(Message message)
        {
            switch(message.what)
            {
                case 11:
                    resbyts = (byte[]) message.obj;
                    response= new String(resbyts);

                    if(response.length()>0){
                        response = response.replace("\r\n","");
                        aBoolean =true;
                        PrintConv(response,false);
                    }
                    else{

                        PrintConv("No Response",false);
                    }



                    break;

                case 22:
                    String responseString=(String) message.obj;
                    if(wifiCommn!=null && wifiCommn.CheckConnection())
                    {
                        wifiCommn.TerminateConnection();
                        PrintConv("CONNECTION LOST",false);
                    }
                    Toast.makeText(context, responseString, Toast.LENGTH_SHORT).show();
                    finish();

                    break;
            }
            return true;
        }
    });

    public void displayMessage(ChatMessage message)
    {
        adapter.add(message);
        adapter.notifyDataSetChanged();
        scroll();
    }
    private void scroll() { logListView.setSelection(logListView.getCount() - 1); }
    private void loadDummyHistory()
    {
        chatHistory = new ArrayList<>();
        ChatMessage msg = new ChatMessage();
        msg.setId(1);
        msg.setMe(false);
        msg.setDate(DateFormat.getDateTimeInstance().format(new Date()));
        chatHistory.add(msg);

        adapter = new ChatAdapter(wifi_terminal.this, new ArrayList<ChatMessage>());
        logListView.setAdapter(adapter);


    }

    public void PrintConv(final String msg, final boolean val)
    {
        runOnUiThread(new Runnable() {
            @Override
            public void run() {
                ChatMessage chatMessage = new ChatMessage();
                chatMessage.setId(11);//dummy
                chatMessage.setMessage(msg);
                chatMessage.setDate(DateFormat.getDateTimeInstance().format(new Date()));
                chatMessage.setMe(val);
                displayMessage(chatMessage);
            }
        });
    }

}```


wifi communication :- 


public class WifiComm {

private Socket socket;
Handler handler;
private boolean minusOne =false;
public static int responseCase;
private int counter;
private Timer timer;
ArrayList<Integer> arr_byte = new ArrayList<Integer>();


static  ArrayList<Byte> readMessage2 = new ArrayList<>();

public WifiComm(Socket socket1)
{
    socket = socket1;

    Receiving recievingThread = new Receiving(socket);
    recievingThread.start();
}


public  void AssignHandler(Handler mhandler)
{
    handler = mhandler;
}
static  byte[] tempBuffer = new byte[2048];

public class Receiving extends Thread
{
    private Receiving(Socket socket1) {
        socket =socket1;
    }

    @Override
    public void run()
    {


        boolean recieveData =false;
        ArrayList<Byte>  readMessage1 =  new ArrayList<>();
        StringBuilder readMessage2 = new StringBuilder();
        ArrayList<Byte> readMessage3 = new ArrayList<>();
        minusOne =false;
        tempBuffer = new byte[2048];
        while (true)
        {

            try {
                int size=0;
                size   = socket.getInputStream().read(tempBuffer);
                //  Log.e("E",new String(tempBuffer));
              //  Log.e("Socket res:",new String(tempBuffer));

                switch (responseCase)
                {
                    case 1:/*Checks response until  "\n" comes*/
                        //readMessage1 = new StringBuilder();
                        String read = new String(tempBuffer,0,size);
                        for (int i = 0; i < size; i++) {
                            if (tempBuffer[i] == ':') {
                                recieveData = true;
                                readMessage1.add(tempBuffer[i]);
                            } else if (tempBuffer[i] == '\n') {
                                readMessage1.add(tempBuffer[i]);
                                byte[] tempByte = new byte[readMessage1.size()];
                                for (int j = 0; j < readMessage1.size(); j++) {
                                    tempByte[j] = readMessage1.get(j);
                                }
                                Log.e("BC1",readMessage1.toString());
                                readMessage1 = new ArrayList<>();

                                handler.obtainMessage(11,  tempByte).sendToTarget();
                                // CollectLogData(" RX :"+new String(tempByte));
                                recieveData = false;
                                tempBuffer = new byte[2048];
                            } else {
                                if (recieveData) {
                                    readMessage1.add(tempBuffer[i]);
                                }
                            }


                        }

                        break;
                    case 2:/*Checks response until  "#" comes*/
                        String read2 = new String(tempBuffer);
                        Log.e("BC2",read2);
                        for(int i=0; i<tempBuffer.length; i++)
                        {
                            switch (read2.charAt(i))
                            {
                                case '\n':
                                    readMessage2.append(read2.charAt(i));
                                    tempBuffer = new byte[2048];
                                    byte[] temp2 =readMessage2.toString().getBytes();

                                    handler.obtainMessage(11, temp2).sendToTarget();
                                    //Log.e("BC n :",readMessage2.toString());

                                    readMessage2 = new StringBuilder();
                                    break;



                                default:
                                    readMessage2.append(read2.charAt(i));
                                    break;
                            }
                        }
                        break;

                    case 3:
                        try
                        {
                            Log.e("BC Res :",new String(tempBuffer));
                            for(int i=0 ; i<size ; i++)
                            {
                                if(size>=2 && tempBuffer[i] == 4 && tempBuffer[i-1]!=5)
                                {
                                    readMessage3.add(tempBuffer[i]);
                                    byte[] tempByte = new byte[readMessage3.size()];
                                    for(int j=0;j<readMessage3.size();j++)
                                    {
                                        tempByte[j] = readMessage3.get(j);
                                    }
                                    handler.obtainMessage(11, tempByte).sendToTarget();
                                    Log.e("BC ResBytes STN:",new String(tempBuffer));
                                    readMessage3.clear();
                                    readMessage3 = new ArrayList<>();
                                    tempBuffer = new byte[8094];
                                }
                                else {
                                    readMessage3.add(tempBuffer[i]);
                                }
                            }
                        }
                        catch (Exception e)
                        {
                            // CollectLogData(" excp @ STN hanlder :"+e.getMessage());

                            e.printStackTrace();
                        }
                        break;
                }
            }
            catch (IOException e)
            {
                minusOne=true;
                handler.obtainMessage(22, "Socket Connection Lost!").sendToTarget();
                e.printStackTrace();
                break;
            }
        }

    }
}


public static void clearBuffer()
{
    readMessage2 = new ArrayList<>();
}
public void Send(final byte[] bite)
{
    final byte[] msg;
    msg=bite;
    Thread t =  new Thread(new Runnable() {
        @Override
        public void run() {
            try
            {
                socket.getOutputStream().write(msg);
                Log.e("BlueComm SENT ",new String(msg));
            }
            catch (IOException e)
            {
                e.printStackTrace();
            }
        }
    });
    t.start();
}

public void TerminateConnection()
{
    if(socket.isConnected())
    {
        try {
            socket.close();
        } catch (IOException e) {
            e.printStackTrace();
        }
    }
}
public boolean CheckConnection()
{
    /*Something made socket disconnected*/
    return minusOne;
}

}


wifi semaphore service is just calling a constructor and does not have anything related to response.

Solution

  • That's a very unconventional way to use handlers.

    Off the top of my head, I'd guess that your message ids are colliding with system message ids. I can't find docs on how one determines a safe range for message ids; but I'd be gravely concerned about using message ID values of 11 and 22. If you REALLY have to minimize allocations, you might try very high numbers for message IDs. I suspect that if you look through logs, you'll find some very irate system handler complaining about receiving data of the wrong type. The fact that you're not getting any callbacks strongly suggests that the system isn't going to let you filter system messages, and it absolutely should not. There's probably all kinds of sensitive information flying around in the body of system messages.

    The more conventional way to use handlers in non-system code is to use Runnable's. Admittedly, there's one extra memory allocation for the Runnable; and a modest amount of extra overhead for the closure capture. But it is the way posts are usually done.

        class HostClass {
        
            private Handler handler;
        
            // calback method
            public void handleResponse(byte[] bytes) {
               // do something on the UI thread.
            }
        };
        
        class ClientClass {
    
            private Handle hostHandler; //set by the constructor.
            private HostClass host
    
            // code running on a background thread.
            private void threadProc()
            {
               byte[] receivedBytes = new byte[...];
        
               // post a runnable to the UI thread (new shiny Java 8 syntax)
               hostHandler.post(() -> {
                   // executing on the UI thread.
                   host->handleResponse(receivedBytes );      
               });
               //  or exactly the same thing, using the more verbose legacy syntax.
               hostHandler.post(new Runnable() {
                  @Override
                 public void run () {
                    host->handleResponse(receivedBytes );
                 }
               });
            }
        };
    

    Best practice would probably suggest that you use a callback interface for your callbacks from the client thread instead of exposing your entire host class, if for no other reason than to clarify what the interaction between the host and client object are.