Sam Stern
Sam Stern

Reputation: 25134

Facebook for Android Integration does not work consistently

I am trying to integrate Facebook login with my app. It's simple: a user clicks a button on my Login screen, I get their email and other info from Facebook, then I submit that information to my website and make them an account (I don't use passwords, so this works).

However, the login button only works like 1/3 of the time. Other times it launches the Facebook activity, I see a loading spinner on the Facebook screen, and then the app exits to my home screen. No force close notification, no logcat errors, just nothing.

Here is the code for my login activity (the parts relevant to Facebook):

package com.taptag.beta;

/** IMPORTS REMOVED FOR BREVITY **/

public class FacebookLogInActivity extends NetworkActivity {
    public static final String APP_ID = "OMITTED FOR PRIVACY";
    public static final String LOG_OUT = "Log Out";

    Facebook facebook = new Facebook(APP_ID);

    private AsyncFacebookRunner mAsyncRunner;
    private Handler mHandler;
    private SharedPreferences mPrefs;
    private Button mLoginButton;
    private static final String[] PERMISSIONS = { "email" };

    private EditText firstName;
    private EditText lastName;
    private EditText email;
    private Button signupButton;

    private TextView errorView;
    private ProgressBar facebookSpinner;
    private ProgressBar signupSpinner;

    //Taken from mkyong
    private static final String EMAIL_PATTERN = "^[_A-Za-z0-9-]+(\\.[_A-Za-z0-9-]+)*@[A-Za-z0-9]+(\\.[A-Za-z0-9]+)*(\\.[A-Za-z]{2,})$";
    private Pattern emailPattern;


    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.facebook_main);

        mPrefs = getSharedPreferences("TapTag", MODE_PRIVATE);
        Integer userId = mPrefs.getInt("user_id", -1);

        mLoginButton = (Button) findViewById(R.id.loginButton);

        // Facebook properties
        mAsyncRunner = new AsyncFacebookRunner(facebook);
        mHandler = new Handler();
        // Get existing saved session information
        String access_token = mPrefs.getString("access_token", null);
        long expires = mPrefs.getLong("access_expires", 0);

        if (access_token != null) {
            facebook.setAccessToken(access_token);
        }
        if (expires != 0) {
            facebook.setAccessExpires(expires);
        }

        errorView = (TextView) findViewById(R.id.signupError);
        facebookSpinner = (ProgressBar) findViewById(R.id.facebookSpinner);
        signupSpinner = (ProgressBar) findViewById(R.id.signupSpinner);

        hideSpinners();
        errorView.setVisibility(View.GONE);

        emailPattern = Pattern.compile(EMAIL_PATTERN);
        firstName = (EditText) findViewById(R.id.signupFirstName);
        lastName = (EditText) findViewById(R.id.signupLastName);
        email = (EditText) findViewById(R.id.signupEmail);
        signupButton = (Button) findViewById(R.id.signupButton);

        signupButton.setOnClickListener(new OnClickListener() {
            @Override
            public void onClick(View v) {
                boolean isValid = validateInputs();
                if (isValid) {
                    SignupTask signupTask = new SignupTask();
                    signupTask.execute(null, null);
                }
            }
        });

        mLoginButton.setOnClickListener(new OnClickListener() {
            @Override
            public void onClick(View v) {
                if (!facebook.isSessionValid()) {
                    logIn();
                } else {
                    logOut();
                }
            }
        });
    }

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

    @Override
    public void onResume() {
        super.onResume();
        // Extend the session information if it is needed
        //if (facebook != null && !facebook.isSessionValid()) {
            facebook.extendAccessTokenIfNeeded(this, null);
        //}
        if (LOG_OUT.equals(getIntent().getAction())) {
            logOut();
        } else  {
            Integer userId = mPrefs.getInt("user_id", -1);
            if (userId > 0) {
                continueToHomeScreen();
            }
        }
    }

    @Override
    public void onBackPressed() {
        //Do nothing, don't want people getting back into the app
    }

    /**
     * Validate the signup form.  True if valid, false otherwise.
     * @return
     */
    public boolean validateInputs() {
        /** NOT RELEVANT **/
    }

    private FacebookUserInfo userFromForm() {
        /** NOT RELEVANT **/
    }

    private boolean validateFirstName() {
        /** NOT RELEVANT **/
    }

    private boolean validateLastName() {
        /** NOT RELEVANT **/
    }

    private boolean validateEmail() {
        /** NOT RELEVANT **/
    }

    public void hideSpinners() {
        facebookSpinner.setVisibility(View.GONE);
        signupSpinner.setVisibility(View.GONE);
    }

    public void continueToHomeScreen() {
        Intent toHomeScreen = new Intent(FacebookLogInActivity.this, HomeScreenActivity.class);
        FacebookLogInActivity.this.startActivity(toHomeScreen);
    }

    public void logIn() {
        facebookSpinner.setVisibility(View.VISIBLE);
        mLoginButton.setVisibility(View.GONE);
        facebook.authorize(FacebookLogInActivity.this, PERMISSIONS, new DialogListener() {
            @Override
            public void onComplete(Bundle values) {
                SharedPreferences.Editor editor = mPrefs.edit();
                editor.putString("access_token", facebook.getAccessToken());
                editor.putLong("access_expires", facebook.getAccessExpires());
                editor.commit();
                requestUserData();
            }

            @Override
            public void onFacebookError(FacebookError e) {
                mLoginButton.setVisibility(View.VISIBLE);
                hideSpinners();

            }
            @Override
            public void onError(DialogError e) {
                mLoginButton.setVisibility(View.VISIBLE);
                hideSpinners();
            }
            @Override
            public void onCancel() {
                mLoginButton.setVisibility(View.VISIBLE);
                hideSpinners();
            }
        });
    }

    public void logOut() {
        /** NOT RELEVANT **/
    }

    public void requestUserData() {
        Bundle params = new Bundle();
        params.putString("field name", "name");
        params.putString("field email", "email");

        mAsyncRunner.request("me", params, new BaseRequestListener() {
            @Override
            public void onComplete(final String response, final Object state) {
                FacebookUserInfo facebookUserInfo = TapTagAPI.userInfoFromFacebook(response);
                UserFetchResponse userFetchResponse = TapTagAPI.fetchUser(facebookUserInfo);
                if (!userFetchResponse.hasError()) {
                    commitUserInfo(userFetchResponse);
                    continueToHomeScreen();
                } else {
                    mHandler.post(new Runnable() {
                        @Override
                        public void run() {
                            hideSpinners();
                            mLoginButton.setVisibility(View.VISIBLE);
                        }
                    });
                }
            }
        });
    }

    public void commitUserInfo(UserFetchResponse userFetchResponse) {
        SharedPreferences.Editor editor = mPrefs.edit();
        editor.putInt("user_id", userFetchResponse.getId());
        editor.putString("user_name", userFetchResponse.getFirst() + " " + userFetchResponse.getLast());
        editor.commit();
    }

    public class SignupTask extends AsyncTask<Void, Void, UserFetchResponse> {
        @Override
        protected void onPreExecute() {
            signupSpinner.setVisibility(View.VISIBLE);
            signupButton.setVisibility(View.GONE);
        }

        @Override
        protected UserFetchResponse doInBackground(Void... arg0) {
            FacebookUserInfo user = userFromForm();
            UserFetchResponse response = TapTagAPI.fetchUser(user);
            return response;
        }

        @Override
        protected void onPostExecute(UserFetchResponse response) {
            if (response.success()) {
                commitUserInfo(response);
                continueToHomeScreen();
            } else {
                errorView.setVisibility(View.VISIBLE);
            }
        }
    }

}

Upvotes: 1

Views: 398

Answers (1)

Dipak Keshariya
Dipak Keshariya

Reputation: 22291

Write below login function instead of your login function, it will solve your problem.

public void logIn() {
    facebookSpinner.setVisibility(View.VISIBLE);
    mLoginButton.setVisibility(View.GONE);
    facebook.authorize(FacebookLogInActivity.this, PERMISSIONS, Facebook.FORCE_DIALOG_AUTH, new DialogListener() {
        @Override
        public void onComplete(Bundle values) {
            SharedPreferences.Editor editor = mPrefs.edit();
            editor.putString("access_token", facebook.getAccessToken());
            editor.putLong("access_expires", facebook.getAccessExpires());
            editor.commit();
            requestUserData();
        }

        @Override
        public void onFacebookError(FacebookError e) {
            mLoginButton.setVisibility(View.VISIBLE);
            hideSpinners();
        }

        @Override
        public void onError(DialogError e) {
            mLoginButton.setVisibility(View.VISIBLE);
            hideSpinners();
        }

        @Override
        public void onCancel() {
            mLoginButton.setVisibility(View.VISIBLE);
            hideSpinners();
        }
    });
}

Upvotes: 2

Related Questions