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.annotation.SuppressLint;
20
import android.app.Dialog;
21
import android.app.ProgressDialog;
22
import android.content.Context;
23
import android.content.DialogInterface;
24
import android.content.Intent;
25
import android.graphics.Bitmap;
26
import android.graphics.Color;
27
import android.graphics.drawable.Drawable;
28
import android.net.Uri;
29
import android.net.http.SslError;
30
import android.os.Bundle;
31
import android.util.DisplayMetrics;
32
import android.view.*;
33
import android.webkit.SslErrorHandler;
34
import android.webkit.WebView;
35
import android.webkit.WebViewClient;
36
import android.widget.FrameLayout;
37
import android.widget.ImageView;
38
import android.widget.LinearLayout;
39
import com.facebook.*;
40
import com.facebook.android.R;
41
import com.facebook.internal.Logger;
42
import com.facebook.internal.ServerProtocol;
43
import com.facebook.internal.Utility;
44
import com.facebook.internal.Validate;
45
 
46
/**
47
 * This class provides a mechanism for displaying Facebook Web dialogs inside a Dialog. Helper
48
 * methods are provided to construct commonly-used dialogs, or a caller can specify arbitrary
49
 * parameters to call other dialogs.
50
 */
51
public class WebDialog extends Dialog {
52
    private static final String LOG_TAG = Logger.LOG_TAG_BASE + "WebDialog";
53
    private static final String DISPLAY_TOUCH = "touch";
54
    private static final int API_EC_DIALOG_CANCEL = 4201;
55
    static final String REDIRECT_URI = "fbconnect://success";
56
    static final String CANCEL_URI = "fbconnect://cancel";
57
    static final boolean DISABLE_SSL_CHECK_FOR_TESTING = false;
58
 
59
    // width below which there are no extra margins
60
    private static final int NO_PADDING_SCREEN_WIDTH = 480;
61
    // width beyond which we're always using the MIN_SCALE_FACTOR
62
    private static final int MAX_PADDING_SCREEN_WIDTH = 800;
63
    // height below which there are no extra margins
64
    private static final int NO_PADDING_SCREEN_HEIGHT = 800;
65
    // height beyond which we're always using the MIN_SCALE_FACTOR
66
    private static final int MAX_PADDING_SCREEN_HEIGHT = 1280;
67
 
68
    // the minimum scaling factor for the web dialog (50% of screen size)
69
    private static final double MIN_SCALE_FACTOR = 0.5;
70
    // translucent border around the webview
71
    private static final int BACKGROUND_GRAY = 0xCC000000;
72
 
73
    public static final int DEFAULT_THEME = android.R.style.Theme_Translucent_NoTitleBar;
74
 
75
    private String url;
76
    private String expectedRedirectUrl = REDIRECT_URI;
77
    private OnCompleteListener onCompleteListener;
78
    private WebView webView;
79
    private ProgressDialog spinner;
80
    private ImageView crossImageView;
81
    private FrameLayout contentFrameLayout;
82
    private boolean listenerCalled = false;
83
    private boolean isDetached = false;
84
    private boolean isDismissed = false;
85
 
86
    /**
87
     * Interface that implements a listener to be called when the user's interaction with the
88
     * dialog completes, whether because the dialog finished successfully, or it was cancelled,
89
     * or an error was encountered.
90
     */
91
    public interface OnCompleteListener {
92
        /**
93
         * Called when the dialog completes.
94
         *
95
         * @param values on success, contains the values returned by the dialog
96
         * @param error  on an error, contains an exception describing the error
97
         */
98
        void onComplete(Bundle values, FacebookException error);
99
    }
100
 
101
    /**
102
     * Constructor which can be used to display a dialog with an already-constructed URL.
103
     *
104
     * @param context the context to use to display the dialog
105
     * @param url     the URL of the Web Dialog to display; no validation is done on this URL, but it should
106
     *                be a valid URL pointing to a Facebook Web Dialog
107
     */
108
    public WebDialog(Context context, String url) {
109
        this(context, url, DEFAULT_THEME);
110
    }
111
 
112
    /**
113
     * Constructor which can be used to display a dialog with an already-constructed URL and a custom theme.
114
     *
115
     * @param context the context to use to display the dialog
116
     * @param url     the URL of the Web Dialog to display; no validation is done on this URL, but it should
117
     *                be a valid URL pointing to a Facebook Web Dialog
118
     * @param theme   identifier of a theme to pass to the Dialog class
119
     */
120
    public WebDialog(Context context, String url, int theme) {
121
        super(context, theme);
122
        this.url = url;
123
    }
124
 
125
    /**
126
     * Constructor which will construct the URL of the Web dialog based on the specified parameters.
127
     *
128
     * @param context    the context to use to display the dialog
129
     * @param action     the portion of the dialog URL following "dialog/"
130
     * @param parameters parameters which will be included as part of the URL
131
     * @param theme      identifier of a theme to pass to the Dialog class
132
     * @param listener the listener to notify, or null if no notification is desired
133
     */
134
    public WebDialog(Context context, String action, Bundle parameters, int theme, OnCompleteListener listener) {
135
        super(context, theme);
136
 
137
        if (parameters == null) {
138
            parameters = new Bundle();
139
        }
140
 
141
        // our webview client only handles the redirect uri we specify, so just hard code it here
142
        parameters.putString(ServerProtocol.DIALOG_PARAM_REDIRECT_URI, REDIRECT_URI);
143
 
144
        parameters.putString(ServerProtocol.DIALOG_PARAM_DISPLAY, DISPLAY_TOUCH);
145
 
146
        Uri uri = Utility.buildUri(
147
                ServerProtocol.getDialogAuthority(),
148
                ServerProtocol.getAPIVersion() + "/" + ServerProtocol.DIALOG_PATH + action,
149
                parameters);
150
        this.url = uri.toString();
151
        onCompleteListener = listener;
152
    }
153
 
154
    /**
155
     * Sets the listener which will be notified when the dialog finishes.
156
     *
157
     * @param listener the listener to notify, or null if no notification is desired
158
     */
159
    public void setOnCompleteListener(OnCompleteListener listener) {
160
        onCompleteListener = listener;
161
    }
162
 
163
    /**
164
     * Gets the listener which will be notified when the dialog finishes.
165
     *
166
     * @return the listener, or null if none has been specified
167
     */
168
    public OnCompleteListener getOnCompleteListener() {
169
        return onCompleteListener;
170
    }
171
 
172
    @Override
173
    public void dismiss() {
174
        if (isDismissed) {
175
            // Some paths may cause dismiss() to be called recursively. Break the loop here.
176
            return;
177
        }
178
        isDismissed = true;
179
 
180
        // If dismiss() was called without sending a result to the listener, let's default to a "cancel" result.
181
        // This will be the case when the user taps the OS-back-button, or the cross-image, or outside the loading
182
        // interstitial.
183
        if (!listenerCalled) {
184
            sendCancelToListener();
185
        }
186
 
187
        if (webView != null) {
188
            webView.stopLoading();
189
        }
190
        if (!isDetached) {
191
            if (spinner.isShowing()) {
192
                spinner.dismiss();
193
            }
194
            super.dismiss();
195
        }
196
    }
197
 
198
    @Override
199
    public void onDetachedFromWindow() {
200
        isDetached = true;
201
        super.onDetachedFromWindow();
202
    }
203
 
204
    @Override
205
    public void onAttachedToWindow() {
206
        isDetached = false;
207
        super.onAttachedToWindow();
208
    }
209
 
210
    @Override
211
    protected void onCreate(Bundle savedInstanceState) {
212
        super.onCreate(savedInstanceState);
213
 
214
        spinner = new ProgressDialog(getContext());
215
       /* spinner.requestWindowFeature(Window.FEATURE_NO_TITLE);*/
216
        spinner.setProgressStyle(ProgressDialog.STYLE_SPINNER);
217
        spinner.setMessage("Logging In");
218
        spinner.setCancelable(false);
219
 
220
        /*spinner.setMessage(getContext().getString(R.string.com_facebook_loading));*/
221
        spinner.setOnCancelListener(new OnCancelListener() {
222
            @Override
223
            public void onCancel(DialogInterface dialogInterface) {
224
                dismiss();
225
            }
226
        });
227
 
228
        requestWindowFeature(Window.FEATURE_NO_TITLE);
229
        contentFrameLayout = new FrameLayout(getContext());
230
 
231
        // First calculate how big the frame layout should be
232
        calculateSize();
233
        getWindow().setGravity(Gravity.CENTER);
234
 
235
        // resize the dialog if the soft keyboard comes up
236
        getWindow().setSoftInputMode(WindowManager.LayoutParams.SOFT_INPUT_ADJUST_RESIZE);
237
 
238
        /* Create the 'x' image, but don't add to the contentFrameLayout layout yet
239
         * at this point, we only need to know its drawable width and height
240
         * to place the webview
241
         */
242
        createCrossImage();
243
 
244
        /* Now we know 'x' drawable width and height,
245
         * layout the webview and add it the contentFrameLayout layout
246
         */
247
        int crossWidth = crossImageView.getDrawable().getIntrinsicWidth();
248
 
249
        setUpWebView(crossWidth / 2 + 1);
250
 
251
        /* Finally add the 'x' image to the contentFrameLayout layout and
252
        * add contentFrameLayout to the Dialog view
253
        */
254
        contentFrameLayout.addView(crossImageView, new ViewGroup.LayoutParams(
255
                ViewGroup.LayoutParams.WRAP_CONTENT, ViewGroup.LayoutParams.WRAP_CONTENT));
256
 
257
        setContentView(contentFrameLayout);
258
    }
259
 
260
    protected void setExpectedRedirectUrl(String expectedRedirectUrl) {
261
        this.expectedRedirectUrl = expectedRedirectUrl;
262
    }
263
 
264
    protected Bundle parseResponseUri(String urlString) {
265
        Uri u = Uri.parse(urlString);
266
 
267
        Bundle b = Utility.parseUrlQueryString(u.getQuery());
268
        b.putAll(Utility.parseUrlQueryString(u.getFragment()));
269
 
270
        return b;
271
    }
272
 
273
    protected boolean isListenerCalled() {
274
        return listenerCalled;
275
    }
276
 
277
    protected WebView getWebView() {
278
        return webView;
279
    }
280
 
281
    private void calculateSize() {
282
        WindowManager wm = (WindowManager) getContext().getSystemService(Context.WINDOW_SERVICE);
283
        Display display = wm.getDefaultDisplay();
284
        DisplayMetrics metrics = new DisplayMetrics();
285
        display.getMetrics(metrics);
286
        // always use the portrait dimensions to do the scaling calculations so we always get a portrait shaped
287
        // web dialog
288
        int width = metrics.widthPixels < metrics.heightPixels ? metrics.widthPixels : metrics.heightPixels;
289
        int height = metrics.widthPixels < metrics.heightPixels ? metrics.heightPixels : metrics.widthPixels;
290
 
291
        int dialogWidth = Math.min(
292
                getScaledSize(width, metrics.density, NO_PADDING_SCREEN_WIDTH, MAX_PADDING_SCREEN_WIDTH),
293
                metrics.widthPixels);
294
        int dialogHeight = Math.min(
295
                getScaledSize(height, metrics.density, NO_PADDING_SCREEN_HEIGHT, MAX_PADDING_SCREEN_HEIGHT),
296
                metrics.heightPixels);
297
 
298
        getWindow().setLayout(dialogWidth, dialogHeight);
299
    }
300
 
301
    /**
302
     * Returns a scaled size (either width or height) based on the parameters passed.
303
     * @param screenSize a pixel dimension of the screen (either width or height)
304
     * @param density density of the screen
305
     * @param noPaddingSize the size at which there's no padding for the dialog
306
     * @param maxPaddingSize the size at which to apply maximum padding for the dialog
307
     * @return a scaled size.
308
     */
309
    private int getScaledSize(int screenSize, float density, int noPaddingSize, int maxPaddingSize) {
310
        int scaledSize = (int) ((float) screenSize / density);
311
        double scaleFactor;
312
        if (scaledSize <= noPaddingSize) {
313
            scaleFactor = 1.0;
314
        } else if (scaledSize >= maxPaddingSize) {
315
            scaleFactor = MIN_SCALE_FACTOR;
316
        } else {
317
            // between the noPadding and maxPadding widths, we take a linear reduction to go from 100%
318
            // of screen size down to MIN_SCALE_FACTOR
319
            scaleFactor = MIN_SCALE_FACTOR +
320
                    ((double) (maxPaddingSize - scaledSize))
321
                            / ((double) (maxPaddingSize - noPaddingSize))
322
                            * (1.0 - MIN_SCALE_FACTOR);
323
        }
324
        return (int) (screenSize * scaleFactor);
325
    }
326
 
327
    protected void sendSuccessToListener(Bundle values) {
328
        if (onCompleteListener != null && !listenerCalled) {
329
            listenerCalled = true;
330
            onCompleteListener.onComplete(values, null);
331
 
332
            dismiss();
333
        }
334
    }
335
 
336
    protected void sendErrorToListener(Throwable error) {
337
        if (onCompleteListener != null && !listenerCalled) {
338
            listenerCalled = true;
339
            FacebookException facebookException = null;
340
            if (error instanceof FacebookException) {
341
                facebookException = (FacebookException) error;
342
            } else {
343
                facebookException = new FacebookException(error);
344
            }
345
            onCompleteListener.onComplete(null, facebookException);
346
 
347
            dismiss();
348
        }
349
    }
350
 
351
    protected void sendCancelToListener() {
352
        sendErrorToListener(new FacebookOperationCanceledException());
353
    }
354
 
355
    private void createCrossImage() {
356
        crossImageView = new ImageView(getContext());
357
        // Dismiss the dialog when user click on the 'x'
358
        crossImageView.setOnClickListener(new View.OnClickListener() {
359
            @Override
360
            public void onClick(View v) {
361
                dismiss();
362
            }
363
        });
364
        Drawable crossDrawable = getContext().getResources().getDrawable(R.drawable.com_facebook_close);
365
        crossImageView.setImageDrawable(crossDrawable);
366
        /* 'x' should not be visible while webview is loading
367
         * make it visible only after webview has fully loaded
368
         */
369
        crossImageView.setVisibility(View.INVISIBLE);
370
    }
371
 
372
    @SuppressLint("SetJavaScriptEnabled")
373
    private void setUpWebView(int margin) {
374
        LinearLayout webViewContainer = new LinearLayout(getContext());
375
        webView = new WebView(getContext()) {
376
            /* Prevent NPE on Motorola 2.2 devices
377
             * See https://groups.google.com/forum/?fromgroups=#!topic/android-developers/ktbwY2gtLKQ
378
             */
379
            @Override
380
            public void onWindowFocusChanged(boolean hasWindowFocus) {
381
                try {
382
                    super.onWindowFocusChanged(hasWindowFocus);
383
                } catch (NullPointerException e) {
384
                }
385
            }
386
        };
387
        webView.setVerticalScrollBarEnabled(false);
388
        webView.setHorizontalScrollBarEnabled(false);
389
        webView.setWebViewClient(new DialogWebViewClient());
390
        webView.getSettings().setJavaScriptEnabled(true);
391
        webView.loadUrl(url);
392
        webView.setLayoutParams(new FrameLayout.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT,
393
                ViewGroup.LayoutParams.MATCH_PARENT));
394
        webView.setVisibility(View.INVISIBLE);
395
        webView.getSettings().setSavePassword(false);
396
        webView.getSettings().setSaveFormData(false);
397
 
398
        webViewContainer.setPadding(margin, margin, margin, margin);
399
        webViewContainer.addView(webView);
400
        webViewContainer.setBackgroundColor(BACKGROUND_GRAY);
401
        contentFrameLayout.addView(webViewContainer);
402
    }
403
 
404
    private class DialogWebViewClient extends WebViewClient {
405
        @Override
406
        @SuppressWarnings("deprecation")
407
        public boolean shouldOverrideUrlLoading(WebView view, String url) {
408
            Utility.logd(LOG_TAG, "Redirect URL: " + url);
409
            if (url.startsWith(WebDialog.this.expectedRedirectUrl)) {
410
                Bundle values = parseResponseUri(url);
411
 
412
                String error = values.getString("error");
413
                if (error == null) {
414
                    error = values.getString("error_type");
415
                }
416
 
417
                String errorMessage = values.getString("error_msg");
418
                if (errorMessage == null) {
419
                    errorMessage = values.getString("error_description");
420
                }
421
                String errorCodeString = values.getString("error_code");
422
                int errorCode = FacebookRequestError.INVALID_ERROR_CODE;
423
                if (!Utility.isNullOrEmpty(errorCodeString)) {
424
                    try {
425
                        errorCode = Integer.parseInt(errorCodeString);
426
                    } catch (NumberFormatException ex) {
427
                        errorCode = FacebookRequestError.INVALID_ERROR_CODE;
428
                    }
429
                }
430
 
431
                if (Utility.isNullOrEmpty(error) && Utility
432
                        .isNullOrEmpty(errorMessage) && errorCode == FacebookRequestError.INVALID_ERROR_CODE) {
433
                    sendSuccessToListener(values);
434
                } else if (error != null && (error.equals("access_denied") ||
435
                        error.equals("OAuthAccessDeniedException"))) {
436
                    sendCancelToListener();
437
                } else if (errorCode == API_EC_DIALOG_CANCEL) {
438
                    sendCancelToListener();
439
                } else {
440
                    FacebookRequestError requestError = new FacebookRequestError(errorCode, error, errorMessage);
441
                    sendErrorToListener(new FacebookServiceException(requestError, errorMessage));
442
                }
443
                return true;
444
            } else if (url.startsWith(WebDialog.CANCEL_URI)) {
445
                sendCancelToListener();
446
                return true;
447
            } else if (url.contains(DISPLAY_TOUCH)) {
448
                return false;
449
            }
450
            // launch non-dialog URLs in a full browser
451
            getContext().startActivity(
452
                    new Intent(Intent.ACTION_VIEW, Uri.parse(url)));
453
            return true;
454
        }
455
 
456
        @Override
457
        public void onReceivedError(WebView view, int errorCode,
458
                String description, String failingUrl) {
459
            super.onReceivedError(view, errorCode, description, failingUrl);
460
            sendErrorToListener(new FacebookDialogException(description, errorCode, failingUrl));
461
        }
462
 
463
        @Override
464
        public void onReceivedSslError(WebView view, SslErrorHandler handler, SslError error) {
465
            if (DISABLE_SSL_CHECK_FOR_TESTING) {
466
                handler.proceed();
467
            } else {
468
                super.onReceivedSslError(view, handler, error);
469
 
470
                handler.cancel();
471
                sendErrorToListener(new FacebookDialogException(null, ERROR_FAILED_SSL_HANDSHAKE, null));
472
            }
473
        }
474
 
475
        @Override
476
        public void onPageStarted(WebView view, String url, Bitmap favicon) {
477
            Utility.logd(LOG_TAG, "Webview loading URL: " + url);
478
            super.onPageStarted(view, url, favicon);
479
            if (!isDetached) {
480
                spinner.show();
481
            }
482
        }
483
 
484
        @Override
485
        public void onPageFinished(WebView view, String url) {
486
            super.onPageFinished(view, url);
487
            if (!isDetached) {
488
                spinner.dismiss();
489
            }
490
            /*
491
             * Once web view is fully loaded, set the contentFrameLayout background to be transparent
492
             * and make visible the 'x' image.
493
             */
494
            contentFrameLayout.setBackgroundColor(Color.TRANSPARENT);
495
            webView.setVisibility(View.VISIBLE);
496
            crossImageView.setVisibility(View.VISIBLE);
497
        }
498
    }
499
 
500
    private static class BuilderBase<CONCRETE extends BuilderBase<?>> {
501
        private Context context;
502
        private Session session;
503
        private String applicationId;
504
        private String action;
505
        private int theme = DEFAULT_THEME;
506
        private OnCompleteListener listener;
507
        private Bundle parameters;
508
 
509
        protected BuilderBase(Context context, String action) {
510
            Session activeSession = Session.getActiveSession();
511
            if (activeSession != null && activeSession.isOpened()) {
512
                this.session = activeSession;
513
            } else {
514
                String applicationId = Utility.getMetadataApplicationId(context);
515
                if (applicationId != null) {
516
                    this.applicationId = applicationId;
517
                } else {
518
                    throw new FacebookException("Attempted to create a builder without an open" +
519
                            " Active Session or a valid default Application ID.");
520
                }
521
            }
522
            finishInit(context, action, null);
523
        }
524
 
525
        protected BuilderBase(Context context, Session session, String action, Bundle parameters) {
526
            Validate.notNull(session, "session");
527
            if (!session.isOpened()) {
528
                throw new FacebookException("Attempted to use a Session that was not open.");
529
            }
530
            this.session = session;
531
 
532
            finishInit(context, action, parameters);
533
        }
534
 
535
        protected BuilderBase(Context context, String applicationId, String action, Bundle parameters) {
536
            if (applicationId == null) {
537
                applicationId = Utility.getMetadataApplicationId(context);
538
            }
539
            Validate.notNullOrEmpty(applicationId, "applicationId");
540
            this.applicationId = applicationId;
541
 
542
            finishInit(context, action, parameters);
543
        }
544
 
545
        /**
546
         * Sets a theme identifier which will be passed to the underlying Dialog.
547
         *
548
         * @param theme a theme identifier which will be passed to the Dialog class
549
         * @return the builder
550
         */
551
        public CONCRETE setTheme(int theme) {
552
            this.theme = theme;
553
            @SuppressWarnings("unchecked")
554
            CONCRETE result = (CONCRETE) this;
555
            return result;
556
        }
557
 
558
        /**
559
         * Sets the listener which will be notified when the dialog finishes.
560
         *
561
         * @param listener the listener to notify, or null if no notification is desired
562
         * @return the builder
563
         */
564
        public CONCRETE setOnCompleteListener(OnCompleteListener listener) {
565
            this.listener = listener;
566
            @SuppressWarnings("unchecked")
567
            CONCRETE result = (CONCRETE) this;
568
            return result;
569
        }
570
 
571
        /**
572
         * Constructs a WebDialog using the parameters provided. The dialog is not shown,
573
         * but is ready to be shown by calling Dialog.show().
574
         *
575
         * @return the WebDialog
576
         */
577
        public WebDialog build() {
578
            if (session != null && session.isOpened()) {
579
                parameters.putString(ServerProtocol.DIALOG_PARAM_APP_ID, session.getApplicationId());
580
                parameters.putString(ServerProtocol.DIALOG_PARAM_ACCESS_TOKEN, session.getAccessToken());
581
            } else {
582
                parameters.putString(ServerProtocol.DIALOG_PARAM_APP_ID, applicationId);
583
            }
584
 
585
            return new WebDialog(context, action, parameters, theme, listener);
586
        }
587
 
588
        protected String getApplicationId() {
589
            return applicationId;
590
        }
591
 
592
        protected Context getContext() {
593
            return context;
594
        }
595
 
596
        protected int getTheme() {
597
            return theme;
598
        }
599
 
600
        protected Bundle getParameters() {
601
            return parameters;
602
        }
603
 
604
        protected WebDialog.OnCompleteListener getListener() {
605
            return listener;
606
        }
607
 
608
        private void finishInit(Context context, String action, Bundle parameters) {
609
            this.context = context;
610
            this.action = action;
611
            if (parameters != null) {
612
                this.parameters = parameters;
613
            } else {
614
                this.parameters = new Bundle();
615
            }
616
        }
617
    }
618
 
619
    /**
620
     * Provides a builder that allows construction of an arbitrary Facebook web dialog.
621
     */
622
    public static class Builder extends BuilderBase<Builder> {
623
        /**
624
         * Constructor that builds a dialog using either the active session, or the application
625
         * id specified in the application/meta-data.
626
         *
627
         * @param context the Context within which the dialog will be shown.
628
         * @param action the portion of the dialog URL following www.facebook.com/dialog/.
629
         *               See https://developers.facebook.com/docs/reference/dialogs/ for details.
630
         */
631
        public Builder(Context context, String action) {
632
            super(context, action);
633
        }
634
 
635
        /**
636
         * Constructor that builds a dialog for an authenticated user.
637
         *
638
         * @param context the Context within which the dialog will be shown.
639
         * @param session the Session representing an authenticating user to use for
640
         *                showing the dialog; must not be null, and must be opened.
641
         * @param action the portion of the dialog URL following www.facebook.com/dialog/.
642
         *               See https://developers.facebook.com/docs/reference/dialogs/ for details.
643
         * @param parameters a Bundle containing parameters to pass as part of the URL.
644
         */
645
        public Builder(Context context, Session session, String action, Bundle parameters) {
646
            super(context, session, action, parameters);
647
        }
648
 
649
        /**
650
         * Constructor that builds a dialog without an authenticated user.
651
         *
652
         * @param context the Context within which the dialog will be shown.
653
         * @param applicationId the application ID to be included in the dialog URL.
654
         * @param action the portion of the dialog URL following www.facebook.com/dialog/.
655
         *               See https://developers.facebook.com/docs/reference/dialogs/ for details.
656
         * @param parameters a Bundle containing parameters to pass as part of the URL.
657
         */
658
        public Builder(Context context, String applicationId, String action, Bundle parameters) {
659
            super(context, applicationId, action, parameters);
660
        }
661
    }
662
 
663
    /**
664
     * Provides a builder that allows construction of the parameters for showing
665
     * the <a href="https://developers.facebook.com/docs/reference/dialogs/feed">Feed Dialog</a>.
666
     */
667
    public static class FeedDialogBuilder extends BuilderBase<FeedDialogBuilder> {
668
        private static final String FEED_DIALOG = "feed";
669
        private static final String FROM_PARAM = "from";
670
        private static final String TO_PARAM = "to";
671
        private static final String LINK_PARAM = "link";
672
        private static final String PICTURE_PARAM = "picture";
673
        private static final String SOURCE_PARAM = "source";
674
        private static final String NAME_PARAM = "name";
675
        private static final String CAPTION_PARAM = "caption";
676
        private static final String DESCRIPTION_PARAM = "description";
677
 
678
        /**
679
         * Constructor that builds a Feed Dialog using either the active session, or the application
680
         * ID specified in the application/meta-data.
681
         *
682
         * @param context the Context within which the dialog will be shown.
683
         */
684
        public FeedDialogBuilder(Context context) {
685
            super(context, FEED_DIALOG);
686
        }
687
 
688
        /**
689
         * Constructor that builds a Feed Dialog using the provided session.
690
         *
691
         * @param context the Context within which the dialog will be shown.
692
         * @param session the Session representing an authenticating user to use for
693
         *                showing the dialog; must not be null, and must be opened.
694
         */
695
        public FeedDialogBuilder(Context context, Session session) {
696
            super(context, session, FEED_DIALOG, null);
697
        }
698
 
699
        /**
700
         * Constructor that builds a Feed Dialog using the provided session and parameters.
701
         *
702
         * @param context    the Context within which the dialog will be shown.
703
         * @param session    the Session representing an authenticating user to use for
704
         *                   showing the dialog; must not be null, and must be opened.
705
         * @param parameters a Bundle containing parameters to pass as part of the
706
         *                   dialog URL. No validation is done on these parameters; it is
707
         *                   the caller's responsibility to ensure they are valid. For more information,
708
         *                   see <a href="https://developers.facebook.com/docs/reference/dialogs/feed/">
709
         *                   https://developers.facebook.com/docs/reference/dialogs/feed/</a>.
710
         */
711
        public FeedDialogBuilder(Context context, Session session, Bundle parameters) {
712
            super(context, session, FEED_DIALOG, parameters);
713
        }
714
 
715
        /**
716
         * Constructor that builds a Feed Dialog using the provided application ID and parameters.
717
         *
718
         * @param context       the Context within which the dialog will be shown.
719
         * @param applicationId the application ID to use. If null, the application ID specified in the
720
         *                      application/meta-data will be used instead.
721
         * @param parameters    a Bundle containing parameters to pass as part of the
722
         *                      dialog URL. No validation is done on these parameters; it is
723
         *                      the caller's responsibility to ensure they are valid. For more information,
724
         *                      see <a href="https://developers.facebook.com/docs/reference/dialogs/feed/">
725
         *                      https://developers.facebook.com/docs/reference/dialogs/feed/</a>.
726
         */
727
        public FeedDialogBuilder(Context context, String applicationId, Bundle parameters) {
728
            super(context, applicationId, FEED_DIALOG, parameters);
729
        }
730
 
731
        /**
732
         * Sets the ID of the profile that is posting to Facebook. If none is specified,
733
         * the default is "me". This profile must be either the authenticated user or a
734
         * Page that the user is an administrator of.
735
         *
736
         * @param id Facebook ID of the profile to post from
737
         * @return the builder
738
         */
739
        public FeedDialogBuilder setFrom(String id) {
740
            getParameters().putString(FROM_PARAM, id);
741
            return this;
742
        }
743
 
744
        /**
745
         * Sets the ID of the profile that the story will be published to. If not specified, it
746
         * will default to the same profile that the story is being published from. The ID must be a friend who also
747
         * uses your app.
748
         *
749
         * @param id Facebook ID of the profile to post to
750
         * @return the builder
751
         */
752
        public FeedDialogBuilder setTo(String id) {
753
            getParameters().putString(TO_PARAM, id);
754
            return this;
755
        }
756
 
757
        /**
758
         * Sets the URL of a link to be shared.
759
         *
760
         * @param link the URL
761
         * @return the builder
762
         */
763
        public FeedDialogBuilder setLink(String link) {
764
            getParameters().putString(LINK_PARAM, link);
765
            return this;
766
        }
767
 
768
        /**
769
         * Sets the URL of a picture to be shared.
770
         *
771
         * @param picture the URL of the picture
772
         * @return the builder
773
         */
774
        public FeedDialogBuilder setPicture(String picture) {
775
            getParameters().putString(PICTURE_PARAM, picture);
776
            return this;
777
        }
778
 
779
        /**
780
         * Sets the URL of a media file attached to this post. If this is set, any picture
781
         * set via setPicture will be ignored.
782
         *
783
         * @param source the URL of the media file
784
         * @return the builder
785
         */
786
        public FeedDialogBuilder setSource(String source) {
787
            getParameters().putString(SOURCE_PARAM, source);
788
            return this;
789
        }
790
 
791
        /**
792
         * Sets the name of the URL being shared. This method only has effect if setLink is called.
793
         *
794
         * @param name the name
795
         * @return the builder
796
         */
797
        public FeedDialogBuilder setName(String name) {
798
            getParameters().putString(NAME_PARAM, name);
799
            return this;
800
        }
801
 
802
        /**
803
         * Sets the caption of the URL being shared. This method only has effect if setLink is called.
804
         *
805
         * @param caption the caption
806
         * @return the builder
807
         */
808
        public FeedDialogBuilder setCaption(String caption) {
809
            getParameters().putString(CAPTION_PARAM, caption);
810
            return this;
811
        }
812
 
813
        /**
814
         * Sets the description of the URL being shared. This method only has effect if setLink is called.
815
         *
816
         * @param description the description
817
         * @return the builder
818
         */
819
        public FeedDialogBuilder setDescription(String description) {
820
            getParameters().putString(DESCRIPTION_PARAM, description);
821
            return this;
822
        }
823
    }
824
 
825
    /**
826
     * Provides a builder that allows construction of the parameters for showing
827
     * the <a href="https://developers.facebook.com/docs/reference/dialogs/requests">Requests Dialog</a>.
828
     */
829
    public static class RequestsDialogBuilder extends BuilderBase<RequestsDialogBuilder> {
830
        private static final String APPREQUESTS_DIALOG = "apprequests";
831
        private static final String MESSAGE_PARAM = "message";
832
        private static final String TO_PARAM = "to";
833
        private static final String DATA_PARAM = "data";
834
        private static final String TITLE_PARAM = "title";
835
 
836
        /**
837
         * Constructor that builds a Requests Dialog using either the active session, or the application
838
         * ID specified in the application/meta-data.
839
         *
840
         * @param context the Context within which the dialog will be shown.
841
         */
842
        public RequestsDialogBuilder(Context context) {
843
            super(context, APPREQUESTS_DIALOG);
844
        }
845
 
846
        /**
847
         * Constructor that builds a Requests Dialog using the provided session.
848
         *
849
         * @param context the Context within which the dialog will be shown.
850
         * @param session the Session representing an authenticating user to use for
851
         *                showing the dialog; must not be null, and must be opened.
852
         */
853
        public RequestsDialogBuilder(Context context, Session session) {
854
            super(context, session, APPREQUESTS_DIALOG, null);
855
        }
856
 
857
        /**
858
         * Constructor that builds a Requests Dialog using the provided session and parameters.
859
         *
860
         * @param context    the Context within which the dialog will be shown.
861
         * @param session    the Session representing an authenticating user to use for
862
         *                   showing the dialog; must not be null, and must be opened.
863
         * @param parameters a Bundle containing parameters to pass as part of the
864
         *                   dialog URL. No validation is done on these parameters; it is
865
         *                   the caller's responsibility to ensure they are valid. For more information,
866
         *                   see <a href="https://developers.facebook.com/docs/reference/dialogs/requests/">
867
         *                   https://developers.facebook.com/docs/reference/dialogs/requests/</a>.
868
         */
869
        public RequestsDialogBuilder(Context context, Session session, Bundle parameters) {
870
            super(context, session, APPREQUESTS_DIALOG, parameters);
871
        }
872
 
873
        /**
874
         * Constructor that builds a Requests Dialog using the provided application ID and parameters.
875
         *
876
         * @param context       the Context within which the dialog will be shown.
877
         * @param applicationId the application ID to use. If null, the application ID specified in the
878
         *                      application/meta-data will be used instead.
879
         * @param parameters    a Bundle containing parameters to pass as part of the
880
         *                      dialog URL. No validation is done on these parameters; it is
881
         *                      the caller's responsibility to ensure they are valid. For more information,
882
         *                      see <a href="https://developers.facebook.com/docs/reference/dialogs/requests/">
883
         *                      https://developers.facebook.com/docs/reference/dialogs/requests/</a>.
884
         */
885
        public RequestsDialogBuilder(Context context, String applicationId, Bundle parameters) {
886
            super(context, applicationId, APPREQUESTS_DIALOG, parameters);
887
        }
888
 
889
        /**
890
         * Sets the string users receiving the request will see. The maximum length
891
         * is 60 characters.
892
         *
893
         * @param message the message
894
         * @return the builder
895
         */
896
        public RequestsDialogBuilder setMessage(String message) {
897
            getParameters().putString(MESSAGE_PARAM, message);
898
            return this;
899
        }
900
 
901
        /**
902
         * Sets the user ID or user name the request will be sent to. If this is not
903
         * specified, a friend selector will be displayed and the user can select up
904
         * to 50 friends.
905
         *
906
         * @param id the id or user name to send the request to
907
         * @return the builder
908
         */
909
        public RequestsDialogBuilder setTo(String id) {
910
            getParameters().putString(TO_PARAM, id);
911
            return this;
912
        }
913
 
914
        /**
915
         * Sets optional data which can be used for tracking; maximum length is 255
916
         * characters.
917
         *
918
         * @param data the data
919
         * @return the builder
920
         */
921
        public RequestsDialogBuilder setData(String data) {
922
            getParameters().putString(DATA_PARAM, data);
923
            return this;
924
        }
925
 
926
        /**
927
         * Sets an optional title for the dialog; maximum length is 50 characters.
928
         *
929
         * @param title the title
930
         * @return the builder
931
         */
932
        public RequestsDialogBuilder setTitle(String title) {
933
            getParameters().putString(TITLE_PARAM, title);
934
            return this;
935
        }
936
    }
937
}