I am getting many crash related to password visibility. One more strange is its crashing on some devices not all.
I have testing in Nokia 5, Samsung note 4 and s7, Honor 5C and 9, Redmi Note 4 and 4, Moto E and G play and moto M all working fine.
JavaCode
EditText loEtPassword = (EditText) findViewById(R.id.etPassword);
loEtPassword.setTransformationMethod(new PasswordTransformationMethod()); // Java internal class.
loEtPassword.setOnEditorActionListener(new DoneOnEditorActionListener(loBtnLogin)); // custom class.
Validation
public static class LoginUser {
public String lsEmail, lsPassword, lsIMEINumber, lsJsonParameter;
}
LoginUser loLoginUser = new LoginUser();
loLoginUser.lsEmail = loEtEmail.getText().toString().trim();
loLoginUser.lsPassword = loEtPassword.getText().toString();
if (validate(loLoginUser)) {
//cont...
}
private boolean validate(LoginUser foLoginUser) {
final EditText loEtPassword = (EditText) findViewById(R.id.etPassword);
boolean lbIsValid = true;
if (foLoginUser.lsPassword.length() <= 0) {
loEtPassword.setError("Please enter Password");
loEtPassword.requestFocus();
lbIsValid = false;
}
return lbIsValid;
}
XML file
<android.support.design.widget.TextInputLayout
android:id="@+id/ilPassword"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:textColorHint="@color/textColorGray"
app:hintEnabled="false"
app:passwordToggleEnabled="true"
app:passwordToggleTint="@color/textColorGray">
<EditText
android:id="@+id/etPassword"
style="@style/editTextStyle"
android:layout_marginBottom="@dimen/MarginBetweenView"
android:backgroundTint="@color/textColorGray"
android:drawableLeft="@drawable/ic_password"
android:drawableStart="@drawable/ic_password"
android:drawablePadding="@dimen/MarginBetweenInnerView"
android:hint="@string/HINT_PASSWORD"
android:imeOptions="actionDone"
android:inputType="textEmailAddress" />
</android.support.design.widget.TextInputLayout>
Design
Gradle
apply plugin: 'com.android.application'
apply plugin: 'io.fabric'
android {
compileSdkVersion 27
buildToolsVersion "27.0.3"
defaultConfig {
applicationId "com.packageName"
minSdkVersion 14
targetSdkVersion 25
multiDexEnabled true
versionName '7.2'
versionCode 96
}
dexOptions {
javaMaxHeapSize "4g"
preDexLibraries = false
}
buildTypes {
release {
minifyEnabled true
shrinkResources true
proguardFiles getDefaultProguardFile('proguard-android.txt'),'proguard-rules.pro'
}
}
productFlavors {
}
}
dependencies {
compile files('libs/gcm.jar')
compile 'com.android.support:support-v4:27.1.0'
compile 'com.android.support:appcompat-v7:27.1.0'
compile 'com.android.support:design:27.1.0'
compile 'com.google.android.gms:play-services-analytics:11.8.0'
compile('com.crashlytics.sdk.android:crashlytics:2.9.1@aar') {
transitive = true
}
compile 'com.google.firebase:firebase-core:11.8.0'
}
apply plugin: 'com.google.gms.google-services'
Refer snap - got 21 crash from last 24 hours.
Crash log
Caused by java.lang.NullPointerException
Attempt to invoke virtual method 'void android.support.design.widget.CheckableImageButton.setChecked(boolean)' on a null object reference arrow_right
android.support.design.widget.TextInputLayout.passwordVisibilityToggleRequested (Unknown Source:1339)
android.support.design.widget.TextInputLayout.onRestoreInstanceState (Unknown Source:1033)
android.view.View.dispatchRestoreInstanceState (View.java:15777)
android.view.ViewGroup.dispatchRestoreInstanceState (ViewGroup.java:3233)
android.support.design.widget.TextInputLayout.dispatchRestoreInstanceState (Unknown Source:1041)
android.view.ViewGroup.dispatchRestoreInstanceState (ViewGroup.java:3239)
android.view.ViewGroup.dispatchRestoreInstanceState (ViewGroup.java:3239)
android.view.ViewGroup.dispatchRestoreInstanceState (ViewGroup.java:3239)
android.view.ViewGroup.dispatchRestoreInstanceState (ViewGroup.java:3239)
android.view.View.restoreHierarchyState (View.java:15755)
com.android.internal.policy.PhoneWindow.restoreHierarchyState (PhoneWindow.java:2106)
android.app.Activity.onRestoreInstanceState (Activity.java:1098)
android.app.Activity.performRestoreInstanceState (Activity.java:1053)
android.app.Instrumentation.callActivityOnRestoreInstanceState (Instrumentation.java:1175)
android.app.ActivityThread.performLaunchActivity (ActivityThread.java:2714)
android.app.ActivityThread.handleLaunchActivity (ActivityThread.java:2802)
android.app.ActivityThread.-wrap12 (ActivityThread.java)
android.app.ActivityThread$H.handleMessage (ActivityThread.java:1549)
android.os.Handler.dispatchMessage (Handler.java:102)
android.os.Looper.loop (Looper.java:163)
android.app.ActivityThread.main (ActivityThread.java:6361)
java.lang.reflect.Method.invoke (Method.java)
com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run (ZygoteInit.java:904)
com.android.internal.os.ZygoteInit.main (ZygoteInit.java:794)
can anyone help how to prevent this bug?
do i need to upgrade my targetSdkVersion
?
If any alternate solution is there please suggest because if i change the target sdk version then i have to update lots of code in my app.
I solved this by simply changing the inputType
of the EditText (or the TextInputEditText in my case) to textPassword
. So you should try this:
<EditText
android:id="@+id/etPassword"
...
android:inputType="textPassword" />
I assume you didn't mean to set it to textEmailAddress
.
Since none of the above answers helped me I spent some time on fixing this problem myself. I've found out that crash occurs in my case when orientation changes (maybe there are more cases).
Initially, the solution was kind of ugly using reflection. Extracted the boolean value indicating password visibility and toggled the visibility after orientation change. But later I noticed that even though crash does not appear anymore my solution is not the reason for this crash to be fixed. So I started commenting the code step by step back to find what was actually the so-called solution.
The solution was to modify AndroidManifest. Unexpected.
I noticed that adding android:configChanges
attribute fixes the problem. Sadly I'm unable to explain exactly how does it fix the problem. The solution was found somewhat accidentally. If orientation
value does not fix the problem try different values.
<activity
android:configChanges="orientation"
android:name="com.example.activity.LoginActivity"
android:screenOrientation="sensor" />
For older version of SDK I had to extend TextInputLayout
in order to fix this problem. Fix with configChanges
does not resolve the issue here.
This solution works for new and old devices, so I recommend to stick with it.
import com.google.android.material.textfield.TextInputLayout;
public class PasswordTextInputLayout extends TextInputLayout {
public PasswordTextInputLayout(Context context) {
super(context);
}
public PasswordTextInputLayout(Context context, AttributeSet attrs) {
super(context, attrs);
}
public PasswordTextInputLayout(Context context, AttributeSet attrs, int defStyleAttr) {
super(context, attrs, defStyleAttr);
}
/**
* We have to change "password visibility toggle enabled"
* state twice in order to recreate private {@link TextInputLayout#passwordToggleView}.
* Calling {@link TextInputLayout#setPasswordVisibilityToggleEnabled(boolean)}
* we also invoke {@link TextInputLayout#updatePasswordToggleView}.
* Which recreates passwordToggleView if it is equals to null.
* UI performance is not affected.
*
* @param state saved when screen configuration has changed (e.g. orientation change).
*/
@Override
protected void onRestoreInstanceState(Parcelable state) {
setPasswordVisibilityToggleEnabled(false);
setPasswordVisibilityToggleEnabled(true);
super.onRestoreInstanceState(state);
}
}
Simple. Instead of tag <com.google.android.material.textfield.TextInputLayout>
use <com.example.view.PasswordTextInputLayout>
.
<com.example.view.PasswordTextInputLayout
... >
<com.google.android.material.textfield.TextInputEditText
...
/>
</com.example.view.PasswordTextInputLayout>
Looks like after activity or fragment saves it's state to Bundle
(that is savedInstanceState
you see in Activity#onCreate
) and later uses it to restore the state TextInputLayout
fails to do it correctly. passwordToggleView
is not restored correctly. A solution for this would be to add in TextInputLayout#onRestoreInstanceState
method call updatePasswordToggleView
or make appropriate changes to recreate passwordToggleView
before it's visibility toggled.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With