I am doing an android app for a school project. I have made an AsyncTask within my main acticity that fetches data from the internet. I want this to be executed at 23:00 every day, and also when the user first installs and opens the app. I have searched online and tried ScheduledExecutorService, AlarmManager and TimerTask but I either run into trouble compiling my code or the application crashes on start. I am hoping for some help to get this working. Would really appreciate some concrete examples on how to schedule my AsyncTask.
I am currently running the AsyncTask when clicking on a button, but want to remove the button and run the task on a schedule.
Thank you in advance!
public class MainActivity extends AppCompatActivity {
private TextView ViewT;
private TextView ViewR;
private String deg;
private String rainD;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
Button button = (Button) findViewById(R.id.button1);
ViewT = (TextView) findViewById(R.id.ViewT);
ViewR = (TextView) findViewById(R.id.ViewR);
button.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
new getData().execute();
ViewR.setText(rainD);
ViewT.setText(deg);
}
});
}
public class getData extends AsyncTask<Void, Void, Void> {
#Override
protected Void doInBackground(Void... params) {
//fetching data here....
}
}
}
Edit:
I tried this today and the application does not crash but nothing shows up on my textviews either.
ScheduledExecutorService scheduler = Executors.newScheduledThreadPool(1);
final Runnable updateUI = new Runnable() {
#Override
public void run() {
new getData().execute();
ViewR.setText(rainD);
ViewT.setText(deg);
}
};
scheduler.scheduleAtFixedRate(updateUI, 5,
60*60*24, TimeUnit.SECONDS);
Related
im using asyncTask to showing a download progress , my download will be done by a library named "file-downloader" in my main activity.
it's github page is "https://github.com/wlfcolin/file-downloader"
my custom dialog shows when i click to my specified button , and download task and progressBar starts when i press download button in this custom dialog
all thing is ok and progressBar works fine.
but when i dismiss this dialog and another time i invoke this dialog the progressBar does not work !
i save download status in database using the fileDownloader library listeners and anothe time i invoke custom dialog it read from database
and detect downloadProgress is currently running but we see no changing in custom dialog's progressBar , what is the problem ?
activity code
public class MainActivity extends AppCompatActivity {
/*
/
/ some variables
/
*/
public static int downloadedFile2SizePercent = 0 ; // downloaded file percent
public static int downloadingFileStatus = 0; // downloading status
Button myBtn ;
DownloadDialog dd;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main2);
Toolbar toolbar = (Toolbar) findViewById(R.id.toolbar);
setSupportActionBar(toolbar);
myBtn = (Button)findViewById(R.id.button22);
myBtn.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
dd = new DownloadDialog(mContext,1);
dd.getWindow().setBackgroundDrawable(new ColorDrawable(Color.TRANSPARENT));
dd.show();
}
});
/*
/ downloadingFileStatus value manages here by file downloader listeners correctly and saves as static variable and also in database
/ downloadedFile2SizePercent value manages here by file downloader listeners correctly and saves as static variable
/
*/
}
}
DownloadDialog Class
public class DownloadDialog extends Dialog implements View.OnClickListener{
public Context c;
public Button download, delete;
private ProgressBar pb;
ProgressTask progressTask;
private int downloadStatus;
private String downloadLink;
private int downloadID
public DownloadDialog(Context a, int downloadId) {
super(a);
this.c = a;
this.downloadId = downloadId
}
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
requestWindowFeature(Window.FEATURE_NO_TITLE);
setContentView(R.layout.download_dialog);
download = (Button) findViewById(R.id.downloaddialot_downloadbtn);
delete = (Button) findViewById(R.id.downloaddialot_deletebtn);
download.setOnClickListener(this);
delete.setOnClickListener(this);
pb = (ProgressBar)findViewById(R.id.progressBar);
pb.setMax(100);
pb.setProgress(0);
//database is opend at mainActivity it's static
downloadStatus=Integer.parseInt(MainActivity.prDb.intSearch(downloadId));// detects download status --> 0 is "notDownloadedYet" and
// 1 is "downloading" and 2 is "downloaded"
downloadLink= MainActivity.puDb.intSearch(downloadId);//detects download link
progressTask = new ProgressTask();
if(downloadStatus==1){
pb.setProgress(MainActivity.downloadedFile2SizePercent);//this code line works every 2nd and after dialog invoking
progressTask.execute(true);
Toast.makeText(c,"test task progress for 2nd started", Toast.LENGTH_SHORT).show();//this code line works every 2nd and afterdialog invoking
}
}
#Override
public void onClick(View v) {
switch (v.getId()) {
case R.id.downloaddialot_downloadbtn:
FileDownloader.start(downloadLink); // download task starts here
progressTask.execute(true);
Toast.makeText(c,"download task progress for 1nd started", Toast.LENGTH_SHORT).show();
break;
case R.id.downloaddialot_deletebtn:
if(downloadStatus==2){
// delete codes
}
break;
}
}
public class ProgressTask extends AsyncTask<Boolean, Integer, Boolean> {
#Override
protected void onPreExecute() {
super.onPreExecute();
}
#Override
protected Boolean doInBackground(Boolean... params) {
while (MainActivity.downloadedFile2SizePercent!=100){
publishProgress(MainActivity.downloadedFile2SizePercent);
}
if(MainActivity.downloadedFile2SizePercent==100){
publishProgress(MainActivity.downloadedFile2SizePercent);
}
return true;
}
#Override
protected void onProgressUpdate(Integer... values) {
pb.setProgress(values[0]);
}
#Override
protected void onPostExecute(Boolean aBoolean) {
super.onPostExecute(aBoolean);
downloadStatus=2; //also saves in database by download listeners in mainActivity
}
}
}
The progress bar just like any other UI element can only be managed or updated from the main UI thread.
It is the time consuming task the part that should be run in a AsyncTask, then this task can save the progress status in a volatile variable and then the UI thread can periodically update the progress bar reading the volatile variable, for example using a timer.
You can read all about AsyncTask here: https://developer.android.com/reference/android/os/AsyncTask.html
But here's my quick example/tutorial:
private class MyAsyncTask extends AsyncTask<Void, Integer, Void> {
#Override
protected void onPreExecute() {
super.onPreExecute();
// prepare your UI for the background task beginning
}
#Override
protected Void doInBackground(Void... params) {
// do some long-running task...
// you can do partial updates like:
publishProgress(25);
/* more hard work */
publishProgress(50);
/* even more hard work */
publishProgress(75);
// and when you're done...
return null;
}
#Override
protected void onProgressUpdate(Integer... values) {
super.onProgressUpdate(values);
// update your UI with the current progress (values[0])
}
#Override
protected void onPostExecute(Void aVoid) {
super.onPostExecute(aVoid);
// update your UI now that it's done
}
}
The key concept to understand regarding AsyncTask is that every method except doInBackground() is executed on the UI thread (the main thread). That means you are free to update your UI from these calls.
doInBackground(), however, is executed on a different thread. That means you can do expensive work here without slowing down your app's user interface.
Of course, all the hard work you're doing on that background thread needs to make its way to the UI thread somehow (so that you can use it). That's what publishProgress() and the return statement of doInBackground() are for. When you call publishProgress(someValue), the system will invoke onProgressUpdate(someValue) for you. When you return someValue, the system will invoke onPostExecute(someValue) for you.
I have the following code which should update UI textview on Asynctask:
public class HelloWorldActivity extends Activity
{
private static TextView txtview;
/** Called when the activity is first created. */
#Override
public void onCreate(Bundle savedInstanceState)
{
super.onCreate(savedInstanceState);
setContentView(R.layout.main);
txtview = (TextView) findViewById(R.id.mainview);
}
private static class SimpleTask extends AsyncTask<Void, Void, Void> {
#Override
protected Void doInBackground(Void... res) {
try {
Thread.sleep(1500);
} catch(InterruptedException exception) {
Thread.currentThread().interrupt();
}
return null;
}
#Override
protected void onPostExecute(Void params) {
txtview.setText("Hola Mundo");
}
}
}
Particularly I'm triying to change Hello World to Hola Mundo after 1,5 seconds passed. The problem is that while running the app the text still is Hello World and doesn't change. I get no error of any sort. I have even set txtview value outside onCreate method to avoid any access problems (or so I think).
If after txtview = (TextView) findViewById(R.id.mainview); I do txtview.setText("Hola Mundo"); then it works flawlessly.
What could be the problem?
Forget to execute AsyncTask by calling AsyncTask.execute() method. do it as by adding following lines in onCreate method after initializing txtview TextView object:
SimpleTask objSimpleTask=new SimpleTask();
objSimpleTask.execute();
You have not called ASyncTask, execute it like this after initializing TextView:
txtview = (TextView) findViewById(R.id.mainview);
SimpleTask objSimpleTask=new SimpleTask();
objSimpleTask.execute();
Hope is what you want.
Currently you are forget to call AsyncTask.
But i think it is a bad practice to use AsyncTask & Thread.sleep() to update UI .
ou can simply do it with Handler.
Runnable updateUI;
Handler h = new Handler();
updateUI=new Runnable() {
#Override
public void run() {
txtview.setText("Hola Mundo");
}
};
h.postDelayed(updateUI,1500);
I have following sample code to understand the TextView update
public class MainActivity extends Activity
{
int i=0;
private ImageButton btnMain;
private TextView txtText;
Context mycont=null;
public void myJob(final String cmd)
{
//txtText.setText(cmd);
runOnUiThread(new Runnable()
{
#Override
public void run() {
txtText.setText(cmd); //---Does not update the TextView here on Main UI
}
});
//----------- Long Work(Take around 15 seconds to complete) ----------
for(i=0;i<=1000000000;i++)
i++;
for(i=0;i<=1000000000;i++)
i++;
//--------------------------------------------------------------------
//---Update the TextView here once above Long work is executed
}
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
mycont=this;
txtText = (TextView) findViewById(R.id.txtText);
txtText.setMovementMethod(new ScrollingMovementMethod());
btnMain = (ImageButton) findViewById(R.id.btnJob);
btnMain.setOnClickListener(new View.OnClickListener()
{
#Override
public void onClick(View v)
{
myJob("Display this msg");
}
});
}
}
TextView is not updating on time, its waiting for other procedure to execute.
Please point me in right direction. I want to Update the TextView in the beginning of the myJob() function.
Look at this link: How will UI changes be processed in the onClickListener before starting a new activity in Android?
"Changes to UI elements are not executed immediately. They're executed the next time the UI loop runs, which is after you release control."
I would suggest you look into AsyncTasks. They allow you to perform actions before and after doing a timeconsuming job. In your case your AsyncTask would look somewhat like this:
private class LongJob extends AsyncTask<Void, Void, Void> {
TextView textViewToChange;
public LongJob(TextView text){
textViewToChange = text;
}
protected void onPreExecute(){
// Executed on main(UI) thread
textViewToChange.setText("Some random text here");
}
protected Long doInBackground(Void... params) {
// Your long job here, executed on background thread so
// it won't freeze your application.
return null;
}
protected void onPostExecute(Void result) {
// Executed on main(UI) thread
textViewToChange.setText("Text for after your job completed");
}
}
If I understand correctly, you want to update the textview, then run the Long Work. In that case do something like this:
public void myJob(final String cmd)
{
txtText.setText(cmd);
txtText.post(new Runnable() {
#Override
public void run() {
//----------- Long Work(Take around 15 seconds to complete) ----------
for(i=0;i<=1000000000;i++)
i++;
for(i=0;i<=1000000000;i++)
i++;
//--------------------------------------------------------------------
}
});
}
Note: In either case, your long work is running on the UI thread.. because you have never created a background task
Thanks to Amulya and Sander.
Both the solutions worked for me.
But as per my need, i will go for the solution by Amulya which is lightweight.
I was already aware of Android AsyncTasks.
But never thought of using in this way.
Thanks to both of you
I have noticed a this over the last few months. If I set a clickListener on a button to execute an AsyncTask, it doesn't always get executed. I solve the problem by wrapping the line of code that executes the AsyncTask in a method.
Here's the code that doesn't work all of the time:
button.setOnClickListener(new OnClickListener() {
#Override
public void onClick(View v) {
new CustomAsyncTask().execute();
}
});
Here's my fix:
button.setOnClickListener(new OnClickListener() {
#Override
public void onClick(View v) {
executeAsyncTask();
}
});
public void executeAsyncTask(){
new CustomAsyncTask().execute();
}
I haven't noticed the pattern as to when it does and doesn't break, but I'm wondering if anyone else has noticed this?
Also, if anyone has an explanation as to why this happens that would be cool too.
Thanks in advance.
EDIT
Here's the CustomAsyncTask (I know it's not being called all of the time because it doesn't print anything)
private class CustomAsyncTask extends AsyncTask<Void, Void, Void>{
#Override
protected Void doInBackground(Void... params) {
Log.i("CustomAsyncTask", "doInBackground");
return null;
}
}
I have a method which is list my items from a server. Therefore, this method takes time until getting all the items. So I want to use ProgressDialog for waiting this method. I read some modules but I couldnt find any useful solution.
public void onCreate(Bundle savedInstanceState)
{
super.onCreate(savedInstanceState);
// setContentView(R.layout.main;
loginScreen();
}
public boolean getItems() throws MessagingException
{
items receiving here
}
public void loginScreen()
{
setContentView(R.layout.main);
Button loginBtn = (Button) findViewById(R.id.btnLogin);
loginBtn.setOnClickListener(new Button.OnClickListener()
{
public void onClick(View arg0)
{
getItems();
}
}
}
On button Click I call the method which received all items. When I click the button I want to show a progressbar until all items getting.
create an AsyncTask which shows an ProgressBar on getItems(). You need an AsyncTask because the main Thread will be busy fetching stuff from server and ProgressBar won't show up untill that is finished.