0

I'm attempting to send an HTTP request from an AsyncTask in Android Studio, using the code below.

protected Long doInBackground(URL... urls) {
    try {
        HttpURLConnection connection = (HttpURLConnection) urls[0].openConnection();
        connection.setRequestMethod("POST");
        connection.connect();

        byte[] loginRequestBytes = new Gson().toJson(loginRequest, LoginRequest.class).getBytes();
        connection.getOutputStream().write(loginRequestBytes);

        if (connection.getResponseCode() == HttpURLConnection.HTTP_OK) {
            ResponseBody responseBody = (ResponseBody) connection.getInputStream(); // ResponseBody extends InputStream
            loginResponse = new Gson().fromJson(responseBody.toString(), LoginResponse.class);
        }
    } catch (IOException e) {
        Log.e("HttpClient", e.getMessage(), e);
    }

    return null;
}

My ResponseBody class extends InputStream, so I thought that using

ResponseBody responseBody = (ResponseBody) connection.getInputStream();

would work, but here is the problem:

I'm getting a ClassCastException in my code, because connection.getInputStream() returns an object of type com.android.okhttp.okio.RealBufferedSource$1. Why is getInputStream not returning InputStream as per Java documentation? Is this an android-specific issue?

EDIT: I defined the ResponseBody class myself (shown below). It is not the one from okhttp, and it does extend InputStream, as far as I can tell.

public class ResponseBody extends InputStream {

    @Override
    public String toString() {
        StringBuilder stringBuilder = new StringBuilder();
        String line;

        try (BufferedReader bufferedReader = new BufferedReader(new InputStreamReader(this, "UTF-8"))) {
            while ((line = bufferedReader.readLine()) != null) {
                stringBuilder.append(line);
            }
        } catch (IOException e) {
            e.printStackTrace();
        }

        return stringBuilder.toString();
    }

    @Override
    public int read() throws IOException {
        return 0;
    }
}
cgoates
  • 55
  • 1
  • 6
  • 1
    this may help u **[Understanding getInputStream and getOutputStream](https://stackoverflow.com/questions/22563986/understanding-getinputstream-and-getoutputstream)** – AskNilesh Dec 31 '18 at 05:36
  • **FYI** the `HttpURLConnection.getInputStream()` returns an **`InputStream`** – AskNilesh Dec 31 '18 at 05:40
  • "My ResponseBody class extends InputStream, so I thought that using." -> Which response body are you referring to? This one - https://square.github.io/okhttp/3.x/okhttp/okhttp3/ResponseBody.html. This does not extend InputStream per the documentation. Would you like to take a look at this page: https://developer.android.com/reference/java/net/HttpURLConnection – Rax Dec 31 '18 at 06:14
  • @RakeshRoy I actually defined the ResponseBody class myself. It is a simple extension of InputStream (see edit) – cgoates Jan 01 '19 at 20:59

1 Answers1

1

The getInputStream() method does return an InputStream. But you are attempting to cast the result to a ResponseBody. That won't work unless the result object is an instance of a subtype of ResponseBody ... which it isn't.

Now, it is unclear which ResponseBody class you are trying to use here, but if it is okhttp3.ResponseBody (javadoc), then you can't obtain it by casting an InputStream.


I actually defined the ResponseBody class myself. It is a simple extension of InputStream (see edit), so I seems like the downward cast should work

Ah. I see.

No that won't work. You cannot cast an object to a type that it isn't. That's not what type casts do ... for reference types.

You have an instance of the anonymous inner class

  com.android.okhttp.okio.RealBufferedSource$1

which is a subtype of InputStream. You are trying to cast it to a ResponseBody which is also a subtype of InputStream. But ResponseBody is NOT a superclass or interface of the anonymous class, so the typecast cannot succeed.

I suggest that you rewrite ResponseBody to be a wrapper class for InputStream and / or use one of the solutions listed here fro extracting the contents of an InputStream to a String:

Stephen C
  • 698,415
  • 94
  • 811
  • 1,216
  • Thanks for your answer! I actually defined the ResponseBody class myself. It is a simple extension of InputStream (see edit), so I seems like the downward cast should work – cgoates Jan 01 '19 at 20:59