0

I am developing an android app which communicates with an Apache Tomcat server for sending and retrieving data. One of the servlets communicates with a python socket server running on localhost and this actually performs logical operations with the database. In my app's code, there are two functions which communicate with the server, first, that receives the response and interprets it to return just "Success" or "Failure" results (dataExchange(String)), and the second which returns the complete response as a JSON array (dataExchangeWithReturn(String))(All communication happens using JSON). The first function internally calls the second function to get the response and the second funtion calls a third function to communicate using Http post request with the server. The second function, when called directly, works perfectly. However, the first function apparently sends garbage data which results in the following error on the Python API server : 'utf-8' codec can't decode byte 0x9b in position 1: invalid start byte. When I print the String to be sent via dataExchange(String) on the Android Studio Logcat, it prints a regular string, identical to the one being sent using dataExchangeWithReturn(String). I am unable to figure out why the data being sent via the first function is unreadable to the server, while the second function works perfectly fine.

Sample Request Response at server side for dataExchangeWithReturn(String):

Request recieved from: ('127.0.0.1', 48358)
Request : {"request":"e_u_m","contact_number":"9898871289"}
Parsed string : {'request': 'e_u_m', 'contact_number': '9898871289'}


--------------
Sending Response : 
[{"name": "Employee", "email": "employeee@email.com", 
"contact_number": "1111111111", "supervisor_id": "9898871289", 
"supervisor_name": "Shivang", "no_assigned_leads": "1", 
"address_street": "Addr", "address_area": "area", "address_city": ""}]

Sample Request Response at server side for dataExchange(String):

Request recieved from: ('127.0.0.1', 48368)
'utf-8' codec can't decode byte 0x9b in position 1: invalid start byte


--------------
Sending Response : 
[{'resp': 'Wrong format'}]

The code for all three functions mentioned here is below :

public static int dataExchange(String data)
{
    int result = FAILURE;
    try
    {
        JSONArray receivedData = dataExchangeWithReturn(data);

        if(receivedData.length() == 0)
            Log.i("DataExchange","Server sent no data !");

        JSONObject dataObject = receivedData.getJSONObject(0);

        String response = dataObject.getString("response");

        if(response.equalsIgnoreCase("success"))
            result = SUCCESS;


    }
    catch (JSONException e)
    {
        Log.i("DataExchange","Server sent malformed data");
        e.printStackTrace();
    }

    return result;
}

public static JSONArray dataExchangeWithReturn(String data)
{
    JSONArray receivedData;
    String received;
    try
    {
        Log.i("SendingRequest", data);
        received = getResponse(data);

        receivedData = new JSONArray(received);
        Log.i("DataExchange", receivedData.toString());

        if(receivedData.length() == 0) {
            Log.i("ServerIssue", "Server did not sent data !");
        }

        return receivedData;


    }
    catch (JSONException e)
    {
        Log.i("DataExchangeReturn", e.getMessage());
        return new JSONArray();
    }
    catch (Exception e)
    {
        e.printStackTrace();
        return new JSONArray();
    }

}

public static String getResponse(String requestString)
{
    try
    {
        String data = "/api-sample/call";
        URL connectionUrl = new URL("http", MainActivity.SERVER_IP_ADDR, MainActivity.SERVER_PORT, data);
        HttpURLConnection conn = (HttpURLConnection) connectionUrl.openConnection();
        conn.setRequestMethod("POST");
        conn.setRequestProperty("Content-Type", "application/json");

        // Writing JSON data
        conn.setDoOutput(true);
        OutputStream osw = conn.getOutputStream();
        osw.write(requestString.getBytes(StandardCharsets.UTF_8));

        osw.close();

        // Reading response
        StringBuilder response = new StringBuilder();
        BufferedReader br = new BufferedReader(new InputStreamReader(conn.getInputStream()));
        String temp;
        while((temp = br.readLine()) != null)
        {
            response.append(temp);
        }

        br.close();

        // System.out.println(response.toString());
        return response.toString();
    }
    catch(Exception e)
    {
        e.printStackTrace();
        return new String();
    }
}

Also note that before setting up the Apache Tomcat server, I was using simple Socket to Socket TCP communication in which all these functions were working perfectly fine.

  • This may help: https://stackoverflow.com/questions/9069799/android-json-charset-utf-8-problems. How do you generate the string? –  Feb 25 '19 at 18:02
  • I generate the String using `JSONObject.toString()` on the JSON instances. – Shivang Gangadia Feb 25 '19 at 18:09
  • also, why could the first function be giving error when it actually uses the second function ? Both functions are used as communication media for a whole lot of other functions who use the same json format – Shivang Gangadia Feb 25 '19 at 18:17
  • The answer to that is in the actual strings - not the code since as you point out is the same. If possible post the strings (or just the first one) (it should preserve the encoding?) and often can be examined using hex editor for strangeness. –  Feb 25 '19 at 18:20
  • String as printed in logcat : `I/SendingRequestDE: {"request":"a_l_e","contact_number_lead":"9427435661","contact_number_employee":"1111111111","next_follow_up_date":"20190312","next_follow_up_action":"na"} ` – Shivang Gangadia Feb 25 '19 at 18:34

1 Answers1

0

I solved the problem, but not from the root cause. On the server side, I printed the received response in the form of bytes and figured that the first function was sending an non - decodable byte before the actual data. So instead of passing decoded string to the logical function, I used another function which picks data from the byte string between the first '{' and last '}'. This way, Python does not need to decode the incoming message at all, hence it won't produce errors.