I have a json file and I want to check this json every minute because my json changes every minute.
I can parse json from an url in this way;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
runOnUiThread(new Runnable() {
#Override
public void run() {
new ReadJSON().execute("http://www.url.com/json1.json");
}
});
}
class ReadJSON2 extends AsyncTask<String, Integer, String> {
#Override
protected String doInBackground(String... params) {
return readURL(params[0]);
}
#Override
protected void onPostExecute(String content) {
try {
JSONObject jsonObject = new JSONObject(content);
JSONArray jsonArray = jsonObject.getJSONArray("level");
for (int i = 0; i < jsonArray.length(); i++) {
JSONObject c = jsonArray.getJSONObject(i);
JSONArray server = c.getJSONArray("server");
for(int j=0; j<server.length(); j++){
JSONObject serverObject = server.getJSONObject(j);
String name = serverObject.getString("name");
}
}
} catch (JSONException e) {
e.printStackTrace();
}
}
}
How can I check this json every minute?
I did everything, but I didn't it.
Thank you for your help.
Use listview.invalidateViews(); or adapter.notifyDataSetchanged(); method in onPostExecute method after parsing your json.
This method works if some of the contents have been changes/added/removed in the list that is attached to the adapter.
So whenever you parse your data . make sure the object of adapter and the List/JsonArray remain same. Means dont initialize it every time on web service result. Just use it like this -> list.add(some data); and jsonArray.put(some data);
Let me know if i misunderstood.
We can use TimerTask to solve this problem:
public void initializeTimerTask() {
timerTask = new TimerTask() {
public void run() {
//use a handler to run a toast that shows the current timestamp
handler.post(new Runnable() {
public void run() {
new ReadJSON().execute("http://www.url.com/json1.json");
}
});
}
};
public void startTimer() {
//set a new Timer
timer = new Timer();
//initialize the TimerTask's job
initializeTimerTask();
//schedule the timer, after the first 0ms the TimerTask will run every 1m
timer.schedule(timerTask, 0, 60 * 1000); //
}
An on ur postExe, after parse JSON, u should check Adapter here, if it's was empty for first time, you set adapter by this json, and if it's already has data, please call adapter.notifyDataSetChanged()
Related
I am building an application that is pretty dependent on async requests to function.
I have the main Activity called MainActivity. This really doesn't do much apart from contain layouts, however it does have a recycleviewer.
I then have a couple of http requests that are done to populate the recycle viewer.
To do this I have wrote a java class as follows:
public class dataforUi extends AsyncTask<String, String, JsonObject> {
private ArrayList<UiElements> els;
protected void onPreExecute() {
progressDialog.setMessage("Downloading your data...");
progressDialog.show();
progressDialog.setOnCancelListener(new DialogInterface.OnCancelListener() {
public void onCancel(DialogInterface arg0) {
RedditRequests.this.cancel(true);
}
});
}
protected JsonObject doInBackground(String... params) {
Do the http request here, get the result and populate uiElements with it
}
#Override
protected void onPostExecute(JsonObject jsonObject) {
super.onPostExecute(jsonObject);
progressDialog.hide();
}
I have a few more classes like this but hopefully it serves as an example of what I'm trying to do.
Then back in Main Activity, I have this code:
public void getUiElements() {
dataforUi ui = new dataforUi(findViewById(android.R.id.content));
try {
ui.execute("https://t").get();
ArrayList<UiElements> r = ui.getEls();
Log.d("MainFeedScreen", "Size of r is:" + r.size());
UiAdapter = new UiAdapter(r);
mRecyclerView.setAdapter(UiAdapter);
} catch (Exception e) {
}
}
This works fine, but it is very jolty due to the use of .get() on execute to make it blocking. If i remove .get() the progress bar shows up and disappears when the task is done, but my ui thread has progressed past this and ha tried to populate my view with an Empty Array and therefore nothing shows.
I have done a bit of looking into it but cant find a conclusive way of managing the notification of the UI thread that an activity is done.
Would really appericiate any advice on this one.
You need to fix your design.
On post execute, use local broadcast to notify your MainActivity that the AsyncTask is done.
Try using a separate thread to process your data. I use a ListView in stead of a RecyclerView, but the principle is the same.
I have no problems with jolting views.
protected void onPostExecute(String result) {
final String value = result;
// dismiss the dialog after getting all data
progressDialog.dismiss();
if (!value.isEmpty()) {
// updating UI from a new thread
runOnUiThread(new Runnable() {
public void run() {
// ListData is my custom class that holds my data
ArrayList<ListData> arrayDriverListData = new ArrayList<ListData>();
ListDataAdapter adapter = new ListDataAdapter(ListActivity.this, arrayListData);
ListData data;
boolean b = true;
try {
// My data is from a Json source from node 'history'
JSONObject object = new JSONObject(value);
JSONArray array = object.getJSONArray("history");
int len = array.length();
if (len > 0) {
for (int i = 0; i < len; i++) {
final JSONObject o = array.getJSONObject(i);
// Parse my data and add it to my adapter
adapter.add(data);
}
}
} catch (JSONException jex) {
Log.e(TAG, "" + jex.getMessage());
}
// setListAdapter is my call to update my list view
setListAdapter(adapter);
}
});
}
}
Now just update the UI thread
private void setListAdapter(ListDataAdapter adapter){
// my ListView
lvHistory.setAdapter(adapter);
}
i have a list view data come from server and show on the list view . i want listview refresh every 10 sec how can i do this here is my code of list view .
protected void showList() {
try {
JSONObject jsonObj = new JSONObject(myJSON);
peoples = jsonObj.getJSONArray(TAG_RESULTS);
for (int i = 0; i < peoples.length(); i++) {
JSONObject c = peoples.getJSONObject(i);
String data = c.getString(TAG_DATA);
final String dataaaa = rcdata.getText().toString().trim();
HashMap<String, String> user_data = new HashMap<String, String>();
user_data.put(TAG_DATA, data);
personList.add(user_data);
}
ListAdapter adapter = new SimpleAdapter(
DataSendActivity.this, personList, R.layout.layout_chat,
new String[]{TAG_DATA},
new int[]{R.id.data}
);
list.setAdapter(adapter);
} catch (JSONException e) {
e.printStackTrace();
}
}
How repeat a piece of code in a fixed interval, in this case update listview
//instance variable for adapter
ListAdapter adapter;
//instance variable for timer
Timer timer;
//create the listview, adapter and set the adapter
public void showList(){
//method code;
adapter=//call adapter constructor
listView.setSetAdapter(adapter);
//create a handler to update the adapter
final Hanlder handler=new Handler(){
//run your listview update command here. Possibly;
adapter.notifyDataSetChanged();
//or else create a new adapter
adapter=new ListAdapter(//parameters);
listView.setAdapter(adapter);
}
//create timer and the scheduled task
//this will run in every 10 seconds. Make sure to stop it when you dont
//want it any more
timer=new Timer();
timer.scheduleAtFixedRate(new TimerTask() {
#Override
public void run() {
handler.obtainMessage().sendToTarget();
}
}, 0, 10000);
}
//if you want to stop the timer on onDestroy()
#Override
public void onDestroy(){
super.onDestroy();
if(timer!=null){
timer.cancel();
}
}
The code is as an example only.
I got a weird problem with an android activity : I re-used one of my previous activity that works well, but this time all I got is "Can't create handler inside thread that has not called Looper.prepare()"
I tried to debug, and everything in the async task is performing well but when I reach then end of onPostExecute() the error is raised.
So I tried to disable my process about the process dialog, the only change is that it's crashing on line upper.
Here is the code :
public class DateActivity extends ActionBarActivity{
ProgressDialog mProgressDialog;
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_date);
ActionBar actionBar = this.getSupportActionBar();
actionBar.setDisplayHomeAsUpEnabled(true);
actionBar.setTitle(getResources().getString(R.string.actionbar_titre_date));
if (VerifConnexion.isOnline(this)) {
this.mProgressDialog = ProgressDialog.show(this, getResources().getString(R.string.loading),
getResources().getString(R.string.loading), true);
new QueryForDateTask().execute(this.mProgressDialog, this, this.getApplicationContext());
} else {
...
}
});
alertDialog.show();
}
}
private class QueryForDateTask extends
AsyncTask<Object, Void, ArrayList<String>> {
private ProgressDialog mProgressDialog;
private Activity act;
private Context context;
protected ArrayList<String> doInBackground(Object... o) {
this.mProgressDialog = (ProgressDialog) o[0];
this.act = (Activity) o[1];
this.context = (Context) o[2];
ArrayList<String> listeDate = this.parseJSON(this.startQuerying());
return listeDate;
}
public JSONObject startQuerying() {
JSONRequest jr = new JSONRequest();
String from = getResources().getString(R.string.api_param_from);
SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd", Locale.FRANCE);
from += "=" + sdf.format(new Date());
String url = getResources().getString(
R.string.api_dates_json);
JSONObject jo = jr.getJSONFromUrl(url + "?" + from);
return jo;
}
public ArrayList<String> parseJSON(JSONObject jsonObject) {
ArrayList<String> l = new ArrayList<String>();
try {
JSONArray array = jsonObject.getJSONArray("dates");
if (array != null) {
for (int i = 0; i < array.length(); i++) {
String type = array.getString(i);
l.add(type);
} // fin parcours JSONArray
}
} catch (Exception _e) {
}
return l;
}
protected void onProgressUpdate(Integer... progress) {
// setProgressPercent(progress[0]);
}
protected void onPostExecute(ArrayList<String> lDate) {
// Create items for the ListView
DateAdapter adapter = new DateAdapter(this.context, R.layout.searchitem_date, lDate, this.act);
// specify the list adaptor
((ListView)findViewById(R.id.list)).setAdapter(adapter);
this.mProgressDialog.dismiss();
}
} // fin async
}
I tried this to replace the call to the AsyncTask :
runOnUiThread(new Runnable() {
public void run() {
QueryForDateTask task = new QueryForDateTask();
task.execute(DateActivity.this.mProgressDialog, DateActivity.this, DateActivity.this.getApplicationContext());
}
});
(like explained in Asynctask causes exception 'Can't create handler inside thread that has not called Looper.prepare()' as far as I understood), but the result is exactly the same.
So I can't understand why it is not working in this activity despite all is ok for the other ones of the project.
Any clue ?
Thank a lot for all ideas :)
Just a post to mark the trouble as resolved :
the adapter i used was buggy in parsing parameters and throwed a NullPointerException.
I just fixed it, the AsyncTask is now running without problem.
I have a asynctask which uses a json function in the doInBackground() and it returns the variables to onPostExecute. The problem is I want the json function to be in a while loop, Every time it goes in the loop it collects a comment. So I could have 15 comments and I want to send them all to onPostExecute to be placed into views. Here is my code
class loadComments extends AsyncTask<JSONObject, String, List<String>> {
DatabaseHandler db = new DatabaseHandler(getApplicationContext());
#Override
protected void onPreExecute() {
super.onPreExecute();
}
#Override
protected void onProgressUpdate(String... values) {
super.onProgressUpdate(values);
}
protected List<String> doInBackground(JSONObject... params) {
//do your work here
List<String> results = new ArrayList<String>();
int i = 0;
while (i < 5 ){
JSONObject json2 = CollectComments.collectComments(usernameforcomments, offsetNumber);
result = json2;
results.add(result);
i++;
}
return results;
}
#Override
protected void onPostExecute(List<String> results) {
try {
if (json2.getString(KEY_SUCCESS) != null) {
registerErrorMsg.setText("");
String res2 = json2.getString(KEY_SUCCESS);
if(Integer.parseInt(res2) == 1){
commentView.setText(json2.getString(KEY_COMMENT));
LinearLayout.LayoutParams commentViewParams = new LinearLayout.LayoutParams(
LinearLayout.LayoutParams.FILL_PARENT, LinearLayout.LayoutParams.WRAP_CONTENT);
commentViewParams.setMargins(20, 10, 20, 20);
commentView.setBackgroundResource(R.drawable.comment_bg);
commentView.setTextColor(getResources().getColor(R.color.black));
commentBox.addView(commentView, commentViewParams);
}//end if key is == 1
else{
// Error in registration
registerErrorMsg.setText(json2.getString(KEY_ERROR_MSG));
}//end else
}//end if
} //end try
catch (JSONException e) {
e.printStackTrace();
}//end catch
}
}
This code does not work but its an example of what I am trying to accomplish
what you could do is:
1. write a function that parses your json data and initialise all required variables as global variables
2. run your function inside the doInBackground() method of AsyncTask without passing any parameters
3. set values to views from the onPostExecute() method
I want to write a function that listens a server by sending get requests reqularly. The next request shouldn't be sent to server until a response is received from the first request. To simulate this, I write the following code which sends consecutive get request to server 5 times:
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
//setContentView(R.layout.main);
TextView tv = new TextView(this);
for (int i = 0; i < 5; i++)
{
tv.setText(retrieve("http://www.mydomain.com/http.php?key=" + i));
setContentView(tv);
}
}
"String retrieve(String url) { ... }" is function that returns content of url, in this case just a number sent by the following PHP file ("http.php"):
<?php
sleep(1);
echo $_GET['key']+1;
?>
Although I put 1 second sleep to see values on my android app, the only thing I see is "5" after some seconds. So are these 5 requests are asyn or are they consecutive or is there another problem?
The code inside the method onCreate is executed only once before you get to see anything, thats probably why you can only see 5 (the last one). Also, you shouldn't do network calls from there since that will block the UI main thread for a while and probably provoke a force close in your app.
You should implement a method to run in background. Something similar to this:
private int i;
public void onCreate(Bundle savedInstanceState) {
i = 0
new ServerRetreiveTask().execute("http://www.mydomain.com/http.php?key=" + i);
}
private class ServerRetreiveTask extends AsyncTask<String, Void, Bitmap> {
protected Bitmap doInBackground(String urls) {
return retrieve(url);
}
protected void onPostExecute(Bitmap result) {
mImageView.setImageBitmap(result);
if (i<5){
i++:
new ServerRetreiveTask().execute("http://www.mydomain.com/http.php?key=" + i);
}
}
}
Read this document for more info about asynchronous task http://developer.android.com/resources/articles/painless-threading.html
Alternative way using Threads (not recommended):
new Thread(new Runnable() {
#Override
public void run() {
final String response;
for (int i = 0; i < 5; i++)
{
response = retrieve("http://www.mydomain.com/http.php?key=" + i);
runOnUiThread(new Runnable() {
#Override
public void run() {
tv.setText(response);
}
});
}
}
}).start();