-1

I am authenticating an external system via a REST API. The http authentication request is of the Basic Authorization form. The response is in JSON format.

I am running this code under an AsyncTask.

  • url The GET url of the API.
  • credentials is the authentication credentials. It is a string.
  • response is the text view.
  • getmessage is a string variable.
connection = (HttpURLConnection)new URL(url).openConnection();
connection.setRequestMethod("GET");
connection.setRequestProperty("Authorization", "Basic" +  Base64.encode(credentials.getBytes(), Base64.DEFAULT ));

// I am reading the response here,
InputStreamReader in = new InputStreamReader(connection.getInputStream());
buf = new BufferedReader(in);
getmessage = buf.readLine();

// After making the request, I am updating the response to a text view on the UI thread
runOnUiThread(new Runnable() {
    @Override
    public void run() {
        response.setText(getmessage);
    }
});

I am unable to write the whole JSON data to the text view. I know that buf.readline returns the response till the end of a line. Right now I am only getting a part of the JSON response, "Not Authenticated:", but I need the whole response.

How do I update the whole JSON response to the text view (response)? If I loop the data using buf.readline in a loop then where can I use it? In which thread?

If there is anything unusual in my code. Please let me know.

gunr2171
  • 16,104
  • 25
  • 61
  • 88
oldcode
  • 1,669
  • 3
  • 22
  • 41

4 Answers4

1

I would suggest you to go trough AsyncTask

private class GetDataFromUrl extends AsyncTask<URL, Integer, String> {

    protected String doInBackground(URL... urls) {

        connection = (HttpURLConnection)new URL(url).openConnection();
        connection.setRequestMethod("GET");
        connection.setRequestProperty("Authorization", "Basic" +  Base64.encode(credentials.getBytes(), Base64.DEFAULT ));

        InputStreamReader in = new InputStreamReader(connection.getInputStream());
        buf = new BufferedReader(in);
        StringBuilder sb = new StringBuilder();

        while ((getmessage = buf.readLine()) != null) {
            sb.append(getmessage);
        }

        getmessage = sb.toString();

        return getmessage;
    }

    protected void onPostExecute(String result) {

         // Result will be available here (this runs on main thread)
         // Show result in text view here.
         response.setText(result);

    }
}

To understand better, as you call AsyncTask, doInBackground runs on the new thread created. Where the network call in placed and data is parsed. Now, we need to access the data on the main thread to update the TextView so override onPostExecute inside AsyncTask that is taking result as a parameter, from doInBackground. Also if you notice..

private class GetDataFromUrl extends AsyncTask<URL, Integer, String> 

Here URL is the type we are passing to our AsyncTask for doInBackground

String is what we passing from doInBackground to onPostExecute

and Integer is used to show progress for another method you can override i.e onProgressUpdate .. You can read more in the documentation liked above. Hope it was helpful.

Kushal Sharma
  • 5,978
  • 5
  • 25
  • 41
  • I am getting the error `Type mismatch: cannot convert from String to Void` in this line `private class GetDataFromUrl extends AsyncTask` – oldcode May 26 '15 at 09:57
  • `protected void onPostExecute(String result)` make sure you using `String result` and not `void result` int the `onPostExecute` – Kushal Sharma May 26 '15 at 09:59
  • `protected void onPostExecute(String result) { // Result will be available here (this runs on main thread) // Show result in text view here. // Something like response.setText(result); response.setText(result); }` is what i have used – oldcode May 26 '15 at 10:00
  • okay `protected String doInBackground(URL... urls) ` and make sure this is also `String` and not `void`. this should solve the mismatch of parameters – Kushal Sharma May 26 '15 at 10:02
  • 1
    There was a prob with my code, I will check and let you know. – oldcode May 26 '15 at 10:05
0

You're only reading the first line of the response with readLine(). Call that in a loop until all lines are read, and append each new line to the previous.

Gabe Sechan
  • 90,003
  • 9
  • 87
  • 127
0

Try this:

StringBuilder sb = new StringBuilder();
while ((getmessage = buf.readLine()) != null) {
    sb.append(getmessage);
}
getmessage = sb.toString();

EDITED

In your code:

getmessage = buf.readLine();

in variable getmessage reads only first line of JSON. You need to read all lines and concatenate it. How to know did you read all lines or not?

Here is what documentation says about it:

public String readLine() throws IOException

Returns:

A String containing the contents of the line, not including any line-termination characters, or null if the end of the stream has been reached

As you can see, you should invoke this method, save result of it into variable, and check, if variable is not null, then you have read line of JSON. If variable is null, then you have read all JSON into variable and you have completely JSON String.

StringBuilder used to avoid creating unnecessary objects, read more about it here

Community
  • 1
  • 1
Aleksandr
  • 4,906
  • 4
  • 32
  • 47
0

If i understood correcly, you are trying to read all response data line by line. Can you try the following?

@Override
protected String doInBackGround(...){
    . . .
    BufferedReader rd = new BufferedReader(new InputStreamReader(inputStream), 8 * 1024);
    String line = "";
    StringBuilder sb = new StringBuilder();
    while ((line = rd.readLine()) != null) {
        sb.append(line);
    }
    String response = sb.toString();
    return response;
}

@Override
protected void onPostExecute(String response){
    Textview tv = your_textview;
    your_textview.settext(whatever_part_you_get_from_response);
}

Hope this helps.

yrazlik
  • 10,411
  • 33
  • 99
  • 165
  • Ok. Which thread do I need to put this piece of code ? If I put it under the `AsynchTask` I will get a network exception – oldcode May 26 '15 at 09:06
  • @Codester you need to put this piece of code where you get the response, it should be in doInBackground – yrazlik May 26 '15 at 11:36
  • Yes, but using in doInBackground will throw an exception if we try to update the UI via a background thread. – oldcode May 26 '15 at 11:40
  • @Codester that piece of code does not update any UI element. You need to return that response from DoInBackground and in onPostExecute you can get that result and set your TextView's text. Edited the answer. – yrazlik May 26 '15 at 11:45