4

I am developing an Android app that I am pushing out to testers using Fabric/Crashlytics.

I have thoroughly tested my app on 2 physical devices myself:

  1. Samsung Galaxy Tab Pro running 4.4.2 (API 19)
  2. LG G3 running 5.0.1 (API 21)

I have recently pushed out a version of my app to a single tester. Her device is:

  • Samsung Galaxy S4 running 5.0.1 (API 21)

I have a login/register Activity / Fragment series that she is trying to use. I am getting a crash report through Crashlytics, which contains the following information:

Here's an excerpt from the log:

Fatal Exception: java.lang.RuntimeException: Unable to start activity ComponentInfo{com.company.app/com.company.app.LoginActivity}: android.view.InflateException: Binary XML file line #70: Error inflating class fragment
    at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:2693)
    ... other lines
Caused by android.view.InflateException: Binary XML file line #70: Error inflating class fragment
    at android.view.LayoutInflater.createViewFromTag(LayoutInflater.java:770)
    ... other lines
    at android.support.v7.app.AppCompatDelegateImplV7.setContentView(AppCompatDelegateImplV7.java:256)
    at android.support.v7.app.AppCompatActivity.setContentView(AppCompatActivity.java:109)
    at com.company.app.LoginActivity.onCreate(LoginActivity.java:25)
    at android.app.Activity.performCreate(Activity.java:6289)
    ... other lines
Caused by java.lang.IllegalStateException: Fragment com.company.app.LoginFragment did not create a view.
    at android.app.FragmentManagerImpl.onCreateView(FragmentManager.java:2160)
    at android.app.Activity.onCreateView(Activity.java:5610)
    at android.support.v4.app.BaseFragmentActivityHoneycomb.onCreateView(BaseFragmentActivityHoneycomb.java:34)
    at android.support.v4.app.FragmentActivity.onCreateView(FragmentActivity.java:79)
    ... other lines
    at android.support.v7.app.AppCompatDelegateImplV7.setContentView(AppCompatDelegateImplV7.java:256)
    at android.support.v7.app.AppCompatActivity.setContentView(AppCompatActivity.java:109)
    at com.company.app.LoginActivity.onCreate(LoginActivity.java:25)
    at android.app.Activity.performCreate(Activity.java:6289)
    ... other lines

Here is a condensed version of my LoginActivity and LoginFragment files:

activity_login.xml

<?xml version="1.0" encoding="utf-8"?>
<android.support.design.widget.CoordinatorLayout>
    <LinearLayout>
        <android.support.v7.widget.Toolbar>
            <LinearLayout>
                <TextView />
                <ImageButton />
            </LinearLayout>
        </android.support.v7.widget.Toolbar>
        <FrameLayout>
            <fragment
                android:id="@+id/container"
                android:layout_width="match_parent"
                android:layout_height="match_parent"
                android:name="com.company.app.LoginFragment"
                tools:layout="@layout/fragment_login" />
            <View />
        </FrameLayout>
    </LinearLayout>
</android.support.design.widget.CoordinatorLayout>

LoginActivity.java

@Override
protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);

    // This next line causes the error
    setContentView(R.layout.activity_login);

    ImageButton infoButton = (ImageButton)findViewById(R.id.info_button);
    infoButton.setColorFilter(ContextCompat.getColor(this, R.color.colorPrimary), PorterDuff.Mode.SRC_ATOP);
    infoButton.setOnClickListener(new View.OnClickListener() {
        @Override
        public void onClick(View v) {
            if (mUserCreationFragment != null) {
                mUserCreationFragment.showInfo();

            } else if (mEnterCodesFragment != null) {
                mEnterCodesFragment.showInfo();

            } else if (mLoginFragment != null) {
                mLoginFragment.showInfo();

            }
        }
    });
    mToolbar                = (Toolbar)findViewById(R.id.toolbar);
    mTitleLabel             = (TextView)findViewById(R.id.title_label);
    mTitleLabel.setText(getString(R.string.login_string));
    setSupportActionBar(mToolbar);

}

fragment_login.xml

<com.company.app.SlidingFrameLayout>
    <ScrollView>
        <LinearLayout>
            <TextView />
            <Button />
            <android.support.design.widget.TextInputLayout>
                <EditText />
            </android.support.design.widget.TextInputLayout>
            <android.support.design.widget.TextInputLayout>
                <EditText />
            </android.support.design.widget.TextInputLayout>
            <Button />
            <Button />
        </LinearLayout>
    </ScrollView>
</com.company.app.SlidingFrameLayout>

Line 70 in fragment_login.xml

Line 69    <android.support.design.widget.TextInputLayout
Line 70    android:layout_height="wrap_content"
Line 71    android:layout_width="match_parent"
Line 72     >
Line 73     <EditText
Line 74        android:id="@+id/password"
Line 75        android:hint="@string/prompt_password"
Line 76        android:imeOptions="actionDone"
Line 77        android:inputType="textPassword"
Line 78        android:layout_height="wrap_content"
Line 79        android:layout_width="match_parent"
Line 80        android:maxLines="1"
Line 71        android:singleLine="true"
Line 82        android:textSize="16sp"
Line 83
Line 84        />
Line 85
Line 86    </android.support.design.widget.TextInputLayout>

LoginFragment.java

@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
    View rootView           = inflater.inflate(R.layout.fragment_login, container, false);

    mPasswordView           = (EditText)rootView.findViewById(R.id.password);
    Button registerButton   = (Button)rootView.findViewById(R.id.register_button);
    TextView registerLabel  = (TextView)rootView.findViewById(R.id.register_label);
    mSignInButton           = (Button)rootView.findViewById(R.id.sign_in_button);
    mUserNameView           = (EditText)rootView.findViewById(R.id.user_name);
    LoginActivity activity  = (LoginActivity)getActivity();
    activity.setLoginFragment(this);

    checkIfComplete();

    mPasswordView.setOnEditorActionListener(new TextView.OnEditorActionListener() {
        @Override
        public boolean onEditorAction(TextView textView, int id, KeyEvent keyEvent) {
            if (id == EditorInfo.IME_ACTION_DONE || id == EditorInfo.IME_NULL) {
                if (mComplete) {
                    beginLogin();
                    return true;
                }
            }
            return false;
        }
    });
    mPasswordView.addTextChangedListener(new TextWatcher() {
        @Override
        public void beforeTextChanged(CharSequence s, int start, int count, int after) {}
        @Override
        public void onTextChanged(CharSequence s, int start, int before, int count) {
            checkIfComplete();
        }
        @Override
        public void afterTextChanged(Editable s) {}
    });

    registerButton.setBackgroundColor(ContextCompat.getColor(getActivity(), R.color.colorPrimaryDark));
    registerButton.setTextColor(ContextCompat.getColor(getActivity(), R.color.colorTextEnabled));
    registerButton.setOnClickListener(new View.OnClickListener() {
        @Override
        public void onClick(View v) {
            EnterCodesFragment fragment = new EnterCodesFragment();
            getFragmentManager()
                    .beginTransaction()
                    .setCustomAnimations(R.animator.slide_in_from_right, R.animator.slide_out_to_left, R.animator.slide_in_from_left, R.animator.slide_out_to_right)
                    .replace(R.id.container, fragment, getString(R.string.basic_information_title_string))
                    .addToBackStack(getString(R.string.enter_codes_fragment_title))
                    .commit();
        }
    });

    registerLabel.setTextColor(ContextCompat.getColor(getActivity(), R.color.colorTextDisabled));

    mSignInButton.setOnClickListener(new View.OnClickListener() {
        @Override
        public void onClick(View view) {
            beginLogin();
        }
    });

    Button forgotPasswordButton = (Button)rootView.findViewById(R.id.forgot_password_button);
    forgotPasswordButton.setPaintFlags(forgotPasswordButton.getPaintFlags() | Paint.UNDERLINE_TEXT_FLAG);
    forgotPasswordButton.setOnClickListener(new View.OnClickListener() {
        @Override

        public void onClick(View v) {
            final View view         = View.inflate(getActivity(), R.layout.reset_password_dialog, null);

            final EightyPercentDialog dialog = new EightyPercentDialog(getActivity());
            dialog.requestWindowFeature(Window.FEATURE_NO_TITLE);
            dialog.setContentView(view);

            final EditText emailEditText  = (EditText)view.findViewById(R.id.email_edit_text);

            Button cancelButton     = (Button)view.findViewById(R.id.cancel_button);
            Button okButton         = (Button)view.findViewById(R.id.ok_button);

            cancelButton.setOnClickListener(new View.OnClickListener() {
                @Override
                public void onClick(View v) {
                    dialog.dismiss();
                }
            });

            okButton.setOnClickListener(new View.OnClickListener() {
                @Override
                public void onClick(View v) {
                    String email    = emailEditText.getText().toString();
                    dialog.dismiss();
                    sendPasswordResetEmail(email);
                }
            });

            dialog.show();

        }
    });

    mUserNameView.addTextChangedListener(new TextWatcher() {
        @Override
        public void beforeTextChanged(CharSequence s, int start, int count, int after) {}
        @Override
        public void onTextChanged(CharSequence s, int start, int before, int count) {
            checkIfComplete();
        }
        @Override
        public void afterTextChanged(Editable s) {}
    });
    
    return rootView;
}

I've looked at several other posts on here related to InflateException, but none of them seem to be applicable to my situation.

For instance:

  1. This question and answer seems to be highlighting a problem with package naming, which isn't an issue in my project.
  2. This question and answer is dealing with an issue where the order of lines of code is incorrect, which isn't an issue in my project.
  3. I had a look at this question in an effort to determine whether my issue might be related to using an AppCompatActivity, but so far I have not seen anything there that would be problematic.

So, basically, what's confusing me is that I do not have this problem at all on either of my devices, and I don't know Android well enough to see anything on her system (also a Samsung phone running 5.0.1, like mine) that would be problematic. Is there something I'm missing? How can I track down what the actual problem is?

Community
  • 1
  • 1
mbm29414
  • 11,558
  • 6
  • 56
  • 87

0 Answers0