Interesting issue with POST requests (HttpURLConnection) - But why does it happen? - java

So I just spent 6 hours worth of work, figuring out this 'little' fact:
Without calling client.getResponseCode() THE POST REQUEST DOES NOT GO THROUGH.
I hope that someone can explain why!
Specifically, for this minimalistic android client standalone code literally nothing happens without the line int status = client.getResponseCode();
but with it,everything works like magic.
I didn't find any official documentation about this, so I'm wondering what's up, or what I don't understand (The people implementing Java usually do outstanding job, so it's probably me not getting something :) ).
public class MainActivity extends AppCompatActivity {
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
final String theUrl = "http://xx.yyy.zz.aa:bb/securitiesFollowServer/users";
final String TAG = getClass().getSimpleName();
AsyncTask<Void, Void, Void> task = new AsyncTask<Void, Void, Void>() {
#Override
protected Void doInBackground(Void... params) {
String body = "BODY OF MESSAGE";
HttpURLConnection client = null;
BufferedWriter outputPost = null;
try {
URL url = new URL(theUrl);
// open the connection
client = (HttpURLConnection) url.openConnection();
client.setRequestProperty("content-type", "text/plain");
//client.setRequestMethod("POST"); Someone claimed that setDoOutput(true) works so I will try that instead (I tried both,mutually and exclusively so all 3 options).
client.setDoOutput(true);
outputPost = new BufferedWriter(new OutputStreamWriter(client.getOutputStream()));
outputPost.write(body);
outputPost.flush();
outputPost.close();
int status = client.getResponseCode();
StackTraceElement[] r = Thread.currentThread().getStackTrace();
String toNotepad = "";
for (int i = 0; i < r.length; ++i) {
toNotepad += '\n' + String.valueOf(i) + '.' + ':' + r[i].toString();
}
// This is where I set a breakpoint and got the stacktrace value from toNotepad,and copy pasted it.
} catch (IOException e) {
Log.e(TAG, "Error ", e);
} finally {
if (client != null) {
client.disconnect();
}
if (outputPost != null) {
try {
outputPost.close();
} catch (IOException e) {
Log.e(TAG, "IO ERROR");
}
}
return null;
}
}
};
task.execute();
}
}
For completeness of the question, here is the "server side" minimalistic code
#POST
#Consumes(MediaType.TEXT_PLAIN)
#Produces(MediaType.TEXT_PLAIN)
public String setDebugResource(String a){
return "I got this string:"+a;}
And here is the stacktrace (I made it obvious in the code above where exactly I copy-pasted its value):
When not working(or working, it is exactly the same stacktrace).:
0.:dalvik.system.VMStack.getThreadStackTrace(Native Method)
1.:java.lang.Thread.getStackTrace(Thread.java:580)
2.:dor.only.dorking.android.apppostrequest.MainActivity$1.doInBackground(MainActivity.java:52)
3.:dor.only.dorking.android.apppostrequest.MainActivity$1.doInBackground(MainActivity.java:28)
4.:android.os.AsyncTask$2.call(AsyncTask.java:292)
5.:java.util.concurrent.FutureTask.run(FutureTask.java:237)
6.:android.os.AsyncTask$SerialExecutor$1.run(AsyncTask.java:231)
7.:java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1112)
8.:java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:587)
9.:java.lang.Thread.run(Thread.java:818)

According to the HttpUrlConnection docs you must call setDoOutput(true) on the client object instead of setting the method to POST. The method will be set automatically to POST through this. They have an example under section "Posting Content".
There's an example here as well and a larger discussion here
Frankly, I would skip using the raw HttpUrlConnection class and use something like Volley.

Related

OpenWeatherMap API : Encounter NullPointerException [duplicate]

This question already has answers here:
Android 8: Cleartext HTTP traffic not permitted
(37 answers)
Closed 2 years ago.
I'm building an application on Android Studio that retrieves weather information in real time thanks to OpenWeatherMap and the API they offer.
The problem is, I'm using two phones with different SDKs. One is SDK 23 / Android 6.0 and the other is SDK 28 / Android 9.0.
Currently on the phone with SDK 23 I have no problem. However on the phone with SDK 28 I have a NullPointerException error. My second activity allows me to display information for city X and its weather information. So, finally the error I'm encountering on the phone with SDK 28 is this one :
java.lang.NullPointerException: Attempt to invoke virtual method 'int java.lang.String.length()' on a null object reference
I've looked into a lot of things to see where that could have come from, if it wasn't my AsyncTask or whatever, but I really don't see it.
Knowing that on the phone with the oldest version of Android it retrieves well the information from my editText that on the most recent version it doesn't retrieve it at all and the nullpointerException must come from there.
Do you know where this might be coming from?
Here is my AsyncTask :
public class ExecuteTask extends AsyncTask<String, Void, String> {
#Override
protected String doInBackground(String... strings) {
HttpURLConnection con = null ;
InputStream is = null;
try {
con = (HttpURLConnection) ( new URL(strings[0])).openConnection();
con.setRequestMethod("GET");
con.setDoInput(true);
con.setDoOutput(true);
con.connect();
// Let's read the response
StringBuffer buffer = new StringBuffer();
is = con.getInputStream();
BufferedReader br = new BufferedReader(new InputStreamReader(is));
String line = null;
while ( (line = br.readLine()) != null )
buffer.append(line + "\r\n");
is.close();
con.disconnect();
return buffer.toString();
}
catch(Throwable t) {
t.printStackTrace();
}
finally {
try { is.close(); } catch(Throwable t) {}
try { con.disconnect(); } catch(Throwable t) {}
}
return null;
}
#Override
protected void onPostExecute(String s) {
super.onPostExecute(s);
try {
String message = "";
String degre="";
String idMeteo="";
JSONObject jsonObject = new JSONObject(s);
String infoWeatherToday = jsonObject.getString("weather");
JSONObject WeatherTemperature = jsonObject.getJSONObject("main");
Integer deg = WeatherTemperature.getInt("temp");
deg = deg - 273;
JSONArray array = new JSONArray(infoWeatherToday);
int tablongueur=array.length();
for (int i = 0; i < tablongueur; i++) {
JSONObject jsonSecondary = array.getJSONObject(i);
String main = "";
//Integer id;
main = jsonSecondary.getString("main");
// id = jsonSecondary.getInt("id");
switch (main) {
case "Clouds":
main = "Nuageux";
PhotoMeteo.setImageResource(R.drawable.cloud);
break;
case "Clear":
main = "Ensoleillé";
PhotoMeteo.setImageResource(R.drawable.sun);
break;
case "Rain":
main = "Pluie";
PhotoMeteo.setImageResource(R.drawable.rain);
break;
case "Snow":
main = "Neige";
PhotoMeteo.setImageResource(R.drawable.snow);
break;
case "Smoke":
main = "Brouillard";
PhotoMeteo.setImageResource(R.drawable.smoke);
break;
case "Drizzle":
main = "Brumeux";
PhotoMeteo.setImageResource(R.drawable.drizzle);
break;
default:
main = "Météo introuvable !";
PhotoMeteo.setImageResource(R.drawable.ic_warning);
}
if (main != "" /*&& id != null*/) {
message += main + "\r\n";
degre += deg + "°C";
//idMeteo += "L'id de la météo est" + id;
}
}
if (message != "") {
resultWeather.setText(message);
resultDegre.setText(degre);
//resultIdMeteo.setText(idMeteo);
} else {
Toast.makeText(AccueilActivity.this, "Une erreur a eu lieu ", Toast.LENGTH_SHORT).show();
}
} catch (JSONException e) {
e.printStackTrace();
}
}
And here is the intent that I keep from my first activity called RegisterActivity to give it as a parameter for the "name" of the city
Intent intent = new Intent(RegisterActivity.this, AccueilActivity.class);
intent.putExtra(EXTRA_TEXT,cityField.getText().toString());
startActivity(intent);
In my 2nd activity called "AccueilActivity"
Intent intent = getIntent();
if(intent!=null)
{
textViewVille.setText(intent.getStringExtra(EXTRA_TEXT));
ville = intent.getStringExtra(EXTRA_TEXT);
FindWeather();
}
And my final function called FindWeather which execute the AsyncTask
public void FindWeather() {
cityToFind = ville;
try {
ExecuteTask tasky = new ExecuteTask();
tasky.execute("http://api.openweathermap.org/data/2.5/weather?q=" + cityToFind + "&APPID={MYAPKKEY}&LANG=fr&UNITS=metric");
} catch (Exception e) {
e.printStackTrace();
}
}
Just I don't give you the value of my APK Key because it isn't something interesting but the value is present in the initial code.
If I have a last things to add, ville is a simple TextView and cityToFind the value of my editText on the first activity.
If you need anything of my source code I can give you more.
Thank you.
doInBackground is going to return null if there is any exception in your HTTP code.
That is passed to onPostExecute as the parameter.
You then try to constuct a JSONObject(null), which is an invalid argument
All in all, please pick a higher level HTTP library with fault tolerance built in
Comparison of Android networking libraries: OkHTTP, Retrofit, and Volley
I also suggest writing unit tests outside of that class and running them from the IDE rather than a device, so you verify the network calls actually work.

Java Stack becomes empty for some reason

I'm working on an Android app that is going to call the DarkSky weather API (I have redacted my API key here for obvious reasons). My problem comes when I parse the JSON data and push it to a stack I named dataStack. At the time of pushing the stack I log its size and it shows correctly. However when my code reaches the buildGraph() method, the stack is now empty and all my data has disappeared. What causes the stack to empty?
EDIT: As of 30 minutes after posting I found a workaround. I am now returning the String and parsing it in my MainActivity Android class. However, I still do not know why the stack was being deleted. I would love to know :)
public class MainActivity extends AppCompatActivity {
Button button;
TextView progressLabel;
GraphView graph;
JSONObject jsonObject;
static Stack<DataPoint> dataStack = new Stack<>(); // stack for graph data points
static final String API_URL = "https://api.darksky.net/forecast/API_KEY/42.3611,-71.0570,"; // #TODO: delete API key before comitting to GitHub
static final String URL_TAIL = "?exclude=currently,flags,hourly"; // end of URL
static final long currTime = System.currentTimeMillis() / 1000L; // current UNIX time
static long unixTime = currTime;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
button = findViewById(R.id.button);
progressLabel = findViewById(R.id.progressLabel);
graph = findViewById(R.id.graph);
}
public void loadResults(View view) {
for (int x = 0; x < 2; x++) { // 7 API calls for each of 7 days
new APICall().execute();
unixTime -= 86400; // subtract 24 hours in UNIX time
dataStack.size();
}
buildGraph(); // after all data is gathered, build a graph using it
}
private void buildGraph() {
// #TODO: Method to build graph
Log.i("STACK pop", String.valueOf(dataStack.size()));
}
class APICall extends AsyncTask<Void, Void, String> { // Extend AsyncTask so we don't hijack the main UI thread
protected void onPreExecute() {
// Do stuff before executing the AsyncTask
progressLabel.setText("Fetching Data");
}
protected String doInBackground(Void... urls) {
// Execute background task here
try {
final String FULL_URL = API_URL + unixTime + URL_TAIL; // build the full URL with latest time
URL url = new URL(FULL_URL); // URL for the API call
HttpURLConnection urlConnection = (HttpURLConnection) url.openConnection(); // connection to URL
try {
// tools for reading API results
BufferedReader bufferedReader = new BufferedReader(new InputStreamReader(urlConnection.getInputStream()));
StringBuilder stringBuilder = new StringBuilder();
String line;
// accumulate results
while ((line = bufferedReader.readLine()) != null) {
stringBuilder.append(line).append("\n");
}
bufferedReader.close(); // always close buffered reader
return stringBuilder.toString(); // return results
}
finally {
// inside a finally block so that no matter what we always end a connection that has been started
urlConnection.disconnect(); // end the connection
}
}
catch(Exception ex) {
Log.e("ERROR", ex.getMessage(), ex);
return null;
}
}
protected void onPostExecute(String response) {
// Do stuff after we're finished executing
if (response == null) {
response = "AN ERROR HAS OCCURRED";
}
else {
try {
jsonObject = new JSONObject(response); // create object from our response
JSONArray arr = jsonObject.getJSONObject("daily").getJSONArray("data"); // get data Array
String arrString = arr.getString(0); // full String
String[] splitString = arrString.split(","); // split String into array by comma
String time = splitString[0].substring(8); // time is the first index of the array, use substring to cutout unecessary info
String temp = splitString[11].substring(18);
dataStack.push(new DataPoint(Integer.valueOf(time), Float.valueOf(temp))); // push our data onto the stack as a DataPoint
Log.i("STACK push", String.valueOf(dataStack.toString()));
response = "Data received"; // display this to user
}
catch(Exception ex) {
response = "ERROR DURING JSON PARSING";
}
}
progressLabel.setText(response);
// parse data here
Log.i("INFO", response);
}
}
}
The stack is empty because result isn't in yet. The issue is with your loadResults().
public void loadResults(View view) {
for (int x = 0; x < 2; x++) { // 7 API calls for each of 7 days
new APICall().execute();
unixTime -= 86400; // subtract 24 hours in UNIX time
dataStack.size();
}
buildGraph(); // after all data is gathered, build a graph using it
}
You issued the new APICall().execute(); to request data and update the dataStack and you expect to get the dataStack results 'immediately' inside the same function loadResults()? It's not possible.
One solution is to remove the buildGraph() in loadResults() to inside onPostExecute().

Status code 404 when calling spring-boot API, but not for postman or browser

I want to make an API call to a local REST server built with Spring-Boot which is interacting with mongodb. I already checked some posts which I found to this topic, but my problem seems to be a little bit different.
Here are some code snippets which are relevant:
protected static CoreEntity[] sendGET(CoreEntity[] resultList, String path) throws IOException {
path = String.join("%20", path.split(" "));
return handleResponse(resultList, getConnection(path, "Get"));
}
private static HttpURLConnection getConnection(String path, String requestMethod) throws IOException {
URL url = new URL(REQUEST_URL + path);
HttpURLConnection connection = (HttpURLConnection) url.openConnection();
connection.setDoOutput(true);
connection.setDoInput(true);
connection.setRequestProperty("Content-Type", "application/json");
connection.setRequestProperty("accept", "application/json");
connection.setConnectTimeout(50000);
connection.setReadTimeout(50000);
connection.setRequestMethod(requestMethod);
initializeGSON();
return connection;
}
private static CoreEntity[] handleResponse(CoreEntity[] resultList, HttpURLConnection connection) {
try {
final int status = connection.getResponseCode();
if (status == HttpURLConnection.HTTP_OK) { // Success
try (InputStreamReader reader = new InputStreamReader(connection.getInputStream()); BufferedReader in = new BufferedReader(reader)) {
String inputLine;
StringBuilder response = new StringBuilder();
while ((inputLine = in.readLine()) != null) { response.append(inputLine); }
reader.close();
in.close();
JSONArray jsonArray = getJSONAsArray(response.toString());
resultList = (CoreEntity[]) Array.newInstance(resultList.getClass().getComponentType(), jsonArray.length());
for (int i = 0; i < jsonArray.length(); i++)
resultList[i] = (CoreEntity) GSON.fromJson(jsonArray.get(i).toString(), resultList.getClass().getComponentType());
} catch (IOException | JSONException e) { e.printStackTrace(); }
} else {
System.out.println("\nRequest failed with error code: " + status);
}
connection.disconnect();
return resultList;
} catch (ConnectException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
return null;
}
The response for http://www.google.com or any other homepage is successful with status code 200. But as soon as I call my API I get an error with status code 404. Strange is that everything works when I am using Postman or the browser. So when I do a get request via postman to the following method (http://localhost:8080/pets/3), I can see the print out and get the data from mongodb, but not for the code above. For the code above nothing happens on server side, no print out, no exception, nothing.
#RequestMapping(value = "/{id}", method = RequestMethod.GET)
public ResponseEntity<T> getById(#PathVariable final long id) {
System.out.println("TEST ===> " + id);
T entity = getService().getById(id);
return entity == null ? ResponseEntity.notFound().build() : ResponseEntity.ok(entity);
}
It seems like my application is not able to find the API, but I already verified that the URL is correct which is why I don’t understand the error code 404.
I also read about package visibility, but my structure looks like the following which is why I don't think that this is the reason.
Package Structure (Don't be confused from name Aerospike)
I've spend way too much time for this now, and I am really desperate for help and hope you can help me or at least point me in the right direction.
Edit
Here is the entire RestController:
#Controller
public abstract class CoreController<S extends CoreService<T>, T extends CoreEntity> {
public static final String SERVER = "http://localhost", PORT = ":8080",
CORE_API = SERVER + PORT + "/"; // controller/v2/
public static final String ID = "id";
private String api;
public CoreController() { }
public CoreController(final String api) { this.api = CORE_API + api; }
#RequestMapping(value = "/{" + ID + "}", method = RequestMethod.GET)
public ResponseEntity<T> getById(#PathVariable final long id) {
System.out.println("TEST ===> " + id);
T entity = getService().getById(id);
return entity == null ? ResponseEntity.notFound().build() : ResponseEntity.ok(entity);
}
public abstract S getService();
}
#Controller
#RequestMapping(value = "pets/")
public class PetController extends CoreController<PetService, Pet> {
#Autowired
protected PetService service;
public static final String API = "pets";
public PetController() { super(API); }
public PetService getService() { return service; }
}
Here the evidence that the spring-boot is listening on 8080 and also postman works with port 8080.
Server print out on start up
I think you missing the slash ("/") in the start and you have duplicate in the end of the exposed value so it's looking for pets//{id} in the controller change to value = { "/pets"}
Anyway, when starting the service syou should see in the logs the exposed uri's

Asynctask doesnt work after too many rows retrieved

I am doing an app where I synchronize my online DB to the offline DB everytime the user logs in. The table is dropped in offline, recreated then new rows gets added ( Its neccessary to drop it and add new instead of just checking and adding the rows that are not in the table already). I had about 200 rows in my online table and they are synchronised to my offline table relatively fast (in the background, then I tried 3000 and it was still processing. But When I generated 90 000 rows and tried to synchronize it to my offline DB it wouldnt move.
The log in onPreExecute() executed, but none of the logs in my doInBackground. json is not null.
For each retrieved row I am adding a row in offline.
Anyone know what could be the issue?
I tried adding LIMIT 200 in my PHP Scripts and still didnt do it, which was weird, cause when I had 200 rows it executed, but when I limit the output to 200 it does not.
Thank you for any answers, that would bring me closer to the solution.
public class SyncVykresToOffline {
String DataParseUrl = "/scriptsforandroidapplicationofflinemode/SyncVykresToOffline.php";
JSONObject json = null;
String str = "";
HttpResponse response;
DBHelper dbh;
private Context mContext;
public static boolean syncedvykres = false;
int k = 200;
public SyncVykresToOffline(Context context) {
mContext = context;
dbh = new DBHelper(mContext);
}
public class SyncVykres extends AsyncTask<Void, Void, Void>
{
public Context context;
public SyncVykres(Context context)
{
this.context = context;
}
#Override
protected void onPreExecute()
{
super.onPreExecute();
Log.i("Poradie_zacal","ano");
}
#Override
protected Void doInBackground(Void... arg0)
{
HttpClient myClient = new DefaultHttpClient();
HttpPost myConnection = new HttpPost(DataParseUrl);
List<NameValuePair> nameValuePairs = new ArrayList<NameValuePair>(2);
nameValuePairs.add(new BasicNameValuePair("limit", String.valueOf(k)));
try {
myConnection.setEntity(new UrlEncodedFormEntity(nameValuePairs));
} catch (UnsupportedEncodingException e1) {
e1.printStackTrace();
}
try {
HttpResponse response = myClient.execute(myConnection);
} catch (IOException e1) {
e1.printStackTrace();
}
try {
response = myClient.execute(myConnection);
str = EntityUtils.toString(response.getEntity(), "UTF-8");
} catch (ClientProtocolException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
int i = 0;
try{
int vykres_version;
JSONArray jArray = new JSONArray(str);
json = jArray.getJSONObject(i);
Log.i("Poradie_json",String.valueOf(jArray.length()));
String
Nazov_vykresu;
int Version,
ID_vykres,
ID_stav,
ID_zakazka,
Poradie;
if(json == null) {
Log.i("Poradie","son is null");
}
while(json != null) {
Log.i("Poradie","been here");
ID_vykres = Integer.parseInt(json.getString("ID_vykres"));
vykres_version = dbh.getVykresVersion(ID_vykres);
Nazov_vykresu = json.getString("Nazov_vykresu");
ID_stav = Integer.parseInt(json.getString("ID_stav"));
ID_zakazka = Integer.parseInt(json.getString("ID_zakazka"));
Version = Integer.parseInt(json.getString("Version"));
Poradie = Integer.parseInt(json.getString("Poradie"));
Log.i("Poradie",json.getString("Poradie"));
dbh.SyncVykresToOffline(new technicky_vykres(ID_vykres,Nazov_vykresu,ID_stav,ID_zakazka,Version,Poradie));
i++;
json = jArray.getJSONObject(i);
}
} catch ( JSONException e) {
e.printStackTrace();
}
catch (Exception e)
{
// TODO Auto-generated catch block
e.printStackTrace();
}
return null;
}
protected void onPostExecute(Void result)
{
syncedvykres = true;
}
}
}
Edit: added Logcat logs.
06-25 20:36:07.013 8278-8308/com.example.chris.normitapplication W/System.err: at org.json.JSON.typeMismatch(JSON.java:111)
at org.json.JSONArray.<init>(JSONArray.java:96)
at org.json.JSONArray.<init>(JSONArray.java:108)
at com.example.chris.normitapplication.offline.SyncVykresToOffline$SyncVykres.doInBackground(SyncVykresToOffline.java:102)
at com.example.chris.normitapplication.offline.SyncVykresToOffline$SyncVykres.doInBackground(SyncVykresToOffline.java:44)
at android.os.AsyncTask$2.call(AsyncTask.java:292)
at java.util.concurrent.FutureTask.run(FutureTask.java:237)
Edit 2: added PHP Script from where the JSON array is retrieved from:
<?php
include 'DatabaseConfig.php';
$conn = mysqli_connect($HostName,$HostUser,$HostPass,$DatabaseName);
if ($conn->connect_error) {
die("Connection failed: " . $conn->connect_error);
}
mysqli_set_charset($conn,"utf8");
$vykres = array();
$sql = "SELECT * FROM `technicky_vykres`";
$result = mysqli_query($conn, $sql) or die("Error in Selecting " . mysqli_error($conn));
while($row =mysqli_fetch_assoc($result))
{
$emparray[] = $row;
}
echo json_encode($emparray);
$conn->close();
?>
Issue identified when logging STR:
<html>
<head><title>502 Bad Gateway</title></head>
<body bgcolor="white">
<center><h1>502 Bad Gateway</h1></center>
<hr><center>openresty</center>
</body>
</html>
My hunch is, its the data that is breaking the loop and causing your program to end without going through the complete data set. I just added simple try/catch (see below) to printout any data objects, that we can't parse and but still continue to process the next row. Of course you'll need to have better error handling in place for production quality code.
while(json != null) {
try{
Log.i("Poradie","been here");
ID_vykres = Integer.parseInt(json.getString("ID_vykres"));
vykres_version = dbh.getVykresVersion(ID_vykres);
Nazov_vykresu = json.getString("Nazov_vykresu");
ID_stav = Integer.parseInt(json.getString("ID_stav"));
ID_zakazka = Integer.parseInt(json.getString("ID_zakazka"));
Version = Integer.parseInt(json.getString("Version"));
Poradie = Integer.parseInt(json.getString("Poradie"));
Log.i("Poradie",json.getString("Poradie"));
dbh.SyncVykresToOffline(new technicky_vykres(ID_vykres,Nazov_vykresu,ID_stav,ID_zakazka,Version,Poradie));
i++;
json = jArray.getJSONObject(i);
}catch(Exception e){
//Something wrong with the data? log it and see if you can find the culprit row/data....
Log.i("The faulty jason obj: " + json);
continue; //Move on the next one....
}
}
The error indicates that JSONArray believes your response is not formed as a Json Array.
Here's the code within JSONArray throwing your error:
public JSONArray(JSONTokener readFrom) throws JSONException {
/*
* Getting the parser to populate this could get tricky. Instead, just
* parse to temporary JSONArray and then steal the data from that.
*/
Object object = readFrom.nextValue();
if (object instanceof JSONArray) {
values = ((JSONArray) object).values;
} else {
throw JSON.typeMismatch(object, "JSONArray");
}
}
So the tokener does not recognize the object as a JSONArray. I would take a look at your raw response and see if adding a limit doesn't change the response to be an object with a result array inside of it (so that it can also include arguments to help web calls handle paging). Either way, there's something in the format of the response that the tokener does not recognize as being a Json array.
Upon realizing that the PHP script stopped working because too many rows & columns were retrieved instead of * I only Selected data that I truly needed (about 1/3 of all columns), then I added a where clause where ID would be above the number I sent from post and I keep repeating the script until finally the response is not "null".
Thank you for everyone who contributed to finding the solution.

Waiting for JSON response to finish before updating fields

Currently in my application I execute a JSONDownloader, then tell my application to wait for a set period of time before updating fields with the retrieved data. How do I go about making the application wait for the JSONDownloader to finish its' task before I update the fields?
The JSONDowloader class is written (abridged) as follows and is run as an asynchronous activity. This class is called when needed and sets global variables which, after a set amount of time after being called are updated. I'd like the fields to be updated as soon as the class has finished running.
public class JSONDownloader extends AsyncTask<Object, Object, Object>{
#Override
protected Object doInBackground(Object... params) {
if(JSONstate == false){
try {
final URL url = new URL("https://irrelevant");
final URLConnection urlConnection = url.openConnection();
urlConnection.setRequestProperty("Content-Type", "application/json; charset=utf-8");
urlConnection.connect();
final InputStream inputStream = urlConnection.getInputStream();
final StringBuilder sb = new StringBuilder();
while (inputStream.available() > 0) {
sb.append((char) inputStream.read());
}
System.out.println("up to setting string");
String result = sb.toString();
JSONObject jsonOrg = new JSONObject(result);
String ok = "ok";
Response = jsonOrg.getString("response");
System.out.println(Response);
if(Response.equals(ok)){
Settingsresponse = true;
orgName = jsonOrg.getString("orgName");
System.out.println("orgName" + orgName);
accessPointName = jsonOrg.getString("accessPointName");
System.out.println("accessPointName" + accessPointName);
lat = jsonOrg.getString("latitude");
System.out.println("lat" + lat);
longi = jsonOrg.getString("longitude");
System.out.println("longi" + longi);
floor = jsonOrg.getString("floor");
System.out.println("floor" + floor);
orgId = jsonOrg.getString("orgId");
System.out.println("orgId" + orgId);
}
else{
System.out.println("Data sent was erroneous");
Settingsresponse = false;
}
} catch (Exception e) {
System.err.print(e);
}
}
return null;
}
protected void onPostExecute(Void result){
}
}
The JSONDownloader is called within whatever method it is needed and then immediately after this is called; currently a set time is used before updating fields as thus:
public void waitthencall()
{
long t0,t1;
t0=System.currentTimeMillis();
do{
t1=System.currentTimeMillis();
}
while (t1-t0<2000);
setfields();
}
you need a Callback listener to update your UI. Example
Create a callback listener and implement it inside your activity or from where you are updating the UI.
By using asynchronous task!
http://www.vogella.com/articles/AndroidBackgroundProcessing/article.html
May help!
Dude, the method onPostExecute is call once doInBackGround has completed processing call your method from there, it will assure you that doInBackGround has finished its execution

Categories

Resources