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();
Related
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..
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.
I'm trying to add a header to a simple okhttp (Get) request. How do I add the HttpHeader properly? Can I debug to ensure that my Header is actually sent to the server?
Request request = new Request.Builder()
.url("URL")
.build();
OkHttpClient okHttpClient = new OkHttpClient.Builder()
.addInterceptor(new Interceptor() {
#Override
public okhttp3.Response intercept(Chain chain) throws IOException {
Request originalRequest = chain.request();
Request newRequest = originalRequest.newBuilder()
.addHeader("Header", "123")
.build();
return chain.proceed(newRequest);
}
})
.build();
okHttpClient.newCall(request).enqueue(new Callback() {
#Override
public void onFailure(Call call, IOException e) {
}
I've looked for basic simple examples but they are with Retrofit, GSON, Interfaces, or in Kotlin. Need to understand it codewise.
You can use by method addHeader send chain as param and add headers.
Request getRequest = chain.request();
Request.Builder requestBuilder = getRequest.newBuilder()
.addHeader("Header", "123");
Request request = requestBuilder.build();
return chain.proceed(request);
You can also visit and look at the answers link1 and link2.
Here is the all-request Structure you can use.
OkHttpClient.Builder httpClient = new OkHttpClient.Builder();
httpClient.addInterceptor(new Interceptor() {
#Override
public Response intercept(Interceptor.Chain chain) throws IOException {
Request original = chain.request();
Request request = original.newBuilder()
.method(original.method(), original.body())
.build();
return chain.proceed(request);
}
};
OkHttpClient client = httpClient.build();
Request request = new Request.Builder()
.url("URL")
.addHeader("Header", "123")
.build();
client.newCall(request).enqueue(new Callback() {
#Override
public void onFailure(Call call, IOException e) {
e.printStackTrace();
Log.d("OKHTTP3", e.getMessage());
// You get this failure
runOnUiThread(() -> {
});
}
#Override
public void onResponse(Call call, Response response) throws IOException {
try {
final String _body = response.body().string();
Log.d("OKHTTP3", _body);
runOnUiThread(() -> {
});
} catch (InterruptedIOException e) {
runOnUiThread(() -> {
// Or this exception depending when timeout is reached
});
}
}
});
To check your request and to add headers, you can use interceptors.
To add headers, (copied from gist):
OkHttpClient.Builder httpClient = new OkHttpClient.Builder();
httpClient.addInterceptor(new Interceptor() {
#Override
public Response intercept(Interceptor.Chain chain) throws IOException {
Request original = chain.request();
Request request = original.newBuilder()
.header("User-Agent", "Your-App-Name")
.header("Accept", "application/vnd.yourapi.v1.full+json")
.method(original.method(), original.body())
.build();
return chain.proceed(request);
}
}
OkHttpClient client = httpClient.build();
Retrofit retrofit = new Retrofit.Builder()
.baseUrl(API_BASE_URL)
.addConverterFactory(GsonConverterFactory.create())
.client(client)
.build();
To see your headers, you can use sample example provided here:
class LoggingInterceptor implements Interceptor {
#Override public Response intercept(Interceptor.Chain chain) throws IOException {
Request request = chain.request();
long t1 = System.nanoTime();
logger.info(String.format("Sending request %s on %s%n%s",
request.url(), chain.connection(), request.headers()));
Response response = chain.proceed(request);
long t2 = System.nanoTime();
logger.info(String.format("Received response for %s in %.1fms%n%s",
response.request().url(), (t2 - t1) / 1e6d, response.headers()));
return response;
}
}
Use addHeader() to add headers. header() sets the already added header name to the value.
Request newRequest = originalRequest.newBuilder()
.addHeader("Header", "123")
.build();
And to verify it's working correctly, you can use HttpLoggingInterceptor to log your network requests.
I do a post request an api running on my localhost but it throws TimeOut exception.
I set every timeout for 1 minutes but still getting error of timeout.
Here is my code for request :
OkHttpClient client = new OkHttpClient.Builder()
.readTimeout(1,TimeUnit.MINUTES)
.writeTimeout(1,TimeUnit.MINUTES)
.connectTimeout(1, TimeUnit.MINUTES)
.build();
RequestBody formBody = new FormBody.Builder()
.add("Username", "***")
.add("Password", "****")
.build();
HttpUrl localUrl = HttpUrl.parse("http://192.168.1.40:44338/api/authorize/login");
Request request = new Request.Builder()
.url(localUrl)
.addHeader("Content-Type","application/json")
.post(formBody)
.build();
client.newCall(request).enqueue(new Callback() {
#Override
public void onFailure(#NotNull Call call, #NotNull IOException e) {
System.out.println("y" + e.getMessage());
e.printStackTrace();
}
#Override
public void onResponse(#NotNull Call call, #NotNull Response response) throws IOException {
System.out.println("ccc :" + response.body().string());
}
});
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!