Activity has leaked window - Custom Dialog - android

I am trying to show a custom dialog within Activity and this error occur. I know why this error occur from here and here and also know it's solution. But the problem is I can't find the problem in my code. I've spent anlot of time in finding the error with no luck.
I've called below method on button click
public void changePassword(View view){
DialogChangePassword dialogChangePassword = new DialogChangePassword(ActivityMyAccount.this);
dialogChangePassword.show();
Window window = dialogChangePassword.getWindow();
window.setLayout(WindowManager.LayoutParams.MATCH_PARENT, WindowManager.LayoutParams.WRAP_CONTENT);
window.setBackgroundDrawable(new ColorDrawable(Color.TRANSPARENT));
}
I am showing the dialog here while Activity should live. My question;
I can't dismiss the dialog here, I am dismissing it from within Dialog class.
I am not finishing the activity. If error occurs because the activity is finishing, why is it finishing?
If error is not because of finishing the activity then why does this error occur?
I have a NetworkOperation to be performed in Dialog class, does it have to do something with that?
Here is my Dialog class
public class DialogChangePassword extends Dialog {
Context context;
Button confirm, cancel;
CustomEditText edtOldPwd, edtNewPwd, edtConfirmNewPwd;
ProgressDialog progressDialog;
String PASSWORD_INCORRECT_MESSAGE = "Old password is incorrect.";
public DialogChangePassword(Context context) {
super(context);
this.context = context;
}
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
requestWindowFeature(Window.FEATURE_NO_TITLE);
setContentView(R.layout.dialog_change_password);
if(progressDialog != null)
progressDialog = null;
progressDialog = new ProgressDialog(context);
progressDialog.setTitle("Please wait...");
progressDialog.setMessage("Updating Password.");
progressDialog.show();
confirm = (Button) findViewById(R.id.btnChangePassword);
cancel = (Button) findViewById(R.id.btnCancel);
edtOldPwd = (CustomEditText) findViewById(R.id.edtOldPassword);
edtNewPwd = (CustomEditText) findViewById(R.id.edtNewPassword);
edtConfirmNewPwd = (CustomEditText) findViewById(R.id.edtConfirmNewPassword);
edtConfirmNewPwd.addTextChangedListener(new TextWatcher() {
#Override
public void beforeTextChanged(CharSequence s, int start, int count, int after) {
}
#Override
public void onTextChanged(CharSequence s, int start, int before, int count) {
}
#Override
public void afterTextChanged(Editable s) {
if (!edtNewPwd.getText().toString().equals(edtConfirmNewPwd.getText().toString()))
edtConfirmNewPwd.setError("Password doesn't match");
}
});
confirm.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
if (!edtNewPwd.getText().toString().equals(edtConfirmNewPwd.getText().toString())) {
Toast.makeText(context, "Password doesn't match", Toast.LENGTH_SHORT).show();
progressDialog.cancel();
return;
}
HashMap<String, String> params = new HashMap<>();
params.put("email", Utility.classUser.getEmailId());
params.put("password", edtOldPwd.getText().toString());
params.put("newPassword", edtNewPwd.getText().toString());
new NetworkOperation().execute(params);
}
});
cancel.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
dismiss();
}
});
}
private class NetworkOperation extends AsyncTask<HashMap<String,String>, Void, String> {
#Override
protected String doInBackground(HashMap<String, String>... params) {
try {
ClassAPIRoutes routes = ClassAPIRoutes.initializeRoutes();
return routes.editUserPassword(params[0]);
} catch (final IOException e) {
e.printStackTrace();
getOwnerActivity().runOnUiThread(new Runnable() {
#Override
public void run() {
Toast.makeText(context, e.toString(), Toast.LENGTH_SHORT).show();
}
});
return "error";
}
}
#Override
protected void onPostExecute(String s) {
super.onPostExecute(s);
progressDialog.cancel();
dismiss();
if(!s.equals("error")){
JSONObject jsonObject;
try {
jsonObject = new JSONObject(s);
if (jsonObject.get("success").toString().equals("true")) {
Toast.makeText(context, "Password successfully changed.", Toast.LENGTH_SHORT).show();
dismiss();
} else if (jsonObject.get("success").toString().equals("false")) {
if (jsonObject.get("message").toString().equals(PASSWORD_INCORRECT_MESSAGE)) {
Toast.makeText(context, PASSWORD_INCORRECT_MESSAGE, Toast.LENGTH_SHORT).show();
resetFields();
}
}
} catch (JSONException e) {
e.printStackTrace();
Toast.makeText(getContext(), s, Toast.LENGTH_SHORT).show();
}
}
}
}
private void resetFields(){
edtOldPwd.setText("");
edtNewPwd.setText("");
edtConfirmNewPwd.setText("");
}
}

I've removed showing progress dialog from onCreate(...) and put it in Async class inside OnPreExecute(...) and it's working fine

Related

Set Progress Dialog properly in asynctask

I currently trying to show a progress dialog on OnclickListener of a Dialogbox since my items are taking too long to fetch from Server.
I use Async task as suggested here (Android progress dialog) and this post (android problem with progress dialog) to show progress dialog The progress dialog is shown , however the code returns exception when it goes to do background that " Looper is not set". And when I set looper nothing happens.
I am not sure at this stage what is it that I am doing wrong.
public void firstMethod()
{
final CustomObj obj = getCustomObj();//not imp
Messages.getInstance().showAlert(MainActivity.this, "message", false, new DialogInterface.OnClickListener()
{
#Override
public void onClick(DialogInterface dialog, int which)
{
dialog.dismiss();
}
}, new DialogInterface.OnClickListener()
{
#Override
public void onClick(DialogInterface dialog, int which)
{
gotoAnotherPge(obj);
}
});
}
public void gotoAnotherPge(final CustomObject obj)
{
final ProgressDialog pd = new ProgressDialog(MainActivity.this);
new AsyncTask<Object, Object, Boolean>()
{
protected void onPreExecute()
{
pd.setMessage(String.format(Statics.getText(MainActivity.this, R.raw.dictionary, "subscriptions_loading_unsubscribing")));
pd.show();
}
protected Boolean doInBackground(Object... params)
{
try{
Looper.prepare();
final LocalPopulator lp = new LocalPopulator(MainActivity.this, 0)
{
#Override
public void populate()
{
List<Serializable> items = Arrays.asList(getItemHere(obj));
List<Serializable> listItems = new ArrayList<Serializable>();
listItems.addAll(items);
Serializable[] sItems = listItems.toArray(new Serializable[menuItems.size()]);
result = sItems;
}
};
showNextPage(true, 1, 0, lp);
Looper.loop();
}catch (Exception e){
Log.e("tag", e.getMessage());
/*
* The task failed
*/
return false;
}
return true;
}
protected void onPostExecute(Boolean result)
{
pd.dismiss();
}
};
MainActivity.this.runOnUiThread (new Runnable()
{
#Override
public void run()
{
// dismiss the progressdialog
pd.dismiss();
}
});
}

Update ProgressBar message as it increments

I have progress bar which show progress of downloading file by defining asyncTask to accomplish this. Now I want to show downloading status as the progress bar updated. Eg. "Current File: 40%" and on next iteration it shows "Current File: 80%" etc
Below is my code:
public class MainActivity extends Activity {
private ProgressDialog _progressDialog;
private int _progress = 0;
#Override
protected
void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
Button btn = (Button) findViewById(R.id.button1);
btn.setOnClickListener(new View.OnClickListener() {
public void onClick(View v) {
final DownloadTask downloadTask = new DownloadTask(MainActivity.this);
downloadTask.execute("xyz.com");
}
});
}
protected
Dialog onCreateDialog(int id) {
switch (id) {
case 0:
//...
case 1:
_progressDialog = new ProgressDialog(this);
_progressDialog.setIcon(R.drawable.ic_launcher);
_progressDialog.setTitle("Downloading files...");
_progressDialog.setProgressStyle(ProgressDialog.STYLE_HORIZONTAL);
_progressDialog.setButton(DialogInterface.BUTTON_POSITIVE, "Hide",new DialogInterface.OnClickListener() {
public void onClick(DialogInterface dialog,int whichButton) {
Toast.makeText(getBaseContext(), "Hide clicked!",Toast.LENGTH_SHORT).show();
}
});
_progressDialog.setButton(DialogInterface.BUTTON_NEGATIVE,"Cancel", new DialogInterface.OnClickListener() {
public void onClick(DialogInterface dialog,int whichButton) {
Toast.makeText(getBaseContext(), "Cancel clicked!",Toast.LENGTH_SHORT).show();
}
});
return _progressDialog;
}
return null;
}
private class DownloadTask extends AsyncTask<String, Integer, String> {
private Context context;
int myProgressCount;
public DownloadTask(Context context) {
this.context = context;
}
#Override
protected String doInBackground(String... sUrl) {
try {
while (......) {
if (isCancelled())
return null;
myProgressCount++;
publishProgress(myProgressCount);
}
} catch (Exception e) {
return e.toString();
}
return null;
}
#Override
protected void onPreExecute() {
super.onPreExecute();
showDialog(1);
_progress = 0;
_progressDialog.setProgress(0);
}
#Override
protected void onProgressUpdate(Integer... progress) {
super.onProgressUpdate(progress);
_progressDialog.setIndeterminate(false);
_progressDialog.setMax(100);
_progressDialog.setProgress(progress[0]);
_progressDialog.setMessage("File:"+progress[0]);
}
#Override
protected void onPostExecute(String result) {
_progressDialog.dismiss();
if (result != null)
Toast.makeText(context,"Download error: "+result, Toast.LENGTH_LONG).show();
else
Toast.makeText(context,"File downloaded", Toast.LENGTH_SHORT).show();
}
}
}
How can we update setMessage as progress[0] changes?
Thanks

Pointing to wrong UI from posted Runnable after screen orintation changes

This is my little test program. My problem is that from run() method I access to fields of wrong (old) Activity, which was destroyed after screen orientation changed. What's the way to handle this situation?
And, by the way, I must have my activity been recreated, because in real application I have different layouts for portrait and landscape modes!
public class MainActivity extends Activity {
private EditText edit;
private Button button;
private ProgressDialog progressDialog;
private boolean isLoginInProgress = false;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
edit = (EditText) findViewById(R.id.edit_timer);
button = (Button) findViewById(R.id.btn_start);
button.setOnClickListener(new OnClickListener() {
#Override
public void onClick(View v) {
try {
if (edit.getText().toString().length() == 0) throw new Exception();
long dTime = Long.parseLong(edit.getText().toString());
new Handler().postDelayed(new Runnable() {
#Override
public void run() {
MainActivity.this.isLoginInProgress = false;
progressDialog.dismiss();
}
}, dTime);
progressDialog.show();
isLoginInProgress = true;
} catch (Exception e) {
Toast.makeText(MainActivity.this, "bad time value", Toast.LENGTH_SHORT).show();
}
}
});
progressDialog = new ProgressDialog(this);
progressDialog.setMessage("loading");
if (savedInstanceState != null) { // activity is restarted
isLoginInProgress = savedInstanceState.getBoolean("fl_login");
edit.setText(savedInstanceState.getString("edit"));
}
if (isLoginInProgress) { // Show dialog again
progressDialog.show();
}
}
#Override
protected void onSaveInstanceState(Bundle outState) {
outState.putBoolean("fl_login", isLoginInProgress);
outState.putString("edit", edit.getText().toString());
}
#Override
public void onDestroy(){
super.onDestroy();
progressDialog.dismiss();
}
}
You Can Use Database(SQLITE) for Storing Your Values..

add progress bar when one activity loads other activity

This is my activity oncreate() method. I set a positive button ok with a dialogue window.
when I click on it, it navigates UI activity staticDisplay.class. I want to set a progress bar after clicking ok in the dialogue window until it loads the next activity.
public void onCreate(Bundle savedInstanceState) {
Log.d(TAG, "ACTIVITY ONCREATE");
super.onCreate(savedInstanceState);
// setContentView(R.layout.dialog);
setContentView(R.layout.main);
if (Registration.isRunning == false) {
TextView title = new TextView(this);
title.setText("DM2");
title.setBackgroundColor(Color.DKGRAY);
title.setPadding(10, 10, 10, 10);
title.setGravity(Gravity.CENTER);
title.setTextColor(Color.WHITE);
title.setTextSize(20);
/* alert message */
AlertDialog.Builder builder = new AlertDialog.Builder(this);
builder.setCustomTitle(title);
builder.setMessage(R.string.app_description).setPositiveButton(
"Ok", new DialogInterface.OnClickListener() {
public void onClick(DialogInterface dialog, int id) {
if (Registration.isRunning == false) {
startService(new Intent(
getApplicationContext(),
Registration.class));
}
staticInfo();
if (Registration.ruid == null)
Registration.ruid = uId;
startActivity(new Intent(getApplicationContext(),
StatisticDisplay.class));
}
});
AlertDialog alert = builder.create();
alert.show();
} else {
startActivity(new Intent(getApplicationContext(),
StatisticDisplay.class));
}
}
StaticDisplay.class on create method
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.statdisplay);
usage_btn = (Button) findViewById(R.id.appstat);
usage_btn.setOnClickListener(this);
setting_btn = (Button) findViewById(R.id.setting);
setting_btn.setOnClickListener(this);
}
you can use AysncTask for background process to be done and showing progressdialog as follows,
call the class
new Task().execute(CurrentActivity.this);
In Task Class:
private class Task extends AsyncTask<Void, Void, Void>
{
ProgressDialog dialog;
Context context;
public Task(Context context)
{
this.context=context;
//constructor for this class
}
protected void onPreExecute() {
//create the progress dialog as
dialog=new ProgressDialog(context);
}
protected Void doInBackground(Void... JSONArray) {
//Place your background process code
}
protected void onPostExecute(Void unused) {
//dismiss the progressdialog
dialog.dismiss();
}
}
This Code , Working For me
private ProgressDialog progress;
Button CallButton;
#Override
protected void onCreate(Bundle savedInstanceState)
{
progress = new ProgressDialog(Page.this);
CallButton=(Button)findViewById(R.id.button1);
CallButton.setOnClickListener(this);
}
#Override
public void onClick(View v)
{
switch (v.getId()) {
case R.id.button1:
progress.setMessage("Please Wait Loading...");
progress.setProgressStyle(ProgressDialog.STYLE_SPINNER);
progress.setIndeterminate(true);
progress.show();
new Thread()
{
public void run()
{
Intent i = new Intent(Page.this,Update.class);
startActivity(i);
progress.dismiss();
}
}.start();
break;
}
}
Please look at to following code snippet,
progDailog = ProgressDialog.show(loginAct,"Process ", "please wait....",true,true);
new Thread ( new Runnable()
{
public void run()
{
// your loading code goes here
}
}).start();
Handler progressHandler = new Handler()
{
public void handleMessage(Message msg1)
{
progDailog.dismiss();
}
}
In the run() method, you can put your loading code.

Android splash screen and server communication

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();
}
}
}
}

Categories

Resources