In my app i have a function that checks the entered text from a displayed AlertDialog with an input text. If the text is equal to a string variable, return True, else return False, and catch this resulting value to continue conditional code.
But it seems its a little difficult to do this as i've read in other posts asking how to solve the same problem.
I've already done this:
private boolean checkAdministratorPassword() {
final enterPasswordResult[0] = false;
AlertDialog.Builder alert = new AlertDialog.Builder(mContext);
alert.setTitle("Confirm action");
alert.setIcon(R.drawable.ic_launcher);
alert.setMessage("Enter administrator pass to continue");
final EditText input = new EditText(mContext);
input.setPadding(5, 0, 5, 0);
alert.setView(input);
alert.setPositiveButton("Accept", new DialogInterface.OnClickListener() {
public void onClick(DialogInterface dialog, int whichButton) {
String strPass = input.getEditableText().toString();
if (strPass.length() == 0) {
dialog.cancel();
}
if (strPass.equalsIgnoreCase(Constantes.ADMIN_PASS)) {
enterPasswordResult[0] = true;
dialog.cancel();
} else {
Toast.makeText(mContext, "Invalid pass..!!", Toast.LENGTH_LONG).show();
dialog.cancel();
}
}
});
alert.setNegativeButton("Cancel", new DialogInterface.OnClickListener() {
public void onClick(DialogInterface dialog, int whichButton) {
dialog.cancel();
}
});
AlertDialog alertDialog = alert.create();
alertDialog.show();
return enterPasswordResult[0];
}
And i call the function this way:
If ( checkAdministratorPassword() == True ){
//true conditions
}
But the problem is that the check function doesnt wait for the result to continue with the code, it just continue by itself and i dont get the appropiate behavior.
The issue is you're trying to handle an async event in the logcal flow of your program. You can do this if you make the Dialog it's own class and use an Interface to callback to your host activity. Check out the documentation on DialogFragment.
public interface PasswordCheckListener{
public void valid(boolean check);
}
private static class PasswordDialog extends DialogFragment {
private PasswordCheckListener listener;
public static PaswordDialog newInstance(PasswordCheckListener listener){
this.listener = listener;
}
#Override
public Dialog onCreateDialog(Bundle savedInstanceState) {
//Put your dialog creation code here
}
private checkAdminPassword(){
//Whatever your check passowrd code is
listener.valid(result);
}
}
I realize I didn't implement all the code for you but that's the general idea. By using an interface you can call back to your host Activity or Fragment when the user enters the password and presses submit. You can then handle the event as it happens, rather than having to deal with it in your program flow.
Thank you all for your answers!! i've found the right way to achieve this problem by creating an Activity whith theme "Theme.Dialog", an input text and two buttons (Accept, Cancel), i start this activity for result asking the user to enter the administrator pass to continue, checking the string and then returning again to onActivityResult() from previous activity with the correct information to proceed.
Related
I have a code written where a user has to answer a question true or false. What I want to do is everytime when a user answers correctly I add +1 to my arraylist. And then at the end of the game I display the number of answered questions. I tried to do it my way, however I get an error.
Here is how I create my list:
final ArrayList<Integer> points = new ArrayList<Integer>();
This is the button if the user presses True(For better understanding: When a user presses true a pop up window opens with the answer correct or false and the correct answer of the question. When the user clicks on the closepopup button an if method runs and checks if he pressed the right button and if its not the last question. If not, it shows the next question and adds the +1 to the list):
mYes.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
initiatePopupWindow();
if(type.get(count[0])){
((TextView)pwindo.getContentView().findViewById(R.id.popupTekstasTiesaArNe)).setText("Correct!");
} else {
((TextView)pwindo.getContentView().findViewById(R.id.popupTekstasTiesaArNe)).setText("False!");
}
//Show the first answer on first button click.
((TextView)pwindo.getContentView().findViewById(R.id.popupTekstas)).setText(questions.get((count[0]) % questions.size()).answer);
// When PopUp button closes open the next question with the if/else conditions.
btnClosePopup.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
//if the question is true show next question/ else close app
if (type.get(count[0])) {
points.add(1); // if the answer is correct add +1 to the list.
if(questions.size()-1 == count[0]) // if you count[0] is init to 0
{
AlertDialog.Builder builder = new AlertDialog.Builder(MainActivity.this);
builder.setTitle("WInner");
builder.setMessage("You won, play again?");
builder.setCancelable(false);
builder.setPositiveButton(android.R.string.yes,
new DialogInterface.OnClickListener() {
public void onClick(DialogInterface dialog, int id) {
// just close dialog
dialog.cancel();
}
});
builder.setNegativeButton(android.R.string.no,
new DialogInterface.OnClickListener() {
public void onClick(DialogInterface dialog, int id) {
finish();
mResult.setText(points.size());// here I try to print the number of answered questions.
}
});
// Create dialog from builder
AlertDialog alert = builder.create();
// Show dialog
alert.show();
count[0]=0;
}
else if(questions.size()-1 < count[0])
try {
throw new Exception("Invalid ");
} catch (Exception e) {
e.printStackTrace();
}
else
count[0]++;
mQuestion.setText(questions.get(count[0]).question); // you dont need calculate the module anymore
pwindo.dismiss();
} else {
count[0]++;
mQuestion.setText(questions.get(count[0]).question); // you dont need calculate the module anymore
pwindo.dismiss();
}
}
});
}
});
EDITED!!!
I figured out why SetText shows a blank textview. I want to show the answered question count in activity before the questions. I have a menuActivity>LevelselectActivity>GameActivity. In game activity I add to the list values. How to post them in LevelselectActivity? Should I use shared preferences? I have no idea now..
I have a language setting in my android app. I save the current language into SharedPreferences and I have a onSharedPreferencesChanged that restarts all activites in the stack so they can be shown in the correct language.
This works like a charm but the language setting is being shown into a Dialog, so when I click on the language I want to change it to, shared preferences changes and then I get a Leaked Window error.
public void showDialog(View v) {
final CharSequence[] items = { res.getString(R.string.english),
res.getString(R.string.spanish) };
AlertDialog.Builder builder = new AlertDialog.Builder(this);
builder.setTitle(res.getString(R.string.change_language));
builder.setSingleChoiceItems(items, selected,
new DialogInterface.OnClickListener() {
#Override
public void onClick(DialogInterface dialog, int item) {
switch (item) {
case 0: // English
if (selected == 0) {
Toast.makeText(
SettingsActivity.this,
res.getString(R.string.current_language),
Toast.LENGTH_LONG).show();
break;
}
changeLocale("en");
break;
case 1: // Spanish
if (selected == 1) {
Toast.makeText(
SettingsActivity.this,
res.getString(R.string.current_language),
Toast.LENGTH_LONG).show();
break;
}
changeLocale("es");
break;
}
alert.dismiss();
}
});
alert = builder.create();
builder.show();
}
#Override
public void onSharedPreferenceChanged(SharedPreferences sharedPreferences,
String key) {
if (key.equals("language")) {
restartActivity();
}
}
This method is in the parent activity of all of my activities:
public void restartActivity() {
Intent intent = getIntent();
finish();
startActivity(intent);
}
Im getting a leaked window in the line builder.show() because I'm restarting all the activities when the shared preferences change. How can I show the dialog and restart my activities without getting this error?
Thanks in advance
Explaining Abdallah's answer try to move dismiss() up as the first statement in your onClick callback method.
EDIT: First of all after you call alert = builder.create(); you should call alert.show() and not builder.show(). Furthermore having the modifications mentioned in comments you should not receive the error no more.
Your code is trying to show a Dialog after exiting the Activity.
To prevent this, you should dismiss() your Dialog before restarting Activities.
The title might not be very clear, its kind of hard to explain in a short title. But here is the problem.
I have an activity, MainActivity which then shows an activity at start to show FragmentA. In MainActivity there is a menu that is shown which is accessible via FragmentA. From the menu in FragmentA the user clicks on Generate Password which then calls another activity called GeneratePassword called using startActivityForResult. When the user presses the submit button the user is then sent back to FragmentA and the function onActivityResult within the MainActivity. Within this function, I then make use of a common class which allows me to show an AlertDialog with Yes and No Buttons. OnActivityResult works fine if I take out the common.showYesNoDialog() if statement, but when this is being used I get an exception
android.view.WindowManager$BadTokenException: Unable to add window -- token null is not for an application
Below is the code that starts the GeneratePassword Activity
Intent generatePasswrodIntent = new Intent(mMainActivity, GeneratePassword.class);
startActivityForResult(generatePasswrodIntent, AddNewLogin.GENERATE_PASSWORD);
return(true);
Below is the code that sets the result from the GeneratePassword activity
Intent intent = new Intent();
Bundle bundle = new Bundle();
bundle.putString("password", generatePassword.generatePassword());
intent.putExtras(bundle);
setResult(AddNewLogin.GENERATE_PASSWORD, intent);
finish();
Below is the code from the onActivityResult that shows the alert dialog
Bundle bundle = data.getExtras();
String password = bundle.getString("password");
Log.d("PASSWORD", password);
if (common.showYesNoDialog("Your Generated Password Is:\n " + password + "\nDo you want to copy this to the clipboard?", false))
{
ClipboardManager clipboard = (ClipboardManager)getSystemService(CLIPBOARD_SERVICE);
clipboard.setText(password);
}
Below is the YesNoDialog function, but I know this works fine as I have used it in several places within my app without problem.
final Handler handler = new Handler()
{
#Override
public void handleMessage(Message mesg)
{
throw new RuntimeException();
}
};
AlertDialog.Builder builder = new AlertDialog.Builder(context);
builder.setCancelable(isCancelable);
builder.setMessage(message)
.setPositiveButton("Yes", new DialogInterface.OnClickListener() {
public void onClick(DialogInterface dialog, int which) {
dialogResult = true;
handler.sendMessage(handler.obtainMessage());
}
})
.setNegativeButton("No", new DialogInterface.OnClickListener() {
public void onClick(DialogInterface dialog, int which) {
dialogResult = false;
handler.sendMessage(handler.obtainMessage());
}
});
AlertDialog alert = builder.create();
alert.show();
try
{
Looper.loop();
}
catch (RuntimeException ex)
{
Log.d("Dialog Error", ex.toString());
}
return dialogResult;
And below is how I am initialising the common class
Common common = new Common(getApplicationContext());
Instead of getApplicationContext, I've tried using this but doesn't make any difference.
I just don't understand what is happening here.
Thanks for any help you can provide
The problem is in your showYesNoDialog(). What does the boolean parameter for your showYesNoDialog() method do?
I have an activity (Main) and I inserted a button in it.
When button the user press it, a dialog box with 2 Radio boxes appear. I want to set "1" or "0" value to "ntv", based on which radiobutton is selected, and then use "ntv" value in Main activity, but it seems that this doesnot transfer "ntv" value to Main activity, what is wrong with my code?
final CharSequence[] chan = {"Minutes", "Seconds"};
builder = new AlertDialog.Builder(Main.this);
builder.setTitle("Please Select:");
builder.setSingleChoiceItems(chan, 0, new DialogInterface.OnClickListener() {
public void onClick(DialogInterface dialog, int item) {
if(chan[item]=="Minutes")
{
Toast.makeText(getApplicationContext(), "Minutes", Toast.LENGTH_SHORT).show();
ntv="1";
}
else if (chan[item]=="Seconds")
{
Toast.makeText(getApplicationContext(), "Seconds", Toast.LENGTH_SHORT).show();
ntv="0";
}
}
});
AlertDialog alert = builder.create();
alert.show();
I defined "ntv" as string and this is part of code when "ntv" is compared to check if it is "0" or "1"
ImageView set1= (ImageView) findViewById(R.id.set1);
ImageView set2= (ImageView) findViewById(R.id.set2);
if (ntv.equals("0")) {
set1.setVisibility(View.INVISIBLE);
}
if (ntv.equals("1")) {
set2.setVisibility(View.INVISIBLE);
}
and because neither (set1) nor (set2) doesnot go invisible I realize that "ntv" have no value.
This all looks OK (except the suggestion to use equals() instead of == for the string compares, although, as you say, it does work (it just isn't good practice).
The only thing I can think of (without seeing all the code) is that the scope of variable ntv is wrong. Have you declared the variable inside a method? It needs to be defined as an instance variable in your class (ie: not within a method).
you should be doing .equals on the string comparison NOT ==
It is unlikely that your if statements will trigger because of this.
if(chan[item].equals("Minutes"))
{
Toast.makeText(getApplicationContext(), "Minutes", Toast.LENGTH_SHORT).show();
ntv="1";
}
else if (chan[item].equals("Seconds"))
{
Toast.makeText(getApplicationContext(), "Seconds", Toast.LENGTH_SHORT).show();
ntv="0";
}
it's not clear the complete code you use and how you call the code that change visibility. Below an example
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
AlertDialog.Builder builder;
final CharSequence[] chan = {"Minutes", "Seconds"};
builder = new AlertDialog.Builder(MainActivity.this);
builder.setTitle("Please Select:");
builder.setSingleChoiceItems(chan, 0, new DialogInterface.OnClickListener() {
public void onClick(DialogInterface dialog, int item) {
if(chan[item].equals("Minutes")) {
showToast("Minutes");
} else if (chan[item].equals("Seconds")) {
showToast("Seconds");
}
}
});
AlertDialog alert = builder.create();
alert.show();
}
private void showToast(String s){
Toast.makeText(getApplicationContext(), s, Toast.LENGTH_SHORT).show();
}
instead of showToast function you can use a your function to change visibility
I am working on an android project where I am trying to show a AlertDialog in a separate normal java class and return the result that the user enters. I can display the dialog fine but the problem I am having is it always returns the value before the dialog has had one of the buttons pressed.
Below is the code that calls the function in the standard java class to show the dialog
private void showDiagreeError()
{
Common common = new Common(this);
boolean dialogResult = common.showYesNoDialog();
Toast.makeText(getApplicationContext(), "Result: " + dialogResult, Toast.LENGTH_LONG).show();
}
And below is the code that shows the actual dialogue
public boolean showYesNoDialog()
{
AlertDialog.Builder builder = new AlertDialog.Builder(context);
builder.setMessage("Are you sure you do not want to agree to the terms, if you choose not to, you cannot use Boardies Password Manager")
.setCancelable(false)
.setPositiveButton("Yes", new DialogInterface.OnClickListener() {
public void onClick(DialogInterface dialog, int which) {
dialogResult = true;
}
})
.setNegativeButton("No", new DialogInterface.OnClickListener() {
public void onClick(DialogInterface dialog, int which) {
dialogResult = false;
}
});
AlertDialog alert = builder.create();
alert.show();
return dialogResult;
}
dialogResult is a global variable visible throughout the class and being set to false. As soon as the dialog is shown the toast message is shown showing the result is false, but I was expecting the return statement to block until the user has pressed one of the buttons too set the variable to the correct value.
How can I get this to work.
After many hours hunting through the inner depths of google pages, I found this Dialogs / AlertDialogs: How to "block execution" while dialog is up (.NET-style).
It does exactly the job I was after and tested to make sure there are no ANR errors, which there isn't