I have an android app which uses Robospice with Google HTTP client to send RESTful request to a server.
All works fine if result is successfully returned but if an exception is returned from my service, the Robospice listener doesn't catch the exception.
public final class FBUserSaveListener implements RequestListener<HttpResponse> {
#Override
public void onRequestFailure( SpiceException spiceException ) {
if(progressDialog.isShowing())
{
progressDialog.dismiss();
}
Toast.makeText(getActivity(),
"Error: " + spiceException.getMessage(), Toast.LENGTH_SHORT)
.show();
Intent i = new Intent(getActivity(), ErrorActivity.class);
startActivity(i);
}
#Override
public void onRequestSuccess(HttpResponse response) {
if (progressDialog.isShowing()) {
progressDialog.dismiss();
}
if(response.getStatusCode() == AppConstants.HTTP_CODE_CREATED_201) {
Intent intent = new Intent(getActivity(), PoolMainActivity.class);
startActivity(intent);
}
else{
//Request was sent successfully but the response was wrong
// Redirect to error page
Intent i = new Intent(getActivity(), ErrorActivity.class);
startActivity(i);
}
}
}
In the above code, when the external service returns an exception, the onRequestFailure() is not hit at all.
My request is :
public HttpResponse loadDataFromNetwork() throws Exception{
String url = context.getString(R.string.BASE_SERVICE_URL) + context.getString(R.string.USER_FB_LOGIN_SAVE);
HttpRequest request = getHttpRequestFactory()//
.buildPostRequest(new GenericUrl(url), ByteArrayContent.fromString("application/json", fbLoginBeanJson));
request.setParser(new com.google.api.client.json.jackson2.JacksonFactory().createJsonObjectParser());
return request.execute();
}
Did I miss something in the Robospice implementation of RESTful services ?
I managed to solve this by debugging my fragment's life cycle.
I realized that the spiceManager was getting cleared due to the changes in my fragment's life cycle. Saw the FAQ section in robospice and it helped me a lot.
Made the spiceManager start and end in the onAttach and onDetach methods of my fragment respectively.
Related
I try many solutions but no once work for me.
I'm receiving images data in this way:
ArrayList<String> filePaths = data.getStringArrayListExtra(Pix.IMAGE_RESULTS);
and uploading images using multipart
MultipartBody requestBody = builder.build();
Call<Status_Response> call = taskMetServer.uploadMultiplePics(requestBody.parts());
call.enqueue(new Callback<Status_Response>() {
#Override
public void onResponse(Call<Status_Response> call, Response<Status_Response> response) {
if(response.isSuccessful()){
Status_Response status_response = response.body();
assert status_response != null;
String msg = status_response.getStatus();
Log.d("myMessage", "\n\nStatus: "+msg);
progressBar.setVisibility(View.GONE);
Toast.makeText(getContext(), "Success " + response.message()+response.code(), Toast.LENGTH_LONG).show();
}
}
#Override
public void onFailure(Call<Status_Response> call, Throwable t) {
progressBar.setVisibility(View.GONE);
Toast.makeText(getContext(), t.getMessage(), Toast.LENGTH_SHORT).show();
}
});
}
my interface is:
#POST("test/store")
Call<Status_Response> uploadMultiplePics(
#Body List<MultipartBody.Part> images
);
but still receiving null in response instead of true of false:
2021-03-20 17:36:38.076 10582-10582/com.example.ourproductapp D/myMessage: [/storage/emulated/0/WhatsApp/Media/WhatsApp Images/IMG-20210320-WA0082.jpeg]
2021-03-20 17:36:38.732 10582-10582/com.example.ourproductapp D/myMessage: Status: null
Thanks in advance
check your backend service, your server is getting file or not.
or you can use https://github.com/gotev/android-upload-service library
I supposed to use MVVM pattern with Data Repository. Data Came from Web Api call. and based on The Data, The Application Start The Web Browser With Returned URL.
on user interaction The Activity calls ViewModel Which owns Data:
CheckOutActivity.java:
MaterialRippleLayout makeOrder = findViewById(R.id.btn_make_order);
makeOrder.setOnClickListener(view ->{
viewModel.makeOrder();
});
viewModel calls DataRepository with Appropriate Data (optionalShippingEntityIds) to call Web Api Async:
CheckOutViewModel.java
public void makeOrder(){
cartRepository.makeOrder(optionalShippingEntityIds.getValue());
}
The Repository has been instantiated before:
public CheckOutViewModel(#NonNull Application application) {
super(application);
cartRepository = new CartRepository(application);
}
in DataRepository Api Call performs:
CartRepository
public void makeOrder(ArrayList<Integer> optionalShippingEntityIds){
HashMap<String,String> map = new HashMap<String,String>();
String idsString=optionalShippingEntityIds.toString();
map.put("shipment_saleitem_id",idsString);
rest.httpRequest(RestAdapter.HttpVerb.POST,"order",map,new makeOrderHandler());
}
The CartRepository Constructor:
private RestAdapter rest;
private Context context;
public CartRepository(Context context) {
this.context = context;
rest = RestAdapter.getInstance(context);
version.setValue(0);
}
4.HttpResponseHandler Handle The Web Browser open URL or Toast fail message
CartRepository.java
class makeOrderHandler extends JsonHttpResponseHandler{
#Override
public void onSuccess(int statusCode, Header[] headers, JSONObject response) {
if(statusCode == 200){
try {
Toast.makeText(context,"order number "+response.getInt("order_id")+"has been created",Toast.LENGTH_SHORT).show();
String redirectUrl = response.getString("init_payment_url");
version.setValue(version.getValue() +1);
final Handler handler = new Handler();
handler.postDelayed(new Runnable() {
#Override
public void run() {
Intent intent = new Intent(Intent.ACTION_VIEW, Uri.parse(redirectUrl));
intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
context.startActivity(intent);
((Activity)context).finishAffinity();
//System.exit(0);
/*Intent chooserIntent = Intent.createChooser(intent, "Open With");
chooserIntent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
context.startActivity(chooserIntent);*/
}
}, 2000);
} catch (JSONException e) {
Toast.makeText(context,"JSON parse error"+" : "+response.toString(), Toast.LENGTH_SHORT).show();
e.printStackTrace();
}
}else{
Log.e("server api changed ", "error in getting response using known api \n" + response.toString());
Toast.makeText(context,"api change",Toast.LENGTH_SHORT).show();
}
}
#Override
public void onFailure(int statusCode, Header[] headers, String res, Throwable t) {
// called when response HTTP status is "4XX" (eg. 401, 403, 404)
Log.e("server 500", "error in getting response using async-apache-http call"+" : "+res);
t.printStackTrace();
Toast.makeText(context, "خطا سرور ", Toast.LENGTH_SHORT).show();
}
#Override
public void onFailure(int statusCode, Header[] headers, Throwable t, JSONObject e) {
if(statusCode == 504){
Toast.makeText(context,"The Order hasnt been created duo to internal problem. please try again",Toast.LENGTH_SHORT).show();
}else{
Log.e("server api changed", "error in getting response using known api \n" + e.toString());
t.printStackTrace();
Toast.makeText(context,"Api is unknown",Toast.LENGTH_SHORT).show();
}
}
}
The Problem is after i launch The Application in some Devices, in The Line ((Activity)context).finishAffinity(); The Application Crashes because The context is an application context instance and not an activity context instance .
if i pass The Activity instance Through ViewModel, i had just violated The MVVM.
if i make an interface in The Activity and implement it. it violates The Activity Single Responsibility (Data Repository Response Handler Should Handle The startActivity)
so i dont know how to handle this perfectly.
if i eliminate The ViewModel makeOrder, and Construct The Repository With The Activity Context I think its ViewModel Responsibility to Handle The Data Manipulation Job.
....
So I am Confused With The Right Solution To Handling StartActivity and Toast in Response.
if anyone could help me With The Right Design Pattern i Would Appreciate.
Your viewmodel can extends from AndroidViewModel.
From documentation:
"Application context aware ViewModel.
Subclasses must have a constructor which accepts Application as the only parameter."
This page says that we can register a Listener to a volley request for handling errors:
https://developer.android.com/training/volley/simple
But it doesn't mention what kind of errors trigger this listener. Volley javadoc doesn't say anything about it either.
Specifically, will this listener be executed if a network error occurs.
I'm asking this because I've encountered an android code of the following form:
private void method() {
String URL = "";
final int[] status_code = new int[1];
StringRequest request = new StringRequest(Request.Method.POST, URL,
new Response.Listener<String>() {
#Override
public void onResponse(String response) {
if (status_code[0] == 200) {
// do something
} else {
// display toast
}
}
},
new Response.ErrorListener() {
#Override
public void onErrorResponse(VolleyError error) {
// display toast
}
}) {
#Override
protected Response<String> parseNetworkResponse(NetworkResponse response) {
status_code[0] = response.statusCode;
return super.parseNetworkResponse(response);
}
};
// add request to queue
}
This code seems to suggest that the registered ErrorListener isn't called for network errors.
What are the conditions which cause the ErrorListener registered to a Volley request to be called
The ErrorListener is triggered for 4xx responses and 5xx responses I cannot tell what happens though for the 3xx redirection responses as it didn't happended to me.
Here is a list with all HTTP Response codes:
https://www.restapitutorial.com/httpstatuscodes.html
I'm not exactly privy to your entire code but poking through the Volley source code:
Response.java takes in VolleyError object
VolleyError references NetworkResponses in its use.
Inspecting NetworkResponses deals with mainly HTTP status codes.
Also I'd note that VolleyError extends Exception.
So I would say the call back method is triggered when an Exception is thrown and VolleyError deals with HTTP status codes.
I just call this statement
#Override
public void onErrorResponse(VolleyError error) {
if (error instanceof TimeoutError) {
Log.i(TAG, "onErrorResponse: " + context.getString(R.string.error_network_timeout));
} else if (error instanceof ServerError) {
Log.i(TAG, "onErrorResponse: " + context.getString(R.string.error_server));
} else if (error instanceof NetworkError) {
//toast or log your error
} else if (error instanceof ParseError) {
Log.i(TAG, "onErrorResponse: " + context.getString(R.string.parse_error));
} else {
Log.i(TAG, "onErrorResponse: Something went wrong ");
}
You don't need to find error code
I'm working on an android app for a Facebook group. Using the graph API, I can easily post a text status but when I upload a photo, it returns error saying
(#100) The picture is not properly formatted
If I use the same code to post to my wall, the photo upload works fine.
Is this an API restriction or there is a separate approach to upload a photo to a group?
Following is my code:
Request photoRequest = Request.newUploadStagingResourceWithImageRequest(session, bitmap, new Request.Callback() {
#Override
public void onCompleted(Response response) {
if (mProgress != null && mProgress.isShowing())
mProgress.dismiss();
if (response.getError() == null) {
Toast.makeText(NewPostActivity.this, "Successfully shared on the group", Toast.LENGTH_SHORT).show();
finish();
} else {
Toast.makeText(NewPostActivity.this, "Facebook sharing error: " + response.getError().getErrorMessage(), Toast.LENGTH_SHORT).show();
}
}
});
Bundle params = photoRequest.getParameters();
if(message != null) {
params.putString("message", message);
}
if(imageBytes != null) {
params.putByteArray("picture", imageBytes);
}
photoRequest.setParameters(params);
photoRequest.setHttpMethod(HttpMethod.POST);
photoRequest.setGraphPath(Constants.URL_FEEDS);
photoRequest.executeAsync();
EDIT
I'm using Graph API v2.3
It does seem to be possible to post a photo in a group.
You can make a POST request to photos edge from the following paths:
/{group_id}/photos
When posting to this edge, a Photo will be created.
Link
Return type
Struct {
id: numeric string,
post_id: token with structure: Post ID,
}
It seems like the POST request to /<group-id>/feed doesn't allow to upload a photo (which otherwise works for /me/feed). I finally got this working with the /<group-id>/photos edge as suggested. Following is my code - hoping that it helps some:
Request photoRequest = Request.newUploadStagingResourceWithImageRequest(session, bitmap, new Request.Callback() {
#Override
public void onCompleted(Response response) {
if (mProgress != null && mProgress.isShowing())
mProgress.dismiss();
if (response.getError() == null) {
Toast.makeText(NewPostActivity.this, "Successfully shared on the group", Toast.LENGTH_SHORT).show();
finish();
} else {
Toast.makeText(NewPostActivity.this, "Facebook sharing error: " + response.getError().getErrorMessage(), Toast.LENGTH_SHORT).show();
}
}
});
Bundle params = photoRequest.getParameters();
if(message != null) {
params.putString("message", message);
photoRequest.setGraphPath(Constants.URL_FEEDS);
}
if(imageBytes != null) {
params.putByteArray("picture", imageBytes);
photoRequest.setGraphPath(Constants.URL_PHOTOS);
}
photoRequest.setParameters(params);
photoRequest.setHttpMethod(HttpMethod.POST);
photoRequest.executeAsync();
I had my app posting feed stories to facebook fine until yesterday.
Now it stopped working and sends this error in the callback:
"com.facebook.FacebookException: could not construct request body"
This comes from:
response.getError();
Strangely the sample app from facebook stopped working and is now reporting the same error, I'm quite sure I didn't change anything on it.
Here's the sample app function:
private void publishStory() {
Session session = Session.getActiveSession();
if (session != null){
// Check for publish permissions
List<String> permissions = session.getPermissions();
if (!isSubsetOf(PERMISSIONS, permissions)) {
pendingPublishReauthorization = true;
Session.NewPermissionsRequest newPermissionsRequest = new Session
.NewPermissionsRequest(this, PERMISSIONS);
session.requestNewPublishPermissions(newPermissionsRequest);
return;
}
Bundle postParams = new Bundle();
postParams.putString("name", "Facebook SDK for Android");
postParams.putString("caption", "Build great social apps and get more installs.");
postParams.putString("description", "The Facebook SDK for Android makes it easier and faster to develop Facebook integrated Android apps.");
postParams.putString("link", "https://developers.facebook.com/android");
postParams.putString("picture", "https://raw.github.com/fbsamples/ios-3.x-howtos/master/Images/iossdk_logo.png");
Request.Callback callback= new Request.Callback() {
public void onCompleted(Response response) {
FacebookRequestError error = response.getError();
if (error != null) {
Toast.makeText(getApplicationContext(),
error.getErrorMessage(),
Toast.LENGTH_SHORT).show();
return;
}
JSONObject graphResponse = response
.getGraphObject()
.getInnerJSONObject();
String postId = null;
try {
postId = graphResponse.getString("id");
} catch (JSONException e) {
Log.i("publishStory",
"JSON error "+ e.getMessage());
}
Toast.makeText(getApplicationContext(), postId,Toast.LENGTH_LONG).show();
}
};
Request request = new Request(session, "me/feed", postParams,
HttpMethod.POST, callback);
RequestAsyncTask task = new RequestAsyncTask(request);
task.execute();
}
}
Can anyone help please!
Thank you in advance.
Now it works...I've turned off my computer and Eclipse during the night and now restarted
I guess it was some bug in the compiler.