Home Proper way of implementing login with fragments
Reply: 0

Proper way of implementing login with fragments

user7824
1#
user7824 Published in April 26, 2018, 5:27 pm

I am currently developing an app that uses Facebook and Google login. Until now, I used a LoginActivity which starts MainActivity when login is successful.

I want to rewrite it using fragments instead of two activities, so what I want to do is, when MainActivity starts, if user is not logged in, display LoginFragment, which does exactly what my LoginActivity did, but what I am missing is how to properly exit LoginFragment, and go back to my main fragment, which is DashboardFragment.

I have read a lot of threads about that but there are so many ways of doing it, that I can't figure out which is the best. Furthermore, solutions given were often like getActivity.onBackPressed() which I don't think is a proper way of doing what I want.

Here is what I do in the onCreate method of my MainActivity

@Override
protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.activity_main);

    BottomNavigationView navigation = findViewById(R.id.navigation);
    navigation.setOnNavigationItemSelectedListener(mOnNavigationItemSelectedListener);

    FragmentManager fragmentManager = getFragmentManager();

    navigation.setVisibility(View.INVISIBLE);
    fragmentManager.beginTransaction()
            .replace(R.id.contentLogin, new LoginFragment()).commit();
}

I replace LoginFragment in contentLogin because I have another FrameLayout content which is above my BottomNavigationView, I want the LoginFragment to take all the available place.

I also override onActivityResult

@Override
protected void onActivityResult(int requestCode, int resultCode, Intent data) {
    super.onActivityResult(requestCode, resultCode, data);
    Fragment fragment = getFragmentManager().findFragmentById(R.id.contentLogin);
    fragment.onActivityResult(requestCode, resultCode, data);
}

And in my LoginFragment

@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
                         Bundle savedInstanceState) {

    View view = inflater.inflate(R.layout.fragment_login, container, false);

    callbackManager = CallbackManager.Factory.create();

    LoginManager.getInstance().registerCallback(callbackManager,
            new FacebookCallback<LoginResult>() {
                @Override
                public void onSuccess(LoginResult loginResult) {
                    final String token = loginResult.getAccessToken().getToken();
                    Toast.makeText(getActivity(), token, Toast.LENGTH_SHORT).show();
                }

                @Override
                public void onCancel() {
                    Toast.makeText(getActivity(), "Login canceled", Toast.LENGTH_SHORT).show();
                }

                @Override
                public void onError(FacebookException exception) {
                    Toast.makeText(getActivity(), "Login error", Toast.LENGTH_SHORT).show();
                }
            });

    return view;
}

@Override
public void onActivityResult(int requestCode, int resultCode, Intent data) {
    callbackManager.onActivityResult(requestCode, resultCode, data);
    super.onActivityResult(requestCode, resultCode, data);
}

Only the Facebook part to keep it simple.

Update 14.01

I got it to work with the following code :

MainActivity :

@Override
public void onBackPressed() {
    Fragment fragment = fragmentManager.findFragmentById(R.id.content);

    if (fragment instanceof LoginFragment) {
        fragmentManager.beginTransaction().replace(R.id.content, new DashboardFragment())
                .commit();
        navigation.setVisibility(View.VISIBLE);
    } else {
        super.onBackPressed();
    }
}

LoginFragment :

                @Override
                public void onSuccess(LoginResult loginResult) {
                    final String token = loginResult.getAccessToken().getToken();
                    final String user = loginResult.getAccessToken().getUserId();
                    loginStatus.setText("Login Success :\n" + user + "\n" + token);
                    getActivity().onBackPressed();
                }

There is still one major problem :

  • When I used two Activities, checking Facebook status worked perfectly, now what happens is that if the user is already login, the app will properly display DashboardFragment, but the Facebook login activity will appear above (like if I clicked the Facebook login button) and after logging in, the app will crash. I am using this code to check for login status :

    if (accessToken != null)
        LoginManager.getInstance().logInWithReadPermissions(this,
                Collections.singletonList("public_profile"));
    else {
        navigation.setVisibility(View.GONE);
        fragmentManager.beginTransaction().replace(R.id.content, new LoginFragment())
     .commit();
    }
    

and this is the exception I get :

E/AndroidRuntime: FATAL EXCEPTION: main
                  Process: fr.pinty, PID: 24751
                  java.lang.RuntimeException: Failure delivering result ResultInfo{who=null, request=64206, result=-1, data=Intent { (has extras) }} to activity {fr.pinty/fr.pinty.MainActivity}: java.lang.NullPointerException: Attempt to invoke virtual method 'void android.app.Fragment.onActivityResult(int, int, android.content.Intent)' on a null object reference
                      at android.app.ActivityThread.deliverResults(ActivityThread.java:4089)
                      at android.app.ActivityThread.handleSendResult(ActivityThread.java:4132)
                      at android.app.ActivityThread.-wrap20(ActivityThread.java)
                      at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1533)
                      at android.os.Handler.dispatchMessage(Handler.java:102)
                      at android.os.Looper.loop(Looper.java:154)
                      at android.app.ActivityThread.main(ActivityThread.java:6119)
                      at java.lang.reflect.Method.invoke(Native Method)
                      at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:886)
                      at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:776)
                   Caused by: java.lang.NullPointerException: Attempt to invoke virtual method 'void android.app.Fragment.onActivityResult(int, int, android.content.Intent)' on a null object reference
                      at fr.pinty.MainActivity.onActivityResult(MainActivity.java:92)
                      at android.app.Activity.dispatchActivityResult(Activity.java:6932)
                      at android.app.ActivityThread.deliverResults(ActivityThread.java:4085)
                      at android.app.ActivityThread.handleSendResult(ActivityThread.java:4132) 
                      at android.app.ActivityThread.-wrap20(ActivityThread.java) 
                      at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1533) 
                      at android.os.Handler.dispatchMessage(Handler.java:102) 
                      at android.os.Looper.loop(Looper.java:154) 
                      at android.app.ActivityThread.main(ActivityThread.java:6119) 
                      at java.lang.reflect.Method.invoke(Native Method) 
                      at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:886) 
                      at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:776)

and as I only implemented Facebook login for now, I guess doing Google login will bring more problems. 

You need to login account before you can post.

About| Privacy statement| Terms of Service| Advertising| Contact us| Help| Sitemap|
Processed in 0.313198 second(s) , Gzip On .

© 2016 Powered by mzan.com design MATCHINFO