Secure Text Entry es un modo de entrada de texto en Android donde los caracteres ingresados se muestran de forma oculta (puntos o asteriscos) en lugar de los caracteres reales. Este modo se usa para campos de contraseñas, códigos PIN, códigos CVV y otra información confidencial. Secure Text Entry no solo protege los datos contra la interceptación visual, sino que también evita filtraciones a través de capturas de pantalla, grabaciones de pantalla y funciones de autocorrección. Según Android Security Best Practices (2026), la entrada oculta es un requisito obligatorio para las aplicaciones que manejan datos de autenticación de usuarios.
Conclusiones clave
Secure Text Entry (entrada de texto protegida) es una función de Android que reemplaza la visualización de cada carácter ingresado con un carácter de enmascaramiento, generalmente un punto (•) o un asterisco (*). Esto evita la lectura de contraseñas por encima del hombro (shoulder surfing) y oculta los datos ingresados de miradas indiscretas. Esta función también se conoce como enmascaramiento de contraseñas y es una práctica estándar en aplicaciones móviles.
A diferencia de iOS, donde Secure Text Entry es una configuración separada de UITextField, en Android esta función se activa mediante el atributo inputType con la variación PASSWORD. Cuando un EditText recibe inputType="textPassword", aplica automáticamente PasswordTransformationMethod — una clase responsable del reemplazo de caracteres. Al ingresar cada nuevo carácter, EditText lo reemplaza instantáneamente con un carácter de enmascaramiento a través del mecanismo de la interfaz TransformationMethod.
Según Android Source Code (AOSP, 2026), la implementación de PasswordTransformationMethod utiliza la clase TextPaint para dibujar los caracteres de enmascaramiento. El tamaño del carácter de enmascaramiento coincide con el tamaño de fuente del campo, lo que evita la filtración de información a través de la longitud de la palabra — todos los caracteres se ven idénticos en ancho. Esto es importante para la protección contra ataques basados en el análisis de la longitud de los datos ingresados.
<!-- Basic Secure Text Entry example -->
@+id/etPassword
android:layout_width="match_parent"
android:hint="Enter password"
android:inputType="textPassword"
android:maxLength="64"
android:importantForAutofill="yes" />
El mecanismo de Secure Text Entry en Android se basa en la interfaz TransformationMethod, definida en el paquete android.text.method. PasswordTransformationMethod es una implementación integrada que sobrescribe el método getTransformation(), devolviendo una secuencia de caracteres reemplazada para su visualización. El texto original en Editable permanece sin cambios — solo se altera su representación visual.
Cuando un usuario ingresa un carácter, EditText llama a dispatchEvent y pasa el carácter a InputConnection, que lo agrega a Editable. Luego EditText llama al método getTransformation() del TransformationMethod actual, que toma el CharSequence original y devuelve un SpannableString con caracteres de enmascaramiento. Este SpannableString se renderiza en pantalla en lugar del texto original. La característica clave es que la transformación en sí no cambia el contenido de Editable, por lo que llamar a getText().toString() devuelve el texto real ingresado.
Según Android Developers Reference (2026), PasswordTransformationMethod agrega un MetricAffectingSpan a cada carácter, que reemplaza el glifo con un punto. Estos spans no afectan la longitud del texto, por lo que el cursor y la posición de entrada se conservan correctamente incluso con visualización oculta. También existe VisiblePasswordTransformationMethod, que muestra el último carácter ingresado por un breve tiempo (similar a iOS).
// PasswordTransformationMethod - built-in masking
editText.transformationMethod = PasswordTransformationMethod.getInstance()
// VisiblePasswordTransformationMethod - shows last char
editText.transformationMethod = VisiblePasswordTransformationMethod.getInstance()
Alternancia de visibilidad (password visibility toggle) es una función que permite al usuario mostrar temporalmente la contraseña ingresada para verificarla antes de enviar el formulario. En Android, esta función se implementa mediante TextInputLayout con el atributo app:endIconMode="password_toggle". Al tocar el ícono del ojo, el campo cambia entre textPassword y textVisiblePassword.
La implementación de password_toggle en TextInputLayout cambia automáticamente el inputType del EditText interno y anima el ícono (ojo abierto/cerrado). Es importante recordar que durante este cambio la posición del cursor puede restablecerse, por lo que TextInputLayout guarda y restaura la posición después del cambio de modo. Además, al cambiar a contraseña visible, la autocorrección y las sugerencias no se activan — se usa TYPE_TEXT_VARIATION_VISIBLE_PASSWORD, no texto normal.
Según Material Design Guidelines (2025), el ícono de mostrar contraseña debe estar siempre visible, no solo cuando el campo está en foco. El usuario debe poder verificar la contraseña en cualquier momento. El ícono no debe ocultar automáticamente la contraseña después de un tiempo — solo mediante acción del usuario.
<!-- TextInputLayout with password toggle -->
@+id/tilPassword
android:layout_width="match_parent"
app:endIconMode="password_toggle"
app:passwordToggleTint="@color/primary">
@+id/etPassword
android:inputType="textPassword"
android:hint="Password" />
</com.google.android.material.textfield.TextInputLayout>
La configuración programática de Secure Text Entry en Kotlin se realiza estableciendo inputType o mediante setTransformationMethod(). Ambos enfoques llevan al mismo resultado pero difieren en detalles. Establecer inputType además configura la autocorrección y las sugerencias, mientras que setTransformationMethod solo afecta la visualización de caracteres.
// Programmatic password visibility toggle
fun togglePasswordVisibility(til: TextInputLayout) {
val editText = til.editText ?: return
val currentType = editText.inputType
val isPassword = (currentType and
InputType.TYPE_TEXT_VARIATION_PASSWORD) != 0
if (isPassword) {
editText.inputType = InputType.TYPE_CLASS_TEXT or
InputType.TYPE_TEXT_VARIATION_VISIBLE_PASSWORD
} else {
editText.inputType = InputType.TYPE_CLASS_TEXT or
InputType.TYPE_TEXT_VARIATION_PASSWORD
}
// Restore cursor position
val cursorPos = editText.selectionStart
editText.setSelection(maxOf(0, cursorPos))
}
// Custom masking — shows only last 4 chars
class PartialPasswordTransformation : TransformationMethod {
override fun getTransformation(source: CharSequence?,
view: View?): CharSequence {
val text = source?.toString() ?: ""
if (text.length <= 4) return text
val dots = "\u2022".repeat(text.length - 4)
return dots + text.substring(text.length - 4)
}
override fun onFocusChanged(view: View?,
sourceText: CharSequence?,
focused: Boolean,
direction: Int,
previouslyFocusedRect: android.graphics.Rect?) {}
}
Secure Text Entry proporciona protección en múltiples niveles. El enmascaramiento visual evita la lectura de contraseñas por encima del hombro (shoulder surfing) — el método más común de robo de contraseñas en lugares públicos. La desactivación de la autocorrección evita que la contraseña se guarde en el diccionario del usuario, eliminando la filtración a través de la entrada predictiva. La protección contra capturas de pantalla (si FLAG_SECURE está habilitado) impide que otras aplicaciones capturen el contenido del campo.
Sin embargo, Secure Text Entry no es una protección completa. Los ataques a través de la interceptación de entrada (keylogging) a nivel del sistema pueden obtener caracteres reales de InputConnection. Las aplicaciones maliciosas con servicios de accesibilidad pueden leer el contenido de EditText incluso si los caracteres están ocultos en pantalla. Además, la interceptación SSL durante la transmisión de datos al servidor puede exponer la contraseña si no se usa HTTPS con validación adecuada de certificados.
Según OWASP Mobile Security Testing Guide (2025), para la máxima protección de contraseñas en Android se recomienda: usar inputType="textPassword" + desactivar autofill para campos críticos; no almacenar en caché la contraseña en memoria más tiempo del necesario; limpiar el campo de contraseña al minimizar la aplicación (onPause/onStop); usar enmascaramiento incluso durante la visualización breve de la contraseña.
| Nivel de protección | Secure Text Entry | Medidas adicionales |
|---|---|---|
| Interceptación visual | Enmascaramiento de caracteres | Autenticación biométrica, evitar shoulder surfing |
| Capturas de pantalla | Parcial (depende de la implementación) | FLAG_SECURE en Window |
| Keylogging | No protege | Usar IME con entrada segura |
| Autocorrección/diccionario | Desactivada | desactivada por defecto para password |
| Interceptación de red | No protege | HTTPS con certificate pinning |
Los desarrolladores de Android deben seguir varias prácticas clave al trabajar con entrada oculta. Primero, usa siempre TextInputLayout con endIconMode="password_toggle" para campos de contraseña — este es el estándar moderno de Material Design. Segundo, no deshabilites la capacidad de mostrar la contraseña — el usuario debe poder verificar lo que ingresó, especialmente en dispositivos móviles con teclados pequeños.
Secure Text Entry también requiere una configuración adecuada de autocompletado. Para campos de contraseña, especifica siempre autofillHints="password" o autofillHints="newPassword" para que los administradores de contraseñas puedan completar y guardar datos correctamente. Para el campo de confirmación de nueva contraseña, usa autofillHints="newPassword" para que el sistema no sugiera completarlo con la contraseña guardada actual.
// Full password field with autofill and cleanup
class SecurePasswordField {
private fun setupPasswordField(til: TextInputLayout) {
val editText = til.editText ?: return
editText.inputType = InputType.TYPE_CLASS_TEXT or
InputType.TYPE_TEXT_VARIATION_PASSWORD
editText.setAutofillHints(View.AUTOFILL_HINT_PASSWORD>)
editText.importantForAutofill = View.IMPORTANT_FOR_AUTOFILL_YES
}
fun clearOnPause(editText: EditText) {
editText.text?.clear()
}
}
Preguntas frecuentes
textPassword oculta todos los caracteres ingresados y desactiva la autocorrección. textVisiblePassword también desactiva la autocorrección pero muestra los caracteres en texto plano. textVisiblePassword se usa al alternar la visibilidad de la contraseña — no es texto normal, ya que la autocorrección y las sugerencias permanecen desactivadas por seguridad.
Sí, crea una clase personalizada que implemente la interfaz TransformationMethod. Sobrescribe el método getTransformation() devolviendo un CharSequence con el carácter de reemplazo deseado. Establécelo mediante editText.transformationMethod = CustomPasswordTransformation(). Recuerda que el carácter debe ser monoespaciado por seguridad.
En dispositivos móviles con pantallas pequeñas y teclados táctiles, la probabilidad de error al ingresar una contraseña es significativamente mayor que en un escritorio. La capacidad de verificar la contraseña ingresada reduce los errores de entrada y disminuye el número de solicitudes de restablecimiento de contraseña, lo que mejora la experiencia del usuario y reduce la carga de soporte.
Establece la bandera FLAG_SECURE en la ventana de Activity o Dialog: window.setFlags(WindowManager.LayoutParams.FLAG_SECURE, WindowManager.LayoutParams.FLAG_SECURE). Esto evita capturas de pantalla y grabación de pantalla para toda la ventana. Sin embargo, ten en cuenta que esto también deshabilitará las capturas de pantalla para contenido normal, lo que puede ser no deseado.
A partir de Android 8.0 (API 26), el framework Autofill detecta automáticamente los campos de contraseña por inputType. Para un funcionamiento correcto, establece importantForAutofill="yes" y especifica autofillHints ("password", "newPassword", "emailAddress"). Gboard y los administradores de contraseñas usan estos atributos para sugerir contraseñas guardadas.
Resumen
Desarrollaremos una aplicación móvil llave en mano
IT Sectr crea aplicaciones para iOS y Android para startups y empresas desde 2017. Le asesoraremos y le propondremos la mejor solución.
Lea también