package com.sromku.simple.fb;
import android.app.Activity;
import android.content.Intent;
import com.facebook.AccessToken;
import com.facebook.CallbackManager;
import com.facebook.FacebookCallback;
import com.facebook.FacebookException;
import com.facebook.login.LoginManager;
import com.facebook.login.LoginResult;
import com.sromku.simple.fb.listeners.OnLoginListener;
import com.sromku.simple.fb.listeners.OnLogoutListener;
import com.sromku.simple.fb.listeners.OnNewPermissionsListener;
import com.sromku.simple.fb.utils.Logger;
import java.lang.ref.WeakReference;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.HashSet;
import java.util.List;
import java.util.Set;
public class SessionManager {
private final static Class<?> TAG = SessionManager.class;
static SimpleFacebookConfiguration configuration;
private WeakReference<Activity> mActivity;
private final LoginManager mLoginManager;
private final LoginCallback mLoginCallback = new LoginCallback();
private final CallbackManager mCallbackManager = CallbackManager.Factory.create();
public class LoginCallback implements FacebookCallback<LoginResult> {
public OnLoginListener loginListener;
boolean doOnLogin = false;
boolean askPublishPermissions = false;
List<String> publishPermissions;
@Override
public void onSuccess(LoginResult loginResult) {
if (loginListener != null) {
if (doOnLogin) {
doOnLogin = false;
askPublishPermissions = false;
publishPermissions = null;
loginListener.onLogin(loginResult.getAccessToken().getToken(), Permission.convert(getAcceptedPermissions()), Permission.convert(loginResult.getRecentlyDeniedPermissions()));
return;
}
if (askPublishPermissions && publishPermissions != null) {
doOnLogin = true;
askPublishPermissions = false;
requestPublishPermissions(publishPermissions);
} else {
loginListener.onLogin(loginResult.getAccessToken().getToken(), Permission.convert(getAcceptedPermissions()), Permission.convert(loginResult.getRecentlyDeniedPermissions()));
}
}
}
@Override
public void onCancel() {
loginListener.onFail("User canceled the permissions dialog");
}
@Override
public void onError(FacebookException e) {
loginListener.onException(e);
}
}
public SessionManager(SimpleFacebookConfiguration configuration) {
SessionManager.configuration = configuration;
mLoginManager = LoginManager.getInstance();
mLoginManager.registerCallback(mCallbackManager, mLoginCallback);
mLoginManager.setDefaultAudience(configuration.getDefaultAudience());
mLoginManager.setLoginBehavior(configuration.getLoginBehavior());
}
public void onActivityResult(int requestCode, int resultCode, Intent data) {
mCallbackManager.onActivityResult(requestCode, resultCode, data);
}
/**
* Login to Facebook
*
* @param onLoginListener
*/
public void login(OnLoginListener onLoginListener) {
if (onLoginListener == null) {
Logger.logError(TAG, "OnLoginListener can't be null in -> 'login(OnLoginListener onLoginListener)' method.");
return;
}
if (isLogin()) {
Logger.logInfo(TAG, "You were already logged in before calling 'login()' method.");
LoginResult loginResult = createLastLoginResult();
onLoginListener.onLogin(loginResult.getAccessToken().getToken(), Permission.convert(getAcceptedPermissions()), null);
return;
}
if (hasPendingRequest()) {
Logger.logWarning(TAG, "You are trying to login one more time, before finishing the previous login call");
onLoginListener.onFail("Already has pending login request");
return;
}
// just do the login
loginImpl(onLoginListener);
}
private void loginImpl(OnLoginListener onLoginListener) {
// user hasn't the access token with all read acceptedPermissions we need, thus we ask him to login
mLoginCallback.loginListener = onLoginListener;
// in case of marking in configuration the option of getting publish permission, just after read permissions
if (configuration.hasPublishPermissions() && configuration.isAllPermissionsAtOnce()) {
mLoginCallback.askPublishPermissions = true;
mLoginCallback.publishPermissions = configuration.getPublishPermissions();
}
// login please, with all read permissions
requestReadPermissions(configuration.getReadPermissions());
}
public void requestReadPermissions(List<String> permissions) {
mLoginManager.logInWithReadPermissions(mActivity.get(), permissions);
}
public void requestPublishPermissions(List<String> permissions) {
mLoginManager.logInWithPublishPermissions(mActivity.get(), permissions);
}
private LoginResult createLastLoginResult() {
return new LoginResult(getAccessToken(), getAccessToken().getPermissions(), getAccessToken().getDeclinedPermissions());
}
/**
* Logout from Facebook
*/
public void logout(OnLogoutListener onLogoutListener) {
if (onLogoutListener == null) {
Logger.logError(TAG, "OnLogoutListener can't be null in -> 'logout(OnLogoutListener onLogoutListener)' method");
return;
}
mLoginManager.logOut();
onLogoutListener.onLogout();
}
/**
* Indicate if you are logged in or not.
*
* @return <code>True</code> if you is logged in, otherwise return
* <code>False</code>
*/
public boolean isLogin() {
AccessToken accessToken = getAccessToken();
if (accessToken == null) {
return false;
}
return !accessToken.isExpired();
}
/**
* Get access token of open session
*
*/
public AccessToken getAccessToken() {
return AccessToken.getCurrentAccessToken();
}
public Set<String> getAcceptedPermissions() {
AccessToken accessToken = getAccessToken();
if (accessToken == null) {
return new HashSet<String>();
}
return accessToken.getPermissions();
}
public Set<String> getNotAcceptedPermissions() {
AccessToken accessToken = getAccessToken();
if (accessToken == null) {
return null;
}
return accessToken.getDeclinedPermissions();
}
void setActivity(Activity activity) {
mActivity = new WeakReference<Activity>(activity);
}
public Activity getActivity() {
return mActivity.get();
}
public LoginCallback getLoginCallback() {
return mLoginCallback;
}
public CallbackManager getCallbackManager() {
return mCallbackManager;
}
/**
* This checks if user had accepted all publish permissions for being able to use PublishAction
* @return
*/
public boolean hasAccepted(String permission) {
if (getAcceptedPermissions().contains(permission)) {
return true;
}
return false;
}
/**
* Requests any new permission in a runtime. <br>
* <br>
*
* Useful when you just want to request the action and won't be publishing
* at the time, but still need the updated <b>access token</b> with the
* permissions (possibly to pass back to your backend).
*
* <br>
* <b>Must be logged in to use.</b>
*
* @param perms
* New permissions you want to have. This array can include READ
* and PUBLISH permissions in the same time. Just ask what you
* need.<br>
* @param onNewPermissionListener
* The callback listener for the requesting new permission
* action.
*/
public void requestNewPermissions(final Permission[] perms, final OnNewPermissionsListener onNewPermissionListener) {
if (onNewPermissionListener == null) {
Logger.logWarning(TAG, "Must pass listener");
return;
}
List<Permission> permissions = Arrays.asList(perms);
if (permissions == null || permissions.size() == 0) {
onNewPermissionListener.onFail("Empty permissions in request");
return;
}
int flag = configuration.getType(permissions);
if (flag == 0) {
onNewPermissionListener.onFail("There is no new permissions in your request");
return;
}
mLoginCallback.loginListener = new OnLoginListener() {
@Override
public void onLogin(String accessToken, List<Permission> acceptedPermissions, List<Permission> declinedPermissions) {
onNewPermissionListener.onSuccess(accessToken, acceptedPermissions, declinedPermissions);
}
@Override
public void onCancel() {
onNewPermissionListener.onCancel();
}
@Override
public void onFail(String reason) {
onNewPermissionListener.onFail(reason);
}
@Override
public void onException(Throwable throwable) {
onNewPermissionListener.onException(throwable);
}
};
switch (flag) {
case 1:
requestReadPermissions(Permission.convert(permissions));
break;
case 3:
// in case of marking in configuration the option of getting publish permission, just after read permissions
if (configuration.isAllPermissionsAtOnce()) {
mLoginCallback.askPublishPermissions = true;
mLoginCallback.publishPermissions = Permission.fetchPermissions(permissions, Permission.Type.PUBLISH);
}
requestReadPermissions(Permission.fetchPermissions(permissions, Permission.Type.READ));
break;
case 2:
requestPublishPermissions(Permission.convert(permissions));
break;
}
}
public boolean hasPendingRequest() {
// waiting for fix on FB side for pull request: https://github.com/facebook/facebook-android-sdk/pull/431
// try {
// Field f = mLoginManager.getClass().getDeclaredField("pendingLoginRequest");
// f.setAccessible(true);
// Object request = f.get(mLoginManager);
// if (request != null) {
// return true;
// }
// } catch (Exception e) {
// // do nothing
// }
return false;
}
private List<String> getNotGrantedReadPermissions() {
Set<String> grantedPermissions = getAcceptedPermissions();
List<String> readPermissions = new ArrayList<String>(configuration.getReadPermissions());
readPermissions.removeAll(grantedPermissions);
return readPermissions;
}
private List<String> getNotGrantedPublishPermissions() {
Set<String> grantedPermissions = getAcceptedPermissions();
List<String> publishPermissions = new ArrayList<String>(configuration.getPublishPermissions());
publishPermissions.removeAll(grantedPermissions);
return publishPermissions;
}
public boolean isAllPermissionsGranted() {
if (getNotGrantedReadPermissions().size() > 0 || getNotGrantedPublishPermissions().size() > 0) {
return false;
}
return true;
}
public void clean() {
mActivity.clear();
}
}