Android Open Source - Robook Facebook App Link Resolver






From Project

Back to project page Robook.

License

The source code is released under:

MIT License

If you think the Android project Robook 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  w w.  j  a  v  a2 s.  co  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_KEY = "app_links";
    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("ids", graphRequestFields.toString());
        appLinkRequestParameters.putString(
                "fields",
                String.format("%s.fields(%s,%s)", APP_LINK_KEY, 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());
                                JSONObject appLinkData = urlData.getJSONObject(APP_LINK_KEY);

                                JSONArray rawTargets = appLinkData.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, appLinkData);
                                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.FacebookTimeSpentData.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
unipg.dmi.robook.AbstractAdkActivity.java
unipg.dmi.robook.MainActivity.java
unipg.dmi.robook.Preview.java
unipg.dmi.robook.UpdaterService.java
unipg.dmi.robook.prefs.java