Android view WindowLeaked - java

I have currently working with some application and exploring things and I encountered this error. This just happened out of nowhere and earlier it seems working fine.
I read some questions related to my problem but I can't relate my codes to them so I am really confused. I'm still beginner so any help would be appreciated.
Logcat
4386-4386/com.example.gab.quadrantms E/WindowManager: android.view.WindowLeaked: Activity com.example.gab.quadrantms.Home has leaked window DecorView#abb868f[] that was originally added here
at android.view.ViewRootImpl.<init>(ViewRootImpl.java:576)
at android.view.WindowManagerGlobal.addView(WindowManagerGlobal.java:363)
at android.view.WindowManagerImpl.addView(WindowManagerImpl.java:128)
at android.app.Dialog.show(Dialog.java:454)
at com.example.gab.quadrantms.SurveysFragment$1$1$1.onDataChange(SurveysFragment.java:120)
Fragment
if (getActivity() != null) {
if (myPosition.equals("Project Manager")) {
bottomSheetDialog = new BottomSheetDialog(getActivity());
final View bottomSheetDialogView = getLayoutInflater().inflate(R.layout.bottom_dialog_layot, null);
bottomSheetDialog.setContentView(bottomSheetDialogView);
View viewView = bottomSheetDialogView.findViewById(R.id.view);
View assignView = bottomSheetDialogView.findViewById(R.id.assign);
View deleteView = bottomSheetDialogView.findViewById(R.id.delete);
bottomSheetDialog.show(); //THIS LINE WHERE THE ERROR IS POINTING
if (bottomSheetDialog.isShowing()) {
assignView.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
String id = viewHolder.setSurveyID(model.getSurveyID());
String loc = viewHolder.setSurveyLocation(model.getSurveyLocation());
String type = viewHolder.setSurveyType(model.getSurveyType());
String progress = viewHolder.setProgress(model.getProgress());
if (progress.equals("Finished")) {
Toast.makeText(getContext(), "This project is Already Finished.", Toast.LENGTH_SHORT).show();
} else {
Intent surveyAssign = new Intent(getActivity(), AssignActivity.class);
surveyAssign.putExtra("id", id);
surveyAssign.putExtra("loc", loc);
surveyAssign.putExtra("type", type);
surveyAssign.putExtra("progress", progress);
startActivity(surveyAssign);
getActivity().finish();
}
}
});
deleteView.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
AlertDialog.Builder message = new AlertDialog.Builder(getContext());
message.setMessage("Are you sure you want to Delete this Project?").setCancelable(false)
.setPositiveButton("Yes", new DialogInterface.OnClickListener() {
#Override
public void onClick(final DialogInterface dialog, int which) {
String id = viewHolder.setSurveyID(model.getSurveyID());
mRemoveDuplicate = FirebaseDatabase.getInstance().getReference().child("Surveys");
mRemoveDuplicate.child(id).removeValue().addOnSuccessListener(new OnSuccessListener<Void>() {
#Override
public void onSuccess(Void aVoid) {
Toast.makeText(getContext(), "Project Deleted.", Toast.LENGTH_SHORT).show();
dialog.dismiss();
}
});
}
})
.setNegativeButton("No", new DialogInterface.OnClickListener() {
#Override
public void onClick(DialogInterface dialog, int which) {
dialog.dismiss();
}
});
AlertDialog alert = message.create();
alert.setTitle("Message");
alert.show();
}
});

Please add your Activity Name in All Dialog where your fragment is run.
Eg.
bottomSheetDialog = new BottomSheetDialog(YourActivity.this);
AlertDialog.Builder message = new AlertDialog.Builder(YourActivity.this);
I hope this can help You!
Thank You.

When does the app crashes? Is it while showing the dialog or while closing the dialog.
If its while closing the dialog, check whether you are dismissing the dialog properly.
Mostly WindowLeaked error occurs when you finish the parent activity before dismissing the dialog properly.
Note : If the app crashes during OnClick on assignView, finishing the activity here getActivity().finish(); in OnClickListener might be the problem.

Related

Visual customization of a dialog button

I am using a dialog in my app that pops up and interacts with the user. I haven't worked with dialogs before, so i know next to nothing about styling them. This is the code:
public void openDialog() {
#SuppressLint("InflateParams") View view = (LayoutInflater.from(AudioRecorder.this)).inflate(R.layout.audio_name_input, null);
AlertDialog.Builder alertBuilder = new AlertDialog.Builder(AudioRecorder.this);
alertBuilder.setView(view);
final EditText userInput = view.findViewById(R.id.userInput);
alertBuilder.setCancelable(true);
alertBuilder.setPositiveButton("Save", new DialogInterface.OnClickListener() {
#Override
public void onClick(DialogInterface dialog, int which) {
inputName = String.valueOf(userInput.getText());
if (!inputName.isEmpty()) {
Toast.makeText(AudioRecorder.this, "Next audio clip will be named... " + inputName, Toast.LENGTH_SHORT).show();
filePathMaking();
} else {
inputName = "recorded_audio";
Toast.makeText(AudioRecorder.this, "Input field empty, next audio clip will be named... " + inputName, Toast.LENGTH_SHORT).show();
}
}
});
alertBuilder.setNegativeButton("cancel", new DialogInterface.OnClickListener() {
#Override
public void onClick(DialogInterface dialogInterface, int i) {
}
});
Dialog dialog = alertBuilder.create();
dialog.show();
}
Can we style the "Save" button to display red text?
You can get the Button and then change it's text color. Something along the following lines should work,
public void openDialog() {
#SuppressLint("InflateParams") View view = (LayoutInflater.from(AudioRecorder.this)).inflate(R.layout.audio_name_input, null);
AlertDialog.Builder alertBuilder = new AlertDialog.Builder(AudioRecorder.this);
alertBuilder.setView(view);
final EditText userInput = view.findViewById(R.id.userInput);
alertBuilder.setCancelable(true);
alertBuilder.setPositiveButton("Save", new DialogInterface.OnClickListener() {
#Override
public void onClick(DialogInterface dialog, int which) {
inputName = String.valueOf(userInput.getText());
if (!inputName.isEmpty()) {
Toast.makeText(AudioRecorder.this, "Next audio clip will be named... " + inputName, Toast.LENGTH_SHORT).show();
filePathMaking();
} else {
inputName = "recorded_audio";
Toast.makeText(AudioRecorder.this, "Input field empty, next audio clip will be named... " + inputName, Toast.LENGTH_SHORT).show();
}
}
});
alertBuilder.setNegativeButton("cancel", new DialogInterface.OnClickListener() {
#Override
public void onClick(DialogInterface dialogInterface, int i) {
}
});
Dialog dialog = alertBuilder.create();
dialog.show();
Button positiveButton = dialog.getButton(AlertDialog.BUTTON_POSITIVE);
positiveButton.setTextColor(Color.parseColor("#FF0B8B42"));
}
You can use AlertDialog as Chrisvin Jem suggested in his answer but I would like to offer another solution:
You can just create a custom dialog class in order to give your dialog a custom layout, control everything in a separate class - I find it cleaner and more organized.
For example, create dialogClass:
public class ProgressDialog extends Dialog {
public ProgressDialog(#NonNull Context context) {
super(context);
setContentView(R.layout.progress_dialog); //this is your layout for the dialog
}
}
And all you need to do is to create dialog instant and call it like this:
ProgressDialog progressDialog = new ProgressDialog(getContext());
progressDialog.show(); // this line shows your dialog
Why I recommend using this and not AlertDialog.Builder :
You can build your layout in a faster way with custom dialog.
No need to write a lot of code just to add views when you can have a custom layout.
It's easier (or so I believe) for you to see myCoolDialog.show(); rather than 50 lines of code or more in a single method.
Do you need to change anything regarding your dialog look and code? good, go to your separate class and change it instead of adding 20 more code lines to your activity.
Chrisvin Jem gave the extact answer to your question however if you want more control over your design you can the this code
final Dialog dialog = new Dialog(context);
dialog.requestWindowFeature(Window.FEATURE_NO_TITLE);
dialog.setCancelable(false);
dialog.setContentView(R.layout.yourview);
RelativeLayout submit = dialog.findViewById(R.id.submit);
final EditText edittext = dialog.findViewById(R.id.edittext);
submit.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
dialog.dismiss();
Toast.makeText(context, getString(R.string.thanks), Toast.LENGTH_SHORT).show();
}
});
dialog.show();

Button in AlertDialog not appearing

I have a NeutralButton that should cause an AlertDialog box I have to disappear. This issue is, when the AlertDialog box comes up, the text set appears just fine but the NeutralButton doesn't show at all. I tried it as a Positive and Negative button, but no difference was made. Here's the code:
Button infoG1;
infoG1 = (Button) findViewById(R.id.iG1);
infoG1.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
AlertDialog.Builder info = new AlertDialog.Builder(game1.this);
info.setMessage("Text here");
info.show();
info.setNeutralButton("Ok", new DialogInterface.OnClickListener() {
#Override
public void onClick(DialogInterface dialog, int which) {
dialog.cancel();
}
});
}
});
I would have expected a button with text "Ok" to appear at the bottom of the AlertDialogue box, which causes the box to disappear once the user presses it.
You shouldn't call setNeutralButton(...) after your show() method. You are doing this, which is causing the problem.
Instead of this:
dialog.show();
dialog.setNeutralButton(...);
Do this:
dialog.setNeutralButton(...);
dialog.show();
Note that you should put everything above your dialog.show(). Otherwise you will have problems.
try this
Button infoG1;
infoG1 = (Button) findViewById(R.id.iG1);
infoG1.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
AlertDialog.Builder info = new AlertDialog.Builder(game1.this);
info.setMessage("Text here");
info.setNeutralButton("Ok", new DialogInterface.OnClickListener() {
#Override
public void onClick(DialogInterface dialog, int which) {
dialog.cancel();
}
});
info.show();
}
});

How to display AlertDialog on List Adapter

ContactsDataList is an Array List that contains the data of all Contacts.
I have written following code that pass data to List Adapter
adapter= new ContactsAdapter(getApplicationContext(), contactsDataList);
listView = (ListView) findViewById(R.id.lv_contacts);
listView.setAdapter(adapter);
On List View, I want to Launch Call_Action event, whenever user clicks on any item in List.
I have written following code in Adapter, but its giving me this error message
java.lang.IllegalStateException: You need to use a Theme.AppCompat
theme (or descendant) with this activity.
contactsHeading.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(final View v) {
AlertDialog alertDialog = new AlertDialog.Builder(context).create();
alertDialog.setTitle("Alert");
alertDialog.setMessage("Are you sure you want to call "+contactsHeading + "?" );
alertDialog.setButton(AlertDialog.BUTTON_POSITIVE, "OK",
new DialogInterface.OnClickListener() {
public void onClick(DialogInterface dialog, int which) {
Intent intent = new Intent(Intent.ACTION_CALL, Uri.parse("tel:" + contactsText));
if (ActivityCompat.checkSelfPermission(v.getContext(), Manifest.permission.CALL_PHONE) != PackageManager.PERMISSION_GRANTED) {
return;
}
v.getContext().startActivity(intent);
}
});
alertDialog.setButton(AlertDialog.BUTTON_NEGATIVE, "Cancel",
new DialogInterface.OnClickListener() {
public void onClick(DialogInterface dialog, int which) {
dialog.dismiss();
}
});
alertDialog.show();
Kindly guide me how to resolve this error message.
This is caused by the Context you passed into the AlertDialog.Builder.
In this line:
AlertDialog alertDialog = new AlertDialog.Builder(context).create();
Replace
context
with
[YourActivityName].this

AlertDialog not showing in Fragment

I've got a really strange problem where on some KitKat devices, my simple yes/no AlertDialog will appear behind the current fragment and not in the foreground. The reason I say the dialog appears behind the current fragment is because the dialog appears in the foreground only after I rotate the device. The app has a MainActivity that switches between different fragments that take up most of the screen.
MainActivity.java
#Override
public void onBackPressed() {
Builder builder = new AlertDialog.Builder(this);
builder.setMessage(getString(R.string.exit_confirm_summary))
.setTitle(getString(R.string.exit_confirm_title))
.setCancelable(true)
.setPositiveButton(getString(R.string.ok),
new OnClickListener() {
#Override
public void onClick(DialogInterface dialog, int which) {
//...
}
})
.setNegativeButton(getString(R.string.cancel),
new OnClickListener() {
#Override
public void onClick(DialogInterface dialog, int which) {
//...
}
});
AlertDialog dialog = builder.create();
dialog.show();
}
After doing some research I found that it is best to use DialogFragment when using Fragments in your app, so I changed my code to this:
MainActivity.java
#Override
public void onBackPressed() {
AlertDialogFragment adf = new AlertDialogFragment();
adf.setRetainInstance(true);
adf.show(getFragmentManager(), "dialog");
}
AlertDialogFragment.java
public class AlertDialogFragment extends DialogFragment {
public AlertDialogFragment() {}
#Override
public Dialog onCreateDialog(Bundle savedInstanceState) {
return new AlertDialog.Builder(getActivity())
.setCancelable(false)
.setTitle("Alert DialogFragment")
.setMessage("AlertDialogFragment Test")
.setPositiveButton("OK", new DialogInterface.OnClickListener() {
public void onClick(DialogInterface dialog, int which) {
// ...
}
})
.setNegativeButton("Cancel", new DialogInterface.OnClickListener() {
public void onClick(DialogInterface dialog, int which) {
// ...
}
}).create();
}
}
However, the effect is still the same. The dialog should appear when I press the back button, but is only visible after I press the back button and then rotate the device. It also becomes visible after I go home and come back into the app. I've noticed it only happens on a few devices but I'd like to get rid of this problem for good.
Note: this behavior happens for all dialogs in the app, not just this one.
Anyone have any ideas what is going on?

Back Button is Unresponsive after Receiving Object from Other Activity

Let's say my first activity has the following code:
#Override
protected void onActivityResult(int requestCode, int resultCode, Intent data) {
// Check which request we're responding to
if (requestCode == SET_PLAN_REQUEST) {
// Make sure the request was successful
if (resultCode == RESULT_OK) {
fixedPlan = data.getParcelableExtra("fixedPlan");
recreate();
}
}
}
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_crop_rotation_planner);
// Hide the action bar; I don't want to see that hideous thing, yet.
getSupportActionBar().hide();
// Initialize imageLoader
MainActivity.imageLoader = new ImageLoader(getApplicationContext());
restore(savedInstanceState);
}
private void restore(Bundle savedInstanceState) {
// Check if activity has been launched previously
if (savedInstanceState != null) {
// Get saved crop rotation plan
fixedPlan = savedInstanceState.getParcelable("fixedPlan");
// Enable or disable btnViewPlan
checkIfEnoughCropFamilies();
// Set number of crop families
setNumberOfCropFamilies();
// get mSoilTypesList
mSoilTypesList = (ArrayList<String>) savedInstanceState.getStringArrayList("mSoilTypesList");
selectedTypeOfSoil = savedInstanceState.getString("selectedTypeOfSoil");
mPlantList = savedInstanceState.getParcelableArrayList("mPlantList");
// if mSoilTypesList hasn't been acquired, then execute loadSoilTypesFromNet to fetch data
if (mSoilTypesList == null) {
loadSoilTypesFromNet.execute();
}
// else if mSoilTypesList already exists, just display the soil types
else {
// only display if user hasn't selected soil yet
if (selectedTypeOfSoil == null) {
displaySoilTypes();
}
// if user has already selected soil type, then display plants
else {
getPlants();
}
}
}
else {
loadSoilTypesFromNet.execute();
}
}
#Override
public void onSaveInstanceState(Bundle savedInstanceState) {
savedInstanceState.putStringArrayList("mSoilTypesList", mSoilTypesList);
savedInstanceState.putParcelableArrayList("mPlantList", mPlantList);
savedInstanceState.putString("selectedTypeOfSoil", selectedTypeOfSoil);
savedInstanceState.putParcelable("fixedPlan", fixedPlan);
}
#Override
protected void onDestroy() {
dismissAlertDialog();
dismissProgressDialog();
loadPlantsFromNet.cancel(true);
loadSoilTypesFromNet.cancel(true);
super.onDestroy();
}
#Override
public void onBackPressed() {
if (!fixedPlan.isEmpty()) {
AlertDialog.Builder builder = new AlertDialog.Builder(CropRotationPlannerActivity.this);
builder.setTitle(R.string.str_dbox_exit_crp_title);
builder.setMessage(R.string.str_dbox_exit_crp_message);
builder.setPositiveButton(R.string.str_dbox_exit_crp_ok, new DialogInterface.OnClickListener() {
#Override
public void onClick(DialogInterface dialog, int which) {
finish();
CropRotationPlannerActivity.super.onBackPressed();
}
});
builder.setNegativeButton(R.string.str_dbox_exit_crp_cancel, new DialogInterface.OnClickListener() {
#Override
public void onClick(DialogInterface dialog, int which) {
dialog.dismiss();
}
});
alert = builder.create();
alert.setCanceledOnTouchOutside(false);
alert.setCancelable(false);
alert.show();
}
else
super.onBackPressed();
}
And my proceeding activity has the following important code:
// We'll be sending our fixedPlan back to previous activity (CropRotationPlannerActivity)
#Override
public void onBackPressed() {
// TODO :: THINK OF THE SAVE FEATURE
final Intent intent = new Intent();
AlertDialog.Builder builder = new AlertDialog.Builder(this);
builder.setTitle(R.string.str_dbox_exit_title);
builder.setMessage(R.string.str_dbox_exit_message);
builder.setPositiveButton(R.string.str_dbox_exit_yes, new DialogInterface.OnClickListener() {
#Override
public void onClick(DialogInterface dialog, int which) {
intent.putExtra("fixedPlan", fixedPlan);
setResult(RESULT_OK, intent);
// TODO : Somewhat buggy code here?
// TODO : Takes quite sometime to process :/
finish();
PlanActivity.super.onBackPressed();
}
});
builder.setNegativeButton(R.string.str_dbox_exit_no, new DialogInterface.OnClickListener() {
#Override
public void onClick(DialogInterface dialog, int which) {
setResult(RESULT_CANCELED, intent);
dialog.dismiss();
finish();
PlanActivity.super.onBackPressed();
}
});
builder.setNeutralButton(R.string.str_dbox_exit_cancel, new DialogInterface.OnClickListener() {
#Override
public void onClick(DialogInterface dialog, int which) {
dialog.dismiss();
}
});
builder.setCancelable(false); // so as to prevent the back button from closing the dialog box
alert = builder.create();
alert.setCanceledOnTouchOutside(false); // prevents user from canceling dialog box by clicking outside
alert.show();
}
When the user exits the first activity and the Object fixedPlan doesn't have any contents, I want the user to exit to the main menu. When it doesn't have any contents, I want to pop a DialogBox so that the user is aware that the current activity contains important info and ask the user one more time if he really wants to exit.
To get to the next activity, fixedPlan should not be empty. And getting out from that activity, fixedPlan is never empty, too. But why does the back button not respond once the user goes back to the previous activity? What should I do?
NOTE THAT THIS ONLY HAPPENS WHEN positive button is pressed ( in the second activity). Another thing is that once I have pressed the positive button on the second activity, and the moment I'm in the first activity, and then I go back there and press the negative button, the back button works. It's really an issue with the positive button. BTW, I can feel the back button's vibration when pressed. LOL. Just that. It doesn't respond.
Adding finish() does not work either (to the else statement in my onBackPressed method for the first activity).
Try changing adding dialog.dismiss() before finish() in Positive button click event inside the second activity?
Also, I believe you should remove the calls to PlanActivity.super.onBackPressed();, both under positive and negative buttons click.

Categories

Resources