Do different Web Hosts give different responses under same conditions? - java

I am working on an Android app. Therefore I'm creating a Login/Register Aktivity.I'm using JsonRequest (Volley) to get the Information stored in an SQL Data-base.Furthermore I wrote some PHP files (for Testing Purpose) to create a JSONObject as the Server Response.
Everything seems to work but only for some webhosts. What I mean by that is that the same Android Code and the same PHP Code once work fine and in the other case Output Errors.
My Test PHP Code uploaded via FileManagers
<?php
$myObj=new stdClass();
$myObj->name = "Test";
$myJSON = json_encode($myObj);
echo $myJSON;
?>
My Java Code
RequestQueue requestQueue= Volley.newRequestQueue(this);
JsonObjectRequest jsonObjectRequest=new JsonObjectRequest(Request.Method.GET,url,null, new Response.Listener<JSONObject>() {
#Override
public void onResponse(JSONObject response) {
try {
String success=response.getString("name");
Toast.makeText(getApplicationContext(),success, Toast.LENGTH_SHORT).show();
} catch (JSONException e) {
e.printStackTrace();
Toast.makeText(getApplicationContext(), "ErrorCatch"+e.toString(), Toast.LENGTH_LONG).show();
}
}
},
new Response.ErrorListener() {
#Override
public void onErrorResponse(VolleyError error) {
Toast.makeText(getApplicationContext(), "ErrorResponse"+error.toString(), Toast.LENGTH_LONG).show();
}
});
requestQueue.add(jsonObjectRequest);
Using one Webhost I get the Correct Toast including the stored Information from the Server. Using another Webhost I get an Error:"Java.lang.String cannot be converted to JSONObject" which I find Odd since I'm doing the same Stuff.

Related

how to prevent code duplication in android

I am new to android and OOP. I know one of Fowler's bad smells is code duplication. I have about 25 volley requests in my whole projects in different activities, and in all of them, there is a 90% same code.
Look at this pseudo code:
on Error:
if no connection:
Toast "no connection"
else if no response:
Toast "server error"
else
show popup with a retry button which will call the function which this request is inside it again.
My first question is how to write these in one place and use the whole request object in different places.
My second question is there are some activity-related codes in some special activities. For example, on my login page I have no unauthorized error but in other pages I have. Or as you see, In my last else in the above code, I have said recall the function and if every request it different. How can I handle that?
How should I do that?
Is there any special reference?
tnx
You can create an util class to create the request.
For example this is a class able to create a GET request using JSONObject that display Toast messages on error, and execute the function that you pass as paramter on success:
public class VolleyUtils{
public static JsonObjectRequest createGetRequest(String url, Consumer<? super JSONObject> successCallback){
return new JsonObjectRequest(Request.Method.GET, url, null, new Response.Listener<JSONObject>() {
#Override
public void onResponse(JSONObject response) {
successCallback.consume(response)
}
}, new Response.ErrorListener() {
#Override
public void onErrorResponse(VolleyError error) {
if (volleyError instanceof TimeoutError || volleyError instanceof NoConnectionError) {
VolleyUtils.showToast("No Internet connection");
} else if (volleyError instanceof AuthFailureError) {
VolleyUtils.showToast("Bad authentication");
} else if (volleyError instanceof ServerError) {
VolleyUtils.showToast("Error with server");
} else if (volleyError instanceof NetworkError) {
VolleyUtils.showToast("Network error");
} else if (volleyError instanceof ParseError) {
VolleyUtils.showToast("Parsing Error");
}
}
});
}
private static void showToast(String errorText){
Toast.makeText(getApplicationContext(), errorText, Toast.LENGTH_SHORT).show();
}
}
So, for create a new request, you just need this:
//supposing you get the RequestQueue with Singleton Pattern
MySingleton.getInstance().addToRequestQueue(VolleyUtils.createGetRequest("www.google.com", (JSONObject response) -> {
//stuff to do when request has success, for example :
myTextView.setText(response.toString())
} ));
Instead of doing duplication of code, Put your code in a function (with or without argument, its depend on your task requirement) and call it where you want in your program.
If you have no idea how to make a function in Android or java Please follow this link
http://www.learnjavaonline.org/en/Functions

How can I store list items when there is no internet connection (data come from server)

Regarding
I have a listview contains 4 items 3 of them are texts and fourth is image
all data are on server within json
the code work correctly but when the internet is off all items and list does not appear how can make the list works with and without internet connection
because I add everyday new items to database
and this my code
requestQueue = Volley.newRequestQueue(this);
JsonObjectRequest jsonObjectRequest = new JsonObjectRequest(Request.Method.GET, url,
new Response.Listener<JSONObject>() {
#Override
public void onResponse(JSONObject response) {
try {
JSONArray jsonArray = response.getJSONArray("allstudents");
for (int i = 0; i < jsonArray.length(); i++) {
JSONObject respons = jsonArray.getJSONObject(i);
String id = respons.getString("id");
String name = respons.getString("name");
String info = respons.getString("info");
String img = respons.getString("img");
link = respons.getString("link");
voicelink = respons.getString("voicelink");
listitmes.add(new listitme(id, name, info, img, link, voicelink));
allitems();
}
} catch (JSONException e) {
e.printStackTrace();
}
}
}
, new Response.ErrorListener() {
#Override
public void onErrorResponse(VolleyError error) {
Log.e("VOLLEY", "ERROR");
}
}
);
requestQueue.add(jsonObjectRequest);
}
public void allitems() {
listAdapter lsadapter = new listAdapter(listitmes);
listView.setAdapter(lsadapter);
}
any solution please I searched a lot but no any answer
and I did not find any thing like here on StackOverflow.Com
Look at https://developer.android.com/reference/android/content/SharedPreferences.
With Shared SharedPreferences you can save the list and call it if there is no wifi!
what you can do is:
Save the data that you download, to a file (image)/properties (text) as soon as you receive data from Internet. ()
Display a message in your activity when the data was fetched (e.g. Last Synced : Timestamp).
If you can can't connect to Internet to get the new data, load the data from file/properties.
If you can't connect to Internet and don't have any saved data, display a message (e.g. can't connect to Internet - may be color it to highlight it's an error).
my 2 cents...

How to get object out of inner class

I am trying to make this application in Android, I am getting data from foursquare's API in JSON format and I need to Parse it to present it in another intent.
I am using Android's volley library to get the JSON but the problem is the onResponse() function of JsonObjectRequest has no return parameter.so I cannot get the JSON object gotten from url outside of the the onResponse.
I haven't worked with volley before and hence don't know much about it, any help is appreciated. Here is the code that I am trying to make it work.
Edit: The main problem I'm facing is that I cannot assign a value to global variable in this case myPlaces inside the JsonObjectRequest's onResponse method. Or to be exact, the variable assigned inside means nothing outside, thus in the last line
Toast.makeText(MainActivity.this, myPlaces[2].getName(), Toast.LENGTH_LONG).show();
when I try to access the myPlaces[2] it gives me an null pointer exception.
Thanks.
public void onClick(View v) {
RequestQueue requestQueue = Volley.newRequestQueue(MainActivity.this);
JsonObjectRequest jsonObjectRequest = new JsonObjectRequest(urlString, null, new com.android.volley.Response.Listener<JSONObject>() {
#Override
public void onResponse(JSONObject response) {
try {
JSONObject meta = response.getJSONObject("meta");
String status = meta.getString("code");
Toast.makeText(MainActivity.this, status, Toast.LENGTH_SHORT).show();
if(status.equals("200"))
{
JSONObject responseJson = response.getJSONObject("response");
JSONArray venues = responseJson.getJSONArray("venues");
Places[] tempPlaces = new Places[venues.length()];
for (int i = 0 ; i < venues.length(); i++)
{
Places place = new Places();
JSONObject venueObject = venues.getJSONObject(i);
place.setName(venueObject.getString("name"));
JSONObject locatVenue = venueObject.getJSONObject("location");
place.setLat(locatVenue.getDouble("lat"));
place.setLon(locatVenue.getDouble("lng"));
tempPlaces[i] = place;
}
Toast.makeText(MainActivity.this, tempPlaces[2].getName(), Toast.LENGTH_LONG).show();
myPlaces = tempPlaces;
}
else
{
Toast.makeText(MainActivity.this, "No response from API", Toast.LENGTH_LONG).show();
}
} catch (JSONException e) {
e.printStackTrace();
Toast.makeText(MainActivity.this, "There is some error here", Toast.LENGTH_LONG).show();
}
}
}, new com.android.volley.Response.ErrorListener() {
#Override
public void onErrorResponse(VolleyError error) {
Toast.makeText(MainActivity.this, "There has been some error", Toast.LENGTH_LONG).show();
}
});
requestQueue.add(jsonObjectRequest);
Toast.makeText(MainActivity.this, myPlaces[2].getName(), Toast.LENGTH_LONG).show();
Volley itself isn't an inner class; the response is an anonymous class.
You don't need a return in Volley, you just use the variables already defined in your class.
I'm assuming myPlaces is a field in your class? Otherwise, I'm not sure where it is declared outside the onClick..
This line assigns myPlaces and looks like it would work fine
myPlaces = tempPlaces;
You could define a method in your class to parse the whole JSONObject instead of needing to return from Volley. This just passes the logic to another method, so you don't need to think about "returning" inside Volley.
public void parseJSON(JsonObject object)
And pass the response from volley into that and do your normal parsing and variable assignment and you can Toast myPlaces inside that method.
Also, note that Volley is asynchronous, meaning you aren't guaranteed an immediate result, so
Toast.makeText(MainActivity.this, myPlaces[2].getName(), Toast.LENGTH_LONG).show();
Would likely have thrown either a NullPointerException or IndexOutOfBoundsException because myPlaces was either undeclared or empty before the Volley request. I say that because it does not appear to be assigned before the Volley request.

Using Future.add call back to retrieve data from Azure mobile service into android applicaton

I am trying to retrieve from a Azure Mobile service to the android application, I have been using Mobile Service client to do so. Here is my code.
try {
mClient = new MobileServiceClient(
"URL", "Key",
this);
ListenableFuture<MyObject> result = mClient.invokeApi("CCOOutageHistoryData", "GET", null, MyObject.class);
Futures.addCallback(result, new FutureCallback<MyObject>() {
#Override
public void onFailure(Throwable exc) {
//createAndShowDialog((Exception) exc, "Error");
}
#Override
public void onSuccess(MyObject result) {
String Incdenti= result.getCount();
//createAndShowDialog(result.getCount() + " item(s) marked as complete.", "Completed Items");
//refreshItemsFromTable();
}
});
However, I don't get any error but , when checking using a breakpoint it does not reach the onSuccess or Onfailure methods within Future.addcallback.
I am trying to retrieve the JSON data after invoking the azure mobile service api . Please help
Try with String[]
try {
mClient = new MobileServiceClient(
"URL", "Key",
this);
ListenableFuture<String[]> result = mClient.invokeApi("CCOOutageHistoryData", "GET", null, (new String[0]).getClass());
Futures.addCallback(result, new FutureCallback<String[]>() {
#Override
public void onFailure(Throwable exc) {
//createAndShowDialog((Exception) exc, "Error");
}
#Override
public void onSuccess(String[] result) {
}
});
There are some samples below that may help you learning the Coutom API for Android with the .NET backend of mobile service.
A test sample for the Custom API in Android, please see https://github.com/Azure/azure-mobile-apps-android-client/blob/master/e2etest/src/main/java/com/microsoft/windowsazure/mobileservices/zumoe2etestapp/tests/CustomApiTests.java
The sample for the .NET backend of mobile service, please see https://github.com/Azure-Samples/app-service-mobile-dotnet-backend-quickstart.
Hope it helps. Best Regards。

Volley request too slow

My app crashes because the images ArrayList is empty when I set the adapter, I figured that out by putting a toast message right after I parse my JSON request, and a Toast message after I initialize my adapter, "second" gets printed first on screen and the app crashes right after, does it have to do with my internet? Or am I missing something, here's my code, thanks!
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_page);
mViewPager = (ViewPager) findViewById(R.id.view_pager);
mVolleySingleton = VolleySingleton.getInstance();
mRequestQueue = mVolleySingleton.getRequestQueue();
//First Toast message inside this method
sendAPIRequest();
//after you get the images
mCustomSwipeAdapter = new CustomSwipeAdapter(this, images);
//SECOND TOAST
Toast.makeText(getApplicationContext(), "Second", Toast.LENGTH_LONG).show();
mViewPager.setAdapter(mCustomSwipeAdapter);
mCustomSwipeAdapter.notifyDataSetChanged();
}
public void sendAPIRequest(){
String requestURL = "";
JsonObjectRequest jsonObjectRequest = new JsonObjectRequest(Request.Method.GET, requestURL, (String) null, new Response.Listener<JSONObject>() {
#Override
public void onResponse(JSONObject response) {
parseJSONResponse(response);
//FIRST TOAST : SHOULD BE CALLED FIRST
Toast.makeText(getApplicationContext(), "First", Toast.LENGTH_LONG).show();
}
}, new Response.ErrorListener() {
#Override
public void onErrorResponse(VolleyError error) {
}
});
mRequestQueue.add(jsonObjectRequest);
}
public void parseJSONResponse(JSONObject response) {
if (response != null || response.length() != 0) {
try {
JSONObject GObject = response.getJSONObject("game");
String name = "N/A";
if (GObject.has("name") && !GObject.isNull("name")) { name = GObject.getString("name"); }
if (GObject.has("screenshots") && !GObject.isNull("screenshots")) {
JSONArray screenShotsArray = GObject.getJSONArray("screenshots");
for (int i = 0; i < screenShotsArray.length(); i++){
JSONObject screenshot = screenShotsArray.getJSONObject(i);
String screenshotURL = screenshot.getString("url");
images.add(screenshotURL);
}
}
} catch (JSONException e) {
e.printStackTrace();
}
}
}
Does it have to do with my internet? Or am I missing something ...
Both. It happens because you have a race condition.
From what I can make out, your images list is being populated asynchronously by the onResponse callback. Basically, that happens when your app gets the responses to the API requests that it is making. That is going to take at least milliseconds, and possibly seconds (or longer).
But your app is (so you say) crashing soon after the swipe adapter is registered, and the evidence is that the images list has not been populated.
There are three possibilities:
There is something wrong with the requests you are sending which is causing the API requests to not give you any response. (Hypothetically, you could have authentication wrong or something.)
The API requests are taking a long time because of internet connection speed, congestion, or the remote server being slow.
The API requests are taking a short time ... but the adapter registration is even quicker.
If (hypothetically) there is a problem with your requests you will need to fix that. But both of the other scenarios have to be fixed by:
modifying the code that uses the images to work properly if there are no images (yet), or
modifying the code to wait until the image loading has completed before registering the adapter.
Please use this code in your onResponse callback :
//after you get the images
mCustomSwipeAdapter = new CustomSwipeAdapter(this, images);
//SECOND TOAST
Toast.makeText(getApplicationContext(), "Second", Toast.LENGTH_LONG).show();
mViewPager.setAdapter(mCustomSwipeAdapter);
mCustomSwipeAdapter.notifyDataSetChanged();
Volley adds your requests in queue , so better do all the dependent tasks in Response or Error callback only.

Categories

Resources