John Alvarez John Alvarez - 17 days ago 10
Android Question

App crashing when I try and return http response

I have made a java class to handle HTTP post requests and it sends back the result in string form. For some reason when I send the request I can print the response to the log but when return the string of the response to update the UI in the method my app crashes. Could any one explain whats happening here? I am trying to get better at java so pointing out any other bad practices would be appreciated .

log:

I/OpenGLRenderer: Initialized EGL, version 1.4
D/OpenGLRenderer: Swap behavior 1
D/NetworkSecurityConfig: No Network Security Config specified, using platform default
D/OKHTTP3: Request body created
D/OKHTTP3: Request body created 2
D/OKHTTP3: Got Response
D/OKHTTP3: {
"failed": "Asset already exists"
}
E/AndroidRuntime: FATAL EXCEPTION: AsyncTask #1
Process: com.example.john.okhttp, PID: 3166
java.lang.RuntimeException: An error occurred while executing doInBackground()
at android.os.AsyncTask$3.done(AsyncTask.java:318)
at java.util.concurrent.FutureTask.finishCompletion(FutureTask.java:354)
at java.util.concurrent.FutureTask.setException(FutureTask.java:223)
at java.util.concurrent.FutureTask.run(FutureTask.java:242)
at android.os.AsyncTask$SerialExecutor$1.run(AsyncTask.java:243)
at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1133)
at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:607)
at java.lang.Thread.run(Thread.java:761)
Caused by: java.lang.IllegalStateException: closed
at okhttp3.internal.http.Http1xStream$FixedLengthSource.read(Http1xStream.java:374)
at okio.Buffer.writeAll(Buffer.java:993)
at okio.RealBufferedSource.readByteArray(RealBufferedSource.java:106)
at okhttp3.ResponseBody.bytes(ResponseBody.java:128)
at okhttp3.ResponseBody.string(ResponseBody.java:154)
at com.example.john.okhttp.PostEx.doPostRequest(PostEx.java:40)
at com.example.john.okhttp.MainActivity$Requesting.doInBackground(MainActivity.java:59)
at com.example.john.okhttp.MainActivity$Requesting.doInBackground(MainActivity.java:51)
at android.os.AsyncTask$2.call(AsyncTask.java:304)
at java.util.concurrent.FutureTask.run(FutureTask.java:237)
at android.os.AsyncTask$SerialExecutor$1.run(AsyncTask.java:243) 
at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1133) 
at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:607) 
at java.lang.Thread.run(Thread.java:761) 
Application terminated.


the code from both java files will be posted below:

MainActivity.java:

package com.example.john.okhttp;


import android.os.AsyncTask;
import android.support.v7.app.AppCompatActivity;
import android.os.Bundle;
import android.util.Log;
import android.view.View;
import android.widget.Button;
import android.widget.EditText;
import android.widget.TextView;
import org.json.JSONObject;
import okhttp3.OkHttpClient;
import okhttp3.Request;



public class MainActivity extends AppCompatActivity {
private Button btnSendHttpRequest;
private EditText etJsonResponse;
private TextView View;
private TextView View2;
private OkHttpClient okHttpClient;
private Request request;
public final String URL = "http://www.mocky.io/v2/582ac99c280000d50953c316";


@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
//set button and text view values
btnSendHttpRequest = (Button) findViewById(R.id.btnSendRequest);
View = (TextView) findViewById(R.id.view1);
View2 = (TextView) findViewById(R.id.textView4);
etJsonResponse = (EditText) findViewById(R.id.etjson);
//response for button
btnSendHttpRequest.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
//http request
PostEx example = new PostEx();
new Requesting().execute();
}
});

}

public class Requesting extends AsyncTask<String, String, String> {
// post request stuff
@Override
protected String doInBackground(String... params) {
String id = "444454";
String userName = "john";
PostEx example = new PostEx();
String jsonstr = example.makeJsonForUser(id, userName);
if(example.doPostRequest(jsonstr)== null){
Log.d("OKHTTP3", "null pointer");
}
String response = example.doPostRequest(jsonstr);
Log.d("OKHTTP3", "sending response");
return response;
}


@Override
protected void onPostExecute(String response) {
super.onPostExecute(response);
//rewrite text view
try {
// create json ob from response
if(response == null){
Log.d("OKHTTP3", "null pointer");
}
JSONObject jsonObj = new JSONObject(response);
//get the values from the json key value pairs
String id = jsonObj.toString();
//update the text views
TextView textView = (TextView) findViewById(R.id.view1);
textView.setText(id);
} catch (Exception e) {

}
}
}
}


PostEx.java:

import android.util.Log;
import org.json.JSONException;
import org.json.JSONObject;
import java.io.IOException;
import okhttp3.MediaType;
import okhttp3.OkHttpClient;
import okhttp3.Request;
import okhttp3.RequestBody;
import okhttp3.Response;



public class PostEx {
public String doPostRequest(String jsonstr) {
String url = "http://45.55.92.243/newuser";
OkHttpClient client = new OkHttpClient();
MediaType JSON = MediaType.parse("application/json; charset=utf-8");

RequestBody body = RequestBody.create(JSON,jsonstr);
Log.d("OKHTTP3","Request body created");
Request newReq = new Request.Builder()
.url(url)
.post(body)
.build();
Log.d("OKHTTP3","Request body created 2");
try {
Response response = client.newCall(newReq).execute();
Log.d("OKHTTP3","Got Response");
Log.d("OKHTTP3",response.body().string());
String Fresponse = response.body().string();
response.close();
return Fresponse;
} catch (IOException e) {
Log.d("OKHTTP3","Got Exception");
e.printStackTrace();
return null;
}

}
public String makeJsonForUser(String id, String Username){
JSONObject data = new JSONObject();
try {
data.put("id", id);
data.put("name", Username);
return data.toString();
} catch (JSONException e) {
Log.d("OKHTTP3", "JSON Exeption");
e.printStackTrace();
return null;
}
}

}


at okhttp3.ResponseBody.string(ResponseBody.java:154):

public final String string() throws IOException {
return new String(bytes(), charset().name());
}


at okhttp3.internal.http.Http1xStream$FixedLengthSource.read(Http1xStream.java:374):

@Override public long read(Buffer sink, long byteCount) throws IOException {
if (byteCount < 0) throw new IllegalArgumentException("byteCount < 0: " + byteCount);
if (closed) throw new IllegalStateException("closed");
if (bytesRemaining == 0) return -1;

long read = source.read(sink, Math.min(bytesRemaining, byteCount));
if (read == -1) {
endOfInput(false); // The server didn't supply the promised content length.
throw new ProtocolException("unexpected end of stream");
}

bytesRemaining -= read;
if (bytesRemaining == 0) {
endOfInput(true);
}
return read;
}

Answer

Your code works, mostly, up to this point

D/OKHTTP3: Request body created
D/OKHTTP3: Request body created 2
D/OKHTTP3: Got Response

I remember reading, you can only receive the body string once

 //   Log.d("OKHTTP3",response.body().string());
String Fresponse = response.body().string();
// log Fresponse here 

And close the resources in a finally block after the catch