I am trying to connect with my webservice restful to login a user.
i do that:
private class LoginTask extends AsyncTask {
OkHttpClient client = new OkHttpClient();
String base64NamePass;
public LoginTask(String base64NamePass){
this.base64NamePass = base64NamePass;
}
#Override
protected Object doInBackground(Object[] params) {
Response response = null;
try {
response = get("http://192.168.0.27:8080/ServicioRestTFG/rest/UsuariosServicesRs/login", base64NamePass);
} catch (IOException e) {
e.printStackTrace();
}
return response;
}
private Response get (String url, String base64NamePass) throws IOException {
Request request = new Request.Builder()
.get()
.url(url)
.addHeader("Authorization", base64NamePass)
.build();
return client.newCall(request).execute();
}
}
First i encoded the user and the pass with base64 and then i send it to my server.
But when i add the header:
Request request = new Request.Builder()
.get()
.url(url)
.addHeader("Authorization", base64NamePass)
.build();
return client.newCall(request).execute();
the app forceclosed and it doesnt show me what is the error, only close.
Any idea?
thanks
Related
I use OkHttp for requests to my raspberry. I am thinking about putting the requests in a separate class.
Currently I have one method to send requests. The code is as follows:
private void sendRequest(String url, JSONObject json) {
Log.d(TAG, "sendRequest: Das Json: " + json);
// Authentication for the request to raspberry
OkHttpClient.Builder client = new OkHttpClient.Builder();
client.authenticator(new Authenticator() {
#Override
public Request authenticate(Route route, Response response) throws IOException {
String credential = Credentials.basic("username", "password");
return response.request().newBuilder()
.header("Authorization", credential)
.build();
}
});
// Sending out the request to the raspberry
OkHttpClient okHttpClient = client.build();
RequestBody body = RequestBody.create(null, new byte[]{});
if( json != null) {
body = RequestBody.create(MediaType.parse(
"application/json"),
json.toString()
);
}
Request request = new Request.Builder()
.url(url)
.post(body)
.build();
okHttpClient.newCall(request).enqueue(new Callback() {
#Override
public void onFailure(Call call, IOException e) {
Log.d(LOG, "Big Fail");
e.printStackTrace();
}
#Override
public void onResponse(Call call, Response response) throws IOException {
try {
ResponseBody responseBody = response.body();
if( !response.isSuccessful() ) {
Log.d(TAG, "onResponse: We are in !response.successful()");
throw new IOException("Response not successful: " + response );
}
Log.d(LOG, "onResponse: Response is: " + responseBody.string());
} catch (Exception e) {
e.printStackTrace();
Log.d(LOG, "onResponse: failed!" + e);
}
}
});
}
Here is an example how the sendRequest() function is called:
private void makePremixCall(Premix premix) {
JSONArray jsonArray = new JSONArray();
ArrayList<Premixable> usedPremixables = premix.getUsedPremixables();
for(Premixable usedPremixable: usedPremixables) {
try {
JSONObject jsonObject = new JSONObject();
jsonObject.put("Silo", usedPremixable.getmSilo());
jsonObject.put("Gramm", usedPremixable.getmKgPerCow() * mFeeding.getmNumberOfCows());
jsonArray.put(jsonObject);
} catch (JSONException e) {
e.printStackTrace();
}
}
try {
JSONObject jsonObject = new JSONObject();
jsonObject.put("Components", jsonArray);
sendRequest("http://192.168.178.49:5000/evaluatePost", jsonObject);
} catch (JSONException e) {
e.printStackTrace();
Log.d(TAG, "makePremixCall: " + e);
}
}
My problem with this: I would like to have a separate class, which offers the function makePremix(Premix premix) and other functions that I need.
The only solution that comes to my mind is implementing the requests synchronously in the separate class and call that separate class in an AsyncTask in the class I am working in.
Do I oversee something? Is there a way to create a separate class and still use the OkHttp enqueue method?
You could extract makePremix(Premix premix) in a separate class and make sendRequest() public (or maybe package-private depending on your use case).
public void sendRequest(String url, JSONObject json)
However since sendRequest is generic and can be used by any other makeAnotherCall() in some other class you would need to get back result of every requests. Hence you can extract the Callback out of sendRequest()
public void sendRequest(String url, JSONObject json, Callback callback)
Now your sendRequest will look like
private void sendRequest(String url, JSONObject json) {
Log.d(TAG, "sendRequest: Das Json: " + json);
// Authentication for the request to raspberry
OkHttpClient.Builder client = new OkHttpClient.Builder();
client.authenticator(new Authenticator() {
#Override
public Request authenticate(Route route, Response response) throws IOException {
String credential = Credentials.basic("username", "password");
return response.request().newBuilder()
.header("Authorization", credential)
.build();
}
});
// Sending out the request to the raspberry
OkHttpClient okHttpClient = client.build();
RequestBody body = RequestBody.create(null, new byte[]{});
if( json != null) {
body = RequestBody.create(MediaType.parse(
"application/json"),
json.toString()
);
}
Request request = new Request.Builder()
.url(url)
.post(body)
.build();
okHttpClient.newCall(request).enqueue(callback);
}
Hope it makes sense!
Also as a side note, see that you are creating a new OkHttp Client every time you call sendRequest. You could probably optimise memory here by caching the client and reusing it.
I am using okHTTP in Android to make a PUT request. I Have added the headers and I have added .put request. But somehow the request is not going through. I have used Log entries to trace that. The code goes like:
String url = "http://xxxxxxxxxx.com/v1.0/xxxxxx/" + xxxxxxx;
JSONObject jSon = new JSONObject();
try {
jSon.put("prescription_interval_id", prescriptionIntervalId);
} catch (JSONException e) {
e.printStackTrace();
}
try {
jSon.put("prescription_auto_refill", false);
} catch (JSONException e) {
e.printStackTrace();
}
String data = jSon.toString();
MediaType JSON = MediaType.parse("application/json; charset=utf-8");
RequestBody body = RequestBody.create(JSON, data);
Request request = new Request.Builder()
.url(url)
.addHeader("Authorization", token)
.addHeader("Content-Type", "application/json")
.put(body)
.build();
//
client.newCall(request).enqueue(new Callback() {
#Override
public void onFailure(Request request, IOException e) {
Log.d("FAIL","CALL FAILED");
Log.d("Request",request.toString());
}
#Override
public void onResponse(Response response) throws IOException {
Log.d("Response",response.toString());
Log.d("SUCCESS","CALL SUCCEEDED");
}
});
The request is not being made. I don't know why.
Oh! Accidentally i was putting a space in between url end points! works fine now :)
I want a JSON but I am getting a response header. I am using Android Studio 2.1.1. I am using the OkHttpClient library and AsyncTask to separate it from the main thread.
public class MainActivity extends AppCompatActivity {
TextView tv;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
tv = (TextView) findViewById(R.id.tv);
new PostTask().execute("url");
}
private class PostTask extends AsyncTask<String, Integer, String> {
#Override
protected void onPreExecute() {
super.onPreExecute();
}
#Override
protected String doInBackground(String... params) {
String url = params[0];
// Dummy code
OkHttpClient client = new OkHttpClient();
client.setConnectTimeout(1, TimeUnit.MINUTES); // connect timeout
client.setReadTimeout(1, TimeUnit.MINUTES); // socket timeout
MediaType mediaType = MediaType.parse("application/x-www-form-urlencoded");
RequestBody body = RequestBody.create(mediaType, "data=something");
Request request = new Request.Builder()
.url(url)
.post(body)
.addHeader("cache-control", "no-cache")
.addHeader("postman-token", "7a4d5df8-5aed-19bf-e1fb-c85f821c1d10")
.addHeader("content-type", "application/x-www-form-urlencoded")
.build();
Response response = null;
try {
response = client.newCall(request).execute();
return response.toString();
} catch (Exception e1) {
e1.printStackTrace();
return e1.toString();
}
}
#Override
protected void onProgressUpdate(Integer... values) {
super.onProgressUpdate(values);
}
#Override
protected void onPostExecute(String result) {
super.onPostExecute(result);
tv.setText(result);
}
}
}
This is the screenshot of the response.
You need to request the body.
Instead of use:
return response.toString();
Use:
return response.body().string();
that sould return the body content.
NOTE:
.toString() method return the object string.
Here you have an example from documentation: http://square.github.io/okhttp/
OkHttpClient client = new OkHttpClient();
String run(String url) throws IOException {
Request request = new Request.Builder()
.url(url)
.build();
Response response = client.newCall(request).execute();
return response.body().string();
}
So, back when I was using Koush's Ion, I was able to add a json body to my posts with a simple .setJsonObjectBody(json).asJsonObject()
I'm moving over to OkHttp, and I really don't see a good way to do that. I'm getting error 400's all over the place.
Anyone have any ideas?
I've even tried manually formatting it as a json string.
String reason = menuItem.getTitle().toString();
JsonObject json = new JsonObject();
json.addProperty("Reason", reason);
String url = mBaseUrl + "/" + id + "/report";
Request request = new Request.Builder()
.header("X-Client-Type", "Android")
.url(url)
.post(RequestBody
.create(MediaType
.parse("application/json"),
"{\"Reason\": \"" + reason + "\"}"
))
.build();
client.newCall(request).enqueue(new com.squareup.okhttp.Callback() {
#Override
public void onFailure(Request request, IOException throwable) {
throwable.printStackTrace();
}
#Override
public void onResponse(Response response) throws IOException {
if (!response.isSuccessful()) throw new IOException(
"Unexpected code " + response);
runOnUiThread(new Runnable() {
#Override
public void run() {
Toast.makeText(context, "Report Received", Toast.LENGTH_SHORT).show();
}
});
}
});
/*Ion.with(getContext(), url)
.setHeader("X-Client-Type", "Android")
.setJsonObjectBody(json)
.asJsonObject()
.setCallback(new FutureCallback<JsonObject>() {
#Override
public void onCompleted(Exception e, JsonObject result) {
Toast.makeText(context, "Report Received", Toast.LENGTH_SHORT).show();
}
});*/
Just use JSONObject.toString(); method.
And have a look at OkHttp's tutorial:
public static final MediaType JSON
= MediaType.parse("application/json; charset=utf-8");
OkHttpClient client = new OkHttpClient();
String post(String url, String json) throws IOException {
RequestBody body = RequestBody.create(json, JSON); // new
// RequestBody body = RequestBody.create(JSON, json); // old
Request request = new Request.Builder()
.url(url)
.post(body)
.build();
Response response = client.newCall(request).execute();
return response.body().string();
}
You can create your own JSONObject then toString().
Remember run it in the background thread like doInBackground in AsyncTask.
OkHttp version > 4:
import okhttp3.MediaType.Companion.toMediaType
// create your json here
JSONObject jsonObject = new JSONObject();
try {
jsonObject.put("KEY1", "VALUE1");
jsonObject.put("KEY2", "VALUE2");
} catch (JSONException e) {
e.printStackTrace();
}
val client = OkHttpClient()
val mediaType = "application/json; charset=utf-8".toMediaType()
val body = jsonObject.toString().toRequestBody(mediaType)
val request: Request = Request.Builder()
.url("https://YOUR_URL/")
.post(body)
.build()
var response: Response? = null
try {
response = client.newCall(request).execute()
val resStr = response.body!!.string()
} catch (e: IOException) {
e.printStackTrace()
}
OkHttp version 3:
// create your json here
JSONObject jsonObject = new JSONObject();
try {
jsonObject.put("KEY1", "VALUE1");
jsonObject.put("KEY2", "VALUE2");
} catch (JSONException e) {
e.printStackTrace();
}
OkHttpClient client = new OkHttpClient();
MediaType JSON = MediaType.parse("application/json; charset=utf-8");
// put your json here
RequestBody body = RequestBody.create(JSON, jsonObject.toString());
Request request = new Request.Builder()
.url("https://YOUR_URL/")
.post(body)
.build();
Response response = null;
try {
response = client.newCall(request).execute();
String resStr = response.body().string();
} catch (IOException e) {
e.printStackTrace();
}
Another approach is by using FormBody.Builder().
Here's an example of callback:
Callback loginCallback = new Callback() {
#Override
public void onFailure(Call call, IOException e) {
try {
Log.i(TAG, "login failed: " + call.execute().code());
} catch (IOException e1) {
e1.printStackTrace();
}
}
#Override
public void onResponse(Call call, Response response) throws IOException {
// String loginResponseString = response.body().string();
try {
JSONObject responseObj = new JSONObject(response.body().string());
Log.i(TAG, "responseObj: " + responseObj);
} catch (JSONException e) {
e.printStackTrace();
}
// Log.i(TAG, "loginResponseString: " + loginResponseString);
}
};
Then, we create our own body:
RequestBody formBody = new FormBody.Builder()
.add("username", userName)
.add("password", password)
.add("customCredential", "")
.add("isPersistent", "true")
.add("setCookie", "true")
.build();
OkHttpClient client = new OkHttpClient.Builder()
.addInterceptor(this)
.build();
Request request = new Request.Builder()
.url(loginUrl)
.post(formBody)
.build();
Finally, we call the server:
client.newCall(request).enqueue(loginCallback);
In kotlin, in okhttp v4.* I got it working that way
// import the extensions!
import okhttp3.MediaType.Companion.toMediaType
import okhttp3.RequestBody.Companion.toRequestBody
// ...
json : String = "..."
val JSON : MediaType = "application/json; charset=utf-8".toMediaType()
val jsonBody: RequestBody = json.toRequestBody(JSON)
// go on with Request.Builder() etc
I'm pulling my hair out trying to get this to work. I'm using OkHTTP to make a POST request to my server. However, every method I've tried of making a successful POST request with parameters, causes the server to go down, giving me a response of '503 service unavailable'. I use exterior clients to test the server, like the Advanced Rest Client extension, and it works perfectly fine.
The URL for the API is in the format of "https://mystuff-herokuapp.com/postuser" and my body parameters are "user_id", "userName", "email". I've tried adding headers to the request, changing from FormBodyEncoding() to MultiPartBuilder(), etc etc.
onCreate
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_dashboard);
//set toolbar as the acting action bar
Toolbar actionToolbar = (Toolbar) findViewById(R.id.toolbar);
setSupportActionBar(actionToolbar);
getSupportActionBar().setDisplayShowTitleEnabled(false);
Intent intent = getIntent();
String photoUrl = intent.getStringExtra("photo");
String userTwitterID = intent.getStringExtra("userID");
String userName = intent.getStringExtra("name");
String userEmail = intent.getStringExtra("email");
JSONObject jObject = new JSONObject();
try {
jObject.put("user_id", userTwitterID);
jObject.put("userName", userName);
jObject.put("userEmail", userEmail);
} catch (JSONException e) {
e.printStackTrace();
}
new UserApiProcess().execute(jObject);
}
Async Task
private class UserApiProcess extends AsyncTask<Object, Void, Void>{
#Override
protected Void doInBackground(Object... strings) {
OkHttpClient client = new OkHttpClient();
RequestBody formBody = new MultipartBuilder()
.addFormDataPart("user_id", "800")
.addFormDataPart("userName", "Nick")
.addFormDataPart("email", "something#something.com")
.build();
Request request = new Request.Builder()
.url("https://mystuff.herokuapp.com/postuser")
.addHeader("Content-Type", "x-www-form-urlencoded")
.post(formBody)
.build();
Response response = null;
try {
response = client.newCall(request).execute();
if(!response.isSuccessful()) throw new IOException("Unexpected code " + response);
System.out.println(response.body().string());
} catch (IOException e) {
e.printStackTrace();
}
return null;
}
}
Successful Response from Advanced Rest Client
My Server Error through Android
Try this. It should work.
private class UserApiProcess extends AsyncTask<Object, Void, Void>{
#Override
protected Void doInBackground(Object... strings) {
OkHttpClient client = new OkHttpClient();
RequestBody formBody = new FormEncodinBuilder()
.add("user_id", "800")
.add("userName", "Nick")
.add("email", "something#something.com")
.build();
Request request = new Request.Builder()
.url("https://mystuff.herokuapp.com/postuser")
.addHeader("Content-Type", "x-www-form-urlencoded")
.post(formBody)
.build();
Response response = null;
try {
response = client.newCall(request).execute();
if(!response.isSuccessful()) throw new IOException("Unexpected code " + response);
System.out.println(response.body().string());
} catch (IOException e) {
e.printStackTrace();
}
return null;
}
}