Cannot call LoginActivity with a null calling package. This can occur if the launchMode of the caller is singleInstance

StackOverflow https://stackoverflow.com/questions/23640933

Question

I have created a singleton class to connect to Facebook and get my user's credentials. Here it is:

public class FacebookHelper implements Session.StatusCallback {

private static final String TAG = FacebookHelper.class.getSimpleName();
private static final int REQUEST_CODE_FACEBOOK = 64206;
public static final String FACEBOOK_STRING = "Facebook";

private static FacebookHelper instance = null;
private static Activity activity;

private FacebookHelper(Context context) {
    CupsLog.d(TAG, "FacebookHelper");
    this.activity = (Activity) context;
}

public static FacebookHelper getInstance(Context context) {
    if (instance == null) {
        instance = new FacebookHelper(context);
    }
    return instance;
}

public void commitFacebookLogin() {
    CupsLog.d(TAG, "commitFacebookLogin");
    FileAccessUtil.getInstance(activity).setStringProperty(Consts.AUTH_TYPE, FacebookHelper.FACEBOOK_STRING);
    if (Session.getActiveSession() != null && Session.getActiveSession().isOpened()) {
        onSessionStateChanged(Session.getActiveSession(), Session.getActiveSession().getState(), null);
    } else {
        Session.openActiveSession(activity, true, this);
    }
}

@Override
public void call(Session session, SessionState state, Exception exception) {
    onSessionStateChanged(session, state, exception);
}

private void onSessionStateChanged(Session session, SessionState state, Exception exception) {
    CupsLog.d(TAG, "onSessionStateChanged, state: " + state.toString());
    if (state.isOpened()) {
        setFacebookTokenAndCookie();
        App.getEventBus().post("Facebook");
    }
}

public void onActivityResult(int requestCode, int resultCode, Intent data) {
    CupsLog.d(TAG, "onActivityResult");
    switch (requestCode) {
        case REQUEST_CODE_FACEBOOK: {
            Session.getActiveSession().onActivityResult(activity, requestCode, resultCode, data);
            break;
        }
        default: {
            break;
        }
    }
}

private void setFacebookTokenAndCookie() {
    CupsLog.i(TAG, "setFacebookTokenAndCookie");
    String val = "fb+" + Session.getActiveSession().getAccessToken();
    CupsLog.i(TAG, "Facebook access_token: " + val);
    CookieUtil.getInstance(activity).setCookie(CookieUtil.AUTH_COOKIE_NAME, val, true);
    CupsTracker.instance.sendAnalyticsEvent(CupsTracker.LOGIN, CupsTracker.FACEBOOK_LOGIN, CupsTracker.FACEBOOK_LOGIN, null);
    CupsTracker.instance.sendAnalyticsView("fb login");
    CupsTracker.instance.trackMobileAppTrackerAction(CupsTracker.FACEBOOK_LOGIN);
    App.getInstance().setAuthSource(App.AuthSource.FACEBOOK);
    AccountService.getInstance(activity).pullAccountDetailsFromServer();
}

public void closeAndClearTokenInformation()
{
    CupsLog.d(TAG, "closeAndClearTokenInformation");
    Session session = Session.getActiveSession();
    if (session != null && !session.isClosed()) {
        session.closeAndClearTokenInformation();
    }
}
}

So, basically when I want to connect to Facebook I run this method from my Activity.

FacebookHelper.getInstance(LoginActivity.this).commitFacebookLogin();

And it works great for the first time, but the problem is that for the second time I get the error specified in the title. Now I know that this helper class of mine is a singleton, but what can I do to change it? what alternatives do I have?

I don't think my query is a duplicate for this question because the situation in which I get this error is completely different from the situations there.

Was it helpful?

Solution

To fix this issue I had to change the singleton getter from this:

public static FacebookHelper getInstance(Context context) {
    if (instance == null) {
        instance = new FacebookHelper(context);
    }
    return instance;
}

To this:

  public static FacebookHelper getInstance(Context context) {
    if (instance == null) {
        instance = new FacebookHelper(context);
    }
    else
    {
        activity = (Activity) context;
    }
    return instance;
}

And use the activity instance instead of the plain simple context. Basically I'm assigning a new activity to the singleton every time I get it's instance.

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top