2

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;
    }        
  • Could you post the full stacktrace of the exception occured? I suspect the "onPostExecute()" is failing. – nilsmagnus Nov 20 '16 at 20:29
  • Your problem is somewhere in `okhttp3.internal.http.Http1xStream$FixedLengthSource.read(Http1xStream.java:374)` but you haven't posted the relevant code from `okhttp3.ResponseBody.string(ResponseBody.java:154)` upwards, please post also all this code – J j Nov 20 '16 at 21:08
  • Why are you posting okhttp source code? – OneCricketeer Nov 20 '16 at 21:53

2 Answers2

7

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

More importantly you are using Okhttp. You don't need Asynctasks! Use the enqueue method instead of execute on the client call object

client.newCall(newReq).enqueue(new Callback() {
  // handle response here 
});

And you're processing JSON, so Retrofit would help you implement what you're already trying to do

OneCricketeer
  • 179,855
  • 19
  • 132
  • 245
0

The problem is you can call string() once. But I don't know why

sajad abbasi
  • 1,988
  • 2
  • 22
  • 43