I have an Activity which downloads the data from the Database. While the Activity is doing this work, I want to show the progress with ProgressDialog.I use ProgressDialog.STYLE_HORIZONTAL because I want to show the actual values. I use a Handler to start the Activity which displays the ProgressDialog:
Intent intent = new Intent(this, ProgressDialogActivity.class);
private Handler handler = new Handler(){
#Override
public void handleMessage(Message msg) {
super.handleMessage(msg);
if(msg.what == SET_PROGRESS){
intent.putExtra("action", "show");
intent.putExtra("progress", msg.arg1);
intent.putExtra("max", msg.arg2);
intent.putExtra("message", syncMessage);
intent.putExtra("title", R.string.please_wait);
intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
startActivity(intent);
}
else if(msg.what == SHOW_PROGRESS){
intent.putExtra("action", "show");
intent.putExtra("title", syncMessage);
intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
startActivity(intent);
}
else if(msg.what == HIDE_PROGRESS){
intent.putExtra("action", "hide");
intent.putExtra("message", "");
intent.putExtra("title", "");
intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
startActivity(intent);
}
}
};
Here is the ProgressDialogActivity:
public class ScreenProgressDialog extends Activity {
ProgressDialog pd;
Bundle extras;
String action;
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
extras = getIntent().getExtras();
pd = new ProgressDialog(this);
pd.setProgressStyle(ProgressDialog.STYLE_HORIZONTAL);
pd.setCancelable(false);
pd.setProgress(extras.getInt("progress"));
pd.setMax(extras.getInt("max"));
pd.setMessage(extras.getCharSequence("message"));
pd.setTitle(extras.getString("title"));
action = extras.getString("action");
if (action.equals("show")){
pd.show();
}
else{
pd.dismiss();
}
}
#Override
public void onDestroy() {
super.onDestroy();
}
}
When the Main Activity downloads a new table from the Database the Handler starts a new ProgressDialogActivity and a new Activity appears. I would like to avoid this. My aim is to show only ONE Activity which displays the ProgressDialog with the correct values.
(I cannot create a ProgressDialog in the Main Activity, I have to find another way. It's some kind of homework but I need some help).
Thank you!
You can use AsyncTask to fetch data in background and show ProgressDialog
Here is code:
// Get feed!
new ProgressTask().execute();
private class ProgressTask extends AsyncTask<String, Void, Boolean> {
private ProgressDialog dialog = new ProgressDialog(HomeActivity.this);
/** progress dialog to show user that the backup is processing. */
/** application context. */
protected void onPreExecute() {
this.dialog.setMessage("Please wait");
this.dialog.show();
}
protected Boolean doInBackground(final String... args) {
try {
/**
* Fetch the RSS Feeds from URL
*/
Utilities.arrayRSS = objRSSFeed
.FetchRSSFeeds(Constants.Feed_URL);
return true;
} catch (Exception e) {
Log.e("tag", "error", e);
return false;
}
}
#Override
protected void onPostExecute(final Boolean success) {
if (dialog.isShowing()) {
dialog.dismiss();
}
if (success) {
// display UI
UpdateDisplay();
}
}
}
What about using an AsyncTask: How to add ProgressDialog
Where you can do the download part in the doInBackground method and update the progress bar accordingly using onProgressUpdate..
Related
Iam calling a Asynctask from Scheduled Service Every 10 mins it will Run.
while running the Service, Progress dialog getting Exception from OnpreExecute.
ERROR :
FATAL EXCEPTION: main
android.view.WindowManager$BadTokenException: Unable to add window -- token null is not for an application
at android.view.ViewRootImpl.setView(ViewRootImpl.java:594)
at android.view.WindowManagerGlobal.addView(WindowManagerGlobal.java:259)
at android.view.WindowManagerImpl.addView(WindowManagerImpl.java:69)
at android.app.Dialog.show(Dialog.java:286)
EDIT 1:
Alarm Manager for calling the service for every 5 mins
/*Alarm manager Service for From Server*/
private void setServerFetch() {
// for to Server to GPS PING
Intent myIntent1 = new Intent(LoginPage.this, AlarmService.class);
pendingintent1 = PendingIntent.getService(LoginPage.this, 1111, myIntent1, 0);
AlarmManager alarmManager5 = (AlarmManager) getSystemService(ALARM_SERVICE);
Calendar calendar1 = Calendar.getInstance();
calendar1.setTimeInMillis(System.currentTimeMillis());
calendar1.add(Calendar.SECOND, 1);
alarmManager5.set(AlarmManager.RTC_WAKEUP, calendar1.getTimeInMillis(), pendingintent1);
alarmManager5.setInexactRepeating(AlarmManager.RTC_WAKEUP, calendar1.getTimeInMillis(), 300 * 1000, pendingintent1);
}
Calling the AsyncTask from Service Onstart
#Override
public void onStart(Intent intent, int startId)
{
super.onStart(intent, startId);
try
{
Asynctask_Incident task=new Asynctask_Incident();
task=new();
}
catch (Exception e)
{
e.printStackTrace();
Log.i("PING", "EXCEPTION in reading Data from Web Async task ONstart.!");
}
}
Asynctask Class onStart Method
public class Asynctask_Incident extends AsyncTask<String, Void, Void>
{
#Override
protected void onPreExecute()
{
super.onPreExecute();
runOnUiThread(new Runnable() {
#Override
public void run() {
if (!pDialog.isShowing())
{
pDialog = new ProgressDialog(appContext);
pDialog.setCanceledOnTouchOutside(false);
pDialog.setCancelable(false);
pDialog.setMessage("Please Wait Updating Data From...");
pDialog.show();
}
}
});
}
#Override
protected Void doInBackground(String... params)
{
try {
getAPICall();
} catch (Exception e) {
e.printStackTrace();
if (pDialog.isShowing()) {
pDialog.dismiss();
}
}
return null;
}
#Override
protected void onPostExecute(Void aVoid)
{
super.onPostExecute(aVoid);
if (pDialog.isShowing()) {
pDialog.dismiss();
}
}
}
Help me to Solve this Issue.
Actually you can't start a progress dialog from a service, because it needs the activity context not application context which come to be null in your case.
More info here:
link1 , link2 and link3
If you want to trigger progress dialog based on service action, you may use Observer design patter, look here.
Update:
If your app is running, you can use Handler and run it each 5 minutes.
Here is a complete example:
public class TestActivity extends AppCompatActivity {
private Handler handler;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_test);
handler = new Handler();
handler.postDelayed(new Runnable() {
#Override
public void run() {
//
new Asynctask_Incident(TestActivity.this).execute("url");
handler.postDelayed(this, 5 * DateUtils.MINUTE_IN_MILLIS);
}
}, 0);
}
public class Asynctask_Incident extends AsyncTask<String, Void, Void> {
ProgressDialog pDialog;
Context appContext;
public Asynctask_Incident(Context ctx) {
appContext = ctx;
}
#Override
protected void onPreExecute() {
super.onPreExecute();
pDialog = new ProgressDialog(appContext);
pDialog.setCanceledOnTouchOutside(false);
pDialog.setCancelable(false);
pDialog.setMessage("Please Wait Updating Data From...");
pDialog.show();
}
#Override
protected Void doInBackground(String... params) {
try {
getAPICall();
} catch (Exception e) {
e.printStackTrace();
if (pDialog.isShowing()) {
pDialog.dismiss();
}
}
return null;
}
private void getAPICall() {
//5 seconds delay for test, you can put your code here
try {
Thread.sleep(5 * DateUtils.SECOND_IN_MILLIS);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
#Override
protected void onPostExecute(Void aVoid) {
super.onPostExecute(aVoid);
if (pDialog.isShowing()) {
pDialog.dismiss();
}
}
}
}
Intialize your ProgressDialog.
OnPreExecute();
runOnUiThread(new Runnable() {
#Override
public void run() {
if (pDialog == null)
{
pDialog = new ProgressDialog(appContext);
pDialog.setCanceledOnTouchOutside(false);
pDialog.setCancelable(false);
pDialog.setMessage("Please Wait Updating Data From...");
}
pDialog.show();
}
});
OnPostExecute();
pDialog.dismiss();
The exception Exception:android.view.WindowManager$BadTokenException: Unable to add window -- token null is not for an application comes when the context is not alive. There may be other reason for this exception but context is major reason. Moreover, if previously shown Dialog is not dismissed, exception may occur.
Please try this code :
runOnUiThread(new Runnable() {
#Override
public void run() {
if(appContext != null) {
// if dialog is already showing, hide it
if(pDialog != null && pDialog.isShowing()) {
pDialog.dismiss();
}
if (pDialog == null) {
pDialog = new ProgressDialog(appContext);
pDialog.setCanceledOnTouchOutside(false);
pDialog.setCancelable(false);
pDialog.setMessage("Please Wait Updating Data From...");
}
pDialog.show();
} else {
Log.e("Error","Context is Null");
}
}
});
An additional check can be added : http://dimitar.me/android-displaying-dialogs-from-background-threads/
You do not need to initialize the dialog in a thread in the onPreExecute. Because this method is always called in the UI thread. By calling a thread you are delaying it. So the doInbackground perhaps happened before the dialog was created.
Also you should not call anything that modifies the UI in the doItBackground method. Because this method runs in a worker thread. Any UI call must be in the main thread. The onPostExecute is called by the main thread. So put your dialog related calls there, but not in the doInBackground.
These lines in the doInbackground need to be removed.
if (pDialog.isShowing()) {
pDialog.dismiss();
}
1) You don't need your ProgressDialog setup inside a Runnable, anything in onPreExecute() and onPostExecute() already runs on the UI thread. Only doInBackground() runs off the UI thread.
2) Put AsyncTask class in MainActivity, call it from MainActivity, not from your Service. Call your AsyncTask from the MainActivity like this:
new MyAsyncTask(MainActivity.this).execute("");
3) Finally, put this constructor in your AsyncTask class:
public MyAsyncTask(Context context) {
appContext = context;
}
It seems like your context does not have the right set of resources.
Make sure that your are using the right context.
Context context = this;
ProgressDialog progressDialog = new ProgressDialog(context);
progressDialog.show();
where "this" - AppCompatActivity or Activity context
what i have is two asynctask each one call a function to parse some data ... and i want the asynctask starts after asynctasknew finish how can i do this??? here is my code ..
send.setOnClickListener(new OnClickListener() {
#Override
public void onClick(View v) {
// TODO Auto-generated method stub
AsyncCallWS task = new AsyncCallWS();
try{
Intent newintent = getIntent();
mixlist=newintent.getStringArrayListExtra("listmix");
Log.e("listmix",mixlist+"");
for(int i=0;i<=mixlist.size();i++){
if(i==mixlist.size()){
Log.d("states","finished");
Item_Name="0";
Item_Price="0";
Item_Quantity="0";
Total_Price="0";
Customer_Name=name.getText().toString();
Log.e("customer_name",Customer_Name);
Customer_Number=mobile.getText().toString();
Customer_Address=addressnew.getText().toString();
//Call execute
task.execute();
}
else{
Item_Name=mixlist.get(i);
i++;
Item_Price=mixlist.get(i);
i++;
Item_Quantity=mixlist.get(i);
i++;
Total_Price=mixlist.get(i);
Customer_Name="0";
Customer_Number="0";
Customer_Address="0";
// AsyncCallWSnew tasknew = new AsyncCallWSnew();
//Call execute
AsyncCallWSnew tasknew = new AsyncCallWSnew();
tasknew.execute();
}
}
}
catch(Exception e){
e.printStackTrace();
}
}
});
}
private class AsyncCallWS extends AsyncTask<Void, Void, Void> {
protected void onPostExecute(Void result) {
//Make Progress Bar invisible
Toast.makeText(getApplicationContext(), "order has been sent + item price", Toast.LENGTH_LONG).show();
Intent intObj = new Intent(PersonalInfo.this,MainActivity.class);
startActivity(intObj);
//Error status is false
}
//Make Progress Bar visible
protected void onPreExecute() {
}
#Override
protected Void doInBackground(Void... params) {
// TODO Auto-generated method stub
loginStatus = WebService.invokeLoginWS(Item_Name,Item_Price,Item_Quantity, Total_Price, Customer_Name,
Customer_Number, Customer_Address,"InsertData");
return null;
}
}
private class AsyncCallWSnew extends AsyncTask<Void, Void, Void> {
protected void onPostExecute(Void result) {
//Make Progress Bar invisible
Toast.makeText(getApplicationContext(), "order has been sent", Toast.LENGTH_LONG).show();
Intent intObj = new Intent(PersonalInfo.this,MainActivity.class);
startActivity(intObj);
//Error status is false
}
//Make Progress Bar visible
protected void onPreExecute() {
}
#Override
protected Void doInBackground(Void... params) {
// TODO Auto-generated method stub
loginStatus = WebService.invokeLoginWS(Item_Name,Item_Price,Item_Quantity, Total_Price, Customer_Name,
Customer_Number, Customer_Address,"InsertData");
return null;
}
}
}
when i make a debug my code works just fine .. but in normal run .. it doesn't can any help me?
There are basically two possibilities:
Simply start the next AsyncTask from onPostExecute() of the previous one
Use AsyncTask.executeOnExecutor() with SerialExecutor and start all of them in a row.
Hi You can use AsyncTask executeonExecutor method to start the async task. But it will require minimum API version 11. Kindly refer the following code.
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.HONEYCOMB) {
new YourFirstTask().executeOnExecutor(AsyncTask.THREAD_POOL_EXECUTOR,params...);
new YourSecondTask().executeOnExecutor(AsyncTask.THREAD_POOL_EXECUTOR,params...);
}else{
new YourFirstTask().execute(params...);
new YourSecondTask().execute(params...);
}
For Lower version you can call directly. automatically system will process one by one.
In my android application I have a MainActivity. It has an EditText and a Button. User enter his twitter handle and press button. An IntentService is launched which retrieves user's tweets and then return the first tweet to a BroadcastReceiver.
Since loading tweets takes time I want to show a loader until loading tweets is done.
I'm using following code in button click listener to show the loading dialog
ProgressDialog progress = new ProgressDialog(MainActivity.this);
progress.setTitle("Loading");
progress.setMessage("Wait while loading...");
progress.show();
But I don't know how to hide this once the loading is done.
Below are the code of the MainActivity , IntentService and BroadcastReceiver
MainActivity
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
analyze = (Button)findViewById(R.id.analyze);
twitter_username = (EditText)findViewById(R.id.twitter_username);
analyze.setOnClickListener(new View.OnClickListener(){
#Override
public void onClick(View v) {
ProgressDialog progress = new ProgressDialog(MainActivity.this);
progress.setTitle("Loading");
progress.setMessage("Wait while loading...");
progress.show();
Intent i = new Intent(MainActivity.this , TwitterChecker.class);
i.putExtra("username", twitter_username.getText().toString());
startService(i);
}});
}
IntentService
public class TwitterChecker extends IntentService {
public TwitterChecker(){
super("TwitterChecker");
}
#Override
protected void onHandleIntent(Intent intent) {
String username = intent.getStringExtra("username");
TwitterAuthenticator authenticator = TwitterAuthenticator.getInstance();
String accessToken = null;
try {
accessToken = authenticator.authenticate();
} catch (UnsupportedEncodingException e) {
e.printStackTrace();
} catch (AuthenticationException e) {
e.printStackTrace();
}
Twitter tweets = FetchTweets.fetch(accessToken , username);
Log.i("Info" , "IntentService started");
Intent tweet = new Intent("com.kaysush.action.TWEET");
tweet.putExtra("tweet", tweets.get(0).getText());
sendBroadcast(tweet); // Once loaded the tweet is sent to the Receiver
}
}
BraodcastReceiver
public class TweetsReceiver extends BroadcastReceiver {
#Override
public void onReceive(Context context, Intent intent) {
Log.i("TWEET RECEIVED" , intent.getStringExtra("tweet"));
//Once loading is done a toast is shown
Toast.makeText(context, intent.getStringExtra("tweet"), Toast.LENGTH_LONG).show();
}
}
Hide a ProgressDialog once data is loaded
You are able to do it but you need to use not static but dynamic BroadcastReceiver. So here is solution:
At first, register in your Activity BroadcastReceiver dynamically:
private void registerReceiver() {
receiver = new BroadcastReceiver() {
#Override
public void onReceive(Context context, Intent intent) {
if (intent.getAction().equals(Const.LOADING_COMPLETE_ACTION)) {
if (dlg != null) {
dlg.dismiss();
}
}
}
}
IntentFilter intentFilter = new IntentFilter();
intentFilter.addAction(Const.LOADING_COMPLETE_ACTION);
registerReceiver(receiver, intentFilter);
}
And then in your IntentService, all what you need is to send Broadcast:
sendBroadcast(new Intent(Const.LOADING_COMPLETE_ACTION));
Note: Also define your ProgressDialog variable on Activity scope to have access to it from onReceive() method.
ProgressDialog progress; // Make global
Assign onClick listener
progress = new ProgressDialog(MainActivity.this);
Then in call back method onReceive()
progress.cancel();
progressDialog = ProgressDialog.show(GetResponse.this, "", "Loading...");
new Thread()
{
public void run()
{
try
{
// inside i have written code for making connection to the server using SSL connection.
}catch (Exception e)
{
progressDialog.dismiss();
exception(e.getMessage())
}.start();
}
private void exception(String msg)
{
Toast.makeText(this, msg, Toast.LENGTH_LONG).show();
this.finish();
Intent i = new Intent(getBaseContext(), LoginPage.class);
startActivity(i);
}
my LoginPage.java is previous activity.
If the connection is successfull it goes to the next activity ot doesnt give any error,
But if der is any prob with connection then i want progress bar should be stopped and go back to the LoginPage activity and also i want the error msg to be displayed.
From the above im getting some error.. Please help me out on this
Pass in and use the context from LoginPage. Also, use the 101010 button to format your code as code in your posts.
you can go up by using try catch mechanism where in your catch place your toast message and u can do it also by asynchronous task,
here simple code
private class Task_News_ArticleView extends AsyncTask<Void, Void, Void> {
private final ProgressDialog dialog = new ProgressDialog(
Bru_Sports_View.this);
// can use UI thread here
protected void onPreExecute() {
this.dialog.setMessage("Loading...");
this.dialog.setCancelable(false);
this.dialog.show();
}
#Override
protected Void doInBackground(Void... params) {
try {
//here the condition to check login details
}
} catch (Exception e) {
}
return null;
}
protected void onPostExecute(Void result) {
if (this.dialog.isShowing()) {
this.dialog.dismiss();
}
}
}
and u can also use try,catch in catch block you can place your toast message
with finsih() method
I'm stuck with a memory leak that I cannot fix. I identified where it occurs, using the MemoryAnalizer but I vainly struggle to get rid of it. Here is the code:
public class MyActivity extends Activity implements SurfaceHolder.Callback {
...
Camera.PictureCallback mPictureCallbackJpeg = new Camera.PictureCallback() {
public void onPictureTaken(byte[] data, Camera c) {
try {
// log the action
Log.e(getClass().getSimpleName(), "PICTURE CALLBACK JPEG: data.length = " + data);
// Show the ProgressDialog on this thread
pd = ProgressDialog.show(MyActivity.this, "", "Préparation", true, false);
// Start a new thread that will manage the capture
new ManageCaptureTask().execute(data, c);
}
catch(Exception e){
AlertDialog.Builder dialog = new AlertDialog.Builder(MyActivity.this);
...
dialog.create().show();
}
}
class ManageCaptureTask extends AsyncTask<Object, Void, Boolean> {
protected Boolean doInBackground(Object... args) {
Boolean isSuccess = false;
// initialize the bitmap before the capture
((myApp) getApplication()).setBitmapX(null);
try{
// Check if it is a real device or an emulator
TelephonyManager telmgr = (TelephonyManager) getSystemService(Context.TELEPHONY_SERVICE);
String deviceID = telmgr.getDeviceId();
boolean isEmulator = "000000000000000".equalsIgnoreCase(deviceID);
// get the bitmap
if (isEmulator) {
((myApp) getApplication()).setBitmapX(BitmapFactory.decodeFile(imageFileName));
} else {
((myApp) getApplication()).setBitmapX(BitmapFactory.decodeByteArray((byte[]) args[0], 0, ((byte[])args[0]).length));
}
((myApp) getApplication()).setImageForDB(ImageTools.resizeBmp(((myApp) getApplication()).getBmp()));
// convert the bitmap into a grayscale image and display it in the preview
((myApp) getApplication()).setImage(makeGrayScale());
isSuccess = true;
}
catch (Exception connEx){
errorMessageFromBkgndThread = getString(R.string.errcapture);
}
return isSuccess;
}
protected void onPostExecute(Boolean result) {
// Pass the result data back to the main activity
if (MyActivity.this.pd != null) {
MyActivity.this.pd.dismiss();
}
if (result){
((ImageView) findViewById(R.id.apercu)).setImageBitmap(((myApp) getApplication()).getBmp());
((myApp) getApplication()).setBitmapX(null);
}
else{
// there was an error
ErrAlert();
}
}
}
};
private void ErrAlert(){
// notify the user about the error
AlertDialog.Builder dialog = new AlertDialog.Builder(this);
...
dialog.create().show();
}
}
The activity is terminated on a button click, like this:
Button use = (Button) findViewById(R.id.use);
use.setOnClickListener(new OnClickListener() {
#Override
public void onClick(View v) {
Intent intent = new Intent(MyActivity.this, NextActivity.class);
intent.putExtra("dbID", "-1");
intent.putExtra("category", category);
((myApp) getApplication()).setBitmapX(null);
MyActivity.this.startActivity(intent);
MyActivity.this.finish();
}
});
MemoryAnalyzer indicated the memory leak at:
((myApp) getApplication()).setBitmapX(BitmapFactory.decodeByteArray((byte[]) args[0], 0, ((byte[])args[0]).length));
I am grateful for any suggestion, thank you in advance.
Is your thread garbage collected after onPostExecute is called or is it still in the memory?
A Async Task will not be canceled or destroyed at the moment the activity is dismissed. If your thread is more or less lightweight and finishes after a small time, just keep it running and add a MyActivity.this.isFinishing() clause in the onPostExecute() method.
Your Task stores a implicit reference to your Activity MyActivity.this because it is a private class inside the activity. This means that your Activity will not be garbage collected until the task exits.
You can try below code snippet
protected void onPostExecute(Boolean result) {
if(YourActivity.this.isFinished()){
//to smomething here
}
}