Android Open Source - facebook-connect-plugin-appbuilder Facebook App Link Resolver






From Project

Back to project page facebook-connect-plugin-appbuilder.

License

The source code is released under:

Apache License

If you think the Android project facebook-connect-plugin-appbuilder listed in this page is inappropriate, such as containing malicious code/tools or violating the copyright, please email info at java2s dot com, thanks.

Java Source Code

/**
 * Copyright 2010-present Facebook.// w  ww.  java 2 s.c  o  m
 *
 * 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;

import android.net.Uri;
import android.os.Bundle;
import bolts.AppLink;
import bolts.AppLinkResolver;
import bolts.Continuation;
import bolts.Task;
import com.facebook.model.GraphObject;
import org.json.JSONArray;
import org.json.JSONException;
import org.json.JSONObject;

import java.util.*;

/**
 * Provides an implementation for the {@link AppLinkResolver AppLinkResolver} interface that uses the Facebook App Link
 * index to solve App Links, given a Url. It also provides an additional helper method that can resolve multiple App
 * Links in a single call.
 */
public class FacebookAppLinkResolver implements AppLinkResolver {

    private static final String APP_LINK_ANDROID_TARGET_KEY = "android";
    private static final String APP_LINK_WEB_TARGET_KEY = "web";
    private static final String APP_LINK_TARGET_PACKAGE_KEY = "package";
    private static final String APP_LINK_TARGET_CLASS_KEY = "class";
    private static final String APP_LINK_TARGET_APP_NAME_KEY = "app_name";
    private static final String APP_LINK_TARGET_URL_KEY = "url";
    private static final String APP_LINK_TARGET_SHOULD_FALLBACK_KEY = "should_fallback";

    private final HashMap<Uri, AppLink> cachedAppLinks = new HashMap<Uri, AppLink>();

    /**
     * Asynchronously resolves App Link data for the passed in Uri
     *
     * @param uri Uri to be resolved into an App Link
     * @return A Task that, when successful, will return an AppLink for the passed in Uri. This may be null if no App
     * Link data was found for this Uri.
     * In the case of general server errors, the task will be completed with the corresponding error.
     */
    public Task<AppLink> getAppLinkFromUrlInBackground(final Uri uri) {
        ArrayList<Uri> uris = new ArrayList<Uri>();
        uris.add(uri);

        Task<Map<Uri, AppLink>> resolveTask = getAppLinkFromUrlsInBackground(uris);

        return resolveTask.onSuccess(new Continuation<Map<Uri, AppLink>, AppLink>() {
            @Override
            public AppLink then(Task<Map<Uri, AppLink>> resolveUrisTask) throws Exception {
                return resolveUrisTask.getResult().get(uri);
            }
        });
    }

    /**
     * Asynchronously resolves App Link data for multiple Urls
     *
     * @param uris A list of Uri objects to resolve into App Links
     * @return A Task that, when successful, will return a Map of Uri->AppLink for each Uri that was successfully
     * resolved into an App Link. Uris that could not be resolved into App Links will not be present in the Map.
     * In the case of general server errors, the task will be completed with the corresponding error.
     */
    public Task<Map<Uri, AppLink>> getAppLinkFromUrlsInBackground(List<Uri> uris) {
        final Map<Uri, AppLink> appLinkResults = new HashMap<Uri, AppLink>();
        final HashSet<Uri> urisToRequest = new HashSet<Uri>();
        StringBuilder graphRequestFields = new StringBuilder();

        for (Uri uri : uris) {
            AppLink appLink = null;
            synchronized (cachedAppLinks) {
                appLink = cachedAppLinks.get(uri);
            }

            if (appLink != null) {
                appLinkResults.put(uri, appLink);
            } else {
                if (!urisToRequest.isEmpty()) {
                    graphRequestFields.append(',');
                }
                graphRequestFields.append(uri.toString());
                urisToRequest.add(uri);
            }
        }

        if (urisToRequest.isEmpty()) {
            return Task.forResult(appLinkResults);
        }

        final Task<Map<Uri, AppLink>>.TaskCompletionSource taskCompletionSource = Task.create();

        Bundle appLinkRequestParameters = new Bundle();
        appLinkRequestParameters.putString("type", "al");
        appLinkRequestParameters.putString("ids", graphRequestFields.toString());
        appLinkRequestParameters.putString(
                "fields",
                String.format("%s,%s", APP_LINK_ANDROID_TARGET_KEY, APP_LINK_WEB_TARGET_KEY));

        Request appLinkRequest = new Request(
                null, /* Session */
                "", /* Graph path */
                appLinkRequestParameters, /* Query parameters */
                null, /* HttpMethod */
                new Request.Callback() { /* Callback */
                    @Override
                    public void onCompleted(Response response) {
                        FacebookRequestError error = response.getError();
                        if (error != null) {
                            taskCompletionSource.setError(error.getException());
                            return;
                        }

                        GraphObject responseObject = response.getGraphObject();
                        JSONObject responseJson = responseObject != null ? responseObject.getInnerJSONObject() : null;
                        if (responseJson == null) {
                            taskCompletionSource.setResult(appLinkResults);
                            return;
                        }

                        for (Uri uri : urisToRequest) {
                            String uriString = uri.toString();
                            if (!responseJson.has(uriString)) {
                                continue;
                            }

                            JSONObject urlData = null;
                            try {
                                urlData = responseJson.getJSONObject(uri.toString());
                                JSONArray rawTargets = urlData.getJSONArray(APP_LINK_ANDROID_TARGET_KEY);

                                int targetsCount = rawTargets.length();
                                List<AppLink.Target> targets = new ArrayList<AppLink.Target>(targetsCount);

                                for (int i = 0; i < targetsCount; i++) {
                                    AppLink.Target target = getAndroidTargetFromJson(rawTargets.getJSONObject(i));
                                    if (target != null) {
                                        targets.add(target);
                                    }
                                }

                                Uri webFallbackUrl = getWebFallbackUriFromJson(uri, urlData);
                                AppLink appLink = new AppLink(uri, targets, webFallbackUrl);

                                appLinkResults.put(uri, appLink);
                                synchronized (cachedAppLinks) {
                                    cachedAppLinks.put(uri, appLink);
                                }
                            } catch (JSONException e) {
                                // The data for this uri was missing or badly formed.
                                continue;
                            }
                        }

                        taskCompletionSource.setResult(appLinkResults);
                    }
                });

        appLinkRequest.executeAsync();

        return taskCompletionSource.getTask();
    }

    private static AppLink.Target getAndroidTargetFromJson(JSONObject targetJson) {
        String packageName = tryGetStringFromJson(targetJson, APP_LINK_TARGET_PACKAGE_KEY, null);
        if (packageName == null) {
            // Package name is mandatory for each Android target
            return null;
        }
        String className = tryGetStringFromJson(targetJson, APP_LINK_TARGET_CLASS_KEY, null);
        String appName = tryGetStringFromJson(targetJson, APP_LINK_TARGET_APP_NAME_KEY, null);
        String targetUrlString = tryGetStringFromJson(targetJson, APP_LINK_TARGET_URL_KEY, null);
        Uri targetUri = null;
        if (targetUrlString != null) {
            targetUri = Uri.parse(targetUrlString);
        }

        return new AppLink.Target(packageName, className, targetUri, appName);
    }

    private static Uri getWebFallbackUriFromJson(Uri sourceUrl, JSONObject urlData) {
        // Try and get a web target. This is best effort. Any failures results in null being returned.
        try {
            JSONObject webTarget = urlData.getJSONObject(APP_LINK_WEB_TARGET_KEY);
            boolean shouldFallback = tryGetBooleanFromJson(webTarget, APP_LINK_TARGET_SHOULD_FALLBACK_KEY, true);
            if (!shouldFallback) {
                // Don't use a fallback url
                return null;
            }

            String webTargetUrlString = tryGetStringFromJson(webTarget, APP_LINK_TARGET_URL_KEY, null);
            Uri webUri = null;
            if (webTargetUrlString != null) {
                webUri = Uri.parse(webTargetUrlString);
            }

            // If we weren't able to parse a url from the web target, use the source url
            return webUri != null ? webUri: sourceUrl;
        } catch (JSONException e) {
            // If we were missing a web target, just use the source as the web url
            return sourceUrl;
        }
    }

    private static String tryGetStringFromJson(JSONObject json, String propertyName, String defaultValue) {
        try {
            return json.getString(propertyName);
        } catch(JSONException e) {
            return defaultValue;
        }
    }

    private static boolean tryGetBooleanFromJson(JSONObject json, String propertyName, boolean defaultValue) {
        try {
            return json.getBoolean(propertyName);
        } catch (JSONException e) {
            return defaultValue;
        }
    }
}




Java Source Code List

com.facebook.AccessTokenSource.java
com.facebook.AccessToken.java
com.facebook.AppEventsConstants.java
com.facebook.AppEventsLogger.java
com.facebook.AppLinkData.java
com.facebook.AuthorizationClient.java
com.facebook.BoltsMeasurementEventListener.java
com.facebook.FacebookAppLinkResolver.java
com.facebook.FacebookAuthorizationException.java
com.facebook.FacebookBroadcastReceiver.java
com.facebook.FacebookDialogException.java
com.facebook.FacebookException.java
com.facebook.FacebookGraphObjectException.java
com.facebook.FacebookOperationCanceledException.java
com.facebook.FacebookRequestError.java
com.facebook.FacebookSdkVersion.java
com.facebook.FacebookServiceException.java
com.facebook.GetTokenClient.java
com.facebook.HttpMethod.java
com.facebook.InsightsLogger.java
com.facebook.LegacyHelper.java
com.facebook.LoggingBehavior.java
com.facebook.LoginActivity.java
com.facebook.NativeAppCallAttachmentStore.java
com.facebook.NativeAppCallContentProvider.java
com.facebook.NonCachingTokenCachingStrategy.java
com.facebook.ProgressNoopOutputStream.java
com.facebook.ProgressOutputStream.java
com.facebook.RequestAsyncTask.java
com.facebook.RequestBatch.java
com.facebook.RequestOutputStream.java
com.facebook.RequestProgress.java
com.facebook.Request.java
com.facebook.Response.java
com.facebook.SessionDefaultAudience.java
com.facebook.SessionLoginBehavior.java
com.facebook.SessionState.java
com.facebook.Session.java
com.facebook.Settings.java
com.facebook.SharedPreferencesTokenCachingStrategy.java
com.facebook.TestSession.java
com.facebook.TokenCachingStrategy.java
com.facebook.UiLifecycleHelper.java
com.facebook.android.AsyncFacebookRunner.java
com.facebook.android.DialogError.java
com.facebook.android.FacebookError.java
com.facebook.android.Facebook.java
com.facebook.android.FbDialog.java
com.facebook.android.Util.java
com.facebook.internal.AnalyticsEvents.java
com.facebook.internal.AttributionIdentifiers.java
com.facebook.internal.CacheableRequestBatch.java
com.facebook.internal.FileLruCache.java
com.facebook.internal.ImageDownloader.java
com.facebook.internal.ImageRequest.java
com.facebook.internal.ImageResponseCache.java
com.facebook.internal.ImageResponse.java
com.facebook.internal.Logger.java
com.facebook.internal.NativeProtocol.java
com.facebook.internal.PlatformServiceClient.java
com.facebook.internal.ServerProtocol.java
com.facebook.internal.SessionAuthorizationType.java
com.facebook.internal.SessionTracker.java
com.facebook.internal.UrlRedirectCache.java
com.facebook.internal.Utility.java
com.facebook.internal.Validate.java
com.facebook.internal.WorkQueue.java
com.facebook.internal.package-info.java
com.facebook.model.CreateGraphObject.java
com.facebook.model.GraphLocation.java
com.facebook.model.GraphMultiResult.java
com.facebook.model.GraphObjectList.java
com.facebook.model.GraphObject.java
com.facebook.model.GraphPlace.java
com.facebook.model.GraphUser.java
com.facebook.model.JsonUtil.java
com.facebook.model.OpenGraphAction.java
com.facebook.model.OpenGraphObject.java
com.facebook.model.PropertyName.java
com.facebook.widget.FacebookDialog.java
com.facebook.widget.FacebookFragment.java
com.facebook.widget.FriendPickerFragment.java
com.facebook.widget.GraphObjectAdapter.java
com.facebook.widget.GraphObjectCursor.java
com.facebook.widget.GraphObjectPagingLoader.java
com.facebook.widget.LoginButton.java
com.facebook.widget.PickerFragment.java
com.facebook.widget.PlacePickerFragment.java
com.facebook.widget.ProfilePictureView.java
com.facebook.widget.SimpleGraphObjectCursor.java
com.facebook.widget.ToolTipPopup.java
com.facebook.widget.UserSettingsFragment.java
com.facebook.widget.WebDialog.java
org.apache.cordova.facebook.ConnectPlugin.java