12

I am attempting to use the Okhttp library to connect my android app to my server via API.

My API call is happening on a button click and I am receiving the following android.os.NetworkOnMainThreadException. I understand that this is due the fact I am attempting network calls on the main thread but I am also struggling to find a clean solution on Android as to how make this code use another thread (async calls).

@Override
public void onClick(View v) {
    switch (v.getId()){
        //if login button is clicked
        case R.id.btLogin:
            try {
                String getResponse = doGetRequest("http://myurl/api/");
            } catch (IOException e) {
                e.printStackTrace();
            }
            break;
    }
}

String doGetRequest(String url) throws IOException{
    Request request = new Request.Builder()
            .url(url)
            .build();

    Response response = client.newCall(request).execute();
    return response.body().string();

}

Above is my code, and the exception is being thrown on the line

Response response = client.newCall(request).execute();

I've also read that Okhhtp supports Async requests but I really can't find a clean solution for Android as most seem to use a new class that uses AsyncTask<>?

halfer
  • 19,824
  • 17
  • 99
  • 186
jjharrison
  • 841
  • 4
  • 19
  • 33

1 Answers1

37

To send an asynchronous request, use this:

void doGetRequest(String url) throws IOException{
    Request request = new Request.Builder()
            .url(url)
            .build();

    client.newCall(request)
            .enqueue(new Callback() {
                @Override
                public void onFailure(final Call call, IOException e) {
                    // Error

                    runOnUiThread(new Runnable() {
                        @Override
                        public void run() {
                            // For the example, you can show an error dialog or a toast
                            // on the main UI thread
                        }
                    });
                }

                @Override
                public void onResponse(Call call, final Response response) throws IOException {
                    String res = response.body().string();

                    // Do something with the response
                }
            });
}

& call it this way:

case R.id.btLogin:
    try {
        doGetRequest("http://myurl/api/");
    } catch (IOException e) {
        e.printStackTrace();
    }
    break;
Mohammed Aouf Zouag
  • 17,042
  • 4
  • 41
  • 67
  • 2
    There is no need in `try {...} catch (IOException e) {...}` and of course `doGetRequest(String url) throws IOException{` – Vlad Feb 13 '16 at 03:41
  • @V.Kalyuzhnyu Try.. catch will handle the error thrown by the `doGetRequest`'s `IOException` – kirtan403 Aug 11 '16 at 06:43
  • 1
    `String res = response.body().string();` will block if the response body is large and not available immediately (so one might want to do it in a separate threadpool for blocking operations). Also – it’d be good idea to wrap it in `try (Response res = response)` to ensure the response is closed, if eg. there is no body in it. – silmeth Nov 15 '17 at 10:47