How to use EditTextPreference as a masked Password text field?
Asked Answered
E

6

49

I have a very simple question:
I have a EditTextPreference dialog which I want to use for getting the user's password and I want it to be masked.

How can I do that?

Exempt answered 28/5, 2011 at 21:24 Comment(0)
B
116

Here is a short example using xml:

<EditTextPreference
    android:key="@string/key"
    android:title="@string/title"
    android:summary="@string/summary"   
    android:inputType="textPassword" />

Or you can use numberPassword instead of textPassword.

Braasch answered 28/5, 2011 at 21:32 Comment(5)
Excellent! i knew it shoult be simple but i didn't expect it to be that simple...Exempt
I need a similar option, but instead of a single edit text i need 3 edit text in my dialog preference. One for old password, new password and confirm password. Can you give me a sample of how to do this. Tha android sample apidemo has only one edit text preference in a dialog. I do not know whow to change this to fit 3 in a same dialog.Bithynia
You should create custom Preference that extends DialogPreference with custom Dialog.Braasch
but when orientation changes to landscape edittext is displayed on full screen and password is not shown as hidden :(Runnels
But how is it possible to store password or password hash securely? The code android:key="@string/key" stores it as plain text.Perdita
H
6

For androidx library you should do it programmatically for example you could do it as follows, optionally I am setting the summary with asterisks according to the length of password:

[...]
import android.os.Bundle;
import android.text.InputType;
import android.widget.EditText;

import androidx.annotation.NonNull;

import androidx.preference.EditTextPreference;
import androidx.preference.Preference;
import androidx.preference.PreferenceFragmentCompat;
import androidx.preference.PreferenceManager;

import static androidx.preference.EditTextPreference.*;

public class MySettingsFragment extends PreferenceFragmentCompat {
    @Override
    public void onCreatePreferences(Bundle savedInstanceState, String rootKey) {
        setPreferencesFromResource(R.xml.preferences, rootKey);

        final EditTextPreference preference = findPreference("password");

        if (preference != null) {
            preference.setSummaryProvider(new SummaryProvider() {
                @Override
                public CharSequence provideSummary(Preference preference) {

                    String getPassword = PreferenceManager.getDefaultSharedPreferences(getContext()).getString("password", "not set");

                    //we assume getPassword is not null
                    assert getPassword != null;

                    //return "not set" else return password with asterisks
                    if (getPassword.equals("not set")) {
                        return getPassword;
                    } else {
                        return (setAsterisks(getPassword.length()));
                    }
                }
            });

            //set input type as password and set summary with asterisks the new password
            preference.setOnBindEditTextListener(
                    new OnBindEditTextListener() {
                        @Override
                        public void onBindEditText(@NonNull final EditText editText) {
                            editText.setInputType(InputType.TYPE_CLASS_TEXT | InputType.TYPE_TEXT_VARIATION_PASSWORD);
                            preference.setSummaryProvider(new SummaryProvider() {
                                @Override
                                public CharSequence provideSummary(Preference preference) {
                                    return setAsterisks(editText.getText().toString().length());
                                }
                            });
                        }
                    });
        }
    }

    //return the password in asterisks
    private String setAsterisks(int length) {
        StringBuilder sb = new StringBuilder();
        for (int s = 0; s < length; s++) {
            sb.append("*");
        }
        return sb.toString();
    }
}

In xml you should have something like:

<EditTextPreference
    android:dialogMessage="Enter your password"
    android:dialogTitle="Password"
    android:key="password"
    android:title="Password" />

For more info please look at developer.android

Haws answered 27/11, 2019 at 14:16 Comment(2)
How do I get the text when clicking "ok"?Dambro
Works nice. I've created gist with common code separated to external file: gist.github.com/mjfryc/3cb8518e19794dd9ba894eef3daca1d6Olivo
M
4

android:inputType="numberPassword" doesn't work for me. Eclipse told me, that no String values are allowed for this attribute. So i used following:

<EditTextPreference
    android:key="@string/key"
    android:title="@string/title"
    android:summary="@string/summary"   
    android:inputType="number"
    android:password="true" />

This got me a EditTextPreference with a dotted textdisplay and a number keyboard for input.

Mev answered 9/1, 2013 at 13:33 Comment(0)
T
2

For AndroidX Preferences, do:

password.setOnBindEditTextListener(editText -> {
    editText.setInputType(InputType.TYPE_CLASS_TEXT | InputType.TYPE_TEXT_VARIATION_PASSWORD);
});

The inputType XML attribute isn't used on androidx.

Tetanus answered 26/9, 2021 at 11:15 Comment(1)
This will change only the preference "dialog" to edit the value. The preference summary will remain visibile with the value in plain text. To customize the preference summary have a look here developer.android.com/guide/topics/ui/settings/…Afterworld
L
1

You can do it with the code below. HOWEVER, I still haven't figured out how to do the PASSWORD_TOGGLE thing. Doesn't work by just defining app:endIconMode="password_toggle" Can someone help with that?

The ANSWER: The "EditTextPreference" field "db_pwd" has the following defined:

android:inputType="textPassword"

The latest Kotlin rev code:

class SettingsFragment : PreferenceFragmentCompat() {
override fun onCreatePreferences(savedInstanceState: Bundle?, rootKey: String?) {
    setPreferencesFromResource(com.unified.helloworld.R.xml.my_preferences, rootKey)
    val pwdPref =
        findPreference<EditTextPreference>("db_pwd")
    if (pwdPref != null) {
        pwdPref.summaryProvider = SummaryProvider<Preference?> {
            val getPassword: String =
                PreferenceManager.getDefaultSharedPreferences(context)
                    .getString("db_pwd", "Not set")!!

            // Return "Not set" else return password with asterisks
            if (getPassword == "Not set") {
                getPassword } else { setAsterisks(getPassword.length) }
        }

        // Set type as password and set summary with asterisks
        pwdPref.setOnBindEditTextListener(
            OnBindEditTextListener { editText ->
                editText.inputType =
                    InputType.TYPE_CLASS_TEXT or InputType.TYPE_TEXT_VARIATION_PASSWORD
                pwdPref.summaryProvider = SummaryProvider<Preference> { setAsterisks(editText.text.toString().length) }
            })
    }
}

// Return the password in asterisks
private fun setAsterisks(length: Int): String {
    val sb = java.lang.StringBuilder()
    for (s in 0 until length) {
        sb.append("*") }
    return sb.toString() }
}
Logjam answered 23/6, 2020 at 17:46 Comment(0)
P
0

If you want that the password mask persist also after device rotation is suffice to add the following imeOption:

in the edit text layout android:imeOptions="flagNoExtractUi"

or programmatically yourEditText.setImeOptions(EditorInfo.IME_FLAG_NO_EXTRACT_UI);

Paleolithic answered 26/6, 2017 at 13:39 Comment(3)
And how is it possible to access the edit text layout from EditTextPreference?Perdita
Take a look at the EditTextPreference documentation: linkAlica
Cannot resolve method 'setImeOptions' in 'EditTextPreference'!Dambro

© 2022 - 2024 — McMap. All rights reserved.