Android Studio - Java - API - java

Im using OkHttpClient to connect to an API.
Request request = new Request.Builder()
.url(BPI_ENDPOINT)
.build();
okHttpClient.newCall(request).enqueue(new Callback() {
#Override
public void onFailure(Call call, IOException e) {
Toast.makeText(Test.this, "Error during BPI loading : "
+ e.getMessage(), Toast.LENGTH_SHORT).show();
}
#Override
public void onResponse(Call call, Response response)
throws IOException {
final String body = response.body().string();
runOnUiThread(new Runnable() {
#Override
public void run() {
parseBpiResponse(body);
}
});
}
});
The parseBpiResponse just displays the data in TextView but the data request from the site takes place only once and in order to get the data again I need to either reopoen the activity or implement a button or swipe-screen etc,
How to call an API request constantly so that the data keeps updating instead of doing it through users input??

you can use Timer class to do a network call periodically
final long period = 0;
new Timer().schedule(new TimerTask() {
#Override
public void run() {
// do your task here
}
}, 0, period);

use this code but you should be careful about your activity and views in this code it my lead to nasty exception and memory leaks better thing to do is using live data with Recursion function !
new Thread(new Runnable() {
#Override
public void run() {
//Checks the life cycle of the activity and if activity was destroyed break the while loop and exits
while (true && getLifecycle().getCurrentState() != Lifecycle.State.DESTROYED) {
okHttpClient.newCall(request).enqueue(new Callback() {
#Override
public void onFailure(Call call, IOException e) {
Toast.makeText(Test.this, "Error during BPI loading : "
+ e.getMessage(), Toast.LENGTH_SHORT).show();
}
#Override
public void onResponse(Call call, Response response)
throws IOException {
final String body = response.body().string();
runOnUiThread(new Runnable() {
#Override
public void run() {
if (getLifecycle().getCurrentState() != Lifecycle.State.DESTROYED)
parseBpiResponse(body);
}
});
}
});
try {
//Waits for 1 sec
TimeUnit.SECONDS.sleep(1);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
}).start();

Just make a recursive call .for example :
public void callAPI()
{
okHttpClient.newCall(request).enqueue(new Callback() {
#Override
public void onFailure(Call call, IOException e) {
Toast.makeText(Test.this, "Error during BPI loading : "
+ e.getMessage(), Toast.LENGTH_SHORT).show();
}
#Override
public void onResponse(Call call, Response response)
throws IOException {
final String body = response.body().string();
runOnUiThread(new Runnable() {
#Override
public void run() {
parseBpiResponse(body);
}
});
**//just use handler/timer or thread to post event after some interval**
new android.os.Handler().postDelayed(new Runnable() {
#Override
public void run() {
callAPI();
}
},2000);
}
});
}
Also i suggest using Rxjava+Retrofit with OkHttp and use interval function to make it easier .

Related

Android Newbie - Can't extract token from the server response

I run this code :
protected Object doInBackground(Object[] objects) {
HttpClient client = new HttpClient();
client.get(get_token, new HttpResponseCallback() {
#Override
public void success(String responseBody) {
runOnUiThread(new Runnable() {
#Override
public void run() {
llHolder.setVisibility(View.VISIBLE);
}
});
token = responseBody;
}
And the responseBody gives me back :
{"response":{"token":"eyJ2ZXJzaW9uIjoyLCJhdXRob3JpemF0aW9uRmlJ9","status":"success"}}
How do I get "token" as a string , same for "status"
Use this code.
protected Object doInBackground(Object[] objects) {
HttpClient client = new HttpClient();
client.get(get_token, new HttpResponseCallback() {
#Override
public void success(String responseBody) {
runOnUiThread(new Runnable() {
#Override
public void run() {
llHolder.setVisibility(View.VISIBLE);
try {
JSONObject jObject = new JSONObject(responseBody);
String token = jObject.getString("token");
} catch (JSONException e) {
e.printStackTrace();
}
}
});
}
for more info look this answer

RxAndroid: Know When Individual Operations Complete as well as When All of them Completes

I am new to RxJava, I have managed to implement RxJava with Retrofit to download multiple files concurrently using flatMap. I am successfully receiving the onComplete Status of individual Downloads. But I am not able to implement Functionality where I receive a Completion Status of all the Downloads.
Below is my code I am using for multiple downloads:
private void downloadFile(String url, final File parentFolder) {
final Uri uri = Uri.parse(url);
Retrofit retrofit = new Retrofit.Builder()
.baseUrl(url.replace(uri.getLastPathSegment(),""))
.client(new OkHttpClient.Builder().build())
.addCallAdapterFactory(RxJavaCallAdapterFactory.create()).build();
RestApi restApi = retrofit.create(RestApi.class);
restApi.downloadFile(url)
.flatMap(new Func1<Response<ResponseBody>, Observable<File>>() {
#Override
public Observable<File> call(final Response<ResponseBody> responseBodyResponse) {
return Observable.fromCallable(new Callable<File>() {
#Override
public File call() throws Exception {
File file = new File(parentFolder.getAbsoluteFile(), uri.getLastPathSegment());
if (!file.exists()) {
file.createNewFile();
BufferedSink sink = Okio.buffer(Okio.sink(file));
sink.writeAll(responseBodyResponse.body().source());
sink.close();
}
return file;
}
});
}
},3)
.subscribeOn(Schedulers.io())
.observeOn(AndroidSchedulers.mainThread())
.subscribe(new Observer<File>() {
#Override
public void onCompleted() {
dManager.logMe(TAG,"file download complete");
}
#Override
public void onError(Throwable e) {
dManager.logMe(TAG,"file download error");
e.printStackTrace();
}
#Override
public void onNext(File file) {
dManager.logMe(TAG,"file download onNext: " + file.getAbsolutePath());
}
});
}
I call downloadFile(String url, final File parentFolder inside a number of for loops wherever I receive URL information.
Thanks in Advance.
Supposing you have a List<String> of urls:
Observable.from(urls)
.flatMap(url -> restApi.downloadFile(url))
.concatMap(new Func1<Response<ResponseBody>, Observable<File>>() {
#Override
public Observable<File> call(final Response<ResponseBody> responseBodyResponse) {
try {
File file = new File(parentFolder.getAbsoluteFile(), uri.getLastPathSegment());
if (!file.exists()) {
file.createNewFile();
}
BufferedSink sink = Okio.buffer(Okio.sink(file));
sink.writeAll(responseBodyResponse.body().source());
sink.close();
return Observable.just(file);
} catch (Exception e) {
return Observable.error(e);
}
}
})
.subscribeOn(Schedulers.io())
.observeOn(AndroidSchedulers.mainThread())
.subscribe(new Observer<File>() {
#Override
public void onCompleted() {
dManager.logMe(TAG, "file download complete");
}
#Override
public void onError(Throwable e) {
dManager.logMe(TAG, "file download error");
e.printStackTrace();
}
#Override
public void onNext(File file) {
dManager.logMe(TAG, "file download onNext: " + file.getAbsolutePath());
}
});
Here is an scratch example
Observable.from(List <Url>)
.flatMap(Observable.fromCallable(downloadImageHereAndReturnTheFile())
.observeOn(AndroidSchedulers.mainThread())
// Do on next is where you get notified when each url is getting downloaded
.doOnNext(doTheUIOperationHere())
.observeOn(Schedulers.io()) //Switch to background thread if you want, in case if you do some other background task otherwise remove the above this and the following next operator
.doOnNext(DoSomeOtherOperationHere()))
.observeOn(AndroidSchedulers.mainThread())
.subscribeOn(Schedulers.io())
.subscribe(new Subscriber<R>() {
#Override
public void onCompleted() {
Log.d(TAG, "The entire process of downloading all the image completed here");
}
#Override
public void onError(Throwable e) {
}
#Override
public void onNext(R r) {
Log.d(TAG, "You receive the file for each url");
}
});

Main thread cannot get notify from thread

I'm using retrofit2 to get data from web service, but when I called notify() from thread , main thread cannot get it . And hang app , I don't know why . I hope someone can help me .
OnCreate()
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
synchronized (listRespones) {
while (listRespones.size() < 2) {
try {
listRespones.wait();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
Thread 1:
apiManager.getChannelListRespone(areaCode).enqueue(new Callback<CommonListRespone>() {
#Override
public void onResponse(Call<CommonListRespone> call, final Response<CommonListRespone> response) {
Thread channel1 = new Thread(new Runnable() {
#Override
public void run() {
synchronized (listRespones) {
CommonListRespone commonChannel = response.body();
listRespones.add(commonChannel);
listRespones.notify();
}
}});
channel1.start();
}
#Override
public void onFailure(Call<CommonListRespone> call, Throwable t) {
}});
Thread 2:
apiManager.getChannelListRespone(areaCode).enqueue(new Callback<CommonListRespone>() {
#Override
public void onResponse(Call<CommonListRespone> call, final Response<CommonListRespone> response) {
Thread channel2 = new Thread(new Runnable() {
#Override
public void run() {
synchronized (listRespones) {
CommonListRespone commonChannel = response.body();
listRespones.add(commonChannel);
listRespones.notify();
}
}
});
channel2.start();
}
#Override
public void onFailure(Call<CommonListRespone> call, Throwable t) {
}
});

Creating a callback function using AsyncTask

I've created an AsyncTask class to handle sending and receiving from my server. What I'm trying to do is fire an event or callback when the data is received so I can use said data to manipulate the UI.
AsyncTask class:
public class DataCollectClass extends AsyncTask<Object, Void, JSONObject> {
private JSONObject collected;
#Override
protected void onPreExecute() {
super.onPreExecute();
}
//#Override -Commented out because it doesn't like the override
protected void onPostExecute() {
try {
Log.d("Net", this.collected.getString("message"));
} catch (JSONException e) {
e.printStackTrace();
}
}
#Override
protected JSONObject doInBackground(Object... params) {
OkHttpClient client = new OkHttpClient();
// Get Parameters //
String requestURI = (String) params[0];
RequestBody formParameters = (RequestBody) params[1];
Request request = new Request.Builder().url(requestURI).post(formParameters).build();
client.newCall(request).enqueue(new Callback() {
#Override
public void onFailure(Call call, IOException e) {
// DO something on FAIL
}
#Override
public void onResponse(Call call, Response response) throws IOException {
String jsonResponse = response.body().string();
Log.d("Net", jsonResponse);
try {
DataCollectClass.this.collected = new JSONObject(jsonResponse);
Log.d("Net", DataCollectClass.this.collected.getString("message"));
} catch (JSONException e) {
e.printStackTrace();
}
}
});
return collected;
}
}
This is working, it prints an expected line of JSON into the log.
It's called from the Activity as:
new DataCollectClass().execute(requestURI, formVars);
I've looked all over, and I can't seem to find a definitive answer on how (and where) to add a callback. Preferably, the callback code itself should be with the DataCollectClass so all related code is reusable in the same place.
Is there a way to create a custom event firing (similar to Javascript libraries) that the program can listen for?
I've been pulling my hair out over this!
UPDATE:
Since AsyncTask is redundant, I've removed it and rewrote the code (in case someone else has this same issue):
public class DataCollectClass {
private JSONObject collected;
public interface OnDataCollectedCallback {
void onDataCollected(JSONObject data);
}
private OnDataCollectedCallback mCallback;
public DataCollectClass(OnDataCollectedCallback callback, String requestURI, RequestBody formParameters){
mCallback = callback;
this.collect(requestURI, formParameters);
}
public JSONObject collect(String requestURI, RequestBody formParameters) {
OkHttpClient client = new OkHttpClient();
Request request = new Request.Builder().url(requestURI).post(formParameters).build();
client.newCall(request).enqueue(new Callback() {
#Override
public void onFailure(Call call, IOException e) {
//TODO Add what happens when shit fucks up...
}
#Override
public void onResponse(Call call, Response response) throws IOException {
String jsonResponse = response.body().string();
Log.d("Net", jsonResponse);
try {
DataCollectClass.this.collected = new JSONObject(jsonResponse);
if(mCallback != null)
mCallback.onDataCollected(DataCollectClass.this.collected);
} catch (JSONException e) {
e.printStackTrace();
}
}
});
return collected;
}
}
Called from Activity:
new DataCollectClass(new DataCollectClass.OnDataCollectedCallback() {
#Override
public void onDataCollected(JSONObject data) {
if(data != null) {
try {
// Do Something //
} catch (JSONException e) {
e.printStackTrace();
}
}
}
}, requestURI, formVars);
All working perfectly!
Thanks!
If you want to utilize a callback for an AsyncTask you can handle it via the following.
Do something like this (modifying your code to add what is below)
public class DataCollectClass extends AsyncTask<Object, Void, JSONObject> {
public interface OnDataCollectedCallback{
void onDataCollected(JSONObject data);
}
private OnDataCollectedCallback mCallback;
public DataCollectClass(OnDataCollectedCallback callback){
mCallback = callback;
}
// your code that is already there
...
#Override
public onPostExecute(JSONObject response){
if(mCallback != null)
mCallback.onDataCollected(response);
}
}
Then to make the magic happen
new DataCollectClass(new OnDataCollectedCallback() {
#Override
public void onDataCollected(JSONObject data) {
if(data != null)
// DO something with your data
}
}).execute(requestURI, formVars);
However, it is worth noting, most networking libraries, including OkHttp, handle background threads internally, and include callbacks to utilize with the requests.
This also implements a custom interface, so others may be able to see how you could use this for any AsyncTask.
There is a asynchronous get in OkHttp, so you don't need an AsyncTask, but as a learning exercise, you could define your callback as a parameter something like so.
new DataCollectClass(new Callback() {
#Override
public void onFailure(Call call, IOException e) {
// DO something on FAIL
}
#Override
public void onResponse(Call call, Response response) throws IOException {
JSONObject collected = null;
String jsonResponse = response.body().string();
Log.d("Callback - Net", jsonResponse);
try {
collected = new JSONObject(jsonResponse);
Log.d("Callback - Net", collected.getString("message"));
} catch (JSONException e) {
e.printStackTrace();
}
}
}).execute(requestURI, formVars);
The AsyncTask
public class DataCollectClass extends AsyncTask<Object, Void, Call> {
private Callback mCallback;
private OkHttpClient client;
public DataCollectClass(Callback callback) {
this.mCallback = callback;
}
#Override
protected void onPreExecute() {
super.onPreExecute();
this.client = new OkHttpClient();
}
#Override
protected void onPostExecute(Call response) {
if (response != null && this.mCallback != null) {
response.enqueue(this.mCallback);
}
}
#Override
protected Call doInBackground(Object... params) {
// Get Parameters //
String requestURI = (String) params[0];
RequestBody formParameters = (RequestBody) params[1];
Request request = new Request.Builder().url(requestURI).post(formParameters).build();
return client.newCall(request); // returns to onPostExecute
}
}
Call Webservice using asynctask is an old fashioned. You can use Volley or retrofit.
But you can use this process to call Webservice . Here is steps:
Create an Interface and implements it in your Activity/Fragment
public interface IAsynchronousTask {
public void showProgressBar();
public void hideProgressBar();
public Object doInBackground();
public void processDataAfterDownload(Object data);
}
Create Class DownloadableAsyncTask . This class is:
import android.os.AsyncTask;
import android.util.Log;
public class DownloadableAsyncTask extends AsyncTask<Void, Void, Object> {
IAsynchronousTask asynchronousTask;
public DownloadableAsyncTask(IAsynchronousTask activity) {
this.asynchronousTask = activity;
}
#Override
protected void onPreExecute() {
if (asynchronousTask != null)
asynchronousTask.showProgressBar();
}
#Override
protected Object doInBackground(Void... params) {
try {
if (asynchronousTask != null) {
return asynchronousTask.doInBackground();
}
} catch (Exception ex) {
Log.d("BSS", ex.getMessage()==null?"":ex.getMessage());
}
return null;
}
#Override
protected void onPostExecute(Object result) {
if (asynchronousTask != null) {
asynchronousTask.hideProgressBar();
asynchronousTask.processDataAfterDownload(result);
}
}
}
Now in your Activity you will find this methods.
DownloadableAsyncTask downloadAsyncTask;
ProgressDialog dialog;
private void loadInformation() {
if (downloadAsyncTask != null)
downloadAsyncTask.cancel(true);
downloadAsyncTask = new DownloadableAsyncTask(this);
downloadAsyncTask.execute();
}
#Override
public void showProgressBar() {
dialog = new ProgressDialog(this, ProgressDialog.THEME_HOLO_LIGHT);
dialog.setMessage(" Plaese wait...");
dialog.setCancelable(false);
dialog.show();
}
#Override
public void hideProgressBar() {
dialog.dismiss();
}
#Override
public Object doInBackground() {
// Call your Web service and return value
}
#Override
public void processDataAfterDownload(Object data) {
if (data != null) {
// data is here
}else{
//"Internal Server Error!!!"
}
}
Now just call loadInformation() method then you will get your response on processDataAfterDownload().

show indeterminate progress indicator

I am trying to show a progress indicator when doing network requests with volley. I am getting the error "Only the original thread that create a view hierarchy can touch its views". I cannot figure out how to get my hideProgressDialog() onto the same thread as showProgressDialog(). Here's my code...
showProgressDialog("Logging you in");
String url = ApplicationController.getInstance().getBaseURL() + "Customer/LoginCustomer";
JsonRequest<String> jr = new JsonRequest<String>(Method.POST, url, jo.toString(), this.createSuccessListener(),
this.createErrorListener()) {
#Override
protected Response<String> parseNetworkResponse(NetworkResponse nr) {
hideProgressDialog();
try {
String str = new String(nr.data, "UTF-8");
} catch (UnsupportedEncodingException e) {
e.printStackTrace();
}
return null;
}
};
ApplicationController.getInstance().addToRequestQueue(jr);
}
/** Create Volley Listeners **/
private Response.ErrorListener createErrorListener() {
return new Response.ErrorListener() {
#Override
public void onErrorResponse(VolleyError error) {
hideProgressDialog();
}
};
}
private Response.Listener<String> createSuccessListener() {
return new Response.Listener<String>() {
#Override
public void onResponse(String response) {
hideProgressDialog();}
};
}
Solution
Thanks to tautvydas. I ended up putting these methods in my base class.
protected void showProgressDialog(String message) {
if(mHandler == null){
mHandler = new Handler();
}
if (mDialog == null || !mDialog.isShowing()) {
mDialog = new ProgressDialog(getActivity());
mDialog.setMessage(message);
mDialog.setCancelable(false);
mDialog.setIndeterminate(true);
mDialog.show();
}
}
protected void hideProgressDialog() {
if (mDialog != null) {
mHandler.post(new Runnable() {
#Override
// this will run on the main thread.
public void run() {
mDialog.hide();
}
});
}
}
Create a Handler and pass a Runnable to it to run on the main thread.
1) Declare Handler in the constructor on onCreate() method by Handler handler = new Handler(). 2) Then in your parseNetworkResponse() method call
handler.post(new Runnable() {
#Override
// this will run on the main thread.
public void run() {
hideProgressDialog();
}
});

Categories

Resources