Blame | Last modification | View Log | RSS feed
/*** Copyright 2010-present Facebook.** Licensed under the Apache License, Version 2.0 (the "License");* you may not use this file except in compliance with the License.* You may obtain a copy of the License at** http://www.apache.org/licenses/LICENSE-2.0** Unless required by applicable law or agreed to in writing, software* distributed under the License is distributed on an "AS IS" BASIS,* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.* See the License for the specific language governing permissions and* limitations under the License.*/package com.facebook.widget;import android.graphics.Bitmap;import android.graphics.drawable.BitmapDrawable;import android.graphics.drawable.Drawable;import android.os.Bundle;import android.text.TextUtils;import android.view.LayoutInflater;import android.view.View;import android.view.ViewGroup;import android.widget.TextView;import com.facebook.*;import com.facebook.android.R;import com.facebook.internal.AnalyticsEvents;import com.facebook.internal.ImageDownloader;import com.facebook.internal.ImageRequest;import com.facebook.internal.ImageResponse;import com.facebook.model.GraphUser;import java.net.URI;import java.net.URISyntaxException;import java.util.Arrays;import java.util.List;/*** A Fragment that displays a Login/Logout button as well as the user's* profile picture and name when logged in.* <p/>* This Fragment will create and use the active session upon construction* if it has the available data (if the app ID is specified in the manifest).* It will also open the active session if it does not require user interaction* (i.e. if the session is in the {@link com.facebook.SessionState#CREATED_TOKEN_LOADED} state.* Developers can override the use of the active session by calling* the {@link #setSession(com.facebook.Session)} method.*/public class UserSettingsFragment extends FacebookFragment {private static final String NAME = "name";private static final String ID = "id";private static final String PICTURE = "picture";private static final String FIELDS = "fields";private static final String REQUEST_FIELDS = TextUtils.join(",", new String[] {ID, NAME, PICTURE});private LoginButton loginButton;private LoginButton.LoginButtonProperties loginButtonProperties = new LoginButton.LoginButtonProperties();private TextView connectedStateLabel;private GraphUser user;private Session userInfoSession; // the Session used to fetch the current user infoprivate Drawable userProfilePic;private String userProfilePicID;private Session.StatusCallback sessionStatusCallback;@Overridepublic View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {View view = inflater.inflate(R.layout.com_facebook_usersettingsfragment, container, false);loginButton = (LoginButton) view.findViewById(R.id.com_facebook_usersettingsfragment_login_button);loginButton.setProperties(loginButtonProperties);loginButton.setFragment(this);loginButton.setLoginLogoutEventName(AnalyticsEvents.EVENT_USER_SETTINGS_USAGE);Session session = getSession();if (session != null && !session.equals(Session.getActiveSession())) {loginButton.setSession(session);}connectedStateLabel = (TextView) view.findViewById(R.id.com_facebook_usersettingsfragment_profile_name);// if no background is set for some reason, then default to Facebook blueif (view.getBackground() == null) {view.setBackgroundColor(getResources().getColor(R.color.com_facebook_blue));} else {view.getBackground().setDither(true);}return view;}@Overridepublic void onCreate(Bundle savedInstanceState) {super.onCreate(savedInstanceState);setRetainInstance(true);}/*** @throws com.facebook.FacebookException if errors occur during the loading of user information*/@Overridepublic void onResume() {super.onResume();fetchUserInfo();updateUI();}/*** Set the Session object to use instead of the active Session. Since a Session* cannot be reused, if the user logs out from this Session, and tries to* log in again, a new Active Session will be used instead.* <p/>* If the passed in session is currently opened, this method will also attempt to* load some user information for display (if needed).** @param newSession the Session object to use* @throws com.facebook.FacebookException if errors occur during the loading of user information*/@Overridepublic void setSession(Session newSession) {super.setSession(newSession);if (loginButton != null) {loginButton.setSession(newSession);}fetchUserInfo();updateUI();}/*** Sets the default audience to use when the session is opened.* This value is only useful when specifying write permissions for the native* login dialog.** @param defaultAudience the default audience value to use*/public void setDefaultAudience(SessionDefaultAudience defaultAudience) {loginButtonProperties.setDefaultAudience(defaultAudience);}/*** Gets the default audience to use when the session is opened.* This value is only useful when specifying write permissions for the native* login dialog.** @return the default audience value to use*/public SessionDefaultAudience getDefaultAudience() {return loginButtonProperties.getDefaultAudience();}/*** Set the permissions to use when the session is opened. The permissions here* can only be read permissions. If any publish permissions are included, the login* attempt by the user will fail. The LoginButton can only be associated with either* read permissions or publish permissions, but not both. Calling both* setReadPermissions and setPublishPermissions on the same instance of LoginButton* will result in an exception being thrown unless clearPermissions is called in between.* <p/>* This method is only meaningful if called before the session is open. If this is called* after the session is opened, and the list of permissions passed in is not a subset* of the permissions granted during the authorization, it will log an error.* <p/>* Since the session can be automatically opened when the UserSettingsFragment is constructed,* it's important to always pass in a consistent set of permissions to this method, or* manage the setting of permissions outside of the LoginButton class altogether* (by managing the session explicitly).** @param permissions the read permissions to use** @throws UnsupportedOperationException if setPublishPermissions has been called*/public void setReadPermissions(List<String> permissions) {loginButtonProperties.setReadPermissions(permissions, getSession());}/*** Set the permissions to use when the session is opened. The permissions here* can only be read permissions. If any publish permissions are included, the login* attempt by the user will fail. The LoginButton can only be associated with either* read permissions or publish permissions, but not both. Calling both* setReadPermissions and setPublishPermissions on the same instance of LoginButton* will result in an exception being thrown unless clearPermissions is called in between.* <p/>* This method is only meaningful if called before the session is open. If this is called* after the session is opened, and the list of permissions passed in is not a subset* of the permissions granted during the authorization, it will log an error.* <p/>* Since the session can be automatically opened when the UserSettingsFragment is constructed,* it's important to always pass in a consistent set of permissions to this method, or* manage the setting of permissions outside of the LoginButton class altogether* (by managing the session explicitly).** @param permissions the read permissions to use** @throws UnsupportedOperationException if setPublishPermissions has been called*/public void setReadPermissions(String... permissions) {loginButtonProperties.setReadPermissions(Arrays.asList(permissions), getSession());}/*** Set the permissions to use when the session is opened. The permissions here* should only be publish permissions. If any read permissions are included, the login* attempt by the user may fail. The LoginButton can only be associated with either* read permissions or publish permissions, but not both. Calling both* setReadPermissions and setPublishPermissions on the same instance of LoginButton* will result in an exception being thrown unless clearPermissions is called in between.* <p/>* This method is only meaningful if called before the session is open. If this is called* after the session is opened, and the list of permissions passed in is not a subset* of the permissions granted during the authorization, it will log an error.* <p/>* Since the session can be automatically opened when the LoginButton is constructed,* it's important to always pass in a consistent set of permissions to this method, or* manage the setting of permissions outside of the LoginButton class altogether* (by managing the session explicitly).** @param permissions the read permissions to use** @throws UnsupportedOperationException if setReadPermissions has been called* @throws IllegalArgumentException if permissions is null or empty*/public void setPublishPermissions(List<String> permissions) {loginButtonProperties.setPublishPermissions(permissions, getSession());}/*** Set the permissions to use when the session is opened. The permissions here* should only be publish permissions. If any read permissions are included, the login* attempt by the user may fail. The LoginButton can only be associated with either* read permissions or publish permissions, but not both. Calling both* setReadPermissions and setPublishPermissions on the same instance of LoginButton* will result in an exception being thrown unless clearPermissions is called in between.* <p/>* This method is only meaningful if called before the session is open. If this is called* after the session is opened, and the list of permissions passed in is not a subset* of the permissions granted during the authorization, it will log an error.* <p/>* Since the session can be automatically opened when the LoginButton is constructed,* it's important to always pass in a consistent set of permissions to this method, or* manage the setting of permissions outside of the LoginButton class altogether* (by managing the session explicitly).** @param permissions the read permissions to use** @throws UnsupportedOperationException if setReadPermissions has been called* @throws IllegalArgumentException if permissions is null or empty*/public void setPublishPermissions(String... permissions) {loginButtonProperties.setPublishPermissions(Arrays.asList(permissions), getSession());}/*** Clears the permissions currently associated with this LoginButton.*/public void clearPermissions() {loginButtonProperties.clearPermissions();}/*** Sets the login behavior for the session that will be opened. If null is specified,* the default ({@link SessionLoginBehavior SessionLoginBehavior.SSO_WITH_FALLBACK}* will be used.** @param loginBehavior The {@link SessionLoginBehavior SessionLoginBehavior} that* specifies what behaviors should be attempted during* authorization.*/public void setLoginBehavior(SessionLoginBehavior loginBehavior) {loginButtonProperties.setLoginBehavior(loginBehavior);}/*** Gets the login behavior for the session that will be opened. If null is returned,* the default ({@link SessionLoginBehavior SessionLoginBehavior.SSO_WITH_FALLBACK}* will be used.** @return loginBehavior The {@link SessionLoginBehavior SessionLoginBehavior} that* specifies what behaviors should be attempted during* authorization.*/public SessionLoginBehavior getLoginBehavior() {return loginButtonProperties.getLoginBehavior();}/*** Sets an OnErrorListener for this instance of UserSettingsFragment to call into when* certain exceptions occur.** @param onErrorListener The listener object to set*/public void setOnErrorListener(LoginButton.OnErrorListener onErrorListener) {loginButtonProperties.setOnErrorListener(onErrorListener);}/*** Returns the current OnErrorListener for this instance of UserSettingsFragment.** @return The OnErrorListener*/public LoginButton.OnErrorListener getOnErrorListener() {return loginButtonProperties.getOnErrorListener();}/*** Sets the callback interface that will be called whenever the status of the Session* associated with this LoginButton changes.** @param callback the callback interface*/public void setSessionStatusCallback(Session.StatusCallback callback) {this.sessionStatusCallback = callback;}/*** Sets the callback interface that will be called whenever the status of the Session* associated with this LoginButton changes.* @return the callback interface*/public Session.StatusCallback getSessionStatusCallback() {return sessionStatusCallback;}@Overrideprotected void onSessionStateChange(SessionState state, Exception exception) {fetchUserInfo();updateUI();if (sessionStatusCallback != null) {sessionStatusCallback.call(getSession(), state, exception);}}// For Testing OnlyList<String> getPermissions() {return loginButtonProperties.getPermissions();}private void fetchUserInfo() {final Session currentSession = getSession();if (currentSession != null && currentSession.isOpened()) {if (currentSession != userInfoSession) {Request request = Request.newMeRequest(currentSession, new Request.GraphUserCallback() {@Overridepublic void onCompleted(GraphUser me, Response response) {if (currentSession == getSession()) {user = me;updateUI();}if (response.getError() != null) {loginButton.handleError(response.getError().getException());}}});Bundle parameters = new Bundle();parameters.putString(FIELDS, REQUEST_FIELDS);request.setParameters(parameters);Request.executeBatchAsync(request);userInfoSession = currentSession;}} else {user = null;}}private void updateUI() {if (!isAdded()) {return;}if (isSessionOpen()) {connectedStateLabel.setTextColor(getResources().getColor(R.color.com_facebook_usersettingsfragment_connected_text_color));connectedStateLabel.setShadowLayer(1f, 0f, -1f,getResources().getColor(R.color.com_facebook_usersettingsfragment_connected_shadow_color));if (user != null) {ImageRequest request = getImageRequest();if (request != null) {URI requestUrl = request.getImageUri();// Do we already have the right picture? If so, leave it alone.if (!requestUrl.equals(connectedStateLabel.getTag())) {if (user.getId().equals(userProfilePicID)) {connectedStateLabel.setCompoundDrawables(null, userProfilePic, null, null);connectedStateLabel.setTag(requestUrl);} else {ImageDownloader.downloadAsync(request);}}}connectedStateLabel.setText(user.getName());} else {connectedStateLabel.setText(getResources().getString(R.string.com_facebook_usersettingsfragment_logged_in));Drawable noProfilePic = getResources().getDrawable(R.drawable.com_facebook_profile_default_icon);noProfilePic.setBounds(0, 0,getResources().getDimensionPixelSize(R.dimen.com_facebook_usersettingsfragment_profile_picture_width),getResources().getDimensionPixelSize(R.dimen.com_facebook_usersettingsfragment_profile_picture_height));connectedStateLabel.setCompoundDrawables(null, noProfilePic, null, null);}} else {int textColor = getResources().getColor(R.color.com_facebook_usersettingsfragment_not_connected_text_color);connectedStateLabel.setTextColor(textColor);connectedStateLabel.setShadowLayer(0f, 0f, 0f, textColor);connectedStateLabel.setText(getResources().getString(R.string.com_facebook_usersettingsfragment_not_logged_in));connectedStateLabel.setCompoundDrawables(null, null, null, null);connectedStateLabel.setTag(null);}}private ImageRequest getImageRequest() {ImageRequest request = null;try {ImageRequest.Builder requestBuilder = new ImageRequest.Builder(getActivity(),ImageRequest.getProfilePictureUrl(user.getId(),getResources().getDimensionPixelSize(R.dimen.com_facebook_usersettingsfragment_profile_picture_width),getResources().getDimensionPixelSize(R.dimen.com_facebook_usersettingsfragment_profile_picture_height)));request = requestBuilder.setCallerTag(this).setCallback(new ImageRequest.Callback() {@Overridepublic void onCompleted(ImageResponse response) {processImageResponse(user.getId(), response);}}).build();} catch (URISyntaxException e) {}return request;}private void processImageResponse(String id, ImageResponse response) {if (response != null) {Bitmap bitmap = response.getBitmap();if (bitmap != null) {BitmapDrawable drawable = new BitmapDrawable(UserSettingsFragment.this.getResources(), bitmap);drawable.setBounds(0, 0,getResources().getDimensionPixelSize(R.dimen.com_facebook_usersettingsfragment_profile_picture_width),getResources().getDimensionPixelSize(R.dimen.com_facebook_usersettingsfragment_profile_picture_height));userProfilePic = drawable;userProfilePicID = id;connectedStateLabel.setCompoundDrawables(null, drawable, null, null);connectedStateLabel.setTag(response.getRequest().getImageUri());}}}}