Android Open Source - CCSocialNetwork Insights Logger






From Project

Back to project page CCSocialNetwork.

License

The source code is released under:

GNU Lesser General Public License

If you think the Android project CCSocialNetwork 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./*from   w ww  .  j  a  va 2s  .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.content.Context;
import android.os.Bundle;
import com.facebook.internal.Logger;
import com.facebook.internal.Utility;
import com.facebook.internal.Validate;
import com.facebook.model.GraphObject;
import org.json.JSONArray;
import org.json.JSONException;
import org.json.JSONObject;

import java.math.BigDecimal;
import java.util.Currency;
import java.util.Set;

/**
 * The InsightsLogger class allows the developer to log various types of events back to Facebook.  In order to log
 * events, the app must create an instance of this class via a {@link #newLogger newLogger} method, and then call
 * the various "log" methods off of that.  Note that a Client Token for the app is required in calls to newLogger so
 * apps that have not authenticated their users can still get meaningful user-demographics from the logged events
 * on Facebook.
 */
public class InsightsLogger {

    // Constants

    // Event names, these match what the server expects.
    private static final String EVENT_NAME_LOG_CONVERSION_PIXEL = "fb_log_offsite_pixel";
    private static final String EVENT_NAME_LOG_MOBILE_PURCHASE  = "fb_mobile_purchase";

    // Event parameter names, these match what the server expects.
    private static final String EVENT_PARAMETER_CURRENCY        = "fb_currency";
    private static final String EVENT_PARAMETER_PIXEL_ID        = "fb_offsite_pixel_id";
    private static final String EVENT_PARAMETER_PIXEL_VALUE     = "fb_offsite_pixel_value";

    // Static member variables
    private static Session appAuthSession = null;

    // Instance member variables
    private final Context context;
    private final String  clientToken;
    private final String  applicationId;
    private final Session specifiedSession;


    /**
     * Constructor is private, newLogger() methods should be used to build an instance.
     */
    private InsightsLogger(Context context, String clientToken, String applicationId, Session session) {

        Validate.notNull(context, "context");

        // Always ensure the client token is present, even if not needed for this particular logging (because at
        // some point it will be required).  Be harsh by throwing an exception because this is all too easy to miss
        // and things will work with authenticated sessions, but start failing with users that don't have
        // authenticated sessions.
        Validate.notNullOrEmpty(clientToken, "clientToken");

        if (applicationId == null) {
            applicationId = Utility.getMetadataApplicationId(context);
        }

        this.context = context;
        this.clientToken = clientToken;
        this.applicationId = applicationId;
        this.specifiedSession = session;
    }

    /**
     * Build an InsightsLogger instance to log events through.  The Facebook app that these events are targeted at
     * comes from this application's metadata.
     *
     * @param context      Used to access the applicationId and the attributionId for non-authenticated users.
     * @param clientToken  The Facebook app's "client token", which, for a given appid can be found in the Security
     *                     section of the Advanced tab of the Facebook App settings found
     *                     at <https://developers.facebook.com/apps/[your-app-id]>.
     *
     * @return          InsightsLogger instance to invoke log* methods on.
     */
    public static InsightsLogger newLogger(Context context, String clientToken) {
        return new InsightsLogger(context, clientToken, null, null);
    }

    /**
     * Build an InsightsLogger instance to log events through.  Allow explicit specification of an Facebook app
     * to target.
     *
     * @param context        Used to access the attributionId for non-authenticated users.
     * @param clientToken    The Facebook app's "client token", which, for a given appid can be found in the Security
     *                       section of the Advanced tab of the Facebook App settings found
     *                       at <https://developers.facebook.com/apps/[your-app-id]>
     * @param applicationId  Explicitly specified Facebook applicationId to log events against.  If null, the
     *                       applicationId embedded in the application metadata accessible from 'context' will
     *                       be used.
     *
     * @return          InsightsLogger instance to invoke log* methods on.
     */
    public static InsightsLogger newLogger(Context context, String clientToken, String applicationId) {
        return new InsightsLogger(context, clientToken, applicationId, null);
    }

    /**
     * Build an InsightsLogger instance to log events through.
     *
     * @param context        Used to access the attributionId for non-authenticated users.
     * @param clientToken    The Facebook app's "client token", which, for a given appid can be found in the Security
     *                       section of the Advanced tab of the Facebook App settings found
     *                       at <https://developers.facebook.com/apps/[your-app-id]>
     * @param applicationId  Explicitly specified Facebook applicationId to log events against.  If null, the
     *                       applicationId embedded in the application metadata accessible from 'context' will
     *                       be used.
     * @param session        Explicitly specified Session to log events against.  If null, the activeSession
     *                       will be used if it's open, otherwise the logging will happen via the "clientToken"
     *                       and specified appId.
     *
     * @return          InsightsLogger instance to invoke log* methods on.
     */
    public static InsightsLogger newLogger(Context context, String clientToken, String applicationId, Session session) {
        return new InsightsLogger(context, clientToken, applicationId, session);
    }

    /**
     * Logs a purchase event with Facebook, in the specified amount and with the specified currency.
     *
     * @param purchaseAmount  Amount of purchase, in the currency specified by the 'currency' parameter. This value
     *                        will be rounded to the thousandths place (e.g., 12.34567 becomes 12.346).
     * @param currency        Currency used to specify the amount.
     */
    public void logPurchase(BigDecimal purchaseAmount, Currency currency) {
        logPurchase(purchaseAmount, currency, null);
    }

    /**
     * Logs a purchase event with Facebook, in the specified amount and with the specified currency.  Additional
     * detail about the purchase can be passed in through the parameters bundle.
     *
     * @param purchaseAmount  Amount of purchase, in the currency specified by the 'currency' parameter. This value
     *                        will be rounded to the thousandths place (e.g., 12.34567 becomes 12.346).
     * @param currency        Currency used to specify the amount.
     * @param parameters      Arbitrary additional information for describing this event.  Should have no more than
     *                        10 entries, and keys should be mostly consistent from one purchase event to the next.
     */
    public void logPurchase(BigDecimal purchaseAmount, Currency currency, Bundle parameters) {

        if (purchaseAmount == null) {
            notifyDeveloperError("purchaseAmount cannot be null");
            return;
        } else if (currency == null) {
            notifyDeveloperError("currency cannot be null");
            return;
        }

        if (parameters == null) {
            parameters = new Bundle();
        }
        parameters.putString(EVENT_PARAMETER_CURRENCY, currency.getCurrencyCode());

        logEventNow(EVENT_NAME_LOG_MOBILE_PURCHASE, purchaseAmount.doubleValue(), parameters);
    }

    /**
     * Log, or "Fire" a Conversion Pixel.  Conversion Pixels are used for Ads Conversion Tracking.  See
     * https://www.facebook.com/help/435189689870514 to learn more.
     *
     * @param pixelId      Numeric ID for the conversion pixel to be logged.  See
     *                     https://www.facebook.com/help/435189689870514 to learn how to create a conversion pixel.
     * @param valueOfPixel Value of what the logging of this pixel is worth to the calling app.  The currency that this
     *                     is expressed in doesn't matter, so long as it is consistent across all logging for this
     *                     pixel. This value will be rounded to the thousandths place (e.g., 12.34567 becomes 12.346).
     */
    public void logConversionPixel(String pixelId, double valueOfPixel) {

        if (pixelId == null) {
            notifyDeveloperError("pixelID cannot be null");
            return;
        }

        Bundle parameters = new Bundle();
        parameters.putString(EVENT_PARAMETER_PIXEL_ID, pixelId);
        parameters.putDouble(EVENT_PARAMETER_PIXEL_VALUE, valueOfPixel);

        logEventNow(EVENT_NAME_LOG_CONVERSION_PIXEL, valueOfPixel, parameters);
    }

    /**
     * This is the workhorse function of the InsightsLogger class and does the packaging and POST.  As InsightsLogger
     * is expanded to support more custom app events, this logic will become more complicated and allow for batching
     * and flushing of multiple events, of persisting to disk so as to survive network outages, implicitly logging
     * (with the dev's permission) SDK actions, etc.
     */
    private void logEventNow(
            final String eventName,
            final double valueToSum,
            final Bundle parameters) {

        // Run everything synchronously on a worker thread.
        Settings.getExecutor().execute(new Runnable() {

            @Override
            public void run() {

                final String eventJSON = buildJSONForEvent(eventName, valueToSum, parameters);
                if (eventJSON == null) {
                    // Failure in building JSON, already reported, so just return.
                    return;
                }

                GraphObject publishParams = GraphObject.Factory.create();
                publishParams.setProperty("event", "CUSTOM_APP_EVENTS");
                publishParams.setProperty("custom_events", eventJSON);

                if (Utility.queryAppAttributionSupportAndWait(applicationId)) {
                    String attributionId = Settings.getAttributionId(context.getContentResolver());
                    if (attributionId != null) {
                        publishParams.setProperty("attribution", attributionId);
                    }
                }

                String publishUrl = String.format("%s/activities", applicationId);

                try {

                    Request postRequest = Request.newPostRequest(sessionToLogTo(), publishUrl, publishParams, null);
                    Response response = postRequest.executeAndWait();

                    // A -1 error code happens if there is no connectivity.  No need to notify the
                    // developer in that case.
                    final int NO_CONNECTIVITY_ERROR_CODE = -1;
                    if (response.getError() != null &&
                        response.getError().getErrorCode() != NO_CONNECTIVITY_ERROR_CODE) {
                        notifyDeveloperError(
                                String.format(
                                        "Error publishing Insights event '%s'\n  Response: %s\n  Error: %s",
                                        eventJSON,
                                        response.toString(),
                                        response.getError().toString()));
                    }

                } catch (Exception e) {

                    Utility.logd("Insights-exception: ", e);

                }
            }
        });

    }

    private static String buildJSONForEvent(String eventName, double valueToSum, Bundle parameters) {
        String result;
        try {

            // Build custom event payload
            JSONObject eventObject = new JSONObject();
            eventObject.put("_eventName", eventName);
            if (valueToSum != 1.0) {
                eventObject.put("_valueToSum", valueToSum);
            }

            if (parameters != null) {

                Set<String> keys = parameters.keySet();
                for (String key : keys) {
                    Object value = parameters.get(key);

                    if (!(value instanceof String) &&
                        !(value instanceof Number)) {

                        notifyDeveloperError(
                                String.format("Parameter '%s' must be a string or a numeric type.", key));
                    }

                    eventObject.put(key, value);
                }
            }

            JSONArray eventArray = new JSONArray();
            eventArray.put(eventObject);

            result = eventArray.toString();

        } catch (JSONException exception) {

            notifyDeveloperError(exception.toString());
            result = null;

        }

        return result;
    }

    /**
     * Using the specifiedSession member variable (which may be nil), find the real session to log to
     * (with an access token).  Precedence: 1) specified session, 2) activeSession, 3) app authenticated
     * session via Client Token.
     */
    private Session sessionToLogTo() {

        synchronized (this) {

            Session session = specifiedSession;

            // Require an open session.

            if (session == null || !session.isOpened()) {
                session = Session.getActiveSession();
            }

            if (session == null || !session.isOpened() || session.getAccessToken() == null) {

                if (appAuthSession == null) {

                    // Build and stash a client-token based session.

                    // Form the clientToken based access token from appID and client token.
                    String tokenString = String.format("%s|%s", applicationId, clientToken);
                    AccessToken token = AccessToken.createFromString(tokenString, null, AccessTokenSource.CLIENT_TOKEN);

                    appAuthSession = new Session(null, applicationId, new NonCachingTokenCachingStrategy(), false);
                    appAuthSession.open(token, null);
                }

                session = appAuthSession;
            }

            return session;
        }
    }

    /**
     * Invoke this method, rather than throwing an Exception, for situations where user/server input might reasonably
     * cause this to occur, and thus don't want an exception thrown at production time, but do want logging
     * notification.
     */
    private static void notifyDeveloperError(String message) {
        Logger.log(LoggingBehavior.DEVELOPER_ERRORS, "Insights", message);
    }
}




Java Source Code List

com.facebook.AccessTokenSource.java
com.facebook.AccessToken.java
com.facebook.AuthorizationClient.java
com.facebook.FacebookAuthorizationException.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.NativeProtocol.java
com.facebook.NonCachingTokenCachingStrategy.java
com.facebook.RequestAsyncTask.java
com.facebook.RequestBatch.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.CacheableRequestBatch.java
com.facebook.internal.FileLruCache.java
com.facebook.internal.Logger.java
com.facebook.internal.ServerProtocol.java
com.facebook.internal.SessionAuthorizationType.java
com.facebook.internal.SessionTracker.java
com.facebook.internal.Utility.java
com.facebook.internal.Validate.java
com.facebook.internal.package-info.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.PropertyName.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.ImageDownloader.java
com.facebook.widget.ImageRequest.java
com.facebook.widget.ImageResponseCache.java
com.facebook.widget.ImageResponse.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.UrlRedirectCache.java
com.facebook.widget.UserSettingsFragment.java
com.facebook.widget.WebDialog.java
com.facebook.widget.WorkQueue.java
org.example.SocialNetwork.CCSocialNetwork.java
org.example.SocialNetwork.EmailSender.java
org.example.SocialNetwork.InternetConnection.java