I am trying to upload a file to Amazon s3 using a PUT request from my android application. I have got a link from server with private key exposed in the same.
When trying to upload the file from POSTMAN its working when uploaded using binary option and content type application/octet-stream or application/x-www-form-urlencoded (Tried with both) in header but if uploading same image using form data its not working.
In my android application i have tried JsonObject request using volley in which i am getting.
Json Org exception
Please find my request below
JsonObjectRequest jsonObjReq = new JsonObjectRequest(Request.Method.PUT,
url, new JSONObject(parameters),
new Response.Listener<JSONObject>() {
#Override
public void onResponse(JSONObject response) {
if (listener != null) {
Log.e("Response", response + "");
listener.onResult(response + "", responseCode);
if (showDialog == true) {
try {
mOverlayDialog.dismiss();
} catch (Exception e) {
// Crashlytics.logException(e);
}
try {
materialDialog.dismiss(); // To hide the progress bar
} catch (Exception e) {
// Crashlytics.logException(e);
}
}
}
}
}, new Response.ErrorListener() {
#Override
public void onErrorResponse(VolleyError error) {
if (listener != null) {
try {
if(error.networkResponse!=null && error.networkResponse.data!=null) {
String responseBody = new String(error.networkResponse.data, "utf-8");
if (!responseBody.equalsIgnoreCase("")) {
JSONObject data = new JSONObject(responseBody);
listener.onResult(data + "", responseCode);
//listener.onResult(error.toString(), WebAPIConstants.VOLLEY_ERROR);
Log.e("ERROR", error.toString() + "");
} else {
listener.onResult("", responseCode);
}
}
else
listener.onResult("", responseCode);
} catch (JSONException e) {
} catch (UnsupportedEncodingException errorr) {
} catch (Exception e) {
Crashlytics.logException(e);
}
}
if (showDialog == true) {
try {
mOverlayDialog.dismiss();
} catch (Exception e) {
// Crashlytics.logException(e);
}
try {
materialDialog.dismiss(); // To hide the progress bar
} catch (Exception e) {
// Crashlytics.logException(e);
}
}
try {
if (error instanceof TimeoutError) {
AlertDialogManager.showAlertDialog(mContext, mContext.getResources().getString(R.string.timeout_error_title), mContext.getResources().getString(R.string.timeout_error_string), new MaterialDialog.SingleButtonCallback() {
#Override
public void onClick(#NonNull MaterialDialog dialog, #NonNull DialogAction which) {
}
});
} else if (error instanceof NoConnectionError) {
if (CheckInternetConnection.haveNetworkConnection(mContext)) {
AlertDialogManager.showAlertDialog(mContext, mContext.getResources().getString(R.string.timeout_error_title), mContext.getResources().getString(R.string.timeout_error_string), new MaterialDialog.SingleButtonCallback() {
#Override
public void onClick(#NonNull MaterialDialog dialog, #NonNull DialogAction which) {
}
});
} else {
AlertDialogManager.showAlertDialog(mContext, mContext.getResources().getString(R.string.no_internet_title), mContext.getResources().getString(R.string.no_internet_message), new MaterialDialog.SingleButtonCallback() {
#Override
public void onClick(#NonNull MaterialDialog dialog, #NonNull DialogAction which) {
}
});
}
}
} catch (Exception e) {
Crashlytics.logException(e);
}
}
(Have sent image in bytecode), On using String request the image is being uploaded but with size 1kB but dosent open on server (Have sent image in bytecode).
String request
StringRequest stringRequest=new StringRequest(Request.Method.PUT, url, new Response.Listener<String>() {
#Override
public void onResponse(String response) {
if (listener != null) {
Log.e("Response", response + "");
if (showDialog == true) {
try {
mOverlayDialog.dismiss();
} catch (Exception e) {
// Crashlytics.logException(e);
}
try {
materialDialog.dismiss(); // To hide the progress bar
} catch (Exception e) {
// Crashlytics.logException(e);
}
}
}
}
}, new Response.ErrorListener() {
#Override
public void onErrorResponse(VolleyError error) {
if (listener != null) {
try {
if(error.networkResponse!=null && error.networkResponse.data!=null) {
String responseBody = new String(error.networkResponse.data, "utf-8");
if (!responseBody.equalsIgnoreCase("")) {
JSONObject data = new JSONObject(responseBody);
listener.onResult(data + "", responseCode);
//listener.onResult(error.toString(), WebAPIConstants.VOLLEY_ERROR);
Log.e("ERROR", error.toString() + "");
} else {
listener.onResult("", responseCode);
}
}
else
listener.onResult("", responseCode);
} catch (JSONException e) {
} catch (UnsupportedEncodingException errorr) {
} catch (Exception e) {
Crashlytics.logException(e);
}
}
if (showDialog == true) {
try {
mOverlayDialog.dismiss();
} catch (Exception e) {
// Crashlytics.logException(e);
}
try {
materialDialog.dismiss(); // To hide the progress bar
} catch (Exception e) {
// Crashlytics.logException(e);
}
}
try {
if (error instanceof TimeoutError) {
AlertDialogManager.showAlertDialog(mContext, mContext.getResources().getString(R.string.timeout_error_title), mContext.getResources().getString(R.string.timeout_error_string), new MaterialDialog.SingleButtonCallback() {
#Override
public void onClick(#NonNull MaterialDialog dialog, #NonNull DialogAction which) {
}
});
} else if (error instanceof NoConnectionError) {
if (CheckInternetConnection.haveNetworkConnection(mContext)) {
AlertDialogManager.showAlertDialog(mContext, mContext.getResources().getString(R.string.timeout_error_title), mContext.getResources().getString(R.string.timeout_error_string), new MaterialDialog.SingleButtonCallback() {
#Override
public void onClick(#NonNull MaterialDialog dialog, #NonNull DialogAction which) {
}
});
} else {
AlertDialogManager.showAlertDialog(mContext, mContext.getResources().getString(R.string.no_internet_title), mContext.getResources().getString(R.string.no_internet_message), new MaterialDialog.SingleButtonCallback() {
#Override
public void onClick(#NonNull MaterialDialog dialog, #NonNull DialogAction which) {
}
});
}
}
} catch (Exception e) {
Crashlytics.logException(e);
}
}
})
{
#Override
protected Response<String> parseNetworkResponse(NetworkResponse response) {
if (listener!=null) {
listener.onResult(mStatusCode + "", responseCode);
}
mStatusCode = response.statusCode;
return super.parseNetworkResponse(response);
}
#Override
protected Map<String, String> getParams() throws AuthFailureError {
return parameters;
}
#Override
public Map<String, String> getHeaders() throws AuthFailureError {
HashMap<String, String> headers = new HashMap<String, String>();
headers.put("Content-Type", "application/octet-stream");
return headers;
}
};
stringRequest.setRetryPolicy(new DefaultRetryPolicy(120000,
DefaultRetryPolicy.DEFAULT_MAX_RETRIES,
DefaultRetryPolicy.DEFAULT_BACKOFF_MULT));
try {
stringRequest.setShouldCache(false);
queue.getCache().clear();
queue.add(stringRequest);
} catch (Exception e) {
Crashlytics.logException(e);
}
Have also tried Multipart request but getting errors like auth error etc.
Multi part request where docUrl is same url as in postman
Dependency added for below request:
compile group: 'org.apache.httpcomponents' , name: 'httpclient-android' , version: '4.3.5.1'
compile('org.apache.httpcomponents:httpmime:4.3') {
exclude module: "httpclient"
}
MultipartRequestAWS class
package spice.mudra.csp_cred;
import com.android.volley.AuthFailureError;
import com.android.volley.NetworkResponse;
import com.android.volley.Request;
import com.android.volley.Response;
import com.android.volley.VolleyLog;
import org.apache.http.entity.mime.MultipartEntity;
import org.apache.http.entity.mime.content.FileBody;
import org.apache.http.entity.mime.content.StringBody;
import java.io.ByteArrayOutputStream;
import java.io.File;
import java.io.IOException;
import java.io.UnsupportedEncodingException;
public class MultipartRequestAWS extends Request<String> {
private MultipartEntity entity = new MultipartEntity();
private static final String FILE_PART_NAME = "file";
private static final String STRING_PART_NAME = "text";
private final Response.Listener<String> mListener;
private final File mFilePart;
private final String mStringPart;
public MultipartRequestAWS(String url, Response.Listener<String> listener, Response.ErrorListener errorListener,File file, String stringPart) {
super(Method.POST, url, errorListener);
mListener = listener;
mFilePart = file;
mStringPart = stringPart;
buildMultipartEntity();
}
private void buildMultipartEntity()
{
entity.addPart(FILE_PART_NAME, new FileBody(mFilePart));
try
{
entity.addPart(STRING_PART_NAME, new StringBody(mStringPart));
}
catch (UnsupportedEncodingException e)
{
VolleyLog.e("UnsupportedEncodingException");
}
}
#Override
public String getBodyContentType()
{
return "application/octet-stream";
}
#Override
public byte[] getBody() throws AuthFailureError
{
ByteArrayOutputStream bos = new ByteArrayOutputStream();
try
{
entity.writeTo(bos);
}
catch (IOException e)
{
VolleyLog.e("IOException writing to ByteArrayOutputStream");
}
return bos.toByteArray();
}
#Override
protected Response<String> parseNetworkResponse(NetworkResponse response)
{
return Response.success("Uploaded", getCacheEntry());
}
#Override
protected void deliverResponse(String response)
{
mListener.onResponse(response);
}
}
****Multipart request****
MultipartRequestAWS request = new MultipartRequestAWS(docUrl, new Response.Listener<String>() {
#Override
public void onResponse(String response) {
Log.e("Responce", "" + response);
}
}, new Response.ErrorListener() {
#Override
public void onErrorResponse(VolleyError error) {
Log.e("Responce", "" + error);
}
}, outputFile, imageArray.toString()
);
request.setRetryPolicy(new DefaultRetryPolicy(300000,
DefaultRetryPolicy.DEFAULT_MAX_RETRIES,
DefaultRetryPolicy.DEFAULT_BACKOFF_MULT));
//adding request to request queue
// if(!Constants.IS_PRODUCTION) {
Volley.newRequestQueue(this).add(request);
// }else{
// Volley.newRequestQueue(getActivity(), new OKHttpStack(new URL(request.getUrl()).getHost())).add(request);
//
// // Volley.newRequestQueue(getActivity(), new HurlStack(null, newSslSocketFactory())).add(request);
// }
Other Multipart request tried
private final String boundary = "apiclient-" + System.currentTimeMillis();
private final String mimeType = "multipart/form-data;boundary=" + boundary;
//multipartBody is byte code of image to be uploaded
MultipartRequest request = new MultipartRequest(url, null, mimeType, multipartBody, new Response.Listener<NetworkResponse>() {
#Override
public void onResponse(NetworkResponse response) {
try {
mOverlayDialogAsync.dismiss();
} catch (Exception e) {
Crashlytics.logException(e);
}
try {
materialDialogAsync.dismiss(); // To hide the progress bar
} catch (Exception e) {
Crashlytics.logException(e);
}
}
}, new Response.ErrorListener() {
#Override
public void onErrorResponse(VolleyError error) {
try {
mOverlayDialogAsync.dismiss();
} catch (Exception e) {
Crashlytics.logException(e);
}
try {
materialDialogAsync.dismiss(); // To hide the progress bar
} catch (Exception e) {
Crashlytics.logException(e);
}
try {
// getting json string form the response obtained from server
String jsonString = new String(error.toString());
Log.e("response multipart", jsonString);
} catch (Exception e) {
Crashlytics.logException(e);
}
try {
//Network errors handling
if (error instanceof TimeoutError) {
AlertDialogManager.showAlertDialog(CustomDialogNetworkRequest.this, getResources().getString(R.string.timeout_error_title), getResources().getString(R.string.timeout_error_string), new MaterialDialog.SingleButtonCallback() {
#Override
public void onClick(#NonNull MaterialDialog dialog, #NonNull DialogAction which) {
}
});
} else if (error instanceof NoConnectionError) {
if (spice.mudra.utils.CheckInternetConnection.haveNetworkConnection(AddYourProffDetails.this)) {
AlertDialogManager.showAlertDialog(AddYourProffDetails.this, getResources().getString(R.string.timeout_error_title), getResources().getString(R.string.timeout_error_string), new MaterialDialog.SingleButtonCallback() {
#Override
public void onClick(#NonNull MaterialDialog dialog, #NonNull DialogAction which) {
}
});
} else {
AlertDialogManager.showAlertDialog(AddYourProffDetails.this, getResources().getString(R.string.no_internet_title), getResources().getString(R.string.no_internet_message), new MaterialDialog.SingleButtonCallback() {
#Override
public void onClick(#NonNull MaterialDialog dialog, #NonNull DialogAction which) {
}
});
}
} else {
AlertDialogManager.showAlertDialog(AddYourProffDetails.this, "", "Something went wrong. Please try again.", new MaterialDialog.SingleButtonCallback() {
#Override
public void onClick(#NonNull MaterialDialog dialog, #NonNull DialogAction which) {
}
});
}
} catch (Exception e) {
Crashlytics.logException(e);
}
}
});
//setting timeout to multipart request
request.setRetryPolicy(new DefaultRetryPolicy(300000,
DefaultRetryPolicy.DEFAULT_MAX_RETRIES,
DefaultRetryPolicy.DEFAULT_BACKOFF_MULT));
//adding request to request queue
Log.i("++++++++++", "Request body: " + new String(request.getBody()));
Volley.newRequestQueue(CustomDialogNetworkRequest.this).add(request);
} catch (Exception e) {
Crashlytics.logException(e);
}
}
Please help with the same.
Please find POSTMAN screenshot for reference. This also has URL type that i am using.
For uploading image file add the following functions to your StringRequest object. Here outputFileUri is the Uri of the file which you want to upload. s3Url is the s3 bucket url where you want to place the image file.
StringRequest putRequest = new StringRequest(Request.Method.PUT, s3Url,
new Response.Listener<String>()
{
#Override
public void onResponse(String response) {
// response
}
},
new Response.ErrorListener()
{
#Override
public void onErrorResponse(VolleyError error) {
// error
}
}){
#Override
public String getBodyContentType() {
return "image/jpeg";
}
#Override
public byte[] getBody() throws AuthFailureError {
try {
ByteArrayOutputStream bos = new ByteArrayOutputStream();
InputStream inputStream = mContext.getContentResolver().openInputStream(outputFileUri);
byte[] b = new byte[8192];
for (int readNum; (readNum = inputStream.read(b)) != -1; ) {
bos.write(b, 0, readNum);
}
inputStream.close();
return bos.toByteArray();
} catch (Exception e) {
Log.d(TAG, e.toString());
}
return null;
}
};
Volley.newRequestQueue(this).add(putRequest);
Related
How do I check if this text appears or not
{"cod":"404","message":"city not found"}
url : http://api.openweathermap.org/data/2.5/weather?q=fddfgdfgdfgdfg&units=metric&appid=efb8013262db1b77b0431909b8b173e1
My try
public void btn_search(View view) {
CheckInternet checkInternet = new CheckInternet(MainActivity.this);
boolean ci = checkInternet.isconnecting();
if(ci)
{
EditText ed_Search = (EditText)findViewById(R.id.ed_Search);
if(ed_Search.getText().length() > 0)
{
String urlOpenWeatherMap = "http://api.openweathermap.org/data/2.5/weather?q=fddfgdfgdfgdfg&units=metric&appid=efb8013262db1b77b0431909b8b173e1";
progressBar = (ProgressBar)findViewById(R.id.progressBar);
btn_search = (ImageView)findViewById(R.id.btn_search);
btn_search.setVisibility(View.INVISIBLE);
progressBar.setVisibility(View.VISIBLE);
RequestQueue requestQueue = Volley.newRequestQueue(MainActivity.this);
JsonObjectRequest jsonobjectrequest = new JsonObjectRequest(Request.Method.GET, urlOpenWeatherMap, null,
new Response.Listener<JSONObject>() {
#Override
public void onResponse(JSONObject response) {
try {
String x = response.getString("message");
if(x.contains("404") || x.contains("city not found") )
{
Toast.makeText(MainActivity.this, "error", Toast.LENGTH_SHORT).show();
}
else
{
Toast.makeText(MainActivity.this, "welcome", Toast.LENGTH_SHORT).show();
}
} catch (JSONException e) {
e.printStackTrace();
}
}
}, new Response.ErrorListener() {
#Override
public void onErrorResponse(VolleyError error) {
}
});
requestQueue.add(jsonobjectrequest);
}
else
{
Toast.makeText(MainActivity.this, "", Toast.LENGTH_SHORT).show();
}
}
else
{
Toast.makeText(MainActivity.this, "no Internet", Toast.LENGTH_SHORT).show();
}
}
I am trying to solve the problem 4 hours ago but no use
I think the problem here
String x = response.getString("message");
I need help please
You are getting json text in the response body, but the server is responding with 404 code which is an error, therefore the logic needs to be inside the overridden method:
#Override
public void onErrorResponse(VolleyError error) {
String body;
String statusCode = String.valueOf(error.networkResponse.statusCode);
if(statusCode == "400") {
// do your thing
}
// do something else
}
Json Might be look like
{"loginNodes":[{"message":"Welcome To Alamofire","name":Enamul Haque,"errorCode":"0","photo":null}]}
Your code should be ..
StringRequest stringRequest = new StringRequest(Request.Method.POST, "http://api.openweathermap.org/data/2.5/weather",
new Response.Listener<String>() {
#Override
public void onResponse(String response) {
//pDialog.dismiss();
try {
JSONObject jsonObject = new JSONObject(response);
JSONArray loginNodes = jsonObject.getJSONArray("loginNodes");
pDialog.dismiss();
for (int i = 0; i < loginNodes.length(); i++) {
JSONObject jo = loginNodes.getJSONObject(i);
String message= jo.getString("message");
}
} catch (JSONException e) {
e.printStackTrace();
}
}
},
new Response.ErrorListener() {
#Override
public void onErrorResponse(VolleyError error) {
pDialog.dismiss();
try {
} catch (Exception e) {
}
}
}) {
#Override
protected Map<String, String> getParams() {
Map<String, String> params = new HashMap<>();
params.put("q", "fddfgdfgdfgdfg");
params.put("units", "metric");
params.put("appid", "efb8013262db1b77b0431909b8b173e1");
return params;
}
};
RequestQueue requestQueue = Volley.newRequestQueue(this);
requestQueue.add(stringRequest);
Check response from GET OR Post.You can debug the error onErrorResponse
try {
if (error instanceof TimeoutError ) {
}else if(error instanceof NoConnectionError){
} else if (error instanceof AuthFailureError) {
} else if (error instanceof ServerError) {
//TODO
} else if (error instanceof NetworkError) {
//TODO
} else if (error instanceof ParseError) {
//TODO
}
} catch (Exception e) {
}
I want to integrate youtube like button in my android app. By refering through this tutorial Videos: rate
I found this api link https://www.googleapis.com/youtube/v3/videos/rate can be used to do that. Can anybody tell me how can I pass a particular video Id along with this api link
Used this code for like youtube Videos....
//getPostLikeBtn (Create this Method.)
private void getPostLikeBtn(final String rating) {
String tag_json_obj = "recipeLike";
final SpotsDialog spotsDialog = new SpotsDialog(context);
spotsDialog.show();
spotsDialog.setMessage("Loading...");
StringRequest jsonObjectRequest = new StringRequest(Request.Method.POST,
"https://www.googleapis.com/youtube/v3/videos/rate",
new Response.Listener<String>() {
#Override
public void onResponse(String response) {
spotsDialog.dismiss();
}
}, new Response.ErrorListener() {
#Override
public void onErrorResponse(VolleyError error) {
try {
spotsDialog.dismiss();
try {
if (error.networkResponse.data != null) {
try {
String body = new String(error.networkResponse.data, "UTF-8");
Log.e("errorLike", body);
} catch (UnsupportedEncodingException e) {
e.printStackTrace();
}
}
spotsDialog.dismiss();
Toast.makeText(context, getResources().getString(R.string.try_again), Toast.LENGTH_SHORT).show();
} catch (Exception e) {
e.printStackTrace();
}
Toast.makeText(context, getResources().getString(R.string.try_again), Toast.LENGTH_SHORT).show();
} catch (Exception e) {
e.printStackTrace();
}
// hide the progress dialog
}
}) {
#Override
protected Response<String> parseNetworkResponse(NetworkResponse response) {
int mStatusCode = response.statusCode;
Log.e("mStatusCode", "" + mStatusCode);
if (mStatusCode == 204) {
Toast.makeText(context, "Successfully updated", Toast.LENGTH_SHORT).show();
getLikeShare();
} else {
Toast.makeText(context, getResources().getString(R.string.try_again), Toast.LENGTH_SHORT).show();
}
return super.parseNetworkResponse(response);
}
#Override
public Map<String, String> getHeaders() throws AuthFailureError {
Map<String, String> params = new HashMap<String, String>();
SharedPreferences prefs = getSharedPreferences("GOOGLE_TOKEN", MODE_PRIVATE);
String token = prefs.getString("token", null);
params.put("Authorization", "Bearer " + token);
return params;
}
#Override
protected Map<String, String> getParams() {
Map<String, String> jsonObject = new HashMap<>();
try {
jsonObject.put("id", "Video id");
jsonObject.put("rating", rating);
} catch (Exception e) {
e.printStackTrace();
}
Log.e("jsonObject", "" + jsonObject);
return jsonObject;
}
};
AppController.getInstance().addToRequestQueue(jsonObjectRequest, tag_json_obj);
}
I hope this is usefull for you..
I have used the volley library to get the API response. Initially when am calling the API the error response is showing exactly from the server. but when i again call the API means i am getting error response is null.
Kindly help me to do this.
Here is my code
public void requestString(final String requestName,
final String webserviceUrl,
final Map<Object, Object> requestParams, final int webMethod,
final boolean getCache) {
LogUtils.i("Sending Request", webserviceUrl);
StringRequest stringRequest = new StringRequest(webMethod,
webserviceUrl, new Response.Listener<String>() {
#Override
public void onResponse(String response) {
LogUtils.i("Response", response);
mRequestCompletedListener.onRequestCompleted(
requestName, true, response, null);
}
}, new Response.ErrorListener() {
#Override
public void onErrorResponse(VolleyError error) {
String errorResponse = null;
if (getCache) {
final Cache cache = AppController.getInstance()
.getRequestQueue().getCache();
final Entry entry = cache.get(webserviceUrl);
if (entry.data != null) {
try {
errorResponse = new String(entry.data, "UTF-8");
mRequestCompletedListener
.onRequestCompleted(requestName,
true, errorResponse, null);
return;
} catch (UnsupportedEncodingException e) {
LogUtils.e(TAG, e);
}
} else {
LogUtils.e(TAG, requestName
+ " Cache does not exist");
}
}
try {
VolleyError responseError = new VolleyError(
new String(error.networkResponse.data));
LogUtils.i("ErrorResponse", responseError.getMessage());
try {
if (responseError != null) {
final JSONObject responseJson = new JSONObject(responseError.getMessage());
// Show Alert Information
errorResponse = responseJson.getString(AppConstants.MESSAGE);
}
} catch (Exception e) {
errorResponse = "Unknown";
}
} catch (Exception e) {
LogUtils.e(TAG, e);
}
mRequestCompletedListener.onRequestCompleted(
requestName, false, null,
errorResponse);
}
})
stringRequest.setTag(requestName);
// Adding String request to request queue
AppController.getInstance().addToRequestQueue(stringRequest);
}
Here am passing the Params:
AppController.getInstance().requestApi(mVolleyRequest, REQUEST_NAME, PATH
+ API, Request.Method.POST, HTTP_POST, Request.Priority.HIGH
, false, out.toString().trim(), true);
I'm using volley library for sending requests and I have a memory leak. I traced it with leak canary and it seems to be from my requests mListeners. after some searching I cancel all my requests in my current activity but still I have a leak I could use some help thanks here is my download code:
(note: I use singleton pattern for getting volley request queue)
private void startImageDownloadService(final NEWS selectedNews) {
if (selectedNews.getIMG_URL() != null && !selectedNews.getIMG_URL().equals("null")) {
ImageRequest imageRequest = new ImageRequest(selectedNews.getIMG_URL(),
new Response.Listener<Bitmap>() {
#Override
public void onResponse(Bitmap bitmap) {
newsImage_imageView.setVisibility(View.VISIBLE);
newsImage_imageView.setImageBitmap(bitmap);
saveImageToFileStarter(bitmap, selectedNews);
}
}, 200, 200, null, null, new Response.ErrorListener() {
#Override
public void onErrorResponse(VolleyError volleyError) {
Toast.makeText(getApplicationContext(), "Failed to download image", Toast.LENGTH_SHORT).show();
}
});
imageRequest.setShouldCache(false);
MyVolleySingleton.getInstance(getApplicationContext()).addToRequestQueue(imageRequest, "newsActivityImage");
//
}
}
private void requestLike(final ImageButton likeButton, final long id) {
try {
StringRequest jsonRequest = new StringRequest(Request.Method.POST, G.likeURL + id + "/like",
new Response.Listener<String>() {
#Override
public void onResponse(String s) {
try {
Log.e("requestLikeJson", s);
JSONObject likeObject = new JSONObject(s);
int likeNumbers = likeObject.getInt("likes");
// Toast.makeText(NewsActivity.this, likeNumbers + "", Toast.LENGTH_LONG)
// .show();
if (likeButton.getTag().equals("notliked")) {
setLikeChangeInDatabase(false, id, likeNumbers);
}
else{
setLikeChangeInDatabase(true, id, likeNumbers);
}
// viewsCount_textView.setText("" + likeNumbers);
} catch (JSONException e) {
e.printStackTrace();
}
}
}, new Response.ErrorListener() {
#Override
public void onErrorResponse(VolleyError volleyError) {
Toast.makeText(NewsActivity.this, "No Internet connection", Toast.LENGTH_LONG).show();
try {
volleyError.printStackTrace();
Log.e("network error", new String(volleyError.networkResponse.data));
} catch (Exception e) {
e.printStackTrace();
}
if (likeButton.getTag().equals("notliked")) {
likeButton.setTag("liked");
likeButtonImageSetter();
} else {
likeButton.setTag("notliked");
likeButtonImageSetter();
}
Animation shake = AnimationUtils.loadAnimation(NewsActivity.this, R.anim.actionfeedback);
likeButton.startAnimation(shake);
}
}) {
#Override
public Priority getPriority() {
return Priority.HIGH;
}
#Override
public Map<String, String> getHeaders() throws AuthFailureError {
Map<String, String> params = new HashMap<>();
Log.e("sent token", "Token " + G.token);
params.put("Authorization", "Token " + G.token);
params.put("Accept-Language", "en-US,en;q=0.8,fa;q=0.6,pt;q=0.4,ar;q=0.2,gl;q=0.2");
return params;
}
#Override
protected Response<String> parseNetworkResponse(NetworkResponse response) {
String utf8String = null;
try {
utf8String = new String(response.data, "UTF-8");
return Response.success(utf8String, HttpHeaderParser.parseCacheHeaders(response));
} catch (UnsupportedEncodingException e) {
return Response.error(new ParseError(e));
}
}
};
jsonRequest.setRetryPolicy(new DefaultRetryPolicy(
G.socketTimeout,
0,
DefaultRetryPolicy.DEFAULT_BACKOFF_MULT));
MyVolleySingleton.getInstance(getApplicationContext()).addToRequestQueue(jsonRequest, "like");
} catch (Exception e) {
}
}
private void requestView(long id) {
try {
StringRequest jsonRequest = new StringRequest(Request.Method.GET, G.viewURL + id + "/view", new Response.Listener<String>() {
#Override
public void onResponse(String s) {
try {
JSONObject viewObject = new JSONObject(s);
Log.e("requestViewJson", s);
} catch (JSONException e) {
e.printStackTrace();
}
}
}, new Response.ErrorListener() {
#Override
public void onErrorResponse(VolleyError volleyError) {
try {
volleyError.printStackTrace();
Log.e("network error", new String(volleyError.networkResponse.data));
} catch (Exception e) {
e.printStackTrace();
}
}
}) {
#Override
public Map<String, String> getHeaders() throws AuthFailureError {
Map<String, String> params = new HashMap<>();
Log.e("sent token", "Token " + G.token);
params.put("Authorization", "Token " + G.token);
params.put("Accept-Language", "en-US,en;q=0.8,fa;q=0.6,pt;q=0.4,ar;q=0.2,gl;q=0.2");
return params;
}
#Override
public Priority getPriority() {
return Priority.HIGH;
}
#Override
protected Response<String> parseNetworkResponse(NetworkResponse response) {
String utf8String = null;
try {
utf8String = new String(response.data, "UTF-8");
return Response.success(utf8String, HttpHeaderParser.parseCacheHeaders(response));
} catch (UnsupportedEncodingException e) {
return Response.error(new ParseError(e));
}
}
};
jsonRequest.setRetryPolicy(new DefaultRetryPolicy(
G.socketTimeout,
0,
DefaultRetryPolicy.DEFAULT_BACKOFF_MULT));
MyVolleySingleton.getInstance(getApplicationContext()).addToRequestQueue(jsonRequest,"view");
} catch (Exception e) {
}
}
and in my onStop() I have :
#Override
protected void onStop() {
try {//new change
MyVolleySingleton.getInstance(getApplicationContext()).cancelPendingRequests("newsActivityImage");
MyVolleySingleton.getInstance(getApplicationContext()).cancelPendingRequests("view");
MyVolleySingleton.getInstance(getApplicationContext()).cancelPendingRequests("like");
loadImageFromFile.cancel(true);
loadImageFromFile=null;
}catch (Exception e){}
super.onStop();
}
After some researching I found that the volley listeners cause the activity leak because they are instantiated as anonymous classes and therefore hold an implicit reference to their outer class (in this example news activity) so I made a separate class for VolleyRequest (just to make them customizable not really related to the leak) and made a listener interface which I implement as an innerclass and use a weak reference to have access to the activity
request code :
public class MyVolleyStringRequest extends com.android.volley.toolbox.StringRequest {
StringResponseListener mListener;
public MyVolleyStringRequest(int method, String url, final StringResponseListener mListener) {
super(method, url, new Response.Listener<String>() {
#Override
public void onResponse(String s) {
mListener.onSuccess(s);
}
}, new Response.ErrorListener() {
#Override
public void onErrorResponse(VolleyError volleyError) {
mListener.onFailure(volleyError);
}
});
this.mListener = mListener;
}
#Override
public Map<String, String> getHeaders() throws AuthFailureError {
Map<String, String> params = new HashMap<>();
Log.e("sent token", "Token " + G.token);
params.put("Authorization", "Token " + G.token);
params.put("Accept-Language", "en-US,en;q=0.8,fa;q=0.6,pt;q=0.4,ar;q=0.2,gl;q=0.2");
return params;
}
#Override
protected Response<String> parseNetworkResponse(NetworkResponse response) {
try {
String utf8String = new String(response.data, "UTF-8");
return Response.success(utf8String, HttpHeaderParser.parseCacheHeaders(response));
} catch (UnsupportedEncodingException e) {
return Response.error(new ParseError(e));
}
}
}
requestLike and requestView Code:
private void requestLike(final ImageButton likeButton, final long id) {
MyVolleyStringRequest likeRequest = new MyVolleyStringRequest(Request.Method.POST, G.likeURL + id + "/like",
new RequestLikeStringListener(this));
MyVolleySingleton.getInstance(getApplicationContext()).addToRequestQueue(likeRequest, "like");
}
private void requestView(long id) {
MyVolleyStringRequest viewRequest = new MyVolleyStringRequest(Request.Method.GET, G.viewURL + id + "/view",
new RequestViewStringListener());
MyVolleySingleton.getInstance(getApplicationContext()).addToRequestQueue(viewRequest, "view");
}
listener interface code :
public interface StringResponseListener {
void onSuccess(String response);
void onFailure(VolleyError error);
}
innerclasses code:
public static class RequestLikeStringListener implements StringResponseListener{
WeakReference<NewsActivity> contextWeakReference;
RequestLikeStringListener(NewsActivity context){
contextWeakReference = new WeakReference<>(context);
}
public void onSuccess(String response) {
try {
NewsActivity context = contextWeakReference.get();
if(context != null) {
ImageButton likeButton = (ImageButton) context.findViewById(R.id.likeButton);
Log.e("requestLikeJson", response);
JSONObject likeObject = new JSONObject(response);
int likeNumbers = likeObject.getInt("likes");
if (likeButton.getTag().equals("notliked")) {
context.setLikeChangeInDatabase(false, contextWeakReference.get().id, likeNumbers);
} else {
context.setLikeChangeInDatabase(true, contextWeakReference.get().id, likeNumbers);
}
}
} catch (JSONException e) {
e.printStackTrace();
}
}
public void onFailure(VolleyError error) {
NewsActivity context = contextWeakReference.get();
if(context != null) {
ImageButton likeButton = (ImageButton) context.findViewById(R.id.likeButton);
Toast.makeText(context, "No Internet connection", Toast.LENGTH_LONG).show();
try {
error.printStackTrace();
Log.e("network error", new String(error.networkResponse.data));
} catch (Exception e) {
e.printStackTrace();
}
if (likeButton.getTag().equals("notliked")) {
likeButton.setTag("liked");
context.likeButtonImageSetter();
} else {
likeButton.setTag("notliked");
context.likeButtonImageSetter();
}
Animation shake = AnimationUtils.loadAnimation(context, R.anim.actionfeedback);
likeButton.startAnimation(shake);
}
}
hope it helps someone!
I want to build a Utils class to make Volley calls simpler, like this:
Utils.java:
public class Utils {
static JsonObjectRequest mJsonObjectRequest;
protected static boolean busy = true;
public static JSONObject makeJsonObjectRequest(Context context, int method, String url){
final JSONObject[] jsonObject = new JSONObject[1];
mJsonObjectRequest = new JsonObjectRequest
(method, url, null, new Response.Listener<JSONObject>() {
#Override
public void onResponse(JSONObject response) {
jsonObject[0] = response;
busy = false;
}
}, new Response.ErrorListener() {
#Override
public void onErrorResponse(VolleyError error) {
// TODO Auto-generated method stub
try {
jsonObject[0] = new JSONObject(error.toString());
} catch (JSONException e) {
e.printStackTrace();
}
busy = false;
}
});
// Access the RequestQueue through your singleton class.
VolleySingleton.getInstance(context).addToRequestQueue(mJsonObjectRequest);
while (true) {
if (!busy) break;
}
return jsonObject[0];
}
}
MainActivity.java:
JSONObject jsonObject = Utils.makeJsonObjectRequest(this, Request.Method.GET, url);
mTxtDisplay.setText("Response: " + jsonObject.toString());
When app runs, jsonObject always null. I want to ask if I can delay return jsonObject[0] inside makeJsonObjectRequest until onResponse called. Can I do that and how?
.
If you execute makeJsonObjectRequest on a background thread, then you can execute synchronous Volley request this way:
Can I do a synchronous request with volley?
If you execute makeJsonObjectRequest on the UI thread, then you shouldn't wait for onResponse to avoid blocking UI thread. Use callback in this case.
I created this and managed like the following way please have a look, hope it will be useful to you
public class APIManager {
public static void createRequest(Context c, String requestTag,
String endPoint, List<NameValuePair> params,
final OnRequestCompletedListener listener,
TransParentProgressDialog pd) {
ServerDetails serverDetails = new ServerDetails(c, endPoint, params);
JsonObjectRequest request = new JsonObjectRequest(Method.GET,
serverDetails.getQueryUrl(), null,
new Response.Listener<JSONObject>() {
#Override
public void onResponse(JSONObject response) {
listener.onRequestCompleted(response);
}
}, getErrorListener(c, pd)) {
};
AppController.getInstance().addToRequestQueue(request, requestTag);
}
public static ErrorListener getErrorListener(final Context c,
final TransParentProgressDialog pd, final TextView tvEmpty,
final String errorText) {
Response.ErrorListener listener = new Response.ErrorListener() {
#Override
public void onErrorResponse(VolleyError error) {
if (pd != null && pd.isShowing()) {
pd.dismiss();
}
if (tvEmpty != null) {
tvEmpty.setText(errorText);
}
MyDialog dialog;
Log.d("volley-error", error.toString());
if (error instanceof TimeoutError) {
dialog = new MyDialog(c, "Server Timeout");
dialog.show();
return;
} else if (error instanceof NoConnectionError) {
dialog = new MyDialog(c, "No Connection or Invalid Url");
dialog.show();
return;
} else if (error instanceof ServerError) {
NetworkResponse response = error.networkResponse;
if (response != null) {
// int statusCode = response.statusCode;
byte[] data = response.data;
if (data != null) {
String str = new String(data);
try {
JSONObject object = new JSONObject(str);
Log.d("error response", object.toString());
if (object.has("errors")) {
JSONArray errors = object
.getJSONArray("errors");
JSONObject errorObject = errors
.getJSONObject(0);
dialog = new MyDialog(c, "Error!",
errorObject.getString("message"));
dialog.show();
} else {
dialog = new MyDialog(c, "Error!",
object.toString());
dialog.show();
}
} catch (JSONException e) {
e.printStackTrace();
dialog = new MyDialog(c, "Error!", "Error");
dialog.show();
}
} else {
dialog = new MyDialog(c, "Server Error");
dialog.show();
}
} else {
dialog = new MyDialog(c, "Server Error");
dialog.show();
}
} else if (error instanceof NetworkError) {
NetworkResponse response = error.networkResponse;
if (response != null) {
// int statusCode = response.statusCode;
byte[] data = response.data;
if (data != null) {
String str = new String(data);
try {
JSONObject object = new JSONObject(str);
Log.d("error response", object.toString());
if (object.has("errors")) {
JSONArray errors = object
.getJSONArray("errors");
JSONObject errorObject = errors
.getJSONObject(0);
dialog = new MyDialog(c, "Error!",
errorObject.getString("message"));
dialog.show();
} else {
dialog = new MyDialog(c, "Error!",
object.toString());
dialog.show();
}
} catch (JSONException e) {
e.printStackTrace();
dialog = new MyDialog(c, "Error!", "Error");
dialog.show();
}
} else {
dialog = new MyDialog(c, "Network Error");
dialog.show();
}
} else {
dialog = new MyDialog(c, "Network Error");
dialog.show();
}
} else if (error instanceof ParseError) {
dialog = new MyDialog(c, "Parse Error");
dialog.show();
} else if (error instanceof AuthFailureError) {
NetworkResponse response = error.networkResponse;
if (response != null) {
// int statusCode = response.statusCode;
byte[] data = response.data;
if (data != null) {
String str = new String(data);
try {
JSONObject object = new JSONObject(str);
Log.d("error response", object.toString());
if (object.has("errors")) {
JSONArray errors = object
.getJSONArray("errors");
JSONObject errorObject = errors
.getJSONObject(0);
dialog = new MyDialog(c, "Error!",
errorObject.getString("message"));
dialog.show();
} else {
dialog = new MyDialog(c, "Error!",
object.toString());
dialog.show();
}
} catch (JSONException e) {
e.printStackTrace();
dialog = new MyDialog(c, "Error!", "Error");
dialog.show();
}
} else {
dialog = new MyDialog(c, "Error!", "Error");
dialog.show();
}
} else {
dialog = new MyDialog(c, "Error connecting server");
dialog.show();
}
}
}
};
return listener;
}
}
And the interface for call back on request completed is
public interface OnRequestCompletedListener {
public void onRequestCompleted(JSONObject response);
}
Thanks to #Gennadii Saprykin's and #Gopal Singh Sirvi's answers, I have tried both Callable and Interface Listener ways. Both worked, however, I prefer Listener way.
OnRequestCompletedListener.java:
package com.example.volleyapp;
import org.json.JSONObject;
public interface OnRequestCompletedListener {
void onRequestCompleted(JSONObject response);
}
Utils.java:
package com.example.volleyapp;
import android.content.Context;
import com.android.volley.Response;
import com.android.volley.VolleyError;
import com.android.volley.toolbox.JsonObjectRequest;
import org.json.JSONException;
import org.json.JSONObject;
import java.util.concurrent.Callable;
public class Utils {
static JsonObjectRequest mJsonObjectRequest;
static Callable<Void> func=null;
public static void makeJsonObjectRequest_Listener(final Context context, final int method, final String url, final OnRequestCompletedListener listener){
mJsonObjectRequest = new JsonObjectRequest
(method, url, null, new Response.Listener<JSONObject>() {
#Override
public void onResponse(JSONObject response) {
listener.onRequestCompleted(response);
}
}, new Response.ErrorListener() {
#Override
public void onErrorResponse(VolleyError error) {
// TODO Auto-generated method stub
try {
listener.onRequestCompleted(new JSONObject(error.toString()));
} catch (JSONException e) {
e.printStackTrace();
}
}
});
// Access the RequestQueue through your singleton class.
VolleySingleton.getInstance(context).addToRequestQueue(mJsonObjectRequest);
}
public static void makeJsonObjectRequest_Callable(final Context context, final int method, final String url, final MainActivity.JsonCallable doRequest){
mJsonObjectRequest = new JsonObjectRequest
(method, url, null, new Response.Listener<JSONObject>() {
#Override
public void onResponse(JSONObject response) {
try{
func = doRequest;
doRequest.jsonObject = response;
func.call();
} catch (Exception e) {
e.printStackTrace();
}
}
}, new Response.ErrorListener() {
#Override
public void onErrorResponse(VolleyError error) {
// TODO Auto-generated method stub
try {
func = doRequest;
doRequest.jsonObject = new JSONObject(error.toString());
func.call();
} catch (JSONException e) {
e.printStackTrace();
}
}
});
// Access the RequestQueue through your singleton class.
VolleySingleton.getInstance(context).addToRequestQueue(mJsonObjectRequest);
}
}
MainActivity.java:
package com.example.volleyapp;
import android.app.Activity;
import android.graphics.Bitmap;
import android.os.Bundle;
import android.view.Menu;
import android.view.MenuItem;
import android.widget.TextView;
import com.android.volley.Request;
import com.android.volley.Response;
import com.android.volley.VolleyError;
import org.json.JSONObject;
import java.util.concurrent.Callable;
public class MainActivity extends Activity {
JsonCallable jsonCallable=null;
TextView mTxtDisplay;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
mTxtDisplay = (TextView) findViewById(R.id.textView);
String url = "https://10.0.2.2/aspnet/webapi/products/1";
// Callable way
// jsonCallable = new JsonCallable();
// Utils.makeJsonObjectRequest_Callable(this, Request.Method.GET, url, jsonCallable);
// Listener way
OnRequestCompletedListener listener = new OnRequestCompletedListener() {
#Override
public void onRequestCompleted(JSONObject response) {
mTxtDisplay.setText(response.toString());
}
};
Utils.makeJsonObjectRequest_Listener(this, Request.Method.GET, url, listener);
}
class JsonCallable implements Callable {
public JSONObject jsonObject;
public JsonCallable(){
}
#Override
public Object call() throws Exception {
mTxtDisplay.setText(jsonObject.toString());
return null;
}
}
}
Once again, thank you all for your help!