I am using:
Andorid Studio.
Okhttp 2.4.0 with AsyncTask. But I can't cancel a request.
Connected to server on wi-fi. And if server is off then okHttp keeps trying to connect, and I can't cancel it.
time outs is working but i want to cancel before timeouts
private OkHttpClient client = new OkHttpClient();
client.setConnectTimeout(30000, TimeUnit.MILLISECONDS);
after execute I press special cancel button in my api
public void onCancelClick(View v){
BaseApplication.getInstance().server.cancel();
synchProducts.cancel(true);
}
first line must stoped okHttp, second line stoped class extended AsyncTask
private static final String myTag = "AsyncCall";
public void cancel(){
client.cancel(myTag);
}
backGround in AsyncTask class
#Override
protected String doInBackground(Void... params) {
publishProgress(1);
String responseStr = sendProductHeaders();
//this performed after timeouts, and spit to my cancel okHttp
publishProgress(2);
if (responseStr != null && !isCancelled()){
ProductsList productsForSend = parseProducts(responseStr);
//correctly stoped thread
I didn't forget to use .tag in the builder request
public Response post(String url, String json) {
RequestBody body = RequestBody.create(JSON, json);
Request request = new Request.Builder()
.tag(myTag)
.url(url)
.post(body)
.build();
return call(request);
}
"call" is my method which makes the okHttp call
private Response call(Request request){
try {
return client.newCall(request).execute();
} catch (IOException e) {
Log.e("Aync call", "IO exception " + e.getMessage());
}
return null;
}
"Tags" is true, code in okHttp Library realy fires call.cancel();
for (Call call : executedCalls) {
if (Util.equal(tag, call.tag())) {
call.cancel();
}
}
method which is running Async
public void onRefreshProducts(View v){
progressLayout.setVisibility(View.VISIBLE);
progressBar.setProgress(0);
synchProducts = new SynchProducts(activityCallBack);
synchProducts.execute();
}
"activityCallBack" is the interface I use when I call to my activity from AsyncTask class
i don't want to use okHttp enqueue, but I can't insert a friendly progress bar in my app.
Thanks!
Try updating the library to okhttp 2.5.0 and use the cancel() method. The ChangeLog for 2.5.0 mentions the following:
Call canceling is more reliable. We had a bug where a socket being connected wasn't being closed when the application used Call.cancel().
Hopefully it will fix the issue.
Related
I want to a upload file on my server and I've decided to try OKHTTP instead of my current method which is based on android own HTTP implementation and AsyncTask.
Anyway, I used OKHTTP and its asynchronous implementation (from its own recipes) but it returns an empty message (the request code is ok, the message is empty) in both GET and POST methods.
Did I implement it wrong or is there anything else remained that I did not considered? In the meantime, I couldn't find a similar case except this which says used AsyncTask.
Here's the code:
Request request;
Response response;
private final OkHttpClient client = new OkHttpClient();
private static final String postman_url = "https://postman-echo.com/get?foo1=bar1&foo2=bar2";
String message_body;
public void Get_Synchronous() throws IOException
{
request = new Request.Builder()
.url(postman_url)
.build();
Call call = client.newCall(request);
response = call.execute();
message_body = response.toString();
//assertThat(response.code(), equalTo(200));
}
public void Get_Asynchronous()
{
request = new Request.Builder()
.url(postman_url)
.build();
Call call = client.newCall(request);
call.enqueue(new Callback() {
public void onResponse(Call call, Response response)
throws IOException
{
message_body = response.toString();
}
public void onFailure(Call call, IOException e)
{
}
});
}
Edit:
I catch the log on response:
onResponse: Response{protocol=h2, code=200, message=, url=https://postman-echo.com/get?foo1=bar1&foo2=bar2}
OK, for anyone who wants to receive an string from a call, response and response.messgage() don't provide that. To catch the response from your provider, you just need to call response.body().string() inside onResponse which returns the message inside your request.
But after all, Retrofit is a better choice if you want to receive a JSON file using
.addConverterFactory(GsonConverterFactory.create(gson)).
If you still want to receive an string just use .addConverterFactory(ScalarsConverterFactory.create()) as explained here.
i'm working on an app that need to do a GET request to update a TextView on screen, now im doing it with a button but i need to update the textview constantly. what's the best way or practice to do it? here the code of the request, the button just call it and put the response string on the TextView.
protected void getEquiposHTTP() {
//Método GET HTTP al servicio Cloudant IBM para las credenciales dadas
final OkHttpClient client = new OkHttpClient();
Uri.Builder builder = new Uri.Builder();
builder.scheme("https")
.authority("data")
.appendPath("data")
.appendPath("data")
.appendPath("data")
.appendPath("data")
.appendPath("data")
.appendQueryParameter("data", "data");
String myUrl = builder.build().toString();
byte[] encoding = Base64.encodeBase64(("data" + ":" + "data").getBytes());
String encodedString = new String(encoding);
final Request request = new Request.Builder()
.url(myUrl)
.addHeader("Content-Type", "application/json")
.addHeader("Authorization", "Basic " + encodedString)
.addHeader("cache-control", "no-cache")
.build();
client.newCall(request).enqueue(new Callback() {
#Override
public void onFailure(Call call, IOException e) {
String mMessage = e.getMessage().toString();
call.cancel();
Log.e(TAG, "Problem at HTTP connection and call.cancel() executed");
}
#Override
public void onResponse(Call call, Response response) throws IOException {
if (response.isSuccessful()) {
try {
addToListEquipos(response.body().string());
} catch (Exception e) {
Log.e(TAG, "Problem at response of HTTP conection, response.isSuccessful() = true then try{} fail");
}
}
}
});
}
One way to achieve this is by running a thread which keeps hitting the server in small intervals to fetch the new data and update the ui. This is not the appropriate way to do things because app will keep hitting the server again and again even in case of no update.
The second way (which is more preferred one but needs extra efforts) is by using something like Push-notification, Firebase Realtime Database
or XMPP server. This way your server will tell the client app about the new data.
From the official site of Firebase Realtime Database
The Firebase Realtime Database is a cloud-hosted database. Data is stored as JSON and synchronized in realtime to every connected client. When you build cross-platform apps with our iOS, Android, and JavaScript SDKs, all of your clients share one Realtime Database instance and automatically receive updates with the newest data.
I am trying to create an android app in which a user enters login details and the data is validated on server ,for server i am using xampp.I want to get the value shown on the php result page in android app and show it to the user using Toast.
#Override
protected Boolean doInBackground(Void... params) {
// TODO: attempt authentication against a network service.
Toast.makeText(getApplicationContext(),"Problem is in http", Toast.LENGTH_LONG).show();
String result;
OkHttpClient client = new OkHttpClient();
Request request = new Request.Builder()
.url("http:192.168.0.102/db.php?username=tkajbaje#gmail.com&password=123456")
.build();
Response response = null;
try {
response = client.newCall(request).execute();
} catch (IOException e) {
e.printStackTrace();
}
result=response.toString();
Toast.makeText(getApplicationContext(),result, Toast.LENGTH_LONG).show();
// TODO: register the new account here.
return true;
}
When I run the app it exits unexpectedly,what could be the problem?Apologies if some important information is missing regarding question.
This is certainly problematic
try {
response = client.newCall(request).execute();
} catch (IOException e) {
e.printStackTrace();
}
You are catching and logging the error but continuing, so response can be null.
There are other issues with the code
You are creating a new OkHttp instance for each call
it's unclear if you are actually running this on a background thread
IIRC Toast.show should be on UI thread, but okhttp calls should be background
I am using Retrofit 2 and before Firebase Auth I used to store my token in SharedPreferences and in my HttpInterceptor
#Named("rest_api")
#Singleton
#Provides
Interceptor provideRESTInterceptor(final UserManager userManager) {
return new Interceptor() {
#Override
public Response intercept(final Chain chain) throws IOException {
final Request original = chain.request();
Request request = original.newBuilder()
.header("Accept", "application/json")
.header("Authorization", "XXXX " + sharedPreference.getToken())
.method(original.method(), original.body())
.build();
Response response = chain.proceed(request);
return response;
}
};
}
How could i achieve something like this with
FirebaseUser.getToken(false/true) ? I don't know how to wait for the listener callback and than process the request with firebase token.
I am also thinking to check for token validity in here and if its about to expire getToken(true)
I am not sure to understand the whole problem, but to wait for the listener callback (in other words, making a synchronous method out of an asynchronous call) can be achieved like this :
private String getToken() {
final StringBuilder token = new StringBuilder() ;
final CountDownLatch countDownLatch = new CountDownLatch(1) ;
FirebaseAuth.getInstance().getCurrentUser().getToken(true).addOnCompleteListener(new OnCompleteListener<GetTokenResult>() {
#Override
public void onComplete(#NonNull Task<GetTokenResult> task) {
token.append(task.getResult().getToken());
countDownLatch.countDown();
}
});
try {
countDownLatch.await(30L, TimeUnit.SECONDS);
return token.toString() ;
} catch (InterruptedException ie) {
return null;
}
}
Notes :
StringBuilder is just used here as a String holder.
Bullet-proof implementation should of course check task.isSuccessful()
Timeout (here 30 sec) should be adapted to your situation
Hope this helps.
Below is my class for handling http requests. I have tried the Volley Request in a new Android Project with no other code and the request is handled properly and I receive the result I expected. But for some reason when I use this code in my working project as a class, it doesn't return any response.
The way I call the request is:
HttpRequest request = new HttpRequest();
String url = "some-url";
String urlReturn = request.getFromURL(url, <ACTIVITY>.this);
where <ACTIVITY> is the activity I am calling the request from and "some-url" is a url that returns a string of data.
public class HttpRequest {
String response_test = "";
public String getFromURL (String url, Context context) {
RequestQueue requestQueue = Volley.newRequestQueue(context);
// Request a string response from the provided URL.
StringRequest stringRequest = new StringRequest(Request.Method.GET, url, new Response.Listener<String>() {
#Override
public void onResponse(String response) {
Log.e("response1", response);
response_test = "1";
}
},
new Response.ErrorListener() {
#Override
public void onErrorResponse(VolleyError error) {
error.printStackTrace();
Log.d("log2=", error.toString());
//requestQueue.stop();
}
});
// Add the request to the RequestQueue.
requestQueue.add(stringRequest);
requestQueue.start();
return response_test;
}
response_test never changes, so onResponse is never called. I thought there may be a timing issue, but when I add loop for it to wait until response_test is changed, it waits forever. Any idea what may be the issue? Anything I may have overlooked in how I'm calling this class?
Any help appreciated.
Volley is async library. It does work on another thread and when the call is ready it executes the code in onResponse. In the example you are returning imideately. Check your logcat for the messages they should be there