我已经将 Facebook SDK(目前是 3.5,但我从 3.0 开始)实现到一个 Android 应用程序中。根据Facebook 最佳实践,我需要提供一个退出选项。问题是我第一次登录它可以工作,但在注销并尝试再次登录后就不行了。
我的应用程序有一个BaseActivity
处理大部分共享代码(包括登录)的应用程序,并由两个类扩展:FacebookLoginActivity
用于登录 UI 和ViewActivity
用于在登录后显示信息。
这是我正在使用的代码,稍作编辑以删除不相关的方法:
[BaseActivity]
package uk.co.cgfindies.wittylater;
import java.util.Arrays;
import java.util.Collection;
import java.util.List;
import android.app.Activity;
import android.content.Context;
import android.content.Intent;
import android.content.SharedPreferences;
import android.net.ConnectivityManager;
import android.net.NetworkInfo;
import android.os.Bundle;
import android.preference.PreferenceManager;
import android.util.Log;
import android.view.View;
import com.actionbarsherlock.app.ActionBar;
import com.actionbarsherlock.app.SherlockFragmentActivity;
import com.actionbarsherlock.view.Menu;
import com.actionbarsherlock.view.MenuItem;
import com.facebook.Session;
import com.facebook.SessionState;
import com.testflightapp.lib.TestFlight;
public class BaseActivity extends SherlockFragmentActivity {
public static final int ACTIVITY_FACEBOOK_LOGIN = 0;
public static final List<String> BASIC_PERMISSIONS = Arrays.asList("basic_info");
public static final List<String> READ_PERMISSIONS = Arrays.asList("basic_info", "read_stream");
public static final List<String> PUBLISH_PERMISSIONS = Arrays.asList("publish_actions");
public static final String GENERIC_TAG = "WITTYLATER";
public static final String PROFILE_PICTURE_CACHE_UNIQUE_NAME = "fb_profile_pictures";
public static final int PROFILE_PICTURE_CACHE_SIZE = 1024 * 1024 * 1;
public static final int DEFAULT_LIKES_REFRESH_INTERVAL_IN_MINUTES = 15;
private static final String PENDING_PUBLISH_KEY = "pendingPublishReauthorization";
private static final String FACEBOOK_LOGIN_TAG = "FACEBOOK_LOGIN_TAG";
public static final int NOTIFICATION_POST_UPDATED = 1;
public static final String ARGS_BOOLEAN_SHOW_MENU = "ARGS_NO_MENU";
public static final String ARGS_BOOLEAN_FACEBOOK_LOGIN = "ARGS_BOOLEAN_FACEBOOK_LOGIN";
private boolean facebookLogin = false; // This will be true if the system is currently trying to log the user in.
private boolean showMenu = true;
protected static boolean pendingPublishReauthorization;
private static String username = "";
private Session.StatusCallback statusCallback = new SessionStatusCallback();
private static SessionState currentState;
private Context context;
private class SessionStatusCallback implements Session.StatusCallback {
@Override
public void call(Session session, SessionState state, Exception exception) {
onSessionStateChange(session, state, exception);
}
}
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
init(savedInstanceState);
}
...
private void init(Bundle savedInstanceState) {
Log.i(BaseActivity.GENERIC_TAG, "init: " + this.getClass().getName());
Session session = Session.getActiveSession();
if (session == null) {
if (savedInstanceState != null) {
session = Session.restoreSession(this, null, statusCallback, savedInstanceState);
}
if (session == null) {
session = new Session(this);
}
Session.setActiveSession(session);
if (session.getState().equals(SessionState.CREATED_TOKEN_LOADED)) {
session.openForRead(new Session.OpenRequest(this).setCallback(statusCallback));
}
}
if (!session.isOpened() && !(this instanceof FacebookLoginActivity)) {
Log.i(BaseActivity.GENERIC_TAG, "Starting FacebookLoginActivity");
Intent i = new Intent(this, FacebookLoginActivity.class);
this.startActivity(i);
this.finish();
return;
}
if (!SyncWithFacebookService.isServiceRunning()) {
Intent intent = new Intent(this, SyncWithFacebookService.class);
startService(intent);
}
}
@Override
protected void onStart() {
super.onStart();
Session.getActiveSession().addCallback(statusCallback);
}
@Override
public void onStop() {
super.onStop();
Session.getActiveSession().removeCallback(statusCallback);
}
@Override
public void onResume() {
Log.i(BaseActivity.GENERIC_TAG, this.getClass().getName() + " onResume()");
super.onResume();
Session session = Session.getActiveSession();
onSessionStateChange(session, session.getState(), null);
}
@Override
public void onActivityResult(int requestCode, int resultCode, Intent data) {
Log.i(BaseActivity.GENERIC_TAG, this.getClass().getName() + " onActivityResult request: " + requestCode);
super.onActivityResult(requestCode, resultCode, data);
Session.getActiveSession().onActivityResult(this, requestCode, resultCode, data);
}
@Override
public void onSaveInstanceState(Bundle outState) {
Log.i(BaseActivity.GENERIC_TAG, this.getClass().getName() + " onSaveInstanceState()");
super.onSaveInstanceState(outState);
Session session = Session.getActiveSession();
Session.saveSession(session, outState);
}
protected void onSessionStateChange(Session session, SessionState state, Exception exception) {
Log.i(BaseActivity.GENERIC_TAG, "onSessionStateChange called from " + this.getClass().getName());
Log.i(BaseActivity.GENERIC_TAG, "current state is " + ((currentState == null) ? "null" : currentState.toString()));
Log.i(BaseActivity.GENERIC_TAG, "state is " + state.toString());
if (state.equals(currentState)) {
Log.i(BaseActivity.GENERIC_TAG, "state hasn't changed, returning.");
return;
}
currentState = state;
if (exception != null) {
Log.d(BaseActivity.GENERIC_TAG, exception.getMessage());
TestFlight.log(exception.getMessage());
}
if (state.isOpened()) {
Log.i(BaseActivity.GENERIC_TAG, "Starting FetchFacebookDataActivity");
Intent i = new Intent(this, FetchFacebookDataActivity.class);
i.addFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP | Intent.FLAG_ACTIVITY_NEW_TASK);
startActivity(i);
finish();
}
}
public void startLogin(View v) {
Log.i(BaseActivity.GENERIC_TAG, this.getClass().getName() + " startLogin()");
Session session = Session.getActiveSession();
if (session != null && !session.isClosed()) {
Log.i(BaseActivity.GENERIC_TAG, "Closing Session, clearing tokens");
session.closeAndClearTokenInformation();
}
if (!session.getState().isOpened() && !session.getState().isClosed()) {
Log.i(BaseActivity.GENERIC_TAG, "Session state is " + session.getState().toString() + ", opening for read.");
session.openForRead(new Session.OpenRequest(this).setCallback(statusCallback));
} else {
Log.i(BaseActivity.GENERIC_TAG, "Opening new active session");
Session.openActiveSession(this, true, statusCallback);
}
}
public void facebookLogout() {
Log.i(BaseActivity.GENERIC_TAG, "Logging out.");
Session session = Session.getActiveSession();
if (!session.isClosed()) {
Log.i(BaseActivity.GENERIC_TAG, "Clearing Facebook tokens.");
session.closeAndClearTokenInformation();
}
Log.i(BaseActivity.GENERIC_TAG, "Starting FacebookLoginActivity");
startNewActivity(FacebookLoginActivity.class, true, true);
finish();
return;
}
protected void startNewActivity(Class<?> cls, boolean clearTop, boolean finish) {
Log.i(BaseActivity.GENERIC_TAG, "Current class is " + this.getClass().getName());
Log.i(BaseActivity.GENERIC_TAG, "Target class is " + cls.getName());
Log.i(BaseActivity.GENERIC_TAG, Boolean.toString(cls.isInstance(this)));
Log.i(BaseActivity.GENERIC_TAG, Boolean.toString(cls.isInstance(this.getClass())));
Log.i(BaseActivity.GENERIC_TAG, Boolean.toString(this.getClass().isInstance(cls)));
if (cls.isInstance(this)) {
Log.i(BaseActivity.GENERIC_TAG, "Already instance of " + cls.getName());
return; // Already in that activity.
}
Log.i(BaseActivity.GENERIC_TAG, "Starting class " + cls.getName());
Intent i = new Intent(this, ViewActivity.class);
i.addFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP | Intent.FLAG_ACTIVITY_NEW_TASK);
startActivity(i);
finish();
}
}
[Facebook登录活动]
package uk.co.cgfindies.wittylater;
import android.content.Intent;
import android.os.Bundle;
import android.support.v4.app.FragmentManager;
import android.support.v4.app.FragmentTransaction;
import android.util.Log;
public class FacebookLoginActivity extends BaseActivity {
@Override
protected void onCreate(Bundle savedInstanceState) {
Log.i(BaseActivity.GENERIC_TAG, this.getClass().getName() + " onCreate()");
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_facebook_login);
FacebookLoginFragment flf = new FacebookLoginFragment();
FragmentManager fragmentManager = getSupportFragmentManager();
FragmentTransaction fragmentTransaction = fragmentManager.beginTransaction();
fragmentTransaction.replace(R.id.facebook_login_container, flf);
fragmentTransaction.commit();
}
}
[Facebook登录片段]
package uk.co.cgfindies.wittylater;
import android.content.Intent;
import android.os.Bundle;
import android.util.Log;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import com.actionbarsherlock.app.SherlockFragment;
public class FacebookLoginFragment extends SherlockFragment {
@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
Log.i(BaseActivity.GENERIC_TAG, this.getClass().getName() + " onCreateView()");
super.onCreateView(inflater, container, savedInstanceState);
View v = inflater.inflate(R.layout.fragment_facebook_login, container, false);
return v;
}
}
[ViewActivity] 包 uk.co.cgfindies.wittylater;
import uk.co.cgfindies.wittylater.ViewPostedFragment.ViewPostedFragment_onClickListeners;
import uk.co.cgfindies.wittylater.ViewUnpostedFragment.ViewUnpostedFragment_onClickListeners;
import android.content.Intent;
import android.os.Bundle;
import android.support.v4.app.Fragment;
import android.support.v4.app.FragmentManager;
import android.support.v4.app.FragmentTransaction;
import android.view.View;
import com.actionbarsherlock.view.Menu;
public class ViewActivity extends BaseActivity implements ViewUnpostedFragment_onClickListeners, ViewPostedFragment_onClickListeners {
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_view);
...
}
}
据我所知,它尝试登录的秒数会Session.openActiveSession()
触发 call ,BaseActivity.onSessionStateChange()
然后启动并ViewActivity.onCreate()
调用一个意图。这意味着登录的活动结果无处可去。我已经尝试了大约 20 个小时以来我能想到的一切,但我无法弄清楚出了什么问题。
为什么ViewActivity
突然被创造出来?可能是因为它被设置为启动器活动,也可能是因为它在 Facebook 应用程序设置中被列为应用程序类名称,但除此之外我不知道。