Perform OkHttp network actions in background thread - java

I am using OKHttp to perform Post request to server, as follow:
public class NetworkManager {
public static final MediaType JSON = MediaType.parse("application/json; charset=utf-8");
OkHttpClient client = new OkHttpClient();
String post(String url, JSONObject json) throws IOException {
try {
JSONArray array = json.getJSONArray("d");
RequestBody body = new FormEncodingBuilder()
.add("m", json.getString("m"))
.add("d", array.toString())
.build();
Request request = new Request.Builder()
.url(url)
.post(body)
.build();
Response response = client.newCall(request).execute();
return response.body().string();
} catch (JSONException jsone) {
return "ERROR: " + jsone.getMessage();
}
}
}
and call it with:
NetworkManager manager = new NetworkManager();
String response = manager.post("http://www.example.com/api/", jsonObject);
When I try to run the App, it prompts an error in the logcat:
android.os.NetworkOnMainThreadException
at
android.os.StrictMode$AndroidBlockGuardPolicy.onNetwork(StrictMode.java:1273)
With reference to other questions in SO, I added this to override the policy:
if (android.os.Build.VERSION.SDK_INT > 9)
{
StrictMode.ThreadPolicy policy = new StrictMode.ThreadPolicy.Builder().permitAll().build();
StrictMode.setThreadPolicy(policy);
}
Yet I think this is unhealthy and I would like to put the NetworkManager actions to background. How can I do so?

Since OkHttp supports async way too, so IMO you can refer to the following GET request sample, then apply for your POST request:
OkHttpClient client = new OkHttpClient();
// GET request
Request request = new Request.Builder()
.url("http://google.com")
.build();
client.newCall(request).enqueue(new Callback() {
#Override
public void onFailure(Request request, IOException e) {
Log.e(LOG_TAG, e.toString());
}
#Override
public void onResponse(Response response) throws IOException {
Log.w(LOG_TAG, response.body().string());
Log.i(LOG_TAG, response.toString());
}
});
Hope it helps!

Related

How do I transfer data from an asynchronous request to a class variable? OkHttp3, Java

I'm using an asynchronous request (because synchronous doesn't work correctly with this API), the OkHttp3 library. Inside the request, I get a response in the form of JSON. I need to somehow pass values from Json to a class variable. I decided to try it this way, but it doesn't work.
public String sessionId = null;
...
public QRcodeReader() throws Exception {
this.sessionId = null;
}
... // between this code I have 1 function, which reg my number.
// in this func I need to confirm my phone by code in SMS.
public void SmsCode(String Code) // String get from another class
{
SmsJson smsJson = new SmsJson("*phoneNumber*", "*secret_key*", "*os*", Code);
Gson gson = new GsonBuilder().disableHtmlEscaping().create();
RequestBody body = RequestBody.create(
MediaType.parse("application/json"), gson.toJson(smsJson));
Request request = new Request.Builder()
.url("https://irkkt-mobile.nalog.ru:8888/v2/auth/phone/verify")
.addHeader("Host", HOST)
.addHeader("Accept", ACCEPT)
.addHeader("Device-OS", DEVICE_OS)
.addHeader("Device-ID", DEVICE_ID)
.addHeader("clientVersion", CLIENT_VERSION)
.addHeader("Accept-Language", ACCEPT_LANGUAGE)
.addHeader("User-Agent", USER_AGENT)
.post(body)
.build();
httpClient.newCall(request).enqueue(new Callback() {
#Override
public void onResponse(#NonNull Call call, #NonNull Response response) throws IOException {
try (Response responseBody = httpClient.newCall(request).execute()) {
if (!responseBody.isSuccessful())
throw new IOException("Unexpected code " + responseBody);
// Here I try to transfer data from request to class variable. Not Work.
SetSessionId(Objects.requireNonNull(responseBody.body()).string());
System.out.println(Objects.requireNonNull(responseBody.body()).string());
} catch (IOException e) {
e.printStackTrace();
}
}
#Override
public void onFailure(Call call, IOException e) {
e.printStackTrace();
}
});
}
void SetSessionId(String sessionId){
this.sessionId = sessionId;
}
I need to use SessionID further along here:
public String GetTicketID(String QR){
TicketID ticketID = new TicketID(QR);
Gson gson = new GsonBuilder().disableHtmlEscaping().create();
RequestBody body = RequestBody.create(
MediaType.parse("application/json"), gson.toJson(ticketID));
Request request = new Request.Builder()
.url("https://irkkt-mobile.nalog.ru:8888/v2/ticket")
.addHeader("Host", HOST)
.addHeader("Accept", ACCEPT)
.addHeader("Device-OS", DEVICE_OS)
.addHeader("Device-ID", DEVICE_ID)
.addHeader("clientVersion", CLIENT_VERSION)
.addHeader("Accept-Language", ACCEPT_LANGUAGE)
.addHeader("User-Agent", USER_AGENT)
.addHeader("sessionId", sessionId) // Here I get NULL and exception!
.post(body)
.build();
httpClient.newCall(request).enqueue(new Callback() {
#Override
public void onResponse(Call call, Response response) throws IOException {
try (Response responseBody = httpClient.newCall(request).execute()) {
if (!responseBody.isSuccessful())
throw new IOException("Unexpected code " + responseBody);
System.out.println(Objects.requireNonNull(responseBody.body()).string());
} catch (IOException e) {
e.printStackTrace();
}
}
#Override
public void onFailure(Call call, IOException e) {
e.printStackTrace();
}
});
return ""; // Here I need to transfer id to another variable, not did it yet.
}
The problem is that SessionID = Null and the request does not work.
I think I'm doing something wrong, but I can't figure out what. May be it is because async request..

Okhttp JSON data parsing

currently working on an Android App and I'm supposed to send JSON data to a server and receive back a response, but the server doesn't recognize the data frame as a JSON type it still shows its content but replies with a 404 code
here's the code I used :
private final OkHttpClient client = new OkHttpClient();
JSONObject jsonObj = new JSONObject();
try{
jsonObj.put("imei",number);
jsonObj.put("longitude", number);
jsonObj.put("latitude", number);
jsonObj.put("speed", number);
jsonObj.put("battery", number);
jsonObj.put("date", date);
jsonObj.put("error", number);
jsonObj.put("acceleroVal", number);
jsonObj.put("apn", string);
} catch (JSONException e) {
e.printStackTrace();
}
String json = jsonObj.toString();
RequestBody.create(json, MediaType.parse("application/json; charset=utf-8"));
RequestBody formBody = new FormBody.Builder()
.build();
Request request = new Request.Builder()
.url("http://xxxx.com:2000/api/xxx")
.put(formBody)
.build();
client.newCall(request).enqueue(new Callback() {
#Override
public void onFailure(#NonNull Call call, #NonNull IOException e) {
e.printStackTrace();
}
#Override
public void onResponse(#NonNull Call call, #NonNull Response response) throws IOException {
if(response.isSuccessful()) {
ResponseBody responseBody = response.body();
}
any help is appreciated, feel free to adjust the code.

Go from OkHttp to HttpURLConnection

For reasons of library compatibility issues I would like to use HttpURLConnection to call requests on an API.
Here is the code I use with OkHttp to get a token access:
private void getAccessToken(){
OkHttpClient okHttpClient = new OkHttpClient();
RequestBody requestBody = new FormEncodingBuilder().add("grant_type", "authorization_code")
.add("client_id", "1568xxxxxxxxxxxxxxxxxjro.apps.googleusercontent.com")
.add("client_secret", "AMe0xxxxxxxxxxxx")
.add("redirect_uri", "")
.add("code", serverCode)
.build();
Request request = new Request.Builder()
.url("https://www.googleapis.com/oauth2/v4/token")
.post(requestBody)
.build();
okHttpClient.newCall(request).enqueue(new Callback() {
#Override
public void onFailure(Request request, IOException e) {
Log.i("severcode","failure");
}
#Override
public void onResponse(Response response) throws IOException {
try {
JSONObject jsonObject = new JSONObject(response.body().string());
token = jsonObject.optString("access_token");
tokenExpired = SystemClock.elapsedRealtime() + jsonObject.optLong("expires_in") * 1000;
Log.i("severcode",String.valueOf(token));
createGooglePhotosClient();
} catch (Exception e) {
e.printStackTrace();
}
}
});
}
So I would like to know how to get the equivalent of requestbody to pass it in setRequestProperty ()?
Thanks for your help
The request body is not a request property (header), it's the body of the request, and without OkHttp or other supporting libraries you have to format it yourself, encode any special characters that need to be encoded etc.
String requestBody = "grant_type=authorization_code&client_id=1568xxxxxxxxxxxxxxxxxjro.apps.googleusercontent.com&"
+ "client_secret=AMe0xxxxxxxxxxxx&redirect_uri=&code=" + serverCode + "\n\n";
byte[] requestBodyBytes = requestBody.getBytes("UTF-8");
Once you have the request body, you write it to the connection's output stream. For example:
connection.setRequestProperty("content-type", "application/x-www-form-urlencoded");
connection.setDoOutput(true);
out = connection.getOutputStream();
out.write(requestBodyBytes)
out.flush();

App crashes when tries to send Json object

I'm trying to send a Json object to a server with android studio, using okhttp3, and my app always crashes when I just try to send the json, when the app says the message was sent. In addition, I need to see in response my own json I created as a confirmation that my Json worked.
public static final MediaType JSON = MediaType.parse("application/json; charset=utf-8");
OkHttpClient client = new OkHttpClient();
void post(String url, String json) throws IOException {
RequestBody body = RequestBody.create(JSON, json);
Request request = new Request.Builder()
.url(url)
.post(body)
.build();
okhttp3.Call call = client.newCall(request);
call.enqueue(new Callback() {
#Override
public void onFailure(okhttp3.Call call, IOException e) {
Log.e("TAG", "Failed sending message!");
Toast.makeText(MainActivity.this,"Failed sending message",Toast.LENGTH_LONG).show();
}
#Override
public void onResponse(okhttp3.Call call, Response response) throws IOException {
Log.d("TAG", "Message sent successfully!");
Log.d("TAG", response.body().string());
Toast.makeText(MainActivity.this,"Message sent successfully!",Toast.LENGTH_LONG).show();
}
});
}
My problem seems to appear in the onResponse and onFaliure functions. Here is the error I get on the variables I put in these functions: http://prntscr.com/i0dhgi
The error appears on all 4 variables, two in onFaliure and two in onResponse
I ran your code on my machine what you need to do is something like that but make sure you have this in you app's build.gradle
compile 'com.android.support:support-annotations:20.0.0' if you are using old android studio version. new versions make project with builtin annotation processor
public static final MediaType JSON = MediaType.parse("application/json; charset=utf-8");
OkHttpClient client = new OkHttpClient();
void post(String url, String json) throws IOException {
RequestBody body = RequestBody.create(JSON, json);
Request request = new Request.Builder()
.url(url)
.post(body)
.build();
okhttp3.Call call = client.newCall(request);
call.enqueue(new Callback() {
#Override
public void onFailure( #NonNull okhttp3.Call call,#NonNull IOException e) {
Log.e("TAG", "Failed sending message!");
//using a toast means updating the UI thread from back thread you have to call Content.runOnUiThread(new Runnable) to sync with the UI thread.
//Toast.makeText(MainActivity.this,"Failed sending message",Toast.LENGTH_LONG).show();
}
#Override
public void onResponse(#NonNull okhttp3.Call call,#NonNull Response response) throws IOException {
Log.d("TAG", "Message sent successfully!");
Log.d("TAG", response.body().string());
//Toast.makeText(MainActivity.this,"Message sent successfully!",Toast.LENGTH_LONG).show();
}
});
}
take a look at the picture I ran the code with dummy values and got to see the logcat clearly saying about thread handling issue!
here is the final solution for you that I made will do the trick
NOTE! you can replace "MainActivity.this" with your local Context
public static final MediaType JSON = MediaType.parse("application/json; charset=utf-8");
OkHttpClient client = new OkHttpClient();
void post(String url, String json) throws IOException {
RequestBody body = RequestBody.create(JSON, json);
Request request = new Request.Builder()
.url(url)
.post(body)
.build();
okhttp3.Call call = client.newCall(request);
call.enqueue(new Callback() {
#Override
public void onFailure( #NonNull okhttp3.Call call,#NonNull IOException e) {
MyActivity.this.runOnUiThread(new Runnable() {
#Override
public void run() {
//Handle UI here
// Toast anything you like here//
}
});
}
#Override
public void onResponse(#NonNull okhttp3.Call call,#NonNull Response response) throws IOException {
MyActivity.this.runOnUiThread(new Runnable() {
#Override
public void run() {
//Handle UI here
//happy on Response Toast here
}
});
}
}
});
}

Synchronous request failing HTTP

I am using okHTTP library to make an http request. It goes through but sometimes, my work in android progresses without complete response arrival. I realize this is happening because of the nature of my request being ASYNC.
OkHttpClient client = new OkHttpClient();
String url = "https://beta-pp-api.polkadoc.com/v1.0/products?category=CP&available_via=mail_order";
{
Request request = new Request.Builder()
.url(url)
.addHeader("Authorization", authentication.getToken())
.addHeader("Content-Type", "application/json")
.addHeader("Accept", "application/json")
.addHeader("X-Service-Code", "PP")
.get()
.build();
client.newCall(request).enqueue(new Callback() {
#Override
public void onFailure(Request request, IOException e){
//do nothing!
}
#Override
public void onResponse(Response response) throws IOException
try {
jsonArray = new JSONArray(response.body().string());
} catch (JSONException e) {
e.printStackTrace();
}
}
});
}
I have tried calling
Response response = client.newCall(request).execute();
However, it fails because in Android we cannot call Sync request on main thread. leads to error NetworkOnMainThread android.os.
Is there a solution to this problem.
Do the process in a background thread something like below:
OkHttpClient client = new OkHttpClient.Builder()
.connectTimeout(15, TimeUnit.SECONDS)
.writeTimeout(15, TimeUnit.SECONDS)
.readTimeout(60, TimeUnit.SECONDS)
.build();
new AsyncTask<Void, Void, JSONArray>() {
#Override
protected JSONArray doInBackground(Void... voids) {
Request request = new Request.Builder()
.url(url)
.addHeader("Authorization", authentication.getToken())
.addHeader("Content-Type", "application/json")
.addHeader("Accept", "application/json")
.addHeader("X-Service-Code", "PP")
.get()
.build();
try {
Response response = client.newCall(request).execute();
if (response.isSuccessful()) {
return new JSONArray(response.body().string());
} else {
// notify error
}
} catch (IOException e) {
// notify error e.getMessage()
}
return null;
}
#Override
protected void onPostExecute(JSONArray jsonArray) {
super.onPostExecute(jsonArray);
if (jsonArray != null && jsonArray.size() > 0) {
// notify status using LocalBroadcastManager or EventBus
}
}
}.execute();

Categories

Resources