OkHttp trigger callback in originated class after finishing network actions - android

Here is the scenario: I have an Activity, named MainActivity, calling a OkHttp wrapper class, named NetworkManager to perform network post in background:
// In MainActivity
NetworkManager manager = new NetworkManager();
try {
manager.post("http://www.example.com/api/", reqObj); // reqObj is a JSONObject
} catch(IOException ioe) {
Log.e(TAG, ioe.getMessage());
}
Then, in the NetworkManager, I perform the POST action in asynchronous mode:
public class NetworkManager {
static String TAG = "NetworkManager";
public static final MediaType JSON = MediaType.parse("application/json; charset=utf-8");
OkHttpClient client = new OkHttpClient();
void post(String url, JSONObject json) throws IOException {
//RequestBody body = RequestBody.create(JSON, json);
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();
// Asynchronous Mode
client.newCall(request).enqueue(new Callback() {
#Override
public void onFailure(Request request, IOException e) {
Log.e(TAG, e.toString());
// what should I put here?
}
#Override
public void onResponse(Response response) throws IOException {
Log.w(TAG, response.body().string());
// what should I put here?
}
});
} catch (JSONException jsone) {
Log.e(TAG, jsone.getMessage());
}
}
}
What I'm trying to achieve is to call a function in MainActivity after network POST is successful or failed. How can I achieve this?

You can create an interface with onFailure and onResponse then let YourActivity implement it. And, on NetworkManagertry to notify YourActivity using listener.
// MainActivity implements NetworkListener
NetworkManager manager = new NetworkManager();
manager.setOnNetWorkListener(this);
try {
manager.post("http://www.example.com/api/", reqObj); // reqObj is a JSONObject
} catch(IOException ioe) {
Log.e(TAG, ioe.getMessage());
}
void onFailure(Request request, IOException e) {
// call your activity methods
}
void onResponse(Response response) {
// call your activity methods
}
// ======NetworkManager class============
public class NetworkManager {
static String TAG = "NetworkManager";
public static final MediaType JSON = MediaType.parse("application/json; charset=utf-8");
OkHttpClient client = new OkHttpClient();
public NetworkListenerv listener;
public void setOnNetWorkListener(NetworkListener listener) {
this.listener = listener
}
// Asynchronous Mode
client.newCall(request).enqueue(new Callback() {
#Override
public void onFailure(Request request, IOException e) {
Log.e(TAG, e.toString());
// what should I put here?
if (listener != null) {
listener.onFailure(request, e);
}
}
#Override
public void onResponse(Response response) throws IOException {
Log.w(TAG, response.body().string());
// what should I put here?
if (listener != null) {
listener.onResponse(response);
}
}
});
// Your interface;
public interface NetworkListener {
void onFailure(Request request, IOException e);
void onResponse(Response response);
}

Related

okhttp get request return body is not as I expected

I use okhttp to get text of certain url.
url I try to get is
https://firebasestorage.googleapis.com/v0/b/famhouse.appspot.com/o/branchname%2Ftextfile?alt=media&token=a58b07a4-ddee-4ece-8222-0854a6c2a713
as you can see, it only have body saying "Testtest"
I get response well and I logged response.body().toString() but it says
okhttp3.internal.http.RealResponseBody#e640919
What I expect to see on log is Testtest
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
mContext=this.getApplicationContext();
checkPermission();
OkHttpHandler okHttpHandler= new OkHttpHandler();
okHttpHandler.execute("https://firebasestorage.googleapis.com/v0/b/famhouse.appspot.com/o/branchname%2Ftextfile?alt=media&token=a58b07a4-ddee-4ece-8222-0854a6c2a713");
}
public class OkHttpHandler extends AsyncTask {
OkHttpClient client = new OkHttpClient();
#Override
protected Object doInBackground(Object[] objects) {
Request request = new Request.Builder()
.url("https://firebasestorage.googleapis.com/v0/b/famhouse.appspot.com/o/branchname%2Ftextfile?alt=media&token=a58b07a4-ddee-4ece-8222-0854a6c2a713").addHeader("Accept", "application/json")
.build();
client.newCall(request).enqueue(new Callback() {
#Override
public void onFailure(Call call, IOException e) {
e.printStackTrace();
}
#Override
public void onResponse(Call call, final Response response) throws IOException {
if (!response.isSuccessful()) {
throw new IOException("Unexpected code " + response);
} else {
Log.e("dialog","response is : "+response.body().toString());
Log.e("dialog","response is : "+response.code());
}
}
});
return null;
}
}
you should use response.body().string()

OkHttp on Android

This is my code to get the JSON string from my PHP server.
When I run this the app crashes and says that there is an error with Response response = client.newCall(request).execute();
What am I doing wrong?
public class MainActivity extends Activity {
//private static final String TAG = "MainActivity";
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
new AsyncTask<Void, Void, String>(){
#Override
protected String doInBackground(Void... params) {
OkHttpClient client = new OkHttpClient();
Request request = new Request.Builder()
.url(url)
.build();
try {
Response response = client.newCall(request).execute();
Log.d("OkHttp", "doInBackground() called with: " + "params = [" + response.body().string() + "]");
return response.body().string();
}
catch (IOException e) {
e.printStackTrace();
}
return null;
}
}.execute();
}
}
You don't need to put this into an async task as you can use the call back of the OKHttp library which itself is async.
Second thing is you are using the wrong method. Instead of execute() you should use enqueue() which has a callback as a parameter as I mentioned above.
Try this code:
OkHttpClient client = new OkHttpClient();
Request request = new Request.Builder()
.url(url)
.build();
Call call = client.newCall(request);
call.enqueue(new Callback() {
#Override
public void onFailure(Call call, IOException e) {
// Observe reason of failure using
e.printStackTrace();
}
#Override
public void onResponse(Call call, Response response) throws IOException {
if(response.isSuccessful()){
// Use response here
}
else{
// Observe error
}
}
});

Android: OkHttp request within AsyncTask is called twice

I have a OkHttp request within an async taks doInBackgroun(), The resquest is a bit heavy and takes some time on my backend. Unfortunatly it looks like when OKHttp doesn't get an answer straight away it tries again, this makes my server blow up !
I have tried to disable this function but it seems to ignore it... What could i do ?
public class AsyncUpdateNewPatients extends AsyncTask<Object, Void, Boolean> {
private static OkHttpClient okHttpClient;
private static DatabaseHandler db;
ActivityMain activityMain;
public AsyncUpdateNewPatients (ActivityMain atv)
{
this.activityMain = atv;
}
#Override
protected void onPreExecute() {
super.onPreExecute();
HttpLoggingInterceptor httpLoggingInterceptor = new HttpLoggingInterceptor(new HttpLoggingInterceptor.Logger() {
#Override
public void log(String message) {
Stormpath.logger().d(message);
}
});
httpLoggingInterceptor.setLevel(HttpLoggingInterceptor.Level.BODY);
okHttpClient = new OkHttpClient.Builder()
.addNetworkInterceptor(httpLoggingInterceptor)
.retryOnConnectionFailure(false)
.connectTimeout(15, TimeUnit.SECONDS)
.readTimeout(15L, TimeUnit.SECONDS)
.writeTimeout(15L, TimeUnit.SECONDS)
.build();
db = new DatabaseHandler(activityMain);
}
#Override
protected Boolean doInBackground(Object... objects) {
List<PatientData> allNewPatients = db.getAllNewPatients();
JSONArray allNewPatientJSONArray = new JSONArray();
for (PatientData tempPatientObject : allNewPatients) {
JSONObject tempPatientJSON = new JSONObject();
try {
tempPatientJSON.put("firstName", tempPatientObject.getFirstName());
tempPatientJSON.put("lastName", tempPatientObject.getLastName());
tempPatientJSON.put("height", tempPatientObject.getHeight());
tempPatientJSON.put("weight", tempPatientObject.getWeight());
tempPatientJSON.put("vaccines", tempPatientObject.getVaccinHistory());
tempPatientJSON.put("address", tempPatientObject.getAddress());
tempPatientJSON.put("zone", tempPatientObject.getZone());
tempPatientJSON.put("id", tempPatientObject.getId());
String dateOfBirth = tempPatientObject.getDateOfBirth().get(Calendar.DAY_OF_MONTH) + "/" + tempPatientObject.getDateOfBirth().get(Calendar.MONTH) + "/" + tempPatientObject.getDateOfBirth().get(Calendar.YEAR);
tempPatientJSON.put("dob",dateOfBirth);
} catch (JSONException e) {
e.printStackTrace();
}
allNewPatientJSONArray.put(tempPatientJSON);
}
if(allNewPatients.size() > 0){
JSONObject bodyJSON = new JSONObject();
try {
bodyJSON.put("allNewPatients", allNewPatientJSONArray);
} catch (JSONException e) {
e.printStackTrace();
}
final MediaType JSON = MediaType.parse("application/json; charset=utf-8");
final RequestBody body = RequestBody.create(JSON, String.valueOf(bodyJSON));
Request request = new Request.Builder()
.url(activityMain.getString(R.string.main_url) + "/api/syncFromOffLine")
.headers(buildStandardHeaders(Stormpath.accessToken()))
.post(body)
.build();
okHttpClient.newCall(request).enqueue(new Callback() {
#Override
public void onFailure(Call call, IOException e) {
Log.d("DEBEUG", "error: " + e.getMessage());
}
#Override
public void onResponse(Call call, Response response) throws IOException {
if(response.code() == 200){
Log.d("DEBEUG", "response: " + response.body().string());
} else {
Log.d("DEBEUG", "there was an error: " + response.message().toString());
}
}
});
}
return true;
}

okhttp3 how to return value from async GET call

I am implementing Helper class in Android studio to service Activity
public void getLastId()
{
//init OkHttpClient
OkHttpClient client = new OkHttpClient();
//backend url
Request request = new Request.Builder()
.url("http://192.168.1.102:8080/aquabackend/public/customers/lastid")
.build();
client.newCall(request).enqueue(new Callback() {
#Override
public void onFailure(Call call, IOException e) {
}
#Override
public void onResponse(Call call, Response response) throws IOException {
String jsonData = response.body().string();
try {
JSONObject jobject = new JSONObject(jsonData);
String id = jobject.getString("id");
//increment current id +1
String last_id = String.valueOf(Integer.parseInt(id)+1);
Log.i("new id", last_id);
} catch (Exception e) {
e.printStackTrace();
}
//Log.i("ok", response.body().string());
}
});
My function call in activity class
Helper helper = new Helper();
helper.getLastId();
//I want to get method to return lastId and then manipulate with the data
How can I make method return value of the id?
As it is an asynchronous process you won't be able to return a value from the method itself. However, you can use a callback to provide you the value when the asynchronous process has been completed. Below is an example of how you might want to do this.
public interface GetLastIdCallback {
void lastId(String id);
}
You would modify getLastId as follows:
public void getLastId(GetLastIdCallback idCallback) {
...
String last_id = String.valueOf(Integer.parseInt(id)+1);
idCallback.lastId(last_id);
...
}
Your Helper class usage would now look like this:
Helper helper = new Helper();
helper.getLastId(new GetLastIdCallback() {
#Override
public void lastId(String id) {
// Do something with your id
}
});
I'd suggest making your callback a bit more generic than I have suggested above. It could look like this:
public interface GenericCallback<T> {
void onValue(T value);
}
...
Helper helper = new Helper();
helper.getLastId(new GenericCallback<String>() {
#Override
public void onValue(String value) {
// Do something
}
});
If you used an interface like above you would be able to work with any return type.
Create a interface.
public interface Result{
void getResult(String id);
}
Now, pass interface to method as parameter.
Helper helper = new Helper();
helper.getLastId(new Result(){
#Override
void getResult(String id){
}
});
And In your method :
public void getLastId(final Result result)
{
//init OkHttpClient
OkHttpClient client = new OkHttpClient();
//backend url
Request request = new Request.Builder()
.url("http://192.168.1.102:8080/aquabackend/public/customers/lastid")
.build();
client.newCall(request).enqueue(new Callback() {
#Override
public void onFailure(Call call, IOException e) {
}
#Override
public void onResponse(Call call, Response response) throws IOException {
String jsonData = response.body().string();
try {
JSONObject jobject = new JSONObject(jsonData);
String id = jobject.getString("id");
//increment current id +1
String last_id = String.valueOf(Integer.parseInt(id)+1);
Log.i("new id", last_id);
result.getResult(last_id);
} catch (Exception e) {
e.printStackTrace();
}
//Log.i("ok", response.body().string());
}
});
You have to create interface for it.
public interface getResponse {
void getJsonResponse(final String id);
}
In Your code :
public void getLastId(fianl getResponse response)
{
//init OkHttpClient
OkHttpClient client = new OkHttpClient();
//backend url
Request request = new Request.Builder()
.url("http://192.168.1.102:8080/aquabackend/public/customers/lastid")
.build();
client.newCall(request).enqueue(new Callback() {
#Override
public void onFailure(Call call, IOException e) {
}
#Override
public void onResponse(Call call, Response response) throws IOException {
String jsonData = response.body().string();
try {
JSONObject jobject = new JSONObject(jsonData);
String id = jobject.getString("id");
//increment current id +1
String last_id = String.valueOf(Integer.parseInt(id)+1);
Log.i("new id", last_id);
if(response!=null){
response.getJsonResponse(last_id)
}
} catch (Exception e) {
e.printStackTrace();
}
//Log.i("ok", response.body().string());
}
});
In Activity :
public class HomeActivity extends AppCompatActivity {
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
Helper helper = new Helper();
helper.getLastId(new getResponse(){
#Override
void getJsonResponse(String id){
}
});
}}
}

Android Listener pattern vs Callback pattern

When I'm working on networking functions in OkHttp, there are mainly 2 patterns I come across with:
Listener pattern
Callback pattern
Listener Pattern example:
// Listener class
public interface NetworkListener {
void onFailure(Request request, IOException e);
void onResponse(Response response);
}
// NetworkManager class
public class NetworkManager {
static String TAG = "NetworkManager";
public NetworkListener listener;
OkHttpClient client = new OkHttpClient();
public void setListener(NetworkListener listener) {
this.listener = listener;
}
void post(String url, JSONObject json) throws IOException {
//RequestBody body = RequestBody.create(JSON, json);
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();
// Asynchronous Mode
client.newCall(request).enqueue(new Callback() {
#Override
public void onFailure(Request request, IOException e) {
Log.e(TAG, e.toString());
if(listener != null) {
listener.onFailure(request, e);
}
}
#Override
public void onResponse(Response response) throws IOException {
Log.w(TAG, response.body().string());
if(listener != null) {
listener.onResponse(response);
}
}
});
} catch (JSONException jsone) {
Log.e(TAG, jsone.getMessage());
}
}
}
// In the Activity
NetworkManager manager = new NetworkManager();
manager.setListener(this);
try {
requestState = RequestState.REQUESTING;
manager.post("http://www.example.com/api.php", reqObj);
} catch(IOException ioe) {
Log.e(TAG, ioe.getMessage());
}
Callback Pattern example:
// in onCreate
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
try {
doGET(new Callback() {
#Override
public void onFailure(Request request, IOException e) {
Log.d("OkHttp", "Shit happens");
}
#Override
public void onResponse(Response response) throws IOException {
if (response.isSuccessful()) {
String strResponse = response.body().string();
Gson gson = new Gson();
Wrapper wrapper = gson.fromJson(strResponse, Wrapper.class);
Log.d("OkHttp", wrapper.getListContents());
} else {
Log.d("OkHttp", "Request not successful");
}
}
});
} catch (IOException e) {
e.printStackTrace();
}
}
Call doGET(Callback callback) throws IOException {
// Start Network Request
OkHttpClient client = new OkHttpClient();
Request request = new Request.Builder().url("http://www.example.com/api.php").build();
Call call = client.newCall(request);
call.enqueue(callback);
return call;
}
What are the advantages and disadvantages of using the 2 patterns above?
IMHO, they are not different, actually you can find that Callback is also an interface.
package com.squareup.okhttp;
import java.io.IOException;
public interface Callback {
/**
* Called when the request could not be executed due to cancellation, a
* connectivity problem or timeout. Because networks can fail during an
* exchange, it is possible that the remote server accepted the request
* before the failure.
*/
void onFailure(Request request, IOException e);
/**
* Called when the HTTP response was successfully returned by the remote
* server. The callback may proceed to read the response body with {#link
* Response#body}. The response is still live until its response body is
* closed with {#code response.body().close()}. The recipient of the callback
* may even consume the response body on another thread.
*
* <p>Note that transport-layer success (receiving a HTTP response code,
* headers and body) does not necessarily indicate application-layer
* success: {#code response} may still indicate an unhappy HTTP response
* code like 404 or 500.
*/
void onResponse(Response response) throws IOException;
}
However, when I want to reuse some codes (or build an util class), I often use as the following:
Interface:
public interface OkHttpListener {
void onFailure(Request request, IOException e);
void onResponse(Response response) throws IOException;
}
Util class:
public class OkHttpUtils {
public static void getData(String url, final OkHttpListener listener){
OkHttpClient client = new OkHttpClient();
// GET request
Request request = new Request.Builder()
.url(url)
.build();
client.newCall(request).enqueue(new Callback() {
#Override
public void onFailure(Request request, IOException e) {
listener.onFailure(request, e);
}
#Override
public void onResponse(Response response) throws IOException {
listener.onResponse(response);
}
});
}
// the following uses built-in okhttp's Callback interface
public static void getData2(String url, Callback callbackListener){
OkHttpClient client = new OkHttpClient();
// GET request
Request request = new Request.Builder()
.url(url)
.build();
client.newCall(request).enqueue(callbackListener);
}
// other methods...
}
Then in activity classes:
OkHttpListener listener = new OkHttpListener() {
#Override
public void onFailure(Request request, IOException e) {
Log.e(LOG_TAG, e.toString());
}
#Override
public void onResponse(Response response) throws IOException {
String responseBody = response.body().string();
Log.i(LOG_TAG, responseBody);
}
};
String url = "http://myserver/api/getvalues";
OkHttpUtils.getData(url, listener);
String url1 = "http://myserver/api/getvalues/123";
OkHttpUtils.getData(url1, listener);
or
Callback callbackListener = new Callback() {
#Override
public void onFailure(Request request, IOException e) {
Log.e(LOG_TAG, e.toString());
}
#Override
public void onResponse(Response response) throws IOException {
String responseBody = response.body().string();
Log.i(LOG_TAG, responseBody);
}
};
String url = "http://myserver/api/getvalues";
OkHttpUtils.getData2(url, callbackListener);
String url1 = "http://myserver/api/getvalues/123";
OkHttpUtils.getData2(url1, callbackListener);
Hope it helps!

Categories

Resources