NullPointerException on JSONArray initialized in background thread - java

I'm writing an android app I use a background thread to pull a JSONArray from a web service. I then need to interact with that JSONArray inside the main activity. Here's what I'm doing now:
public class MainActivity extends Activity {
JSONArray stories;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
new getAll().execute();
// try {
System.out.println("stories.length());
// } catch (JSONException e) {
// TODO Auto-generated catch block
// e.printStackTrace();
//}
}
And the background thread:
private class getAll extends AsyncTask <Void, Void, JSONArray> {
private static final String url = "http://10.0.2.2:8080/CalibServer/webresources/storypkg.story/";
#Override
protected JSONArray doInBackground(Void... params) {
//set up client and prepare request object to accept a json object
HttpClient httpclient = new DefaultHttpClient();
HttpGet httpget = new HttpGet(url);
httpget.addHeader("accept", "application/json");
HttpResponse response;
String resprint = new String();
try {
response = httpclient.execute(httpget);
// Get the response entity
HttpEntity entity = response.getEntity();
if (entity != null) {
// get entity contents and convert it to string
InputStream instream = entity.getContent();
String result= convertStreamToString(instream);
resprint = result;
// construct a JSON object with result
stories =new JSONArray(result);
// Closing the input stream will trigger connection release
instream.close();
}
}
catch (ClientProtocolException e) {System.out.println("CPE"); e.printStackTrace();}
catch (IOException e) {System.out.println("IOE"); e.printStackTrace();}
catch (JSONException e) { System.out.println("JSONe"); e.printStackTrace();}
System.out.println("FUCKYEAHBG: " + resprint);
// stories = object;
return stories;
}
My problem is that I'm getting a NullPointerException at the call to
System.out.println("stories.length());
It's acting like a didn't initialize the stories array, but should't that have been taken care of by the background thread (at the line: stories =new JSONArray(result); ) before that call is ever made?
I have a feeling this is because of the threading - perhaps there is another step I have to take to update the main activity after the AsyncTask runs?

You're initializing the variable in a background thread. That means that the line
System.out.println(stories.length());
is executed in parallel with the code initializing the variable. That thus means that there is a huge chance that the background thread has not had the time to initialize the variable yet when this line is executed.
Your code is similar to the following situation: you have an empty cup in front of you, and ask someone to go make some coffee and to fill your cup. And immediately after asking, you start drinking. There will be no coffee inside the cup, obviously.
Re-read the android documentation on how to execute asynchronous tasks.

You can't rely on stories to be initialized when a separate Thread that runs parallel to the UI Thread initializes and updates stories.
perhaps there is another step I have to take to update the main
activity after the AsyncTask runs?
onPostExecute() of the AsyncTask. Do whatever UI updates you need there. Since getAll is already a private inner class, you have full access to the Activity. You already return stories off to that (unoverriden) method, so this should be a minor change.
#Override
protected void onPostExecute (JSONArray stories)
{
//use the now initialized stories
}

Related

Should JSON be downloaded in background?

After user press the button it fires up weather function. But it doesn't log any JSON data or any error. Should it be done in background? I've used gson libary to download JSON.
Edit: I edited my code but user must enter a city which is pasted to the link. So is it possible to run in background process when the button is tapped?
public class MainActivity extends AppCompatActivity {
public class Download extends AsyncTask<String,Void,String>{
#Override
protected String doInBackground(String... strings) {
try {
URL url = new URL("api.openweathermap.org/data/2.5/weather?q="+strings[0]+"&APPID=****");
URLConnection request = url.openConnection();
request.connect();
JsonParser jp=new JsonParser();
JsonElement root = jp.parse(new InputStreamReader((InputStream) request.getContent()));
JsonObject rootobj = root.getAsJsonObject();
String weather = rootobj.getAsString();
Log.i("weather:",weather);
}
catch (Exception e){
e.printStackTrace();;
}
return null;
}
}
public void weather(View view){
TextView textView=(TextView) findViewById(R.id.editText);
String city=textView.getText().toString();
Download download=new Download();
download.execute(city);
}
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
}
}
All io operation should be executed in background , because all this operations are time consuming . which means you will block your main thread if you donot execute these codes in background and may cause Android Not Respond exception. IO operation in ui thread generally lead to bad user experience . so i strongly advice you do this in background.
You should definitely load your data in the background. The Main Thread i.e. the UI Thread is the thread that renders the UI components so no heavy operation should be done there. If heavy operation is done in the UI Thread, it will freeze the UI.
You should look at the AsyncTask class to perform your loading in the background.
Here is some good tutorials:
https://alvinalexander.com/android/asynctask-examples-parameters-callbacks-executing-canceling
https://www.journaldev.com/9708/android-asynctask-example-tutorial
https://www.tutorialspoint.com/android-asynctask-example-and-explanation

Fail whe i try to connect my app to webServices

Actully i working in a app, but i have problems to connect my Web services, i have this code:
try{
HttpServices post = new HttpServices ("http://sotem.com.mx/WebServices/controller.php");
post.add("funcion", "test");
System.out.println("Si lo mande///////////////////Jhgfdsa");
String respuesta = post.getRespueta();
System.out.println(respuesta);
Toast.makeText(getApplicationContext(),"Cool: "+respuesta, Toast.LENGTH_SHORT).show();
}catch (Exception ex) {
Toast.makeText(getApplicationContext(),"error: "+ex.toString(), Toast.LENGTH_SHORT).show();
}
but i can make connection, i try to make other thinks, but i can make the thread, i'am new in this part, the app launcher this error:
android os network on main thread exception
It is not okay to do the Network Operation on main thread.. You can use AsyncTask to perform such operations and handle the result in onPostExecute method.
class YourNetworkingTasks extends AsyncTask<Void, Void, Void> {
#Override
protected Void doInBackground(Void... voids) {
try{
HttpServices post = new HttpServices ("http://sotem.com.mx/WebServices/controller.php");
post.add("funcion", "test");
String respuesta = post.getRespueta();
Log.d("Output", respuesta);
// DON'T DO ANY UI CHANGES LIKE TOAST FROM BACKGROUND THREAD.. Toast.makeText(getApplicationContext(),"Cool: "+respuesta, Toast.LENGTH_SHORT).show();
}catch (Exception ex) {
// DON'T DO ANY UI CHANGES LIKE TOAST FROM BACKGROUND THREAD.. Toast.makeText(getApplicationContext(),"error: "+ex.toString(), Toast.LENGTH_SHORT).show();
}
return null;
}
protected void onPostExecute(RSSFeed feed) {
// TODO: YOU CAN MAKE U.I. Changes Like Display text in TextView, TOAST HERE.
// TODO: do something with the result
}
}
And write new YourNetworkingTasks().execute(); to run that code in background thread.
Please also not that since you are using http and not https you may get Network Security Exception and may not get any output due to recent security change in android.

Java code won't execute after calling a classes function

I have created a program that will connect to a database through PHP and echo back a response. My android program then makes a request to the PHP file and reads the echo in.
public class Read_Author extends AsyncTask<String, Void, String> {
String authorName = "";
#Override
public String doInBackground(String... params) {
try {
HttpClient httpclient = new DefaultHttpClient();
HttpPost httppost = new HttpPost("http://localhost/scripts/read_information.php");
HttpResponse response = httpclient.execute(httppost);
authorName = String.valueOf(EntityUtils.toString(response.getEntity()));
String myStr = "ANSWER";
Log.v(myStr, authorName);
}
catch(Exception e){
}
return authorName;
}
public String returnAuthor(){
return authorName;
}
}
I successfully retrieve the echo string and put it in the author name string variable. But when I then try to call return author from my main activity I get no error but the code does not get run.
I call a function called "readValue" within my main activity and within that function, the execute function gets read and then what is supposed to happen is the returnauthor function is supposed to run. But instead, nothing happens
Main Activity Code:
public void returnAuthor(){
loadAuthor.execute();
String a = loadAuthor.returnAuthor();
Log.v("HIT ME", a);
}
If anyone has any suggestion on why this could be happening and how to fix it that will be very much appreciated!
You seem to have misconception about AsyncTask. The result of AsyncTask may not be available instantly, because the background task might not have been completed.
You need to override the method onPostExecute in your AsyncTask to perform some task after the background task has been completed.
First show a progressDialog before executing the AsyncTask
final ProgressDialog progressDialog = new ProgressDialog(this);
progressDialog.setMessage("Loading..");
progressDialog.setCancelable(false);
progressDialog.show();
Then in the onPostExecute:
#Override
protected void onPostExecute(String result) {
progressDialog.dismiss();
Log.d("author", result);
}

Android AsyncTask sending message to a Handler on a dead thread

I am trying to make a program that should work something like a catalog - I have a JSON array that I loop through and parse the JSON objects into a string containing the image link, and two strings for descriptions for each object. Now, when downloading the images from the internet with the link, I run into a problem at the same image every time, image number 93. I checked the link, and it's working, just the same as the others.
This happens:
W/MessageQueue: Handler (android.os.Handler) {f95f6fe} sending message to a Handler on a dead thread
java.lang.IllegalStateException: Handler (android.os.Handler) {f95f6fe} sending message to a Handler on a dead thread
at android.os.MessageQueue.enqueueMessage(MessageQueue.java:543)
at android.os.Handler.enqueueMessage(Handler.java:643)
at android.os.Handler.sendMessageAtTime(Handler.java:612)
at android.os.Handler.sendMessageDelayed(Handler.java:582)
at android.os.Handler.post(Handler.java:338)
at android.os.ResultReceiver$MyResultReceiver.send(ResultReceiver.java:57)
at com.android.internal.os.IResultReceiver$Stub.onTransact(IResultReceiver.java:58)
at android.os.Binder.execTransact(Binder.java:565)
This is how my AsyncTask looks:
private class DownloadImageTask extends AsyncTask<String, Void, Bitmap> {
ImageView bmImage;
public DownloadImageTask(ImageView bmImage) {
this.bmImage = bmImage;
}
protected Bitmap doInBackground(String... urls) {
String urldisplay = urls[0];
Bitmap mIcon11 = null;
try {
InputStream in = new java.net.URL(urldisplay).openStream();
mIcon11 = BitmapFactory.decodeStream(in);
} catch (Exception e) {
e.printStackTrace();
}
return mIcon11;
}
protected void onPostExecute(Bitmap result) {
bmImage.setImageBitmap(result);
}
}
This is how I call the AsyncTask:
new DownloadImageTask(imgProductPicture).execute(pictureLink);
layoutTest.addView(NewImgView);
In my code I make sure that no more than 5 of these are called at a time, and they all load without issue until reaching the object indexed 92. The object itself is fine, but the app shuts off at this point always. Does anyone have an idea why? I've tried downloading less images at a time (one by one) and it still fails at the same point. I'd appreciate any help.
AsyncTask uses handler of the main thread, to callback onPostExecute(). If the main thread is dead when to callback, system throws the exception. To avoid this, you have to keep the main thread alive until all the work completes.
I solved the problem by creating a new handler/runnable every time I called the DownloadImageTask. Thanks to all who have tried to help.

Fetch JSON Data from URL and Repeatedly Update SQLite Database

In my app, I create a SQLite database. Then I populate it with JSON data fetched from a URL using an instance of the HttpAsyncTask class in my main activity. That works fine, but I also want to update the database. New data (one row in the database) is added to the URL page once per day, and I want to implement a "synchronize" button in the app that updates the database with only the new information. Could I get some advice on how to do this? My HttpAsyncTask is below, if that helps - I'm thinking I might need an if/else clause in the onPostExecute() method that adds all the rows only if the database is getting created for the first time. I thought about trying to put an HttpAsyncTask class in my DatabaseHelper, but that doesn't really make sense.
private class HttpAsyncTask extends AsyncTask<String, Void, String> {
#Override
protected String doInBackground(String...urls) {
return GET(urls[0]);
}
#Override
protected void onPostExecute(String result) {
try {
JSONObject main = new JSONObject(result);
JSONObject body = main.getJSONObject("body");
JSONArray measuregrps = body.getJSONArray("measuregrps");
// get measurements for date, unit, and value (weight)
for (int i = 0; i < measuregrps.length(); i++) {
JSONObject row = measuregrps.getJSONObject(i);
// a lot of getting & parsing data happens
db.addEntry(new Entry(date, weight, null, null));
//adds all the lines every time this is run, but I only want to add all
//the lines once and then add new rows one by one from there
}
} catch (JSONException e) {
e.printStackTrace();
}
}
}
public static String GET(String url) {
InputStream is = null;
String result = "";
try {
HttpClient client = new DefaultHttpClient();
HttpGet get = new HttpGet(url);
HttpResponse httpResponse = client.execute(get);
is = httpResponse.getEntity().getContent();
if (is != null)
result = convertInputStream(is);
else
result = "Did not work!";
} catch (Exception e) {
Log.d("input stream", e.getLocalizedMessage());
}
return result;
}
private static String convertInputStream(InputStream is) throws IOException {
StringBuilder builder = new StringBuilder();
BufferedReader reader = new BufferedReader(new InputStreamReader(is));
String line = "";
while((line = reader.readLine()) != null)
builder.append(line);
is.close();
return builder.toString();
}
Your implementation totally depends on the project requirements.
If there are continuously changes over the server, the right way to implement the synchronization process is:
1.
Implement the sync process, which works totally in background. This sync will be customized to call specific API calls/Service classes which will be required to sync.
2.
Server will prompt the mobile client for the data change.
3.
To get server updates, A continuously running service/Sync at some predefined intervals will be run and checks for the updates or implements the GCM.
Sync Adapter would be the best for the sync services.
Ohh, also don't forget to apply the content provider, as database calls would be concurrent from UI and background both.
Hope it may help to decide.
You have to check there is similar data available in the table if yes update the table and if no insert new data to table

Categories