com.facebook.share.internal.DeviceShareDialogFragment.java Source code

Java tutorial

Introduction

Here is the source code for com.facebook.share.internal.DeviceShareDialogFragment.java

Source

/**
 * Copyright (c) 2014-present, Facebook, Inc. All rights reserved.
 *
 * You are hereby granted a non-exclusive, worldwide, royalty-free license to use,
 * copy, modify, and distribute this software in source code or binary form for use
 * in connection with the web services and APIs provided by Facebook.
 *
 * As with any software that integrates with the Facebook platform, your use of
 * this software is subject to the Facebook Developer Principles and Policies
 * [http://developers.facebook.com/policy/]. This copyright notice shall be
 * included in all copies or substantial portions of the software.
 *
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
 * FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
 * COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
 * IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
 * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
 */

package com.facebook.share.internal;

import android.app.Activity;
import android.app.Dialog;
import android.content.DialogInterface;
import android.content.Intent;
import android.os.Bundle;
import android.os.Parcel;
import android.os.Parcelable;
import android.support.annotation.NonNull;
import android.support.annotation.Nullable;
import android.support.v4.app.DialogFragment;
import android.text.Html;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.Button;
import android.widget.ProgressBar;
import android.widget.TextView;

import com.facebook.FacebookRequestError;
import com.facebook.GraphRequest;
import com.facebook.GraphResponse;
import com.facebook.HttpMethod;
import com.facebook.R;
import com.facebook.devicerequests.internal.DeviceRequestsHelper;
import com.facebook.internal.Validate;
import com.facebook.share.model.ShareContent;
import com.facebook.share.model.ShareLinkContent;
import com.facebook.share.model.ShareOpenGraphContent;

import org.json.JSONException;
import org.json.JSONObject;

import java.util.concurrent.ScheduledFuture;
import java.util.concurrent.ScheduledThreadPoolExecutor;
import java.util.concurrent.TimeUnit;

/**
 * com.facebook.share.internal is solely for the use of other packages within the
 * Facebook SDK for Android. Use of any of the classes in this package is
 * unsupported, and they may be modified or removed without warning at any time.
 */
public class DeviceShareDialogFragment extends DialogFragment {
    public static final String TAG = "DeviceShareDialogFragment";
    private static final String DEVICE_SHARE_ENDPOINT = "device/share";
    private static final String REQUEST_STATE_KEY = "request_state";
    private ProgressBar progressBar;
    private TextView confirmationCode;
    private Dialog dialog;
    private volatile RequestState currentRequestState;
    private volatile ScheduledFuture codeExpiredFuture;
    private static ScheduledThreadPoolExecutor backgroundExecutor;
    private ShareContent shareContent;

    @Nullable
    @Override
    public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
        View view = super.onCreateView(inflater, container, savedInstanceState);
        if (savedInstanceState != null) {
            RequestState requestState = savedInstanceState.getParcelable(REQUEST_STATE_KEY);
            if (requestState != null) {
                setCurrentRequestState(requestState);
            }
        }
        return view;
    }

    @NonNull
    @Override
    public Dialog onCreateDialog(Bundle savedInstanceState) {
        dialog = new Dialog(getActivity(), R.style.com_facebook_auth_dialog);
        LayoutInflater inflater = getActivity().getLayoutInflater();
        View view = inflater.inflate(R.layout.com_facebook_device_auth_dialog_fragment, null);
        progressBar = (ProgressBar) view.findViewById(R.id.progress_bar);
        confirmationCode = (TextView) view.findViewById(R.id.confirmation_code);

        Button cancelButton = (Button) view.findViewById(R.id.cancel_button);
        cancelButton.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                dialog.dismiss();
            }
        });

        TextView instructions = (TextView) view.findViewById(R.id.com_facebook_device_auth_instructions);
        instructions.setText(Html.fromHtml(getString(R.string.com_facebook_device_auth_instructions)));

        dialog.setContentView(view);

        this.startShare();
        return dialog;
    }

    @Override
    public void onDismiss(final DialogInterface dialog) {
        super.onDismiss(dialog);
        if (codeExpiredFuture != null) {
            codeExpiredFuture.cancel(true);
        }
        Intent resultIntent = new Intent();
        finishActivity(Activity.RESULT_OK, resultIntent);
    }

    @Override
    public void onSaveInstanceState(Bundle outState) {
        super.onSaveInstanceState(outState);
        if (currentRequestState != null) {
            outState.putParcelable(REQUEST_STATE_KEY, currentRequestState);
        }
    }

    private void finishActivity(int resultCode, Intent data) {
        DeviceRequestsHelper.cleanUpAdvertisementService(currentRequestState.getUserCode());

        if (isAdded()) {
            Activity activity = getActivity();
            activity.setResult(resultCode, data);
            activity.finish();
        }
    }

    private void detach() {
        if (isAdded()) {
            this.getFragmentManager().beginTransaction().remove(this).commit();
        }
    }

    public void setShareContent(ShareContent shareContent) {
        this.shareContent = shareContent;
    }

    private Bundle getGraphParametersForShareContent() {
        ShareContent content = this.shareContent;
        if (content == null) {
            return null;
        }
        if (content instanceof ShareLinkContent) {
            return WebDialogParameters.create((ShareLinkContent) content);
        } else if (content instanceof ShareOpenGraphContent) {
            return WebDialogParameters.create((ShareOpenGraphContent) content);
        }
        return null;
    }

    private void startShare() {
        Bundle parameters = getGraphParametersForShareContent();
        if (parameters == null || parameters.size() == 0) {
            this.finishActivityWithError(new FacebookRequestError(0, "", "Failed to get share content"));
        }

        String accessToken = Validate.hasAppID() + "|" + Validate.hasClientToken();
        parameters.putString(GraphRequest.ACCESS_TOKEN_PARAM, accessToken);
        parameters.putString(DeviceRequestsHelper.DEVICE_INFO_PARAM, DeviceRequestsHelper.getDeviceInfo());

        GraphRequest graphRequest = new GraphRequest(null, DEVICE_SHARE_ENDPOINT, parameters, HttpMethod.POST,
                new GraphRequest.Callback() {
                    @Override
                    public void onCompleted(GraphResponse response) {
                        FacebookRequestError error = response.getError();
                        if (error != null) {
                            finishActivityWithError(error);
                            return;
                        }

                        JSONObject jsonObject = response.getJSONObject();
                        RequestState requestState = new RequestState();
                        try {
                            requestState.setUserCode(jsonObject.getString("user_code"));
                            requestState.setExpiresIn(jsonObject.getLong("expires_in"));
                        } catch (JSONException ex) {
                            finishActivityWithError(new FacebookRequestError(0, "", "Malformed server response"));
                            return;
                        }

                        setCurrentRequestState(requestState);
                    }
                });
        graphRequest.executeAsync();
    }

    private void finishActivityWithError(FacebookRequestError error) {
        // detach so that we don't send a cancellation message back ondismiss.
        detach();
        Intent intent = new Intent();
        intent.putExtra("error", error);
        finishActivity(Activity.RESULT_OK, intent);
    }

    private static synchronized ScheduledThreadPoolExecutor getBackgroundExecutor() {
        if (backgroundExecutor == null) {
            backgroundExecutor = new ScheduledThreadPoolExecutor(1);
        }
        return backgroundExecutor;
    }

    private void setCurrentRequestState(RequestState currentRequestState) {
        this.currentRequestState = currentRequestState;
        confirmationCode.setText(currentRequestState.getUserCode());
        confirmationCode.setVisibility(View.VISIBLE);
        progressBar.setVisibility(View.GONE);

        codeExpiredFuture = getBackgroundExecutor().schedule(new Runnable() {
            @Override
            public void run() {
                dialog.dismiss();
            }
        }, currentRequestState.getExpiresIn(), TimeUnit.SECONDS);
    }

    private static class RequestState implements Parcelable {
        private String userCode;
        private long expiresIn;

        RequestState() {
        }

        public String getUserCode() {
            return userCode;
        }

        public void setUserCode(String userCode) {
            this.userCode = userCode;
        }

        public long getExpiresIn() {
            return expiresIn;
        }

        public void setExpiresIn(long expiresIn) {
            this.expiresIn = expiresIn;
        }

        protected RequestState(Parcel in) {
            userCode = in.readString();
            expiresIn = in.readLong();
        }

        @Override
        public int describeContents() {
            return 0;
        }

        @Override
        public void writeToParcel(Parcel dest, int flags) {
            dest.writeString(userCode);
            dest.writeLong(expiresIn);
        }

        @SuppressWarnings("unused")
        public static final Parcelable.Creator<RequestState> CREATOR = new Parcelable.Creator<RequestState>() {
            @Override
            public RequestState createFromParcel(Parcel in) {
                return new RequestState(in);
            }

            @Override
            public RequestState[] newArray(int size) {
                return new RequestState[size];
            }
        };
    }
}