我已经将Facebook SDK(目前为3.5,但我从3.0开始)实施到Android应用中。根据{{3}},我需要提供一个注销选项。问题是我第一次登录时有效,但是在退出并尝试再次登录后却没有。
我的应用有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();
}
}
[FacebookLoginActivity]
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();
}
}
[FacebookLoginFragment]
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] package 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()
,触发BaseActivity.onSessionStateChange()
,然后启动意图并调用ViewActivity.onCreate()
。这意味着登录的活动结果无处可去。我现在已经尝试了大约20个小时所能想到的一切,而且我无法弄清楚出了什么问题。
为什么突然创建ViewActivity
?这可能是因为它被设置为启动器活动,或者可能是因为它在Facebook应用程序设置中列为应用程序类名称,但除此之外我不知道。
答案 0 :(得分:0)
我终于想通了,我正在寻找完全错误的地方。
在另一堂课中,我使用的是Facebook UiLifecycleHelper
课程,但我忘了实施一些Android生命周期方法,例如onPause
和onDestroy
。
这意味着UiLifecycleHelper
仍处于活动状态并导致各种问题。一旦修复,登录/注销就能完美运行。
答案 1 :(得分:0)
问题可能是您上传的哈希键以及我从下面的代码得到的哈希键是不同的。尝试此代码此代码,在控制台中获取哈希代码,在Facebook控制台上更新它,它将登录完美。我发布这个是为了让我的开发人员节省一些时间来解决这个问题。
try {
PackageInfo info = getPackageManager().getPackageInfo(
"com.facebook.samples.loginhowto", PackageManager.GET_SIGNATURES);
for (Signature signature : info.signatures){
MessageDigest md = MessageDigest.getInstance("SHA");
md.update(signature.toByteArray());
Log.d("KeyHash:", Base64.encodeToString(md.digest(), Base64.DEFAULT));
}
} catch (NameNotFoundException e) {
} catch (NoSuchAlgorithmException e) {
}