I am making a loading effect when calling MainActivity. I have no idea why my Dialog.show is not working in the AsyncTask. All i just see the just the instant when it dismiss, but the dialog never appear before that.
Thank you.
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
new LoadViewTask().execute();
setContentView(R.layout.activity_main);
....}
private class LoadViewTask extends AsyncTask<Void, Integer, Void>
{
#Override
protected void onPreExecute() {
progressDialog = ProgressDialog.show(MainActivity.this,"Loading...","Loading application View, please wait...", false, false);
}
#Override
protected Void doInBackground(Void... params)
{
try
{
synchronized (this)
{
int counter = 0;
while(counter <= 4)
{
this.wait(1000);
counter++;
publishProgress(counter*25);
}
}
}
catch (InterruptedException e)
{
e.printStackTrace();
}
return null;
}
#Override
protected void onProgressUpdate(Integer... values)
{
progressDialog.setProgress(values[0]);
}
#Override
protected void onPostExecute(Void result)
{
progressDialog.dismiss();
}
}
You should use FragmentDialogs for using dialogs in Android.
Here it is well explained:
http://developer.android.com/intl/es/reference/android/app/DialogFragment.html
Try to set the content view before starting your async task:
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
// Set the content view first
setContentView(R.layout.activity_main);
new LoadViewTask().execute();
....}
Related
I run loading screen which should show current status "scanning packages, etc" . So that my activity wouldn't freeze I must use thread, but then I can't update status (TextField). I tried using AsyncTask but that didn't helped me at all, still after running I see text field unchanged.
public class LoadingScreen extends Activity {
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.loadingscreen_layout);
try {
startLoadingScreen();
}catch (Exception e){
Log.e("Scanner","Scanner",e);
}
}
public void startLoadingScreen(){
try{
new Thread(new Runnable() {
#Override
public void run() {
new ScanningOperation().execute("Scanning");
//loadingScreen.setStatus("Scanning");
final PackageManager pm = getPackageManager();
//get a list of installed apps.
List<ApplicationInfo> packages = pm.getInstalledApplications(PackageManager.GET_META_DATA);
//changeIntent();
//finish();
}
});
} catch (Exception e){
Log.e("Thread","Thread");
}
}
private class ScanningOperation extends AsyncTask<String, Void, String> {
#Override
protected String doInBackground(String... params) {
return params[0];
}
#Override
protected void onPostExecute(String result) {
super.onPostExecute(result);
TextView txt = findViewById(R.id.statusView);
txt.setText(result);
}
#Override
protected void onPreExecute() {}
#Override
protected void onProgressUpdate(Void... values) {}
}
}
I'm facing a problem: I created two Activities.
One is the main Activity, which has a Button.
When I click this Button, the second Activity starts.
The second Activity uses an Asynctask in which a number is incremented from 1 to 10 and displays this number in a Textview
What I'm facing is that when I click the back Button while the Asynctask has not completed and then again go to the second Activity the Asynctask is not run from start immediately.
I know because in background when it completed the old task then it again starts a new task. Is there a way to fix this when destroying the Activity it also destroy the Asynctask?
Here is video sample for my problem.
Code for Main Activity:
public class MainActivity extends AppCompatActivity {
Button bt;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
bt = (Button) findViewById(R.id.bt);
bt.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
Intent i = new Intent(MainActivity.this,SecondAcitivity.class);
startActivity(i);
}
});
}
}
Code of Second Activity:
public class SecondAcitivity extends AppCompatActivity {
TextView t1;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_second_acitivity);
t1 = (TextView) findViewById(R.id.t1);
OurWork obj = new OurWork();
obj.execute();
}
class OurWork extends AsyncTask<Void, Integer, String> {
#Override
protected String doInBackground(Void... params) {
int i = 0;
while (i < 11) {
try {
Thread.sleep(700);
publishProgress(i);
i++;
} catch (InterruptedException e) {
e.printStackTrace();
}
}
return "Successfully Completed";
}
#Override
protected void onProgressUpdate(Integer... values) {
t1.setText(values[0] + "%");
}
#Override
protected void onPostExecute(String result) {
t1.setText(result);
}
}
}
you need to cancel the task on back pressed, and you need to monitor if the task is canceled while executing the doInbackground().
1- override onbackpressed:
#Override
public void onBackPressed() {
obj.cancel(true); // where obj is the asyncTask refernce object name
super.onBackPressed();
}
2- monitor isCanceled()
#Override
protected String doInBackground(Void... params) {
int i = 0;
while (i < 11 && !isCancelled()) { // added !isCancelled()
try {
Thread.sleep(700);
publishProgress(i);
i++;
} catch (InterruptedException e) {
e.printStackTrace();
}
}
return "Successfully Completed";
}
on next iteration of the while loop, after cancel(true); is called,the loop will quit, and doInBackground() will return.
When you press back button , onBackPressed callback is called. so you can basically try this :
#Override
public void onBackPressed() {
if (asyncFetch.getStatus() == AsyncTask.Status.RUNNING) {
asyncFetch.cancel(true);
}
finish();
}
Try to use :
private OurWork task;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_second_acitivity);
t1 = (TextView) findViewById(R.id.t1);
task = new OurWork();
task.execute();
}
#Override
public void onBackPressed() {
task.cancel(true);
super.onBackPressed();
}
AsyncTask runs in background of the activity where it was hosted. If OnPause or OnDestroy is called, AsyncTask is destroyed, so to solve this issue, Override OnResume and execute AsyncTask again.
To cancel the asyncTask even when it is running when back is pressed, add this to onBackPressed:
public class SecondAcitivity extends AppCompatActivity {
TextView t1;
static OurWork obj;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_second_acitivity);
t1 = (TextView) findViewById(R.id.t1);
obj = new OurWork();
obj.execute();
}
class OurWork extends AsyncTask<Void, Integer, String> {
#Override
protected String doInBackground(Void... params) {
int i = 0;
while (i < 11) {
try {
Thread.sleep(700);
publishProgress(i);
i++;
} catch (InterruptedException e) {
e.printStackTrace();
}
}
return "Successfully Completed";
}
#Override
protected void onProgressUpdate(Integer... values) {
t1.setText(values[0] + "%");
}
#Override
protected void onPostExecute(String result) {
t1.setText(result);
}
}
//override onBackPressed and do this
#Override
public void onBackPressed() {
if (obj!=null && (obj.getStatus()== AsyncTask.Status.RUNNING ||
obj.getStatus()== AsyncTask.Status.PENDING ))
obj.cancel(true);
super.onBackPressed();
}
}
I'm developing an app that when user clicks on a Button it executes an Asynctask that this class calls a method at it's onPostExecute method that calls another Asynctask! It works when user clicks once, but at the second time it crashes and says Cannot execute task: the task has already been executed (a task can be executed only once)
.
public class Test extends Activity {
A a;
B b;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.test);
Button btn = (Button) findViewById(R.id.btn);
btn.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View arg0) {
a = new A();
a.execute();
}
});
}
class A extends AsyncTask<Void, Void, Void> {
#Override
protected Void doInBackground(Void... arg0) {
// doing st
return null;
}
#Override
protected void onPostExecute(Void result) {
super.onPostExecute(result);
runB();
a.cancel(true);
}
}
public void runB() {
b = new B();
b.execute();
}
class B extends AsyncTask<Void, Void, Void> {
#Override
protected Void doInBackground(Void... arg0) {
// doing st
return null;
}
#Override
protected void onPostExecute(Void result) {
super.onPostExecute(result);
//doing st
b.cancel(true);
}
}
Use AsyncTask.Status for checking status of AsyncTask before calling AsyncTask.execute() method on Button onClick:
#Override
public void onClick(View arg0) {
if(a ==null){
a = new A();
a.execute();
}
}
And in onPostExecute of B class assign null to a :
#Override
protected void onPostExecute(Void result) {
super.onPostExecute(result);
//doing st
b.cancel(true);
a=null;
}
I'm new to Android and I'm practicing creating a progress dialog. I want to change the message in the dialog every couple of seconds, but my application crashes when I change the message. Any ideas what I may be doing wrong?
private void progressDialogTest(final ArrayList<String> messages)
{
AsyncTask<Void, Void, Void> task = new AsyncTask<Void, Void, Void>()
{
private ProgressDialog progressDialog;
#Override
protected void onPreExecute()
{
progressDialog = new ProgressDialog(MainActivity.this);
progressDialog.setTitle("Progress Dialog");
progressDialog.show();
}
#Override
protected Void doInBackground(Void... arg0)
{
try
{
for(int i=0; i<messages.size(); i++)
{
/******** APPLICATION SEEMS TO CRASH AT LINE BELOW ********/
progressDialog.setMessage(messages.get(i));
Thread.sleep(3000);
}
}
catch (InterruptedException e)
{
e.printStackTrace();
}
return null;
}
#Override
protected void onPostExecute(Void result)
{
progressDialog.dismiss();
}
};
task.execute((Void[])null);
}
Move the code to onProgressUpdate instead, eg:
#Override
protected void onProgressUpdate(Integer... progress) {
super.onProgressUpdate(progress);
progressDialog.setMessage(messages.get(progress[0]));
}
#Override
protected void doInBackground(Void... arg0) {
/* ... */
//progressDialog.setMessage(messages.get(i)); Change this line to
publishProgress(i);
/* ... */
}
I am developing an application in android, where i need to display a splash screen and at the same time there will be server communication. The problem here is when i launch the app, first application is communicating with the server and then it is displaying the splash screen. I want to both server communication and splash screen at the same time.
The following is my code:
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.splash_screen);
try {
Thread thread = new Thread(this);
thread.start();
thread.join();
//Attractions
CommonMethods.getSystemOutput("Response Json Array String Attractions:::"+jArrayMobileAttractions);
attractionsDate = JsonParsing.getLatestDate(jArrayMobileAttractions);
attractionsDate = getDate(attractionsDate);
CommonMethods.getSystemOutput("Attractions Date:::::"+attractionsDate);
//Categories
CommonMethods.getSystemOutput("Response Json Array String Categories:::"+jArrayCategories);
categoryDate = JsonParsing.getLatestDate(jArrayCategories);
categoryDate = getDate(categoryDate);
CommonMethods.getSystemOutput("Category date:::"+categoryDate);
//Contacts
CommonMethods.getSystemOutput("Response Json Array String Contacts:::"+jArrayContacts);
contactsDate = JsonParsing.getLatestDate(jArrayContacts);
contactsDate = getDate(contactsDate);
CommonMethods.getSystemOutput("Contacts Date:::"+contactsDate);
} catch (Exception e) {
CommonMethods.getSystemOutput("Exception in Splash screen thread:::"+e);
}
}
public void run() {
// if (attractionsDate == null) {
jArrayMobileAttractions = RequestHandler.getJSONfromURL(Constants.MOBILE_ATTRACTIONS_URL);
jArrayCategories = RequestHandler.getJSONfromURL(Constants.CATEGORY_URL);
jArrayContacts = RequestHandler.getJSONfromURL(Constants.CONTACTS_URL);
// } else {
// jArrayMobileAttractions = RequestHandler.getJSONfromURL(Constants.MOBILE_ATTRACTIONS_URL+"?lastupdateddate="+attractionsDate);
// }
}
You can use the AsynchTask Manager in which it has a method
private class DownloadWebPageTask extends AsyncTask<String, Void, String> {
#Override
protected String doInBackground(String... urls) {
// Do Server Interaction Here
return response;
}
#Override
protected void onPreExecute(String result) {
//Show your Splash Screen
}
#Override
protected void onPostExecute(String result) {
//Gone the Splash Screen view
}
}
For this purpose it will be better start from "SplashActivity" - in onCreate() start new Thread for communication with server, and when all communication finished - call startActivityForResult(mainActivityIntent). For correct behavior back button finish splash activity on finish main activity. Approximate code:
public class SplashActivity extends Activity {
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
//setup view for activity
new Thread(new Runnable() {
public void run() {
// do here some long operation
startActivityForResult(new Intent(SplashActivity.this, MainActivity.class), 0);
}
}).start();
}
#Override
protected void onActivityResult(int requestCode, int resultCode, Intent data) {
finish();
}
}
I had the same thing to do and I did it this way and it works just fine. I had to show the splashscreen and download some file from the server, unzip it, move files insto proper directories and then start the apps main screen. Here is the code, I used AsyncTask.
So, you have three AsyncTask classes, one for each task and in the onPostExecute() I call the next AsyncTask. I can't say if this is the best way but it works for me.
I removed unneccessary code but for clarity I left a call to a dialog where I ask a user ih he wants to proceed with downloading as it may take a while. Also I check if FIRST_RUN is true just so I know if I should download the package since for my app I need to do it only the first time, so if it is true I do the spashscreen activities and if it is false I proceed to MAINAPP activity.
Hope it helps.
public class SplashScreen extends Activity {
#Override
protected void onCreate(Bundle savedInstanceState) {
// TODO Auto-generated method stub
super.onCreate(savedInstanceState);
setContentView(R.layout.splashscreen);
SharedPreferences settings = getSharedPreferences(PREFS_NAME,0);
boolean firstRun = settings.getBoolean("FIRST_RUN", true);
if (firstRun) {
showDialog(INITIAL_DLG);
} else {
startActivity(new Intent(appContext, MAINAPP.class));
}
}
/***
* First entry after YES on Dialog!
*/
protected void initialize() {
messageTV.setVisibility(TextView.VISIBLE);
progressBar.setVisibility(ProgressBar.VISIBLE);
downloadThread = new DownloadFiles();
downloadThread.execute();
}
protected void rollback() {
}
#Override
protected Dialog onCreateDialog(int id) {
AlertDialog.Builder builder;
switch (id) {
case INITIAL_DLG:
builder = new AlertDialog.Builder(this);
builder.setMessage(R.string.app_setup)
.setCancelable(false)
.setPositiveButton(R.string.yes, new DialogInterface.OnClickListener() {
public void onClick(DialogInterface dialog, int which) {
dialog.dismiss();
initialize();
}
})
.setNegativeButton(R.string.no, new DialogInterface.OnClickListener() {
public void onClick(DialogInterface dialog, int which) {
finish();
}
});
alertDlg = builder.create();
return alertDlg;
default:
return null;
}
}
protected class DownloadFiles extends AsyncTask<String, Integer, Boolean> {
#Override
protected Boolean doInBackground(String... params) {
try {
//file download
} catch (Exception e) {
result = false;
}
return true;
}
#Override
protected void onProgressUpdate(Integer... values) {
super.onProgressUpdate(values);
progressBar.setProgress(values[0]);
}
#Override
protected void onPostExecute(Boolean result) {
// TODO Auto-generated method stub
super.onPostExecute(result);
unzipThread = new DecompressZipFile();
unzipThread.execute();
}
#Override
protected void onPreExecute() {
// TODO Auto-generated method stub
messageTV.setText("Step 1/4:Downloading data...");
progressBar.setProgress(0);
progressBar.setMax(100);
super.onPreExecute();
}
}
protected class DecompressZipFile extends AsyncTask<String, Integer, Boolean> {
#Override
protected Boolean doInBackground(String... params) {
try {
//unzip files
return true;
} catch(Exception e) {
return false;
}
}
#Override
protected void onProgressUpdate(Integer... values) {
super.onProgressUpdate(values);
if (values[0]<0) progressBar.setMax(values[0]*-1);
else progressBar.setProgress(values[0]);
}
#Override
protected void onPostExecute(Boolean result) {
// TODO Auto-generated method stub
super.onPostExecute(result);
moveDBThread = new MoveDBFile();
moveDBThread.execute();
}
#Override
protected void onPreExecute() {
// TODO Auto-generated method stub
messageTV.setText("Step 2/4:Decompressing data...");
progressBar.setProgress(0);
progressBar.setMax(100);
super.onPreExecute();
}
}
protected class MoveDBFile extends AsyncTask<String, Integer, Boolean> {
#Override
protected Boolean doInBackground(String... params) {
try {
//moving files
return true;
} catch (Exception e) {
globalE = e;
finish();
return false;
}
}
#Override
protected void onPreExecute() {
messageTV.setText("Step 3/4:Shufflin'...");
progressBar.setProgress(0);
progressBar.setMax(100);
super.onPreExecute();
}
#Override
protected void onProgressUpdate(Integer... values) {
super.onProgressUpdate(values);
progressBar.setProgress(values[0]);
}
#Override
protected void onPostExecute(Boolean result) {
super.onPostExecute(result);
if (result) {
getSharedPreferences(PREFS_NAME,0).edit().putBoolean("FIRST_RUN", false).commit();
startActivity(new Intent(appContext, MAINAPP.class));
} else {
rollback();
}
}
}
}