Subversion Repositories SmartDukaan

Rev

Details | Last modification | View Log | RSS feed

Rev Author Line No. Line
14792 manas 1
/**
2
 * Copyright 2010-present Facebook.
3
 *
4
 * Licensed under the Apache License, Version 2.0 (the "License");
5
 * you may not use this file except in compliance with the License.
6
 * You may obtain a copy of the License at
7
 *
8
 *    http://www.apache.org/licenses/LICENSE-2.0
9
 *
10
 * Unless required by applicable law or agreed to in writing, software
11
 * distributed under the License is distributed on an "AS IS" BASIS,
12
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13
 * See the License for the specific language governing permissions and
14
 * limitations under the License.
15
 */
16
 
17
package com.facebook.widget;
18
 
19
import android.graphics.Bitmap;
20
import android.graphics.drawable.BitmapDrawable;
21
import android.graphics.drawable.Drawable;
22
import android.os.Bundle;
23
import android.text.TextUtils;
24
import android.view.LayoutInflater;
25
import android.view.View;
26
import android.view.ViewGroup;
27
import android.widget.TextView;
28
import com.facebook.*;
29
import com.facebook.android.R;
30
import com.facebook.internal.AnalyticsEvents;
31
import com.facebook.internal.ImageDownloader;
32
import com.facebook.internal.ImageRequest;
33
import com.facebook.internal.ImageResponse;
34
import com.facebook.model.GraphUser;
35
 
36
import java.net.URI;
37
import java.net.URISyntaxException;
38
import java.util.Arrays;
39
import java.util.List;
40
 
41
/**
42
 * A Fragment that displays a Login/Logout button as well as the user's
43
 * profile picture and name when logged in.
44
 * <p/>
45
 * This Fragment will create and use the active session upon construction
46
 * if it has the available data (if the app ID is specified in the manifest).
47
 * It will also open the active session if it does not require user interaction
48
 * (i.e. if the session is in the {@link com.facebook.SessionState#CREATED_TOKEN_LOADED} state.
49
 * Developers can override the use of the active session by calling
50
 * the {@link #setSession(com.facebook.Session)} method.
51
 */
52
public class UserSettingsFragment extends FacebookFragment {
53
 
54
    private static final String NAME = "name";
55
    private static final String ID = "id";
56
    private static final String PICTURE = "picture";
57
    private static final String FIELDS = "fields";
58
 
59
    private static final String REQUEST_FIELDS = TextUtils.join(",", new String[] {ID, NAME, PICTURE});
60
 
61
    private LoginButton loginButton;
62
    private LoginButton.LoginButtonProperties loginButtonProperties = new LoginButton.LoginButtonProperties();
63
    private TextView connectedStateLabel;
64
    private GraphUser user;
65
    private Session userInfoSession; // the Session used to fetch the current user info
66
    private Drawable userProfilePic;
67
    private String userProfilePicID;
68
    private Session.StatusCallback sessionStatusCallback;
69
 
70
    @Override
71
    public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
72
        View view = inflater.inflate(R.layout.com_facebook_usersettingsfragment, container, false);
73
        loginButton = (LoginButton) view.findViewById(R.id.com_facebook_usersettingsfragment_login_button);
74
        loginButton.setProperties(loginButtonProperties);
75
        loginButton.setFragment(this);
76
        loginButton.setLoginLogoutEventName(AnalyticsEvents.EVENT_USER_SETTINGS_USAGE);
77
 
78
        Session session = getSession();
79
        if (session != null && !session.equals(Session.getActiveSession())) {
80
            loginButton.setSession(session);
81
        }
82
        connectedStateLabel = (TextView) view.findViewById(R.id.com_facebook_usersettingsfragment_profile_name);
83
 
84
        // if no background is set for some reason, then default to Facebook blue
85
        if (view.getBackground() == null) {
86
            view.setBackgroundColor(getResources().getColor(R.color.com_facebook_blue));
87
        } else {
88
            view.getBackground().setDither(true);
89
        }
90
        return view;
91
    }
92
 
93
    @Override
94
    public void onCreate(Bundle savedInstanceState) {
95
        super.onCreate(savedInstanceState);
96
        setRetainInstance(true);
97
    }
98
 
99
    /**
100
     * @throws com.facebook.FacebookException if errors occur during the loading of user information
101
     */
102
    @Override
103
    public void onResume() {
104
        super.onResume();
105
        fetchUserInfo();
106
        updateUI();
107
    }
108
 
109
    /**
110
     * Set the Session object to use instead of the active Session. Since a Session
111
     * cannot be reused, if the user logs out from this Session, and tries to
112
     * log in again, a new Active Session will be used instead.
113
     * <p/>
114
     * If the passed in session is currently opened, this method will also attempt to
115
     * load some user information for display (if needed).
116
     *
117
     * @param newSession the Session object to use
118
     * @throws com.facebook.FacebookException if errors occur during the loading of user information
119
     */
120
    @Override
121
    public void setSession(Session newSession) {
122
        super.setSession(newSession);
123
        if (loginButton != null) {
124
            loginButton.setSession(newSession);
125
        }
126
        fetchUserInfo();
127
        updateUI();
128
    }
129
 
130
    /**
131
     * Sets the default audience to use when the session is opened.
132
     * This value is only useful when specifying write permissions for the native
133
     * login dialog.
134
     *
135
     * @param defaultAudience the default audience value to use
136
     */
137
    public void setDefaultAudience(SessionDefaultAudience defaultAudience) {
138
        loginButtonProperties.setDefaultAudience(defaultAudience);
139
    }
140
 
141
    /**
142
     * Gets the default audience to use when the session is opened.
143
     * This value is only useful when specifying write permissions for the native
144
     * login dialog.
145
     *
146
     * @return the default audience value to use
147
     */
148
    public SessionDefaultAudience getDefaultAudience() {
149
        return loginButtonProperties.getDefaultAudience();
150
    }
151
 
152
    /**
153
     * Set the permissions to use when the session is opened. The permissions here
154
     * can only be read permissions. If any publish permissions are included, the login
155
     * attempt by the user will fail. The LoginButton can only be associated with either
156
     * read permissions or publish permissions, but not both. Calling both
157
     * setReadPermissions and setPublishPermissions on the same instance of LoginButton
158
     * will result in an exception being thrown unless clearPermissions is called in between.
159
     * <p/>
160
     * This method is only meaningful if called before the session is open. If this is called
161
     * after the session is opened, and the list of permissions passed in is not a subset
162
     * of the permissions granted during the authorization, it will log an error.
163
     * <p/>
164
     * Since the session can be automatically opened when the UserSettingsFragment is constructed,
165
     * it's important to always pass in a consistent set of permissions to this method, or
166
     * manage the setting of permissions outside of the LoginButton class altogether
167
     * (by managing the session explicitly).
168
     *
169
     * @param permissions the read permissions to use
170
     *
171
     * @throws UnsupportedOperationException if setPublishPermissions has been called
172
     */
173
    public void setReadPermissions(List<String> permissions) {
174
        loginButtonProperties.setReadPermissions(permissions, getSession());
175
    }
176
 
177
    /**
178
     * Set the permissions to use when the session is opened. The permissions here
179
     * can only be read permissions. If any publish permissions are included, the login
180
     * attempt by the user will fail. The LoginButton can only be associated with either
181
     * read permissions or publish permissions, but not both. Calling both
182
     * setReadPermissions and setPublishPermissions on the same instance of LoginButton
183
     * will result in an exception being thrown unless clearPermissions is called in between.
184
     * <p/>
185
     * This method is only meaningful if called before the session is open. If this is called
186
     * after the session is opened, and the list of permissions passed in is not a subset
187
     * of the permissions granted during the authorization, it will log an error.
188
     * <p/>
189
     * Since the session can be automatically opened when the UserSettingsFragment is constructed,
190
     * it's important to always pass in a consistent set of permissions to this method, or
191
     * manage the setting of permissions outside of the LoginButton class altogether
192
     * (by managing the session explicitly).
193
     *
194
     * @param permissions the read permissions to use
195
     *
196
     * @throws UnsupportedOperationException if setPublishPermissions has been called
197
     */
198
    public void setReadPermissions(String... permissions) {
199
        loginButtonProperties.setReadPermissions(Arrays.asList(permissions), getSession());
200
    }
201
 
202
    /**
203
     * Set the permissions to use when the session is opened. The permissions here
204
     * should only be publish permissions. If any read permissions are included, the login
205
     * attempt by the user may fail. The LoginButton can only be associated with either
206
     * read permissions or publish permissions, but not both. Calling both
207
     * setReadPermissions and setPublishPermissions on the same instance of LoginButton
208
     * will result in an exception being thrown unless clearPermissions is called in between.
209
     * <p/>
210
     * This method is only meaningful if called before the session is open. If this is called
211
     * after the session is opened, and the list of permissions passed in is not a subset
212
     * of the permissions granted during the authorization, it will log an error.
213
     * <p/>
214
     * Since the session can be automatically opened when the LoginButton is constructed,
215
     * it's important to always pass in a consistent set of permissions to this method, or
216
     * manage the setting of permissions outside of the LoginButton class altogether
217
     * (by managing the session explicitly).
218
     *
219
     * @param permissions the read permissions to use
220
     *
221
     * @throws UnsupportedOperationException if setReadPermissions has been called
222
     * @throws IllegalArgumentException if permissions is null or empty
223
     */
224
    public void setPublishPermissions(List<String> permissions) {
225
        loginButtonProperties.setPublishPermissions(permissions, getSession());
226
    }
227
 
228
    /**
229
     * Set the permissions to use when the session is opened. The permissions here
230
     * should only be publish permissions. If any read permissions are included, the login
231
     * attempt by the user may fail. The LoginButton can only be associated with either
232
     * read permissions or publish permissions, but not both. Calling both
233
     * setReadPermissions and setPublishPermissions on the same instance of LoginButton
234
     * will result in an exception being thrown unless clearPermissions is called in between.
235
     * <p/>
236
     * This method is only meaningful if called before the session is open. If this is called
237
     * after the session is opened, and the list of permissions passed in is not a subset
238
     * of the permissions granted during the authorization, it will log an error.
239
     * <p/>
240
     * Since the session can be automatically opened when the LoginButton is constructed,
241
     * it's important to always pass in a consistent set of permissions to this method, or
242
     * manage the setting of permissions outside of the LoginButton class altogether
243
     * (by managing the session explicitly).
244
     *
245
     * @param permissions the read permissions to use
246
     *
247
     * @throws UnsupportedOperationException if setReadPermissions has been called
248
     * @throws IllegalArgumentException if permissions is null or empty
249
     */
250
    public void setPublishPermissions(String... permissions) {
251
        loginButtonProperties.setPublishPermissions(Arrays.asList(permissions), getSession());
252
    }
253
 
254
 
255
    /**
256
     * Clears the permissions currently associated with this LoginButton.
257
     */
258
    public void clearPermissions() {
259
        loginButtonProperties.clearPermissions();
260
    }
261
 
262
    /**
263
     * Sets the login behavior for the session that will be opened. If null is specified,
264
     * the default ({@link SessionLoginBehavior SessionLoginBehavior.SSO_WITH_FALLBACK}
265
     * will be used.
266
     *
267
     * @param loginBehavior The {@link SessionLoginBehavior SessionLoginBehavior} that
268
     *                      specifies what behaviors should be attempted during
269
     *                      authorization.
270
     */
271
    public void setLoginBehavior(SessionLoginBehavior loginBehavior) {
272
        loginButtonProperties.setLoginBehavior(loginBehavior);
273
    }
274
 
275
    /**
276
     * Gets the login behavior for the session that will be opened. If null is returned,
277
     * the default ({@link SessionLoginBehavior SessionLoginBehavior.SSO_WITH_FALLBACK}
278
     * will be used.
279
     *
280
     * @return loginBehavior The {@link SessionLoginBehavior SessionLoginBehavior} that
281
     *                      specifies what behaviors should be attempted during
282
     *                      authorization.
283
     */
284
    public SessionLoginBehavior getLoginBehavior() {
285
        return loginButtonProperties.getLoginBehavior();
286
    }
287
 
288
    /**
289
     * Sets an OnErrorListener for this instance of UserSettingsFragment to call into when
290
     * certain exceptions occur.
291
     *
292
     * @param onErrorListener The listener object to set
293
     */
294
    public void setOnErrorListener(LoginButton.OnErrorListener onErrorListener) {
295
        loginButtonProperties.setOnErrorListener(onErrorListener);
296
    }
297
 
298
    /**
299
     * Returns the current OnErrorListener for this instance of UserSettingsFragment.
300
     *
301
     * @return The OnErrorListener
302
     */
303
    public LoginButton.OnErrorListener getOnErrorListener() {
304
        return loginButtonProperties.getOnErrorListener();
305
    }
306
 
307
    /**
308
     * Sets the callback interface that will be called whenever the status of the Session
309
     * associated with this LoginButton changes.
310
     *
311
     * @param callback the callback interface
312
     */
313
    public void setSessionStatusCallback(Session.StatusCallback callback) {
314
        this.sessionStatusCallback = callback;
315
    }
316
 
317
    /**
318
     * Sets the callback interface that will be called whenever the status of the Session
319
     * associated with this LoginButton changes.
320
 
321
     * @return the callback interface
322
     */
323
    public Session.StatusCallback getSessionStatusCallback() {
324
        return sessionStatusCallback;
325
    }
326
 
327
    @Override
328
    protected void onSessionStateChange(SessionState state, Exception exception) {
329
        fetchUserInfo();
330
        updateUI();
331
 
332
        if (sessionStatusCallback != null) {
333
            sessionStatusCallback.call(getSession(), state, exception);
334
        }
335
    }
336
 
337
    // For Testing Only
338
    List<String> getPermissions() {
339
        return loginButtonProperties.getPermissions();
340
    }
341
 
342
    private void fetchUserInfo() {
343
        final Session currentSession = getSession();
344
        if (currentSession != null && currentSession.isOpened()) {
345
            if (currentSession != userInfoSession) {
346
                Request request = Request.newMeRequest(currentSession, new Request.GraphUserCallback() {
347
                    @Override
348
                    public void onCompleted(GraphUser me, Response response) {
349
                        if (currentSession == getSession()) {
350
                            user = me;
351
                            updateUI();
352
                        }
353
                        if (response.getError() != null) {
354
                            loginButton.handleError(response.getError().getException());
355
                        }
356
                    }
357
                });
358
                Bundle parameters = new Bundle();
359
                parameters.putString(FIELDS, REQUEST_FIELDS);
360
                request.setParameters(parameters);
361
                Request.executeBatchAsync(request);
362
                userInfoSession = currentSession;
363
            }
364
        } else {
365
            user = null;
366
        }
367
    }
368
 
369
    private void updateUI() {
370
        if (!isAdded()) {
371
            return;
372
        }
373
        if (isSessionOpen()) {
374
            connectedStateLabel.setTextColor(getResources().getColor(R.color.com_facebook_usersettingsfragment_connected_text_color));
375
            connectedStateLabel.setShadowLayer(1f, 0f, -1f,
376
                    getResources().getColor(R.color.com_facebook_usersettingsfragment_connected_shadow_color));
377
 
378
            if (user != null) {
379
                ImageRequest request = getImageRequest();
380
                if (request != null) {
381
                    URI requestUrl = request.getImageUri();
382
                    // Do we already have the right picture? If so, leave it alone.
383
                    if (!requestUrl.equals(connectedStateLabel.getTag())) {
384
                        if (user.getId().equals(userProfilePicID)) {
385
                            connectedStateLabel.setCompoundDrawables(null, userProfilePic, null, null);
386
                            connectedStateLabel.setTag(requestUrl);
387
                        } else {
388
                            ImageDownloader.downloadAsync(request);
389
                        }
390
                    }
391
                }
392
                connectedStateLabel.setText(user.getName());
393
            } else {
394
                connectedStateLabel.setText(getResources().getString(
395
                        R.string.com_facebook_usersettingsfragment_logged_in));
396
                Drawable noProfilePic = getResources().getDrawable(R.drawable.com_facebook_profile_default_icon);
397
                noProfilePic.setBounds(0, 0,
398
                        getResources().getDimensionPixelSize(R.dimen.com_facebook_usersettingsfragment_profile_picture_width),
399
                        getResources().getDimensionPixelSize(R.dimen.com_facebook_usersettingsfragment_profile_picture_height));
400
                connectedStateLabel.setCompoundDrawables(null, noProfilePic, null, null);
401
            }
402
        } else {
403
            int textColor = getResources().getColor(R.color.com_facebook_usersettingsfragment_not_connected_text_color);
404
            connectedStateLabel.setTextColor(textColor);
405
            connectedStateLabel.setShadowLayer(0f, 0f, 0f, textColor);
406
            connectedStateLabel.setText(getResources().getString(
407
                    R.string.com_facebook_usersettingsfragment_not_logged_in));
408
            connectedStateLabel.setCompoundDrawables(null, null, null, null);
409
            connectedStateLabel.setTag(null);
410
        }
411
    }
412
 
413
    private ImageRequest getImageRequest() {
414
        ImageRequest request = null;
415
        try {
416
            ImageRequest.Builder requestBuilder = new ImageRequest.Builder(
417
                    getActivity(),
418
                    ImageRequest.getProfilePictureUrl(
419
                            user.getId(),
420
                            getResources().getDimensionPixelSize(R.dimen.com_facebook_usersettingsfragment_profile_picture_width),
421
                            getResources().getDimensionPixelSize(R.dimen.com_facebook_usersettingsfragment_profile_picture_height)));
422
 
423
            request = requestBuilder.setCallerTag(this)
424
                    .setCallback(
425
                            new ImageRequest.Callback() {
426
                                @Override
427
                                public void onCompleted(ImageResponse response) {
428
                                    processImageResponse(user.getId(), response);
429
                                }
430
                            })
431
                    .build();
432
        } catch (URISyntaxException e) {
433
        }
434
        return request;
435
    }
436
 
437
    private void processImageResponse(String id, ImageResponse response) {
438
        if (response != null) {
439
            Bitmap bitmap = response.getBitmap();
440
            if (bitmap != null) {
441
                BitmapDrawable drawable = new BitmapDrawable(UserSettingsFragment.this.getResources(), bitmap);
442
                drawable.setBounds(0, 0,
443
                        getResources().getDimensionPixelSize(R.dimen.com_facebook_usersettingsfragment_profile_picture_width),
444
                        getResources().getDimensionPixelSize(R.dimen.com_facebook_usersettingsfragment_profile_picture_height));
445
                userProfilePic = drawable;
446
                userProfilePicID = id;
447
                connectedStateLabel.setCompoundDrawables(null, drawable, null, null);
448
                connectedStateLabel.setTag(response.getRequest().getImageUri());
449
            }
450
        }
451
    }
452
}