0

I got a very strange exception while using Sharedpreferences and DialogFragment:

Unable to start activity ComponentInfo{com.example.barta1.site_patrol/com.example.barta1.site_patrol.MainActivity}: 
java.lang.NullPointerException: Attempt to invoke virtual method
 'void android.app.Dialog.setOwnerActivity(android.app.Activity)'
 on a null object reference  -  
android.app.ActivityThread.performLaunchActivity(ActivityThread.java:2679)

I really do not have a clue what causes this error, but after this happened, I never be able to start my application again, it continuosly crashed with the same exception above. The MainActivity is my launching activity in my application with a DialogFragment attached which I use to login users. I show this dialogfragment if the users not logged in (the "logged in" status saved in a sharedpreference object).

My MainActivity is like this:

public class MainActivity extends AppCompatActivity implements LoginDialogFragment.NoticeDialogListener {
    //...
    private LoginDialogFragment dialogFragment;
    SharedPreferences pref;
    SharedPreferences.Editor edit;
    //...

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        pref = getSharedPreferences("Globals", MODE_PRIVATE);
        edit = pref.edit();

        boolean isloggedin = pref.getBoolean("Loggedin", false);


        if (!isloggedin) {
            //if not logged in show the login dialog
            showLoginDialog();
        } 
        else {
            //... doing some network calls...
        }
    }

    public void showLoginDialog() {
        dialogFragment = new LoginDialogFragment();
        dialogFragment.show(getFragmentManager(), "LoginDialogFragment");
    }

    /***
     * Network calls if dialog dismissed
     * Login dialog can only be closed if logging in is successful
     * (if loginname and password matches). 
     */
    @Override
    public void onDismiss() {
        //... some network related jobs
    }

}


And here is the fragment class:

public class LoginDialogFragment extends DialogFragment {

    public interface NoticeDialogListener{
         void onDismiss();
    }

    NoticeDialogListener mListener;
    Activity activity;
    AlertDialog dialog;
    SharedPreferences pref;
    SharedPreferences.Editor edit;


    @Override
    public void onAttach(Context context) {

        super.onAttach(context);

        try{
            activity = (Activity) context;
            mListener = (NoticeDialogListener) activity;
            pref = activity.getSharedPreferences("Globals", MODE_PRIVATE);
            edit = pref.edit();

        } catch (ClassCastException e){
            throw new ClassCastException(activity.toString() + "must implement NoticeDialogListener");
        }
    }

    @Override
    public Dialog onCreateDialog(Bundle savedInstanceState) {

        String username = pref.getString("Username", null);

        if(username==null) {

            LayoutInflater inflater = getActivity().getLayoutInflater();
            View view = inflater.inflate(R.layout.dialog_signin, null);

            final AutoCompleteTextView actv_username =  view.findViewById(R.id.username);
            final EditText password =  view.findViewById(R.id.password);

            dialog = new AlertDialog.Builder(new ContextThemeWrapper(getContext(), R.style.AlertDialogCustom))
                    .setView(view)
                    .setTitle("Bejelentkezés")
                    .setPositiveButton("OK", null)
                    .create();


            dialog.setOnShowListener(new DialogInterface.OnShowListener() {
                @Override
                public void onShow(DialogInterface dialogInterface) {
                    final Button button = ( dialog).getButton(AlertDialog.BUTTON_POSITIVE);
                    button.setOnClickListener(new View.OnClickListener() {
                        @Override
                        public void onClick(View v) {
                            String passw = password.getText().toString();
                            String user = actv_username.getText().toString();
                            try {
                                if (user.length() < 4 || passw.length() < 4) {
                                    Toast.makeText(getContext(), "Too short user/pass.", Toast.LENGTH_SHORT).show();
                                    dialog.show();
                                } else {
                                    //login to account, if success dismiss.
                                    login(user, passw, dialog);
                                }


                            } catch (Exception e) {
                                e.printStackTrace();
                            }
                            //  dialog.dismiss();
                        }
                    });
                }
            });
            dialog.setCanceledOnTouchOutside(false);

            // set the DialogFragment to make the dialog unable to dismiss with back button
            // (because not working if called on the dialog directly)
            this.setCancelable(false);
            return dialog;
        } // end of - if username == null.

        return null;
    }

    public void login(final String username, String password, final AlertDialog dialog){

          //... some network call
          //... if successful: 
          //              edit.putString("Username", username);
          //              edit.commit();
          //              edit.putBoolean("Loggedin", true);
          //              edit.commit();
          //              dialog.dismiss();
          //              dialog.setOnShowListener(null);
          //     
          //     else 
          //              Toast.makeText(getContext(),"Wrong login credentials", 
          //                   Toast.LENGTH_SHORT).show();
    }


    @Override
    public void onDismiss(DialogInterface dialog) {
        mListener.onDismiss();
        dismissAllowingStateLoss();
    }

After reinstalling the package, I could not recreate this exception (even when I killed app process, and start it from the recent apps), end users somehow managed to do this and that time, restarting the application was an instant crash (see the exception above.). It looks like parent activity becomes null somehow ( possible after saving the state and after cannot recover).

How to avoid this in the future? Is there a simple way to deal with this situation?

It would be also a great help if someone can explain to me when this "setOwnerActivity(Activity activity)" from the android library called, that way maybe I can identify what went wrong.

Thanks for any help.

Newbie1001
  • 131
  • 11
  • 2
    You cannot return null from `onCreateDialog()`. That's too late to be canceling or aborting the `Dialog` showing. Do your `username` check in `showLoginDialog()` instead. – Mike M. Dec 07 '19 at 11:01
  • 1
    Awww men. That is the fastest answer ever. And you are right, that caused the exception. Thank you very much! – Newbie1001 Dec 07 '19 at 11:05

1 Answers1

0

As Mike M. stated out,

You cannot return null from onCreateDialog(). That's too late to be canceling or aborting the Dialog showing.

And the username check before creating the fragment will obviously solve the problem. Also, the LoggedIn field looks redundant now.

Newbie1001
  • 131
  • 11