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.annotation.SuppressLint;import android.app.Dialog;import android.app.ProgressDialog;import android.content.Context;import android.content.DialogInterface;import android.content.Intent;import android.graphics.Bitmap;import android.graphics.Color;import android.graphics.drawable.Drawable;import android.net.Uri;import android.net.http.SslError;import android.os.Bundle;import android.util.DisplayMetrics;import android.view.*;import android.webkit.SslErrorHandler;import android.webkit.WebView;import android.webkit.WebViewClient;import android.widget.FrameLayout;import android.widget.ImageView;import android.widget.LinearLayout;import com.facebook.*;import com.facebook.android.R;import com.facebook.internal.Logger;import com.facebook.internal.ServerProtocol;import com.facebook.internal.Utility;import com.facebook.internal.Validate;/*** This class provides a mechanism for displaying Facebook Web dialogs inside a Dialog. Helper* methods are provided to construct commonly-used dialogs, or a caller can specify arbitrary* parameters to call other dialogs.*/public class WebDialog extends Dialog {private static final String LOG_TAG = Logger.LOG_TAG_BASE + "WebDialog";private static final String DISPLAY_TOUCH = "touch";private static final int API_EC_DIALOG_CANCEL = 4201;static final String REDIRECT_URI = "fbconnect://success";static final String CANCEL_URI = "fbconnect://cancel";static final boolean DISABLE_SSL_CHECK_FOR_TESTING = false;// width below which there are no extra marginsprivate static final int NO_PADDING_SCREEN_WIDTH = 480;// width beyond which we're always using the MIN_SCALE_FACTORprivate static final int MAX_PADDING_SCREEN_WIDTH = 800;// height below which there are no extra marginsprivate static final int NO_PADDING_SCREEN_HEIGHT = 800;// height beyond which we're always using the MIN_SCALE_FACTORprivate static final int MAX_PADDING_SCREEN_HEIGHT = 1280;// the minimum scaling factor for the web dialog (50% of screen size)private static final double MIN_SCALE_FACTOR = 0.5;// translucent border around the webviewprivate static final int BACKGROUND_GRAY = 0xCC000000;public static final int DEFAULT_THEME = android.R.style.Theme_Translucent_NoTitleBar;private String url;private String expectedRedirectUrl = REDIRECT_URI;private OnCompleteListener onCompleteListener;private WebView webView;private ProgressDialog spinner;private ImageView crossImageView;private FrameLayout contentFrameLayout;private boolean listenerCalled = false;private boolean isDetached = false;private boolean isDismissed = false;/*** Interface that implements a listener to be called when the user's interaction with the* dialog completes, whether because the dialog finished successfully, or it was cancelled,* or an error was encountered.*/public interface OnCompleteListener {/*** Called when the dialog completes.** @param values on success, contains the values returned by the dialog* @param error on an error, contains an exception describing the error*/void onComplete(Bundle values, FacebookException error);}/*** Constructor which can be used to display a dialog with an already-constructed URL.** @param context the context to use to display the dialog* @param url the URL of the Web Dialog to display; no validation is done on this URL, but it should* be a valid URL pointing to a Facebook Web Dialog*/public WebDialog(Context context, String url) {this(context, url, DEFAULT_THEME);}/*** Constructor which can be used to display a dialog with an already-constructed URL and a custom theme.** @param context the context to use to display the dialog* @param url the URL of the Web Dialog to display; no validation is done on this URL, but it should* be a valid URL pointing to a Facebook Web Dialog* @param theme identifier of a theme to pass to the Dialog class*/public WebDialog(Context context, String url, int theme) {super(context, theme);this.url = url;}/*** Constructor which will construct the URL of the Web dialog based on the specified parameters.** @param context the context to use to display the dialog* @param action the portion of the dialog URL following "dialog/"* @param parameters parameters which will be included as part of the URL* @param theme identifier of a theme to pass to the Dialog class* @param listener the listener to notify, or null if no notification is desired*/public WebDialog(Context context, String action, Bundle parameters, int theme, OnCompleteListener listener) {super(context, theme);if (parameters == null) {parameters = new Bundle();}// our webview client only handles the redirect uri we specify, so just hard code it hereparameters.putString(ServerProtocol.DIALOG_PARAM_REDIRECT_URI, REDIRECT_URI);parameters.putString(ServerProtocol.DIALOG_PARAM_DISPLAY, DISPLAY_TOUCH);Uri uri = Utility.buildUri(ServerProtocol.getDialogAuthority(),ServerProtocol.getAPIVersion() + "/" + ServerProtocol.DIALOG_PATH + action,parameters);this.url = uri.toString();onCompleteListener = listener;}/*** Sets the listener which will be notified when the dialog finishes.** @param listener the listener to notify, or null if no notification is desired*/public void setOnCompleteListener(OnCompleteListener listener) {onCompleteListener = listener;}/*** Gets the listener which will be notified when the dialog finishes.** @return the listener, or null if none has been specified*/public OnCompleteListener getOnCompleteListener() {return onCompleteListener;}@Overridepublic void dismiss() {if (isDismissed) {// Some paths may cause dismiss() to be called recursively. Break the loop here.return;}isDismissed = true;// If dismiss() was called without sending a result to the listener, let's default to a "cancel" result.// This will be the case when the user taps the OS-back-button, or the cross-image, or outside the loading// interstitial.if (!listenerCalled) {sendCancelToListener();}if (webView != null) {webView.stopLoading();}if (!isDetached) {if (spinner.isShowing()) {spinner.dismiss();}super.dismiss();}}@Overridepublic void onDetachedFromWindow() {isDetached = true;super.onDetachedFromWindow();}@Overridepublic void onAttachedToWindow() {isDetached = false;super.onAttachedToWindow();}@Overrideprotected void onCreate(Bundle savedInstanceState) {super.onCreate(savedInstanceState);spinner = new ProgressDialog(getContext());/* spinner.requestWindowFeature(Window.FEATURE_NO_TITLE);*/spinner.setProgressStyle(ProgressDialog.STYLE_SPINNER);spinner.setMessage("Logging In");spinner.setCancelable(false);/*spinner.setMessage(getContext().getString(R.string.com_facebook_loading));*/spinner.setOnCancelListener(new OnCancelListener() {@Overridepublic void onCancel(DialogInterface dialogInterface) {dismiss();}});requestWindowFeature(Window.FEATURE_NO_TITLE);contentFrameLayout = new FrameLayout(getContext());// First calculate how big the frame layout should becalculateSize();getWindow().setGravity(Gravity.CENTER);// resize the dialog if the soft keyboard comes upgetWindow().setSoftInputMode(WindowManager.LayoutParams.SOFT_INPUT_ADJUST_RESIZE);/* Create the 'x' image, but don't add to the contentFrameLayout layout yet* at this point, we only need to know its drawable width and height* to place the webview*/createCrossImage();/* Now we know 'x' drawable width and height,* layout the webview and add it the contentFrameLayout layout*/int crossWidth = crossImageView.getDrawable().getIntrinsicWidth();setUpWebView(crossWidth / 2 + 1);/* Finally add the 'x' image to the contentFrameLayout layout and* add contentFrameLayout to the Dialog view*/contentFrameLayout.addView(crossImageView, new ViewGroup.LayoutParams(ViewGroup.LayoutParams.WRAP_CONTENT, ViewGroup.LayoutParams.WRAP_CONTENT));setContentView(contentFrameLayout);}protected void setExpectedRedirectUrl(String expectedRedirectUrl) {this.expectedRedirectUrl = expectedRedirectUrl;}protected Bundle parseResponseUri(String urlString) {Uri u = Uri.parse(urlString);Bundle b = Utility.parseUrlQueryString(u.getQuery());b.putAll(Utility.parseUrlQueryString(u.getFragment()));return b;}protected boolean isListenerCalled() {return listenerCalled;}protected WebView getWebView() {return webView;}private void calculateSize() {WindowManager wm = (WindowManager) getContext().getSystemService(Context.WINDOW_SERVICE);Display display = wm.getDefaultDisplay();DisplayMetrics metrics = new DisplayMetrics();display.getMetrics(metrics);// always use the portrait dimensions to do the scaling calculations so we always get a portrait shaped// web dialogint width = metrics.widthPixels < metrics.heightPixels ? metrics.widthPixels : metrics.heightPixels;int height = metrics.widthPixels < metrics.heightPixels ? metrics.heightPixels : metrics.widthPixels;int dialogWidth = Math.min(getScaledSize(width, metrics.density, NO_PADDING_SCREEN_WIDTH, MAX_PADDING_SCREEN_WIDTH),metrics.widthPixels);int dialogHeight = Math.min(getScaledSize(height, metrics.density, NO_PADDING_SCREEN_HEIGHT, MAX_PADDING_SCREEN_HEIGHT),metrics.heightPixels);getWindow().setLayout(dialogWidth, dialogHeight);}/*** Returns a scaled size (either width or height) based on the parameters passed.* @param screenSize a pixel dimension of the screen (either width or height)* @param density density of the screen* @param noPaddingSize the size at which there's no padding for the dialog* @param maxPaddingSize the size at which to apply maximum padding for the dialog* @return a scaled size.*/private int getScaledSize(int screenSize, float density, int noPaddingSize, int maxPaddingSize) {int scaledSize = (int) ((float) screenSize / density);double scaleFactor;if (scaledSize <= noPaddingSize) {scaleFactor = 1.0;} else if (scaledSize >= maxPaddingSize) {scaleFactor = MIN_SCALE_FACTOR;} else {// between the noPadding and maxPadding widths, we take a linear reduction to go from 100%// of screen size down to MIN_SCALE_FACTORscaleFactor = MIN_SCALE_FACTOR +((double) (maxPaddingSize - scaledSize))/ ((double) (maxPaddingSize - noPaddingSize))* (1.0 - MIN_SCALE_FACTOR);}return (int) (screenSize * scaleFactor);}protected void sendSuccessToListener(Bundle values) {if (onCompleteListener != null && !listenerCalled) {listenerCalled = true;onCompleteListener.onComplete(values, null);dismiss();}}protected void sendErrorToListener(Throwable error) {if (onCompleteListener != null && !listenerCalled) {listenerCalled = true;FacebookException facebookException = null;if (error instanceof FacebookException) {facebookException = (FacebookException) error;} else {facebookException = new FacebookException(error);}onCompleteListener.onComplete(null, facebookException);dismiss();}}protected void sendCancelToListener() {sendErrorToListener(new FacebookOperationCanceledException());}private void createCrossImage() {crossImageView = new ImageView(getContext());// Dismiss the dialog when user click on the 'x'crossImageView.setOnClickListener(new View.OnClickListener() {@Overridepublic void onClick(View v) {dismiss();}});Drawable crossDrawable = getContext().getResources().getDrawable(R.drawable.com_facebook_close);crossImageView.setImageDrawable(crossDrawable);/* 'x' should not be visible while webview is loading* make it visible only after webview has fully loaded*/crossImageView.setVisibility(View.INVISIBLE);}@SuppressLint("SetJavaScriptEnabled")private void setUpWebView(int margin) {LinearLayout webViewContainer = new LinearLayout(getContext());webView = new WebView(getContext()) {/* Prevent NPE on Motorola 2.2 devices* See https://groups.google.com/forum/?fromgroups=#!topic/android-developers/ktbwY2gtLKQ*/@Overridepublic void onWindowFocusChanged(boolean hasWindowFocus) {try {super.onWindowFocusChanged(hasWindowFocus);} catch (NullPointerException e) {}}};webView.setVerticalScrollBarEnabled(false);webView.setHorizontalScrollBarEnabled(false);webView.setWebViewClient(new DialogWebViewClient());webView.getSettings().setJavaScriptEnabled(true);webView.loadUrl(url);webView.setLayoutParams(new FrameLayout.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT,ViewGroup.LayoutParams.MATCH_PARENT));webView.setVisibility(View.INVISIBLE);webView.getSettings().setSavePassword(false);webView.getSettings().setSaveFormData(false);webViewContainer.setPadding(margin, margin, margin, margin);webViewContainer.addView(webView);webViewContainer.setBackgroundColor(BACKGROUND_GRAY);contentFrameLayout.addView(webViewContainer);}private class DialogWebViewClient extends WebViewClient {@Override@SuppressWarnings("deprecation")public boolean shouldOverrideUrlLoading(WebView view, String url) {Utility.logd(LOG_TAG, "Redirect URL: " + url);if (url.startsWith(WebDialog.this.expectedRedirectUrl)) {Bundle values = parseResponseUri(url);String error = values.getString("error");if (error == null) {error = values.getString("error_type");}String errorMessage = values.getString("error_msg");if (errorMessage == null) {errorMessage = values.getString("error_description");}String errorCodeString = values.getString("error_code");int errorCode = FacebookRequestError.INVALID_ERROR_CODE;if (!Utility.isNullOrEmpty(errorCodeString)) {try {errorCode = Integer.parseInt(errorCodeString);} catch (NumberFormatException ex) {errorCode = FacebookRequestError.INVALID_ERROR_CODE;}}if (Utility.isNullOrEmpty(error) && Utility.isNullOrEmpty(errorMessage) && errorCode == FacebookRequestError.INVALID_ERROR_CODE) {sendSuccessToListener(values);} else if (error != null && (error.equals("access_denied") ||error.equals("OAuthAccessDeniedException"))) {sendCancelToListener();} else if (errorCode == API_EC_DIALOG_CANCEL) {sendCancelToListener();} else {FacebookRequestError requestError = new FacebookRequestError(errorCode, error, errorMessage);sendErrorToListener(new FacebookServiceException(requestError, errorMessage));}return true;} else if (url.startsWith(WebDialog.CANCEL_URI)) {sendCancelToListener();return true;} else if (url.contains(DISPLAY_TOUCH)) {return false;}// launch non-dialog URLs in a full browsergetContext().startActivity(new Intent(Intent.ACTION_VIEW, Uri.parse(url)));return true;}@Overridepublic void onReceivedError(WebView view, int errorCode,String description, String failingUrl) {super.onReceivedError(view, errorCode, description, failingUrl);sendErrorToListener(new FacebookDialogException(description, errorCode, failingUrl));}@Overridepublic void onReceivedSslError(WebView view, SslErrorHandler handler, SslError error) {if (DISABLE_SSL_CHECK_FOR_TESTING) {handler.proceed();} else {super.onReceivedSslError(view, handler, error);handler.cancel();sendErrorToListener(new FacebookDialogException(null, ERROR_FAILED_SSL_HANDSHAKE, null));}}@Overridepublic void onPageStarted(WebView view, String url, Bitmap favicon) {Utility.logd(LOG_TAG, "Webview loading URL: " + url);super.onPageStarted(view, url, favicon);if (!isDetached) {spinner.show();}}@Overridepublic void onPageFinished(WebView view, String url) {super.onPageFinished(view, url);if (!isDetached) {spinner.dismiss();}/** Once web view is fully loaded, set the contentFrameLayout background to be transparent* and make visible the 'x' image.*/contentFrameLayout.setBackgroundColor(Color.TRANSPARENT);webView.setVisibility(View.VISIBLE);crossImageView.setVisibility(View.VISIBLE);}}private static class BuilderBase<CONCRETE extends BuilderBase<?>> {private Context context;private Session session;private String applicationId;private String action;private int theme = DEFAULT_THEME;private OnCompleteListener listener;private Bundle parameters;protected BuilderBase(Context context, String action) {Session activeSession = Session.getActiveSession();if (activeSession != null && activeSession.isOpened()) {this.session = activeSession;} else {String applicationId = Utility.getMetadataApplicationId(context);if (applicationId != null) {this.applicationId = applicationId;} else {throw new FacebookException("Attempted to create a builder without an open" +" Active Session or a valid default Application ID.");}}finishInit(context, action, null);}protected BuilderBase(Context context, Session session, String action, Bundle parameters) {Validate.notNull(session, "session");if (!session.isOpened()) {throw new FacebookException("Attempted to use a Session that was not open.");}this.session = session;finishInit(context, action, parameters);}protected BuilderBase(Context context, String applicationId, String action, Bundle parameters) {if (applicationId == null) {applicationId = Utility.getMetadataApplicationId(context);}Validate.notNullOrEmpty(applicationId, "applicationId");this.applicationId = applicationId;finishInit(context, action, parameters);}/*** Sets a theme identifier which will be passed to the underlying Dialog.** @param theme a theme identifier which will be passed to the Dialog class* @return the builder*/public CONCRETE setTheme(int theme) {this.theme = theme;@SuppressWarnings("unchecked")CONCRETE result = (CONCRETE) this;return result;}/*** Sets the listener which will be notified when the dialog finishes.** @param listener the listener to notify, or null if no notification is desired* @return the builder*/public CONCRETE setOnCompleteListener(OnCompleteListener listener) {this.listener = listener;@SuppressWarnings("unchecked")CONCRETE result = (CONCRETE) this;return result;}/*** Constructs a WebDialog using the parameters provided. The dialog is not shown,* but is ready to be shown by calling Dialog.show().** @return the WebDialog*/public WebDialog build() {if (session != null && session.isOpened()) {parameters.putString(ServerProtocol.DIALOG_PARAM_APP_ID, session.getApplicationId());parameters.putString(ServerProtocol.DIALOG_PARAM_ACCESS_TOKEN, session.getAccessToken());} else {parameters.putString(ServerProtocol.DIALOG_PARAM_APP_ID, applicationId);}return new WebDialog(context, action, parameters, theme, listener);}protected String getApplicationId() {return applicationId;}protected Context getContext() {return context;}protected int getTheme() {return theme;}protected Bundle getParameters() {return parameters;}protected WebDialog.OnCompleteListener getListener() {return listener;}private void finishInit(Context context, String action, Bundle parameters) {this.context = context;this.action = action;if (parameters != null) {this.parameters = parameters;} else {this.parameters = new Bundle();}}}/*** Provides a builder that allows construction of an arbitrary Facebook web dialog.*/public static class Builder extends BuilderBase<Builder> {/*** Constructor that builds a dialog using either the active session, or the application* id specified in the application/meta-data.** @param context the Context within which the dialog will be shown.* @param action the portion of the dialog URL following www.facebook.com/dialog/.* See https://developers.facebook.com/docs/reference/dialogs/ for details.*/public Builder(Context context, String action) {super(context, action);}/*** Constructor that builds a dialog for an authenticated user.** @param context the Context within which the dialog will be shown.* @param session the Session representing an authenticating user to use for* showing the dialog; must not be null, and must be opened.* @param action the portion of the dialog URL following www.facebook.com/dialog/.* See https://developers.facebook.com/docs/reference/dialogs/ for details.* @param parameters a Bundle containing parameters to pass as part of the URL.*/public Builder(Context context, Session session, String action, Bundle parameters) {super(context, session, action, parameters);}/*** Constructor that builds a dialog without an authenticated user.** @param context the Context within which the dialog will be shown.* @param applicationId the application ID to be included in the dialog URL.* @param action the portion of the dialog URL following www.facebook.com/dialog/.* See https://developers.facebook.com/docs/reference/dialogs/ for details.* @param parameters a Bundle containing parameters to pass as part of the URL.*/public Builder(Context context, String applicationId, String action, Bundle parameters) {super(context, applicationId, action, parameters);}}/*** Provides a builder that allows construction of the parameters for showing* the <a href="https://developers.facebook.com/docs/reference/dialogs/feed">Feed Dialog</a>.*/public static class FeedDialogBuilder extends BuilderBase<FeedDialogBuilder> {private static final String FEED_DIALOG = "feed";private static final String FROM_PARAM = "from";private static final String TO_PARAM = "to";private static final String LINK_PARAM = "link";private static final String PICTURE_PARAM = "picture";private static final String SOURCE_PARAM = "source";private static final String NAME_PARAM = "name";private static final String CAPTION_PARAM = "caption";private static final String DESCRIPTION_PARAM = "description";/*** Constructor that builds a Feed Dialog using either the active session, or the application* ID specified in the application/meta-data.** @param context the Context within which the dialog will be shown.*/public FeedDialogBuilder(Context context) {super(context, FEED_DIALOG);}/*** Constructor that builds a Feed Dialog using the provided session.** @param context the Context within which the dialog will be shown.* @param session the Session representing an authenticating user to use for* showing the dialog; must not be null, and must be opened.*/public FeedDialogBuilder(Context context, Session session) {super(context, session, FEED_DIALOG, null);}/*** Constructor that builds a Feed Dialog using the provided session and parameters.** @param context the Context within which the dialog will be shown.* @param session the Session representing an authenticating user to use for* showing the dialog; must not be null, and must be opened.* @param parameters a Bundle containing parameters to pass as part of the* dialog URL. No validation is done on these parameters; it is* the caller's responsibility to ensure they are valid. For more information,* see <a href="https://developers.facebook.com/docs/reference/dialogs/feed/">* https://developers.facebook.com/docs/reference/dialogs/feed/</a>.*/public FeedDialogBuilder(Context context, Session session, Bundle parameters) {super(context, session, FEED_DIALOG, parameters);}/*** Constructor that builds a Feed Dialog using the provided application ID and parameters.** @param context the Context within which the dialog will be shown.* @param applicationId the application ID to use. If null, the application ID specified in the* application/meta-data will be used instead.* @param parameters a Bundle containing parameters to pass as part of the* dialog URL. No validation is done on these parameters; it is* the caller's responsibility to ensure they are valid. For more information,* see <a href="https://developers.facebook.com/docs/reference/dialogs/feed/">* https://developers.facebook.com/docs/reference/dialogs/feed/</a>.*/public FeedDialogBuilder(Context context, String applicationId, Bundle parameters) {super(context, applicationId, FEED_DIALOG, parameters);}/*** Sets the ID of the profile that is posting to Facebook. If none is specified,* the default is "me". This profile must be either the authenticated user or a* Page that the user is an administrator of.** @param id Facebook ID of the profile to post from* @return the builder*/public FeedDialogBuilder setFrom(String id) {getParameters().putString(FROM_PARAM, id);return this;}/*** Sets the ID of the profile that the story will be published to. If not specified, it* will default to the same profile that the story is being published from. The ID must be a friend who also* uses your app.** @param id Facebook ID of the profile to post to* @return the builder*/public FeedDialogBuilder setTo(String id) {getParameters().putString(TO_PARAM, id);return this;}/*** Sets the URL of a link to be shared.** @param link the URL* @return the builder*/public FeedDialogBuilder setLink(String link) {getParameters().putString(LINK_PARAM, link);return this;}/*** Sets the URL of a picture to be shared.** @param picture the URL of the picture* @return the builder*/public FeedDialogBuilder setPicture(String picture) {getParameters().putString(PICTURE_PARAM, picture);return this;}/*** Sets the URL of a media file attached to this post. If this is set, any picture* set via setPicture will be ignored.** @param source the URL of the media file* @return the builder*/public FeedDialogBuilder setSource(String source) {getParameters().putString(SOURCE_PARAM, source);return this;}/*** Sets the name of the URL being shared. This method only has effect if setLink is called.** @param name the name* @return the builder*/public FeedDialogBuilder setName(String name) {getParameters().putString(NAME_PARAM, name);return this;}/*** Sets the caption of the URL being shared. This method only has effect if setLink is called.** @param caption the caption* @return the builder*/public FeedDialogBuilder setCaption(String caption) {getParameters().putString(CAPTION_PARAM, caption);return this;}/*** Sets the description of the URL being shared. This method only has effect if setLink is called.** @param description the description* @return the builder*/public FeedDialogBuilder setDescription(String description) {getParameters().putString(DESCRIPTION_PARAM, description);return this;}}/*** Provides a builder that allows construction of the parameters for showing* the <a href="https://developers.facebook.com/docs/reference/dialogs/requests">Requests Dialog</a>.*/public static class RequestsDialogBuilder extends BuilderBase<RequestsDialogBuilder> {private static final String APPREQUESTS_DIALOG = "apprequests";private static final String MESSAGE_PARAM = "message";private static final String TO_PARAM = "to";private static final String DATA_PARAM = "data";private static final String TITLE_PARAM = "title";/*** Constructor that builds a Requests Dialog using either the active session, or the application* ID specified in the application/meta-data.** @param context the Context within which the dialog will be shown.*/public RequestsDialogBuilder(Context context) {super(context, APPREQUESTS_DIALOG);}/*** Constructor that builds a Requests Dialog using the provided session.** @param context the Context within which the dialog will be shown.* @param session the Session representing an authenticating user to use for* showing the dialog; must not be null, and must be opened.*/public RequestsDialogBuilder(Context context, Session session) {super(context, session, APPREQUESTS_DIALOG, null);}/*** Constructor that builds a Requests Dialog using the provided session and parameters.** @param context the Context within which the dialog will be shown.* @param session the Session representing an authenticating user to use for* showing the dialog; must not be null, and must be opened.* @param parameters a Bundle containing parameters to pass as part of the* dialog URL. No validation is done on these parameters; it is* the caller's responsibility to ensure they are valid. For more information,* see <a href="https://developers.facebook.com/docs/reference/dialogs/requests/">* https://developers.facebook.com/docs/reference/dialogs/requests/</a>.*/public RequestsDialogBuilder(Context context, Session session, Bundle parameters) {super(context, session, APPREQUESTS_DIALOG, parameters);}/*** Constructor that builds a Requests Dialog using the provided application ID and parameters.** @param context the Context within which the dialog will be shown.* @param applicationId the application ID to use. If null, the application ID specified in the* application/meta-data will be used instead.* @param parameters a Bundle containing parameters to pass as part of the* dialog URL. No validation is done on these parameters; it is* the caller's responsibility to ensure they are valid. For more information,* see <a href="https://developers.facebook.com/docs/reference/dialogs/requests/">* https://developers.facebook.com/docs/reference/dialogs/requests/</a>.*/public RequestsDialogBuilder(Context context, String applicationId, Bundle parameters) {super(context, applicationId, APPREQUESTS_DIALOG, parameters);}/*** Sets the string users receiving the request will see. The maximum length* is 60 characters.** @param message the message* @return the builder*/public RequestsDialogBuilder setMessage(String message) {getParameters().putString(MESSAGE_PARAM, message);return this;}/*** Sets the user ID or user name the request will be sent to. If this is not* specified, a friend selector will be displayed and the user can select up* to 50 friends.** @param id the id or user name to send the request to* @return the builder*/public RequestsDialogBuilder setTo(String id) {getParameters().putString(TO_PARAM, id);return this;}/*** Sets optional data which can be used for tracking; maximum length is 255* characters.** @param data the data* @return the builder*/public RequestsDialogBuilder setData(String data) {getParameters().putString(DATA_PARAM, data);return this;}/*** Sets an optional title for the dialog; maximum length is 50 characters.** @param title the title* @return the builder*/public RequestsDialogBuilder setTitle(String title) {getParameters().putString(TITLE_PARAM, title);return this;}}}