Java tutorial
/* * Licensed to Scoreflex (www.scoreflex.com) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. Scoreflex licenses this * file to you 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.scoreflex; import java.lang.ref.WeakReference; import java.lang.reflect.Method; import java.util.ArrayList; import java.util.HashMap; import java.util.HashSet; import java.util.Iterator; import java.util.List; import java.util.Locale; import java.util.Map; import java.util.Map.Entry; import java.util.Set; import org.json.JSONException; import org.json.JSONObject; import android.annotation.SuppressLint; import android.app.Activity; import android.content.BroadcastReceiver; import android.content.Context; import android.content.Intent; import android.content.IntentFilter; import android.content.SharedPreferences; import android.graphics.Point; import android.location.Location; import android.location.LocationManager; import android.net.ConnectivityManager; import android.os.Build; import android.os.Bundle; import android.os.Handler; import android.os.Parcel; import android.os.Parcelable; import android.support.v4.content.LocalBroadcastManager; import android.text.TextUtils; import android.util.Log; import android.view.Display; import android.view.Gravity; import android.view.View; import android.view.ViewGroup; import android.view.WindowManager; import android.widget.FrameLayout; import com.scoreflex.ScoreflexView.ScoreflexViewListener; import com.scoreflex.facebook.ScoreflexFacebookWrapper; import com.scoreflex.facebook.ScoreflexFacebookWrapper.FacebookException; import com.scoreflex.google.ScoreflexGcmWrapper; import com.scoreflex.google.ScoreflexGoogleWrapper; import com.scoreflex.model.JSONParcelable; import android.content.res.Configuration; import org.OpenUDID.*; /** * The main class to access to Scoreflex * */ public class Scoreflex { private static Context sApplicationContext; private static String sClientId; private static String sClientSecret; private static boolean sIsInitialized = false; private static String sBaseURL; private static String sLang; private static Location sLocation; private static boolean sIsReachable; private static int sDefaultGravity = Gravity.BOTTOM; private static WeakReference<ScoreflexView> mScoreflexView; private static HashMap<String, ScoreflexView> mPreloadedViews; public static boolean showDebug = false; protected static final String API_VERSION = "v1"; protected static final String SDK_VERSION = "Unity-Android-1.0.0.2"; private static final String PRODUCTION_API_URL = "https://api.scoreflex.com/" + API_VERSION; private static final String SANDBOX_API_URL = "https://sandbox.api.scoreflex.com/" + API_VERSION; private static final int PLAY_SERVICES_RESOLUTION_REQUEST = 9000; private static final String PREF_FILE = "scoreflex"; /** * the timeout for a webview request */ public static final int WEBVIEW_REQUEST_TOTAL_TIMEOUT = 10000; protected static final int SUCCESS_LOGOUT = 200000; protected static final int SUCCESS_CLOSE_WEBVIEW = 200001; protected static final int SUCCESS_PLAY_LEVEL = 200002; protected static final int SUCCESS_NEEDS_AUTH = 200003; protected static final int SUCCESS_AUTH_GRANTED = 200004; protected static final int SUCCESS_MOVE_TO_NEW_URL = 200005; protected static final int SUCCESS_NEEDS_CLIENT_AUTH = 200006; protected static final int SUCCESS_START_CHALLENGE = 200007; protected static final int SUCCESS_LINK_SERVICE = 200008; protected static final int SUCCESS_INVITE_WITH_SERVICE = 200009; protected static final int SUCCESS_SHARE_WITH_SERVICE = 200010; protected static final int ERROR_INVALID_PARAMETER = 10001; protected static final int ERROR_MISSING_MANDATORY_PARAMETER = 10002; protected static final int ERROR_INVALID_ACCESS_TOKEN = 11003; protected static final int ERROR_SECURE_CONNECTION_REQUIRED = 10005; protected static final int ERROR_INVALID_PREV_NEXT_PARAMETER = 12011; protected static final int ERROR_INVALID_SID = 12017; protected static final int ERROR_SANDBOX_URL_REQUIRED = 12018; protected static final int ERROR_INACTIVE_GAME = 12019; protected static final int ERROR_MISSING_PERMISSIONS = 12020; protected static final int ERROR_PLAYER_DOES_NOT_EXIST = 12000; protected static final int ERROR_DEVELOPER_DOES_NOT_EXIST = 12001; protected static final int ERROR_GAME_DOES_NOT_EXIST = 12002; protected static final int ERROR_LEADERBOARD_CONFIG_DOES_NOT_EXIST = 12004; protected static final int ERROR_SERVICE_EXCEPTION = 12009; /** * Intent extra key for GCM notification data when the user clicks the * notification. */ public static final String NOTIFICATION_EXTRA_KEY = "_sfxNotification"; /** * A push notification sent from the developer to the player (using * Scoreflex). */ public static final int NOTIFICATION_TYPE_DEVELOPER_TO_PLAYER = 1; /** * A push notification sent from the player to another player (using your * game). */ public static final int NOTIFICATION_TYPE_PLAYER_TO_PLAYER = 2; /** * A notification received when the player has been invited to a challenge. */ public static final int NOTIFICATION_TYPE_CHALLENGE_INVITATION = 100; /** * A notification received when a challenge is ended. */ public static final int NOTIFICATION_TYPE_CHALLENGE_ENDED = 101; /** * A notification received when it is the player's turn in a challenge. */ public static final int NOTIFICATION_TYPE_YOUR_TURN_IN_CHALLENGE = 102; /** * A notification received when a friend of the player joins the game. */ public static final int NOTIFICATION_TYPE_FRIEND_JOINED_GAME = 103; /** * A notification received when the player highscore has been beaten by a * friend. */ public static final int NOTIFICATION_TYPE_FRIEND_BEAT_YOUR_HIGHSCORE = 104; /** * A notification received when a player gets a new rating. */ public static final int NOTIFICATION_TYPE_PLAYER_LEVEL_CHANGED = 105; /** * Local intent broadcasted when the game should load a challenge. */ public static final String INTENT_START_CHALLENGE = "scoreflexStartChallenge"; /** * The extra key for the full challenge instance (a JSONParcelable object) * in a {@link #INTENT_START_CHALLENGE} intent */ public static final String INTENT_START_CHALLENGE_EXTRA_INSTANCE = "challengeInstance"; /** * Local intent broadcasted when the reachability to Scoreflex has changed. */ public static final String INTENT_CONNECTIVITY_CHANGED = "scoreflexConnectivityChanged"; /** * The extra key for the reachability state in a * {@link #INTENT_CONNECTIVITY_CHANGED} intent. */ public static final String INTENT_CONNECTIVITY_EXTRA_CONNECTIVITY = "scoreflexConnectivityState"; /** * Local intent broadcasted when the Scoreflex sdk has been initialized and * is reachable. */ public static final String INTENT_SCOREFLEX_INTIALIZED = "scoreflexInitialized"; /** * Local intent broadcasted when the Scoreflex sdk could not be initialized */ public static final String INTENT_SCOREFLEX_INTIALIZE_FAILED = "scoreflexInitializeFailed"; /** * The extra key for the scoreflex initialisation failed reason in a * {@link #INTENT_SCOREFLEX_INTIALIZE_FAILED} intent. */ public static final String INTENT_SCOREFLEX_INTIALIZE_FAILED_EXTRA_REASON = "scoreflexInitializeFailedReason"; /** * Local intent broadcasted when a resource has been successfully preloaded. */ public static final String INTENT_RESOURCE_PRELOADED = "scoreflexResourcePreloaded"; /** * The extra key for the path of a preloaded resource in a * {@link #INTENT_RESOURCE_PRELOADED} intent. */ public static final String INTENT_RESOURCE_PRELOADED_EXTRA_PATH = "scoreflexResourcePreloadedPath"; /** * Local intent broadcasted when the current user has changed. */ public static final String INTENT_USER_LOGED_IN = "scoreflexUserLoggedIn"; /** * The extra key for the new SID of the player in a * {@link #INTENT_USER_LOGED_IN} intent. */ public static final String INTENT_USER_LOGED_IN_EXTRA_SID = "sid"; /** * The extra key for the new access token of the player in a * {@link #INTENT_USER_LOGED_IN} intent. */ public static final String INTENT_USER_LOGED_IN_EXTRA_ACCESS_TOKEN = "accessToken"; /** * Local intent broadcasted when the game should load a level. */ public static final String INTENT_PLAY_LEVEL = "scoreflexPlayLevel"; /** * The extra key for the leaderboard ID in a {@link #INTENT_PLAY_LEVEL} * intent. */ public static final String INTENT_PLAY_LEVEL_EXTRA_LEADERBOARD_ID = "leaderboardId"; private static ConnectivityReceiver sConnectivityReceiver = new ConnectivityReceiver(); protected static final String DEFAULT_LANGUAGE_CODE = "en"; protected static final String[] VALID_LANGUAGE_CODES = { "af", "ar", "be", "bg", "bn", "ca", "cs", "da", "de", "el", "en", "en_GB", "en_US", "es", "es_ES", "es_MX", "et", "fa", "fi", "fr", "fr_FR", "fr_CA", "he", "hi", "hr", "hu", "id", "is", "it", "ja", "ko", "lt", "lv", "mk", "ms", "nb", "nl", "pa", "pl", "pt", "pt_PT", "pt_BR", "ro", "ru", "sk", "sl", "sq", "sr", "sv", "sw", "ta", "th", "tl", "tr", "uk", "vi", "zh", "zh_CN", "zh_TW", "zh_HK", }; static final int FILECHOOSER_RESULTCODE = 0; private static long playingSessionStart; /** * Checks if Scoreflex is initialized. * * @return True if the SDK is initialized. */ public static boolean isInitialized() { return sIsInitialized; } /** * Initialize Scoreflex. Call this method before using Scoreflex. Will * initialize a production mode not sandbox * * @param clientId * The clientId of your game. * @param clientSecret * The clientSecret of your game. */ public static void initialize(Context context, String clientId, String clientSecret) { initialize(context, clientId, clientSecret, false); } /** * Initialize Scoreflex. Call this method before using Scoreflex. A good * place to initialize Scoreflex is in your main activity's onCreate method * as follow * * <pre> * <code> * protected void onCreate(Bundle savedInstance) { * Scoreflex.initialize(this, "clientId", "clientSecret", isSandbox); * } * </code> * </pre> * * @param clientId * The clientId of your game. * @param clientSecret * The clientSecret of your game. */ public static void initialize(Context context, final String clientId, String clientSecret, boolean useSandbox) { setNetworkAvailable(false); sApplicationContext = context.getApplicationContext(); sClientId = clientId; sClientSecret = clientSecret; sBaseURL = useSandbox ? SANDBOX_API_URL : PRODUCTION_API_URL; sIsInitialized = true; // Initialize OpenUDID OpenUDID_manager.sync(sApplicationContext); // Wait for UDID to be ready and fetch anonymous token if needed. new Runnable() { @Override public void run() { if (OpenUDID_manager.isInitialized()) { boolean isFetchingToken = ScoreflexRestClient .fetchAnonymousAccessTokenIfNeeded(new ResponseHandler() { @Override public void onFailure(Throwable e, Response errorResponse) { Intent broadcast = new Intent(INTENT_SCOREFLEX_INTIALIZE_FAILED); if (errorResponse != null) { JSONParcelable parcelable = new JSONParcelable( errorResponse.getJSONObject()); broadcast.putExtra(INTENT_SCOREFLEX_INTIALIZE_FAILED_EXTRA_REASON, parcelable); } LocalBroadcastManager.getInstance(Scoreflex.getApplicationContext()) .sendBroadcast(broadcast); } @Override public void onSuccess(Response response) { Intent broadcast = new Intent(INTENT_SCOREFLEX_INTIALIZED); LocalBroadcastManager.getInstance(Scoreflex.getApplicationContext()) .sendBroadcast(broadcast); } }); if (!isFetchingToken) { // even if we have an access token, we need to ensure // connectivity // state Scoreflex.get("/network/ping", null, new ResponseHandler() { @Override public void onFailure(Throwable e, Response errorResponse) { Intent broadcast = new Intent(INTENT_SCOREFLEX_INTIALIZE_FAILED); if (errorResponse != null) { JSONParcelable parcelable = new JSONParcelable(errorResponse.getJSONObject()); broadcast.putExtra(INTENT_SCOREFLEX_INTIALIZE_FAILED_EXTRA_REASON, parcelable); } LocalBroadcastManager.getInstance(Scoreflex.getApplicationContext()) .sendBroadcast(broadcast); } @Override public void onSuccess(Response response) { Intent broadcast = new Intent(INTENT_SCOREFLEX_INTIALIZED); LocalBroadcastManager.getInstance(Scoreflex.getApplicationContext()) .sendBroadcast(broadcast); } }); } } else { new Handler().postDelayed(this, 100); } } }.run(); ScoreflexRequestVault.initialize(); } /** * True if the SDK is running in sandbox mode. * * (@see {@link #initialize(Context, String, String, boolean) Sandbox}). * * @return True if the SDK is running in sandbox mode. */ public static boolean usesSandbox() { return SANDBOX_API_URL.equals(sBaseURL); } /** * Returns the base URL for the Scoreflex API. This is the URL used to * prefix every API resource path and might change depending if you're using * {@link #initialize(Context, String, String, boolean) Sandbox}. * * @return The base URL. */ public static String getBaseURL() { return sBaseURL; } /** * Returns the base URL for the Scoreflex API with a <code>http:</code> * scheme. * * (@see {@link #getBaseURL()}). * * @return The base URL. */ public static String getNonSecureBaseURL() { return sBaseURL.replaceFirst("https:", "http:"); } /** * A GET request. * * @param resource * The resource path, starting with /. * @param params * AsyncHttpClient request parameters. * @param responseHandler * An AsyncHttpClient response handler. */ public static void get(String resource, Scoreflex.RequestParams params, Scoreflex.ResponseHandler responseHandler) { ScoreflexRestClient.get(resource, params, responseHandler); } /** * A POST request. * * @param resource * The resource path, starting with /. * @param params * AsyncHttpClient request parameters. * @param responseHandler * An AsyncHttpClient response handler. */ public static void post(String resource, Scoreflex.RequestParams params, Scoreflex.ResponseHandler responseHandler) { ScoreflexRestClient.post(resource, params, responseHandler); } /** * A POST request that is guaranteed to be executed when a network * connection is present, surviving application reboot. The responseHandler * will be called only if the network is present when the request is first * run. * * @param resource * @param params * The request parameters. Only serializable parameters are * guaranteed to survive a network error or device reboot. * @param responseHandler * An AsyncHttpClient response handler. */ public static void postEventually(String resource, Scoreflex.RequestParams params, Scoreflex.ResponseHandler responseHandler) { ScoreflexRestClient.postEventually(resource, params, responseHandler); } /** * A PUT request. * * @param resource * The resource path, starting with /. * @param params * AsyncHttpClient request parameters. * @param responseHandler * An AsyncHttpClient response handler. */ public static void put(String resource, Scoreflex.RequestParams params, Scoreflex.ResponseHandler responseHandler) { ScoreflexRestClient.put(resource, params, responseHandler); } /** * A DELETE request. * * @param resource * The resource path, starting with /. * @param params * AsyncHttpClient request parameters. * @param responseHandler * An AsyncHttpClient response handler. */ public static void delete(String resource, Scoreflex.ResponseHandler responseHandler) { ScoreflexRestClient.delete(resource, responseHandler); } /** * Changes the default gravity. * * @param defaultGravity * The new default gravity. */ public static void setDefaultGravity(int defaultGravity) { if (Gravity.TOP == (defaultGravity & Gravity.VERTICAL_GRAVITY_MASK)) sDefaultGravity = Gravity.TOP; else sDefaultGravity = Gravity.BOTTOM; } /** * Returns the default gravity. * * @return The default gravity. */ public static int getDefaultGravity() { return sDefaultGravity; } /** * Displays a Scoreflex panel on the provided activity using the default * gravity. * * @param activity * The activity that will host the view. * @param leaderboardId * The leaderboard id of the rankbox that you want to show. * @param score * The last score the user did. */ public static ScoreflexView showRanksPanel(Activity activity, String leaderboardId, long score) { return showRanksPanel(activity, leaderboardId, score, sDefaultGravity); } /** * Displays a Scoreflex panel on the provided activity. * * @param activity * The activity that will host the view. * @param leaderboardId * The leaderboard id of the rankbox that you want to show. * @param score * the last score the user did. * @param gravity * Choose if the view should be up are down of the screen. */ public static ScoreflexView showRanksPanel(Activity activity, String leaderboardId, long score, int gravity) { // Params Scoreflex.RequestParams params = new Scoreflex.RequestParams(); params.put("score", "" + score); return showRanksPanel(activity, leaderboardId, gravity, params); } /** * Shows a view of the specified resource to the user. * * @param activity * The activity that will host the view. * @param resource * The string of the Scoreflex resource you want to display. * @param params * The parameter to be given to the resource (query string). * @return The displayed view call close() to hide it. */ public static ScoreflexView showFullScreenView(Activity activity, String resource, Scoreflex.RequestParams params) { ScoreflexView view = Scoreflex.view(activity, resource, params, true); activity.addContentView(view, view.getLayoutParams()); view.requestFocus(); view.requestFocusFromTouch(); return view; } /** * Shows a view of the specified url to the user. * * @param activity * The activity that will host the view. * @param url * the url to show * @return The displayed view call close() to hide it. */ public static ScoreflexView showFullScreenView(Activity activity, String url) { ScoreflexView view = Scoreflex.view(activity, url, true); activity.addContentView(view, view.getLayoutParams()); view.requestFocus(); view.requestFocusFromTouch(); return view; } /** * Shows a panel view (small view) of the specified resource to the user. * * @param activity * The activity that will host the view. * @param resource * The string of the Scoreflex resource you want to display. * @param params * The parameter to be given to the resource (query string). * @param gravity * Whether the panel should be shown on top or bottom of the * screen. * @return The displayed view call close() to hide it. */ public static ScoreflexView showPanelView(Activity activity, String resource, Scoreflex.RequestParams params, int gravity) { ScoreflexView view = Scoreflex.view(activity, resource, params, false); attachView(activity, view, gravity); return view; } /** * Shows the player profile of the player (playerId) or the logged player if * playerId is null. Endpoint: <code>/web/players/:id</code>. * * @param activity * The activity that will host the view. * @param playerId * The identifier of the player or null for the current logged * player. * @param params * The parameter to be given to the resource (query string). * @return The Scoreflex view on screen. */ public static ScoreflexView showPlayerProfile(Activity activity, String playerId, Scoreflex.RequestParams params) { if (null == playerId) { playerId = "me"; } return showFullScreenView(activity, "/web/players/" + playerId, params); } /** * Shows the friends of the player (playerId) or the logged player if * playerId is null. Endpoint: <code>/web/players/:id/friends</code>. * * @param activity * The activity that will host the view. * @param playerId * The identifier of the player or null for the current logged * player. * @param params * The parameter to be given to the resource (query string). * @return The Scoreflex view on screen. */ public static ScoreflexView showPlayerFriends(Activity activity, String playerId, Scoreflex.RequestParams params) { if (null == playerId) { playerId = "me"; } return showFullScreenView(activity, "/web/players/" + playerId + "/friends", params); } /** * Shows the news feed of the logged player. Endpoint: * <code>/web/players/me/newsfeed</code>. * * @param activity * The activity that will host the view. * @param params * The parameter to be given to the resource (query string). * @return The Scoreflex view on screen. */ public static ScoreflexView showPlayerNewsFeed(Activity activity, Scoreflex.RequestParams params) { return showFullScreenView(activity, "/web/players/me/newsfeed", params); } /** * Shows the edit profile form of the logged player. Endpoint: * <code>/web/players/me/edit</code>. * * @param activity * The activity that will host the view. * @param params * The parameter to be given to the resource (query string). * @return The Scoreflex view on screen. */ public static ScoreflexView showPlayerProfileEdit(Activity activity, Scoreflex.RequestParams params) { return showFullScreenView(activity, "/web/players/me/edit", params); } /** * Shows the settings form of the logged player. Endpoint: * <code>/web/players/me/settings</code>. * * @param activity * The activity that will host the view. * @param params * The parameter to be given to the resource (query string). * @return The Scoreflex view on screen. */ public static ScoreflexView showPlayerSettings(Activity activity, Scoreflex.RequestParams params) { return showFullScreenView(activity, "/web/players/me/settings", params); } /** * Shows the rating of the logged player. Endpoint: * <code>/web/players/me/rating</code> * * @param activity * The activity that will host the view. * @param params * The parameter to be given to the resource (query string). * @return The Scoreflex view on screen. */ public static ScoreflexView showPlayerRating(Activity activity, Scoreflex.RequestParams params) { return showFullScreenView(activity, "/web/players/me/rating", params); } /** * Shows the profile of the developer (developerId). Endpoint: * <code>/web/developers/:id</code>. * * @param activity * The activity that will host the view. * @param developerId * The identifier of the developer. * @param params * The parameter to be given to the resource (query string). * @return The Scoreflex view on screen. */ public static ScoreflexView showDeveloperProfile(Activity activity, String developerId, Scoreflex.RequestParams params) { return showFullScreenView(activity, "/web/developers/" + developerId, params); } /** * Shows the games of the developer (developerId). Endpoint: * <code>/web/developers/:id/games</code>. * * @param activity * The activity that will host the view. * @param developerId * The identifier of the developer. * @param params * The parameter to be given to the resource (query string). * @return The Scoreflex view on screen. */ public static ScoreflexView showDeveloperGames(Activity activity, String developerId, Scoreflex.RequestParams params) { return showFullScreenView(activity, "/web/developers/" + developerId + "/games", params); } /** * Shows the details of the game (gameId). Endpoint: * <code>/web/games/:id</code> * * @param activity * The activity that will host the view. * @param gameId * The identifier the game. * @param params * The parameter to be given to the resource (query string). * @return The Scoreflex view on screen. */ public static ScoreflexView showGameDetails(Activity activity, String gameId, Scoreflex.RequestParams params) { return showFullScreenView(activity, "/web/games/" + gameId, params); } /** * Shows the players of the game (gameId). Endpoint: * <code>/web/games/:id/players</code>. * * @param activity * The activity that will host the view. * @param gameId * The identifier the game. * @param params * The parameter to be given to the resource (query string). * @return The Scoreflex view on screen. */ public static ScoreflexView showGamePlayers(Activity activity, String gameId, Scoreflex.RequestParams params) { return showFullScreenView(activity, "/web/games/" + gameId + "/players", params); } /** * Shows a leaderboard (leaderboardId). Endpoint: * <code>/web/leaderboards/:leaderboardId</code>. * * @param activity * The activity that will host the view. * @param leaderboardId * The identifier of the leaderboard. * @param params * The parameter to be given to the resource (query string). * @return The Scoreflex view on screen. */ public static ScoreflexView showLeaderboard(Activity activity, String leaderboardId, Scoreflex.RequestParams params) { return showFullScreenView(activity, "/web/leaderboards/" + leaderboardId, params); } /** * Shows the overview of the leaderboard (leaderboardId). Endpoint: * <code>/web/leaderboards/:leaderboardId/overview</code> * * @param activity * The activity that will host the view. * @param leaderboardId * The identifier of the leaderboard. * @param params * The parameter to be given to the resource (query string). * @return The Scoreflex view on screen. */ public static ScoreflexView showLeaderboardOverview(Activity activity, String leaderboardId, Scoreflex.RequestParams params) { return showFullScreenView(activity, "/web/leaderboards/" + leaderboardId + "/overview", params); } /** * Shows the challenges list of the current player. Endpoint: * <code>/web/challenges</code>. * * @param activity * The activity that will host the view. * @param params * The parameter to be given to the resource (query string). * @return The Scoreflex view on screen. */ public static ScoreflexView showChallenges(Activity activity, Scoreflex.RequestParams params) { return showFullScreenView(activity, "/web/challenges", params); } /** * Shows the search form. Endpoint: <code>/web/search</code> * * @param activity * The activity that will host the view. * @param params * The parameter to be given to the resource (query string). * @return The Scoreflex view on screen. */ public static ScoreflexView showSearch(Activity activity, Scoreflex.RequestParams params) { return showFullScreenView(activity, "/web/search", params); } /** * Shows a Scoreflex panel on the provided activity. * * @param activity * The activity that will host the view. * @param leaderboardId * The leaderboard id of the rankbox that you want to show. * @param gravity * Chooses if the view should be up are down of the screen. * @param params * The parameter to be given to the resource (query string). */ public static ScoreflexView showRanksPanel(Activity activity, String leaderboardId, int gravity, Scoreflex.RequestParams params) { return showRanksPanel(activity, leaderboardId, gravity, params, false); } /** * Shows a Scoreflex panel on the provided activity. * * @param activity * The activity that will host the view. * @param leaderboardId * The leaderboard id of the rankbox that you want to show. * @param gravity * Chooses if the view should be up are down of the screen. * @param params * The parameter to be given to the resource (query string). * @param openAsActivity * Tell wether or not the full view (when the rank panel is clicked) * should be opened as a new activity */ public static ScoreflexView showRanksPanel(final Activity activity, String leaderboardId, int gravity, Scoreflex.RequestParams params, boolean openAsActivity) { // Resource String resource = String.format(Locale.getDefault(), "/web/scores/%s/ranks", leaderboardId); // Get the leaderboard & display ScoreflexView leaderboardView = Scoreflex.view(activity, resource, params, false); attachView(activity, leaderboardView, gravity); if (openAsActivity) { leaderboardView.setScoreflexViewListener(new ScoreflexViewListener() { @Override public void onViewClosed() { } @Override public boolean handleOpenNewFullscreenView(String fullUrlString) { Intent intent = new Intent(activity, ScoreflexActivity.class); intent.putExtra(ScoreflexActivity.INTENT_SHOW_EXTRA_KEY, ScoreflexActivity.INTENT_EXTRA_SHOW_ABSTRACT_URL); intent.putExtra(ScoreflexActivity.INTENT_EXTRA_ABSTRACT_URL, fullUrlString); activity.startActivity(intent); return true; } }); } return leaderboardView; } /** * Attach the given view above the activity's view hierarchy. * * @param activity * The activity that will host the view. * @param view * The view to attach. * @param gravity * Chooses if the view should be up are down of the screen. */ private static void attachView(Activity activity, View view, int gravity) { ViewGroup contentView = (ViewGroup) activity.getWindow().getDecorView().findViewById(android.R.id.content); // final float scale = // activity.getResources().getDisplayMetrics().density; FrameLayout.LayoutParams layoutParams = new FrameLayout.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT, getDensityIndependantPixel( activity.getResources().getDimensionPixelSize(R.dimen.scoreflex_panel_height)), gravity); view.setLayoutParams(layoutParams); view.setVisibility(View.GONE); contentView.addView(view); // activity.addContentView(view, layoutParams); if (view instanceof ScoreflexView) ((ScoreflexView) view).addDropShadow(gravity); } /** * Build a view that displays Scoreflex content. * * @param activity * The activity that will host the view. * @param resource * The REST resource corresponding to that view. * @return A view that you can attach to your view hierarchy. */ protected static ScoreflexView view(Activity activity, String resource) { return view(activity, resource, null); } /** * Builds a view that displays Scoreflex content. * * @param activity * The activity that will host the view. * @param resource * The REST resource corresponding to that view. * @param params * The request parameters. * @return A view that you can attach to your view hierarchy. */ protected static ScoreflexView view(Activity activity, String resource, Scoreflex.RequestParams params) { ScoreflexView result = null; if (mPreloadedViews != null) { result = getPreloadedView(resource); } if (result == null) { result = new ScoreflexView(activity); } else { removePreloadedView(resource, false); setCurrentScoreflexView(result); return result; } result.setResource(resource, params); return result; } /** * Builds a fullscreen view to Scoreflex content and returns it. * * @param activity * The activity that will host the view. * @param resource * The REST resource corresponding to that view. * @param params * The request parameters. * @return A view that you can attach to your view hierarchy. */ public static ScoreflexView getFullscreenView(Activity activity, String resource, Scoreflex.RequestParams params) { return view(activity, resource, params, true); } /** * Builds a panel view to Scoreflex content and returns it. * * @param activity * The activity that will host the view. * @param resource * The REST resource corresponding to that view. * @param params * The request parameters. * @return A view that you can attach to your view hierarchy. */ public static ScoreflexView getPanelView(Activity activity, String resource, Scoreflex.RequestParams params) { return view(activity, resource, params, false); } /** * Builds a view that displays Scoreflex content. * * @param activity * The activity that will host the view. * @param resource * The REST resource corresponding to that view. * @param params * The request parameters. * @param forceFullScreen * Set wether the view should be full screen. * @return A view that you can attach to your view hierarchy. */ protected static ScoreflexView view(Activity activity, String resource, Scoreflex.RequestParams params, boolean forceFullScreen) { ScoreflexView result = null; if (mPreloadedViews != null) { result = getPreloadedView(resource); } if (result == null) { result = new ScoreflexView(activity); } else { removePreloadedView(resource, false); setCurrentScoreflexView(result); result.startOpeningAnimation(); return result; } result = new ScoreflexView(activity); result.setResource(resource, params, forceFullScreen); return result; } /** * build a view in with the given url * @param activity the activity that will host the view * @param url the url to show * @param forceFullscreen Set wether the view should be full screen. * @return A view that you can attach to your view hierarchy. */ protected static ScoreflexView view(Activity activity, String url, boolean forceFullscreen) { ScoreflexView result = new ScoreflexView(activity); result.setFullUrl(url, forceFullscreen, false); return result; } /** * Handles Scoreflex activity results. This method MUST be called from your * Activity's onActivityResult method in order to handle facebook / google * login. Your onActivityResult should look like this : * * <pre> * <code> * protected void onActivityResult(int requestCode, int resultCode, Intent data) { * super.onActivityResult(requestCode, resultCode, data); * Scoreflex.onActivityResult(this, requestCode, resultCode, data); * } * * </code> * </pre> * * @param activity * The current activity that received the result. * @param requestCode * The requestCode the activity received. * @param responseCode * The responseCode the activity received. * @param intent * The intent the activity received. */ public static void onActivityResult(Activity activity, int requestCode, int responseCode, Intent intent) { if (requestCode == FILECHOOSER_RESULTCODE && mScoreflexView != null) { ScoreflexView view = mScoreflexView.get(); if (view != null) { view.onActivityResult(activity, requestCode, responseCode, intent); return; } } ScoreflexGoogleWrapper.onActivityResult(activity, requestCode, responseCode, intent); ScoreflexFacebookWrapper.onActivityResult(activity, requestCode, responseCode, intent); } /** * A helper method that submits a score. * * @param leaderboardId * The leaderboad id to submit the score to. * @param score * The score of the player. * @param params * Other parameters that will be used for the api call. * @param responseHandler * A response handler that will be called if the request is sent * immediatly otherwise, will never get called (@see * {@link #postEventually(String, RequestParams, ResponseHandler)} * ). */ public static void submitScore(String leaderboardId, long score, Scoreflex.RequestParams params, Scoreflex.ResponseHandler responseHandler) { if (params == null) { params = new Scoreflex.RequestParams(); } params.put("score", Long.toString(score)); submitScore(leaderboardId, params, responseHandler); } protected static void submitScore(String leaderboardId, Scoreflex.RequestParams params, Scoreflex.ResponseHandler responseHandler) { final String scoreResource = "/scores/" + leaderboardId; // RequestParams params = new RequestParams(); // params.put("score", Long.toString(score)); Scoreflex.postEventually(scoreResource, params, responseHandler); } /** * A helper method that submits a score to a leaderboard ID and show the * rank panel for the current player. * * @param activity * The activity that will host the view. * @param leaderboardId * The leaderboad id to submit the score to. * @param score * The score of the player. * @param params * Other parameters that will be used for the api call and the * rankbox display. * @param gravity * Chooses if the view should be up are down of the screen. * @return the Scoreflex view call close() to hide it. */ public static ScoreflexView submitScoreAndShowRanksPanel(final Activity activity, final String leaderboardId, long score, RequestParams params, final int gravity) { if (params == null) { params = new RequestParams(); } params.put("score", Long.toString(score)); final RequestParams finalParams = params; ScoreflexView rankbox = Scoreflex.showRanksPanel(activity, leaderboardId, gravity, finalParams); submitScore(leaderboardId, params, new Scoreflex.ResponseHandler() { @Override public void onFailure(Throwable e, Response errorResponse) { Log.d("Scoreflex", "Could not submit score, Rankbox wont be shown"); } @Override public void onSuccess(Response response) { } }); return rankbox; } /** * Gets the current player id from the local cache. * * @return The current player id from the local cache. */ public static String getPlayerId() { return ScoreflexRestClient.getPlayerId(); } /** * Gets the access token from the local cache. * * @return The access token from the local cache. */ public static String getAccessToken() { return ScoreflexRestClient.getAccessToken(); } /** * A helper method that submits a turn to a challenge instance. * * @param challengeInstanceId * The challenge instance id. * @param turn * The turn data. * @param responseHandler * A response handler if the request is sent immediatly * otherwise, will never get called (@see * {@link #postEventually(String, RequestParams, ResponseHandler)} * ). */ public static void submitTurn(String challengeInstanceId, RequestParams turn, Scoreflex.ResponseHandler responseHandler) { final String turnResource = "/challenges/instances/" + challengeInstanceId + "/turns"; JSONObject body = new JSONObject(); try { Set<String> parameters = turn.getParamNames(); for (String parameterName : parameters) { body.put(parameterName, turn.getParamValue(parameterName)); } long playingTime = Scoreflex.getPlayingSessionTime(); if (playingTime > 0) { body.put("playingTime", playingTime); } RequestParams params = new RequestParams(); params.put("body", body.toString()); Scoreflex.postEventually(turnResource, params, responseHandler); } catch (JSONException e) { e.printStackTrace(); } } /** * A helper method that submits turn data and directly show challenge * detail. * * @param activity * The activity that will host the view. * @param challengeInstanceId * The challenge instance id. * @param turn * The turn data. */ public static void submitTurnAndShowChallengeDetail(final Activity activity, final String challengeInstanceId, RequestParams turn) { final String resource = "/web/challenges/instances/" + challengeInstanceId; submitTurn(challengeInstanceId, turn, new Scoreflex.ResponseHandler() { @Override public void onFailure(Throwable e, Response errorResponse) { Log.d("Scoreflex", "Could not submit score, Chalenge detail wont be shown"); } @Override public void onSuccess(Response response) { View view = Scoreflex.view(activity, resource, null, true); activity.addContentView(view, view.getLayoutParams()); view.requestFocus(); view.requestFocusFromTouch(); } }); } /** * A class that handles the parameter to provide to either an api call or a * view. * */ public static class RequestParams extends com.loopj.android.http.RequestParams implements Parcelable { public static final String TAG = "RequestParams"; public RequestParams(Parcel in) throws JSONException { JSONObject json = new JSONObject(in.readString()); Iterator<?> it = json.keys(); String key; while (it.hasNext()) { key = (String) it.next(); this.put(key, json.optString(key)); } } /** * Constructs a new empty <code>RequestParams</code> instance. */ public RequestParams() { super(); } /** * Constructs a new RequestParams instance containing the key/value * string params from the specified map. * * @param source * The source key/value string map to add. */ public RequestParams(Map<String, String> source) { super(source); } /** * Constructs a new RequestParams instance and populate it with multiple * initial key/value string param. * * @param keysAndValues * A sequence of keys and values. Objects are automatically * converted to Strings (including the value {@code null}). * @throws IllegalArgumentException * If the number of arguments isn't even. */ public RequestParams(Object... keysAndValues) { super(keysAndValues); } /** * Constructs a new RequestParams instance and populate it with a single * initial key/value string param. * * @param key * The key name for the intial param. * @param value * The value string for the initial param. */ public RequestParams(String key, String value) { super(key, value); } /** * Return the names of all parameters. * * @return */ public Set<String> getParamNames() { HashSet<String> result = new HashSet<String>(); result.addAll(this.fileParams.keySet()); result.addAll(this.urlParams.keySet()); result.addAll(this.urlParamsWithArray.keySet()); return result; } /** * Returns the value for the given param. If the given param is * encountered multiple times, the first occurrence is returned. * * @param paramName * @return */ public String getParamValue(String paramName) { if (this.urlParams.containsKey(paramName)) return this.urlParams.get(paramName); if (this.urlParamsWithArray.containsKey(paramName)) { List<String> values = this.urlParamsWithArray.get(paramName); if (0 < values.size()) return values.get(0); } return null; } /** * Checks whether the provided key has been specified as parameter. * * @param key * @return */ public boolean has(String key) { return urlParams.containsKey(key) || fileParams.containsKey(key) || urlParamsWithArray.containsKey(key); } public String getURLEncodedString() { return getParamString(); } @Override public int describeContents() { return 0; } public JSONObject toJSONObject() { JSONObject result = new JSONObject(); java.util.List<org.apache.http.message.BasicNameValuePair> params = getParamsList(); for (org.apache.http.message.BasicNameValuePair parameter : params) { try { result.put(parameter.getName(), parameter.getValue()); } catch (JSONException e) { e.printStackTrace(); } } return result; } @Override public void writeToParcel(Parcel destination, int flags) { destination.writeString(toJSONObject().toString()); } public static final Parcelable.Creator<Scoreflex.RequestParams> CREATOR = new Parcelable.Creator<Scoreflex.RequestParams>() { public RequestParams createFromParcel(Parcel in) { try { return new RequestParams(in); } catch (JSONException e) { Log.e(TAG, "Error while unserializing JSON from a Scoreflex.RequestParams", e); return null; } } public RequestParams[] newArray(int size) { return new RequestParams[size]; } }; } /** * Http response handler. * * * */ public static abstract class ResponseHandler { /** * Called when the request failed. Default implementation is empty. * * @param e * @param errorResponse */ public abstract void onFailure(Throwable e, Response errorResponse); /** * Called on request success. Default implementation is empty. * * @param response */ public abstract void onSuccess(Response response); /** * Called on request success. Default implementation calls * onSuccess(response). * * @param response */ public void onSuccess(int statusCode, Response response) { onSuccess(response); } } /** * An HTTP response object * */ public static class Response { JSONObject mJson; public Response(String responseContent) { try { mJson = new JSONObject(responseContent); } catch (JSONException e) { Log.e("Scoreflex", "Invalid JSON in response content: " + responseContent, e); } } public Response(JSONObject responseJson) { mJson = responseJson; } public boolean isError() { return mJson.has("error"); } public String getErrorMessage() { if (!isError()) return null; return mJson.optJSONObject("error").optString("message"); } public int getErrorStatus() { if (!isError()) return 0; return mJson.optJSONObject("error").optInt("status"); } public int getErrorCode() { if (!isError()) return 0; return mJson.optJSONObject("error").optInt("code"); } public JSONObject getJSONObject() { return mJson; } } /** * Gets the application context that was captured during the {@link * Scoreflex.initialize(Context, String, String} call. * * @return */ protected static Context getApplicationContext() { if (null == sApplicationContext) Log.e("Scoreflex", "Application context is null, did you call Scoreflex.initialize ?"); return sApplicationContext; } protected static SharedPreferences getSharedPreferences(Context c) { if (null == c) throw new IllegalArgumentException("Context must be set"); return c.getSharedPreferences(PREF_FILE, 0); } /** * Gets the Scoreflex shared preferences for that application. * * @return */ protected static SharedPreferences getSharedPreferences() { if (null == getApplicationContext()) return null; return getApplicationContext().getSharedPreferences(PREF_FILE, 0); } /** * Gets the clientId that was specified during the {@link * Scoreflex.initialize(Context, String, String} call. * * @return */ public static String getClientId() { return sClientId; } /** * Gets the clientSecret that was specified during the {@link * Scoreflex.initialize(Context, String, String} call. * * @return */ protected static String getClientSecret() { return sClientSecret; } /** * Gets the model of this android device. * * @return */ protected static String getDeviceModel() { return String.format("%s - %s", Build.MANUFACTURER, Build.MODEL); } /** * Returns the UDID determined by OpenUDID. * * @return The UDID determined by OpenUDID or null if OpenUDID is not * initialized. */ protected static String getUDID() { if (OpenUDID_manager.isInitialized()) return OpenUDID_manager.getOpenUDID(); return null; } /** * Gets the current language. If language was specified using {@link * Scoreflex.setLang(String)}, this value is returned. Otherwise it is * guessed from the system. * * @return The locale in use. */ public static String getLang() { if (null != sLang) return sLang; Locale locale = Locale.getDefault(); if (null == locale) return DEFAULT_LANGUAGE_CODE; String language = locale.getLanguage(); String country = locale.getCountry(); String localeString = String.format("%s_%s", language != null ? language.toLowerCase(Locale.ENGLISH) : "", country != null ? country.toUpperCase(Locale.ENGLISH) : ""); // 1. if no language is specified, return the default language if (null == language) return DEFAULT_LANGUAGE_CODE; // 2. try to match the language or the entire locale string among the // list of available language codes String matchedLanguageCode = null; for (int i = 0; i < VALID_LANGUAGE_CODES.length; i++) { if (VALID_LANGUAGE_CODES[i].equals(localeString)) { // return here as this is the most precise match we can get return localeString; } if (VALID_LANGUAGE_CODES[i].equals(language)) { // set the matched language code, and continue iterating as we // may match the localeString in a later iteration. matchedLanguageCode = language; } } if (null != matchedLanguageCode) return matchedLanguageCode; return DEFAULT_LANGUAGE_CODE; } /** * Sets the language code used by the Scoreflex SDK. This language code will * affect the responses of the REST server as well as Scoreflex web content. * * @param lang * Valid values are available in * {@link Scoreflex.VALID_LANGUAGE_CODES}. * @throws IllegalArgumentException * If the lang is not a valid language. */ public static void setLang(String lang) throws IllegalArgumentException { for (int i = 0; i < VALID_LANGUAGE_CODES.length; i++) { if (VALID_LANGUAGE_CODES[i].equals(lang)) { sLang = lang; return; } } throw new IllegalArgumentException(String.format("%s is not a valid language code", lang)); } /** * Sets the location of the user. If you are collecting user location, this * setting will allow the SDK to forward user location to the Scoreflex REST * server when appropriate and present the user location specific * information. * * @param location */ public static void setLocation(Location location) { sLocation = location; } /** * Returns the Location as set in {@link setLocation(Location)} or the best * last known location of the {@link LocationManager} or null if permission * was not given. */ public static Location getLocation() { if (null != sLocation) return sLocation; Context applicationContext = getApplicationContext(); if (applicationContext == null) return null; LocationManager locationManager = (LocationManager) applicationContext .getSystemService(Context.LOCATION_SERVICE); try { Location locations[] = { locationManager.getLastKnownLocation(LocationManager.NETWORK_PROVIDER), locationManager.getLastKnownLocation(LocationManager.GPS_PROVIDER), locationManager.getLastKnownLocation(LocationManager.PASSIVE_PROVIDER), }; Location best = null; for (int i = 0; i < locations.length; i++) { // If this location is null, discard if (null == locations[i]) continue; // If we have no best yet, use this first location if (null == best) { best = locations[i]; continue; } // If this location is significantly older, discard long timeDelta = locations[i].getTime() - best.getTime(); if (timeDelta < -1000 * 60 * 2) continue; // If we have no accuracy, discard if (0 == locations[i].getAccuracy()) continue; // If this location is less accurate, discard if (best.getAccuracy() < locations[i].getAccuracy()) continue; best = locations[i]; } return best; } catch (java.lang.SecurityException e) { // Missing permission; return null; } } protected static void setCurrentScoreflexView(ScoreflexView view) { mScoreflexView = new WeakReference<ScoreflexView>(view); } /** * Method to be called when the back button is pressed (hardware) to handle * history in a scoreflexView. Call it in the activity's back button pressed * method as follow: * * <pre> * <code> * public void onBackPressed() { * if (Scoreflex.backButtonPressed() == false) { * super.onBackPressed(); * } * } * </code> * </pre> * * @return <code>true</code> If handled <code>false</code> otherwise. */ public static boolean backButtonPressed() { if (mScoreflexView == null) { return false; } ScoreflexView view = mScoreflexView.get(); if (view != null) { if (view.canGoBack()) { view.goBack(); return true; } else { view.close(); mScoreflexView = null; return true; } } return false; } private static boolean checkPlayService(Activity activity) { return ScoreflexGcmWrapper.isGooglePlayServiceAvailable(activity); } /** * If network is available, preload a view with the specified ressource and * hold a reference on it until the view is shown or freed. * * @param activity * The activity that will host the view. * @param resource * The ressource to preload. */ public static void preloadResource(Activity activity, String resource) { if (activity == null) { throw new IllegalArgumentException("activity can not be null"); } if (resource == null) { throw new IllegalArgumentException("resource can not be null"); } if (mPreloadedViews == null) { mPreloadedViews = new HashMap<String, ScoreflexView>(); } if (mPreloadedViews.containsKey(resource)) { return; } if (null == getPlayerId() || !isReachable()) { return; } if (sApplicationContext == null) { sApplicationContext = activity.getApplicationContext(); } ScoreflexView preloadView = new ScoreflexView(activity); preloadView.preloadResource(resource); addPreloadedView(resource, preloadView); return; } private static void addPreloadedView(String resource, ScoreflexView view) { synchronized (mPreloadedViews) { mPreloadedViews.put(resource, view); } } private static void removePreloadedView(String resource) { removePreloadedView(resource, true); } private static void removePreloadedView(String resource, boolean closeView) { synchronized (mPreloadedViews) { ScoreflexView view = mPreloadedViews.get(resource); if (view != null) { if (closeView) { view.close(); } mPreloadedViews.remove(resource); } } } private static void clearPreloadedView() { synchronized (mPreloadedViews) { for (Entry<String, ScoreflexView> entry : mPreloadedViews.entrySet()) { entry.getValue().close(); } mPreloadedViews.clear(); } } private static ScoreflexView getPreloadedView(String resource) { ScoreflexView view = null; synchronized (mPreloadedViews) { view = mPreloadedViews.get(resource); } return view; } /** * Free the specified preloaded ressource from memory. * * @param resource * The ressource to free (all preloaded resource if null). */ public static void freePreloadedResources(String resource) { if (null == mPreloadedViews) { return; } if (resource == null) { clearPreloadedView(); return; } removePreloadedView(resource); } /** * Helper method that will register a device for google cloud messages * notification and register the device token to Scoreflex. This method must * be called after the initialize. * * @param senderId * Google Cloud Message sender id to register to. * @param activity * The current activity. */ public static void registerForPushNotification(Activity activity) { if (checkPlayService(activity)) { ScoreflexGcmClient.registerForPushNotification(activity); } } protected static void showView(Activity activity, String resource, Scoreflex.RequestParams params, boolean useActivityForViews) { if (useActivityForViews) { Intent intent = new Intent(activity, ScoreflexActivity.class); intent.putExtra(ScoreflexActivity.INTENT_SHOW_EXTRA_KEY, ScoreflexActivity.INTENT_EXTRA_SHOW_FULLSCREEN_VIEW); intent.putExtra(ScoreflexActivity.INTENT_EXTRA_FULLSCREEN_RESOURCE, resource); intent.putExtra(ScoreflexActivity.INTENT_EXTRA_REQUEST_PARAMS_KEY, params); activity.startActivity(intent); } else { showFullScreenView(activity, resource, params); } } /** * Method to call on your onCreate method to handle the Scoreflex * notification, it must be added to the Activity implementation of the * class you gave to * {@link #onBroadcastReceived(Context, Intent, int, Class)} (must be called * after Scoreflex.initialize(). As follow: * * <pre> * <code> * protected void onCreate(Bundle savedInstance) { * Scoreflex.onCreateMainActivity(this, getIntent()); * } * </code> * </pre> * * @param activity * The current activity. * @param intent * The intent the activity received. * @param useActivityForViews * Set if scoreflex views should be presented as separate activities * * @return <code>true</code> if handled, <code>false</code> otherwise. */ public static boolean onCreateMainActivity(final Activity activity, Intent intent, final boolean useActivityForViews) { if (intent.hasExtra(Scoreflex.NOTIFICATION_EXTRA_KEY)) { String notificationString = intent.getStringExtra(Scoreflex.NOTIFICATION_EXTRA_KEY); try { JSONObject notification = new JSONObject(notificationString); JSONObject data = notification.getJSONObject("data"); String resource = null; Scoreflex.RequestParams parameters = null; int code = notification.getInt("code"); Scoreflex.RequestParams trackParams = new Scoreflex.RequestParams(); trackParams.put("code", Integer.toString(code)); Scoreflex.postEventually("/notifications/track", trackParams, null); if (NOTIFICATION_TYPE_CHALLENGE_INVITATION == code || NOTIFICATION_TYPE_YOUR_TURN_IN_CHALLENGE == code || NOTIFICATION_TYPE_CHALLENGE_ENDED == code) { resource = "/web/challenges/instances/" + data.getString("challengeInstanceId"); } else if (NOTIFICATION_TYPE_FRIEND_JOINED_GAME == code) { resource = "/web/players/" + data.getString("friendId"); } else if (NOTIFICATION_TYPE_FRIEND_BEAT_YOUR_HIGHSCORE == code) { parameters = new RequestParams(); parameters.put("friendsOnly", "true"); parameters.put("focus", data.getString("friendId")); resource = "/web/leaderboards/" + data.getString("leaderboardId"); } else if (NOTIFICATION_TYPE_PLAYER_LEVEL_CHANGED == code) { resource = "/web/players/me"; } if (isInitialized()) { showView(activity, resource, parameters, useActivityForViews); } else { final String finalResource = resource; final Scoreflex.RequestParams params = parameters; BroadcastReceiver receiver = new BroadcastReceiver() { @Override public void onReceive(Context context, Intent intent) { showView(activity, finalResource, params, useActivityForViews); LocalBroadcastManager.getInstance(activity).unregisterReceiver(this); } }; IntentFilter filter = new IntentFilter(Scoreflex.INTENT_SCOREFLEX_INTIALIZED); LocalBroadcastManager.getInstance(activity).registerReceiver(receiver, filter); } return true; } catch (JSONException e) { e.printStackTrace(); } } return false; } /** * Method to call on your onCreate method to handle the Scoreflex * notification, it must be added to the Activity implementation of the * class you gave to * {@link #onBroadcastReceived(Context, Intent, int, Class)} (must be called * after Scoreflex.initialize(). As follow: * * <pre> * <code> * protected void onCreate(Bundle savedInstance) { * Scoreflex.onCreateMainActivity(this, getIntent()); * } * </code> * </pre> * * @param activity * The current activity. * @param intent * The intent the activity received. * @return <code>true</code> if handled, <code>false</code> otherwise. */ public static boolean onCreateMainActivity(Activity activity, Intent intent) { onCreateMainActivity(activity, intent, false); return false; } /** * Starts listening to network connectivity change. * * @param context */ public static void registerNetworkReceiver(Context context) { // registering network listener IntentFilter filter = new IntentFilter(); filter.addAction(ConnectivityManager.CONNECTIVITY_ACTION); try { context.registerReceiver(sConnectivityReceiver, filter); } catch (Exception e) { } } /** * Stops listening to network connectivity change * * @param context */ public static void unregisterNetworkReceiver(Context context) { try { context.unregisterReceiver(sConnectivityReceiver); } catch (Exception e) { } } /** * Method to be called in your Google Cloud Message Broadcast receiver to * handle scoreflex cloud messages and show the appropiate notification. * Implement your onBroadcastReceived as follow : * * <pre> * <code> * public void onReceive(Context context, Intent intent) { * if (Scoreflex.onBroadcastReceived(context, intent, R.drawable.icon, GoblinsAttackActivity.class)) { * return; * } * // do your own handling here * } * </code> * </pre> * * For more information about Google Cloud Message visit: * {@linkplain <a href="http://developer.android.com/google/gcm/index.html">http://developer.android.com/google/gcm/index.html</a>} * . * * @param context * The current context. * @param intent * The received intent. * @param iconResource * The icon you want to show in the notification. * @param activityClass * The activity class you want to start when the user touches * the. notification * @return <code>true</code> if handled, <code>false</code> otherwise. */ public static boolean onBroadcastReceived(Context context, Intent intent, int iconResource, Class<? extends Activity> activityClass) { return ScoreflexGcmClient.onBroadcastReceived(context, intent, iconResource, activityClass); } /** * Returns the time interval between {@link #startPlayingSession()} and * {@link #stopPlayingSession()} have been called. * * @return The current playing session time of the player in milliseconds. */ public static long getPlayingSessionTime() { if (playingSessionStart != 0) { return System.currentTimeMillis() - playingSessionStart; } return 0; } @SuppressWarnings("deprecation") @SuppressLint("NewApi") private static Point getScreenSize() { final Point size = new Point(); WindowManager w = (WindowManager) getApplicationContext().getSystemService(Context.WINDOW_SERVICE); Display d = w.getDefaultDisplay(); try { Method getSizeMethod = d.getClass().getDeclaredMethod("getSize", Point.class); getSizeMethod.invoke(d, size); } catch (Exception e) { size.x = d.getWidth(); size.y = d.getHeight(); } return size; } /** * Retuns whether Scoreflex is reachable or not. * * @return <code>true</code> if Scoreflex is reachable <code>false</code> * otherwise */ public static boolean isReachable() { return sIsReachable; } protected static void setNetworkAvailable(boolean state) { if (state != sIsReachable) { Intent connectivityChangedIntent = new Intent(Scoreflex.INTENT_CONNECTIVITY_CHANGED); connectivityChangedIntent.putExtra(Scoreflex.INTENT_CONNECTIVITY_EXTRA_CONNECTIVITY, state); LocalBroadcastManager.getInstance(getApplicationContext()).sendBroadcast(connectivityChangedIntent); } sIsReachable = state; } protected static int getDensityIndependantPixel(int size) { Point screenSize = getScreenSize(); float width = 480.0f; float height = 320.0f; if (getApplicationContext().getResources() .getConfiguration().orientation == Configuration.ORIENTATION_LANDSCAPE) { width = 320.0f; height = 480.0f; } float xRatio = (float) ((float) screenSize.x / width); float yRatio = (float) ((float) screenSize.y / height); float ratio = yRatio < xRatio ? yRatio : xRatio; return (int) ratio * size; } /** * Sends a google interactive post inviting a user (or a list of users) to * install the game * * @param activity * the current activity * @param text * the message that will be prefilled in the invitation * @param friendIds * a list of friend you want to invite * @param url * the url your want to share on the interactive post button * @param deeplinkPath * the deeplink that your application will receive on launch */ public static void sendGoogleInvitation(Activity activity, String text, List<String> friendIds, String url, String deeplinkPath) { ScoreflexGoogleWrapper.sendInvitation(activity, text, friendIds, url, deeplinkPath); } /** * Share a link on google plus * * @param activity * the current activity * @param text * the message that will be prefilled in the invitation * @param url * the url your want to share */ public static void shareOnGoogle(Activity activity, String text, String url) { ScoreflexGoogleWrapper.shareUrl(activity, text, url); } /** * Post on the facebook feed of the current logged user * * @param activity * the current activity * @param title * the title of the link * @param text * the message that will be prefilled in the invitation * @param url * the url your want to share */ public static void shareOnFacebook(Activity activity, String title, String text, String url) { try { ScoreflexFacebookWrapper.shareUrl(activity, title, text, url); } catch (Exception e) { e.printStackTrace(); } } /** * Sends a facebook app request inviting a user (or a list of users) to * install the game * * @param activity * the current activity * @param text * the message that will be prefilled in the invitation * @param friendIds * a list of friend you want to invite * @param suggestedFriendIds * the suggested friend (appears in the invitation dialog) * @param data * any data you want to attach to the invitation (deeplink) */ public static void sendFacebookInvitation(Activity activity, String text, List<String> friendIds, List<String> suggestedFriendIds, String data) { try { ScoreflexFacebookWrapper.sendInvitation(activity, text, friendIds, suggestedFriendIds, data, new SocialShareCallback() { @Override public void OnSuccessShare(List<String> invitedFriends) { String concatenatedFriends = "Facebook%3A" + TextUtils.join(",Facebook%3A", invitedFriends); Scoreflex.postEventually("/social/invitations/" + concatenatedFriends, null, null); } }); } catch (FacebookException e) { e.printStackTrace(); } } /** * Stops the playing session of a player (user for tracking player session * time). */ public static void stopPlayingSession() { playingSessionStart = 0; } /** * Starts the playing session of a player (user for tracking player session * time). */ public static void startPlayingSession() { Scoreflex.playingSessionStart = System.currentTimeMillis(); } }