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();
Related
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()
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 an AsyncTask class in android which I use for all kinds of requests from a server - improtant to point out that my requests are not working in parallel, every request loads the data to the activity and after it loads the data -> the user can browse to another activity which sends another request.
I also have a TaskCanceler which is responsible to cancel the AsyncTask if it takes more than 8 seconds.
The problem -
For some reason, when I open the app and browse between, lets say, 5-6 activities, could be less or more,
(each Activity sends a request to the server -> waits for respond -> populate the Activity with data), at some point I go to an Activity and it starts to load the data, and then, after about 1 second, I see the OnCancelled() Error message ("no connection to server!").
This means that the OnCancelled() has been called - and the TaskCenceler should only call it after 8 seconds!.
I checked, and the server answers all the requests - but the android app just "doesn't wait" for one of the requests out of nowhere.
Why is it happening? its not specific to an Activity, each time it happens on a different one. why all of the sudden the TaskCenceler doesn't wait to full 8 seconds?
My AsyncTask:
private class executeRequest extends AsyncTask<HttpRequest, Void, Integer> {
private ResponseListener listener;
public executeRequest(ResponseListener responseListener) {
listener = responseListener;
// Listener in the Activity to respond to Error/Success
}
#Override
protected void onCancelled() {
handleCancelled();
// if more than 8 seconds passed
}
private void handleCancelled() {
if (taskCanceler != null && handler != null) {
handler.removeCallbacks(taskCanceler);
}
listener.onError("no connection to server!");
}
#Override
protected Integer doInBackground(HttpRequest... params) {
// TODO Auto-generated method stub
HttpRequest request = params[0];
int responseCode = -1;
HttpResponse response;
responseResult = "";
response = httpClient.execute((HttpUriRequest) request);
responseCode = response.getStatusLine().getStatusCode();
responseResult = EntityUtils.toString(response.getEntity(),
HTTP.UTF_8);
return responseCode;
}
#Override
protected void onPostExecute(Integer result) {
// handle response
}
}
TaskCanceller:
public class TaskCanceler implements Runnable {
public executeRequest task;
public TaskCanceler() {
}
public void setTask(executeRequest task) {
this.task = task;
}
#Override
public void run() {
if (task != null)
if (task.getStatus() == AsyncTask.Status.RUNNING) {
task.onCancelled();
}
}
}
This is how I start all of my Tasks:
// Setting up the Handler and the TaskCanceler
private Handler handler = new Handler();
private TaskCanceler taskCanceler = new TaskCanceler();
task = new executeRequest(responseListener, type);
taskCanceler.setTask(task);
handler.postDelayed(taskCanceler, 8 * 1000); // cancel after 8 seconds
task.execute(refuseJoinRide);
Any ideas?
Any help would be appreciated!
Maybe, the log that you are getting is actually not from the task that you recently started. It could be from other activity that you started earlier.
webservice.UpdateAllNews();
This function is downloading data from online database to local database.
What i want is i want to launch next activity after detect the function has downloaded finish all the data.
P/S the data is large
This is my current situation
webservice.UpdateAllNews();
int secondsDelayed = 17;
new Handler().postDelayed(new Runnable() {
public void run() {
startActivity(new Intent(Main_Launcher.this,
Main_AllLatestNews.class));
finish();
}
}, secondsDelayed * 1000);
This is another class function
public void UpdateAllNews() {
try {
List<List_CategoryNews> newsCat = dbhelper.getAllNewsCategories();
for (List_CategoryNews nwCat : newsCat) {
int CatNewsID = nwCat.getCatID();
if (CatNewsID != 0) {
dbhelper.DeleteNews(CatNewsID);
GetNews(CatNewsID, datetemp1, datetemp2);
}
String log = " NewsCatID- " + nwCat.getCatID()
+ " category Name- " + nwCat.getNewCatName();
System.out.println(log);
}
} catch (Exception ex) {
AlertDialog.Builder b = new AlertDialog.Builder(mContext);
b.setMessage(ex.toString());
b.show();
}
}
This one is constant launch after 17 seconds, i want auto start activity after finish downloading data from online database instead of delay 17 seconds.
Any suggestion?
Maybe try to use AsyncTask:
private class YourTask extends AsyncTask<String, Void, String>
{
#Override
protected String doInBackground(String... urls)
{
webservice.UpdateAllNews();
}
#Override
protected void onPostExecute(String result)
{
startActivity(new Intent(Main_Launcher.this,Main_AllLatestNews.class));
finish();
}
}
and how to run it:
YourTask task = new YourTask();
task.execute("...");
Why don't you use simple client-server methodology like Observer-Observable?
When the task is done the observable will call update function of the observer which will be your primary activity.
I am new to Android development and Java and was wondering if somebody could help me with the following:
I have created an application that runs a server thread listening on a specified port. I would like to print messages received from a connected client into a TextView in the activity.
The server thread is in a separate class. The run method in this class listens for a client connection and reads any data received into a String.
What would be the best way for me to transfer the contents of this String back to the activity so that it can update the TextView?
From my (limited) understanding, only the ui thread should update a TextView and I can't find a way to get runOnUiThread to update the TextView.
Added code as requested.
Activity code:
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.main);
TextView messages = (TextView) findViewById(R.id.messages);
try {
newThread server = new newThread(this, messages);
} catch(Exception e) {
Toast.makeText(ChatActivity.this, e.toString(), Toast.LENGTH_LONG).show();
}
}
Run method in newThread class:
public void run()
{
serv = new ServerSocket(8000);
while(true)
{
cli = serv.accept();
user = cli.getInetAddress().toString();
BufferedReader cli_in = new BufferedReader(new InputStreamReader(cli.getInputStream()));
OutputStreamWriter cli_out = new OutputStreamWriter(cli.getOutputStream());
while((buf = cli_in.readLine()) != null)
{
// Update the messages TextView with buf
}
}
}
To avoid making things too cluttered I have omitted what irrelevant code I can.
Basically, in the inner while loop in run() I would like to pass the "buf" String to the activity so that the messages textview can be updated with it's content.
Cheers
Maybe a bad idea, but how about using AsyncTask? Didn't try if this would work, but it just might, since onProgressUpdate has access to UI thread.
private TextView messages;
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.main);
messages = (TextView) findViewById(R.id.messages);
ReceiveTask receive = new ReceiveTask();
receive.execute(100)
}
private void updateTextView(String text)
{
messages.setText(text);
}
private class ReceiveTask extends AsyncTask<Integer, String, Long> {
#Override
protected void onPreExecute() {
}
protected Long doInBackground(Integer... urls) {
newThread nt = new newThread();
while(true)
{
publishProgress(run());
}
return (long)0;
}
protected void onProgressUpdate(String... value) {
updateTextView(value[0]); //method in Activity class, to update TextView
}
protected void onPostExecute(Long result) {
}
}
Basically publishProgress will send data to onProgressUpdate, which will then send data to method (updateTextView) in main class and update TextView.
Usually it helps if you tell people you're working on a chat. Also, run() will need to be modified, to return string back, and remove while(true) loop from it. This is NOT the best idea, I suggest you go through a few tutorials on how to make an android chat first.