Android SDK User’s Guide

Contents

Android SDK User’s Guide#

Introduction#

The Rave Android SDK provides a complete solution to adding beautiful personal and social experiences to your mobile games.

Running and Using the Demo App#

The demo app is distributed in binary form as an APK which you can install and run on any API 15+ device. Simply install the demo APK on an Android device or emulator and launch it.

Opening the Demo Project in Android Studio#

You can also open and run the demo project in Android Studio:

  1. Open Android Studio and select “Open”.

  2. Select the “demo” folder of the Rave Android SDK distribution. After Android Studio finishes loading, open the Project tab. You should see the following:

_images/AndroidStudioProjectView-bfc.png
  1. Run the “BigFishDemo” configuration to start the demo app.

Integrating Rave into your Android Project#

Different game engines and environments have different requirements for this. RaveSocial is packaged as a collection of Android Archive (AAR) files that you can compile into your Android Studio game project.

  1. Include the RaveSocial libraries and ScenePack into Your Project.

    • Copy the Rave AAR libraries to your project’s “libs” directory.

    • Import the ScenePack module from the demo project, or build it and include it as an AAR.

  2. Add the following to the dependencies section of your app’s build.gradle:

    dependencies {
        ...
        implementation 'androidx.security:security-crypto:1.0.0'
        implementation 'androidx.work:work-runtime:2.8.1'
        implementation 'com.squareup.okhttp3:okhttp:4.11.0'
        implementation(name: "RaveSocial", ext: "aar")
        implementation 'com.facebook.android:facebook-android-sdk:16.2.0'
        implementation(name: "RaveFacebookPlugin", ext: "aar")
        implementation 'com.google.android.gms:play-services-auth:20.7.0'
        implementation(name: "RaveGooglePlugin", ext: "aar")
        implementation project(':BigFishScenePack')
        ...
    }
    
  3. Add a “flatDir” resolver to the repositories section so the Gradle plugin can locate the Rave AAR libraries in the “libs” directory:

    repositories {
        ...
        flatDir {
            dirs 'libs'
        }
        ...
    }
    
  4. Copy the following from AndroidManifest.xml from the demo project into your game’s Manifest:

    • uses-permissions (android.permission.READ_CONTACTS only required if using the Phonebook plugin)

    • uses-feature

    • services

    • activities, except for DemoStartActivity

    • “com.facebook.sdk.ApplicationId” and “com.facebook.sdk.ClientToken” meta data

    • (optional) remaining meta data

  5. Add the call to your ScenePack’s .initializeScenePack() as shown in the next section.

    • You can use any of the available initialize methods, including the ones with completion callback.

    • It doesn’t have to be called from application onCreate, but it should be called only once.

    • Near this call is a good place to change important settings or add listeners.

    • Please note that the login listener needs to be added before initialization for proper function.

  6. Copy the demo’s res/raw/config.json into the same location in your game.

    • Edit any settings there that need changing.

    • The Android Manifest can also be used to override settings that are configured in the demo.

  7. Add Required Lifecycle calls - Make sure to add calls to RaveSocial.onStart(context) and RaveSocial.onStop() to your game’s onResume and onPause.

    If you are having problems getting projects to compile:

    • Make sure you have Android SDK 25 installed and Build Tools 25.0.3 which are available via the Android SDK Manager.

    • Make sure you have the Android Support Library repository installed, also available via the Android SDK Manager.

    If you’re using a another build system:

    • Follow the system’s directions on how to include code, assets and resources and include all of the Rave AAR libraries and dependencies.

    • Please contact your Rave Social support rep if using a custom build system. Custom built Android projects may require a merge and your rep may be able to assist you with tools or scripts.

Note

Android’s “DEX” file format has a limit of 65,535 method signatures in its index. Please review the section on Optimizing Android optimizing Android to mitigate this issue.

Optimizing Android#

The Android platform has a hard limit of 64k method signatures that can exist in a single DEX file. This includes all Java methods in your app plus all included libraries and SDKs. By default Android does not optimize the compiled code - it includes all methods, even unused ones. We highly recommend using the standard optimization tool for Android: Proguard. Proguard can significantly reduce the number of method signatures required to use any library as well as save significant compiled code space. There are many configuration options for Proguard and many third party libraries have specific requirements for working with Proguard. Please consult the Proguard documentation here http://developer.android.com/tools/help/proguard.html and consult the documentation for any other libraries or SDKs you are including with your project to determine what the correct Proguard configuration is.

A working proguard configuration for Rave:

# General Android config

-optimizationpasses 5
-dontusemixedcaseclassnames
-dontskipnonpubliclibraryclasses
-dontpreverify
-verbose
-optimizations !code/simplification/arithmetic,!field/*,!class/merging/*,!code/allocation/variable

-keep public class * extends android.app.Activity
-keep public class * extends android.app.Application
-keep public class * extends android.app.Service
-keep public class * extends android.content.BroadcastReceiver
-keep public class * extends android.content.ContentProvider
-keep public class * extends android.app.backup.BackupAgentHelper
-keep public class * extends android.preference.Preference
-keep public class com.android.vending.licensing.ILicensingService

-keepclasseswithmembernames class * {
        native <methods>;
}

-keepclasseswithmembers class * {
        public <init>(android.content.Context, android.util.AttributeSet);
}

-keepclasseswithmembers class * {
        public <init>(android.content.Context, android.util.AttributeSet, int);
}

-keepclassmembers class * extends android.app.Activity {
   public void *(android.view.View);
}

-keepclassmembers enum * {
        public static **[] values();
        public static ** valueOf(java.lang.String);
}

-keep class * implements android.os.Parcelable {
  public static final android.os.Parcelable$Creator *;
}

-keepclassmembers class * implements java.io.Serializable {
        static final long serialVersionUID;
        private static final java.io.ObjectStreamField[] serialPersistentFields;
        private void writeObject(java.io.ObjectOutputStream);
        private void readObject(java.io.ObjectInputStream);
        java.lang.Object writeReplace();
        java.lang.Object readResolve();
}

# Rave global settings

-dontobfuscate
-keepattributes InnerClasses,Signature,Exceptions,*Annotation*,AnnotationDefault,EnclosingMethod,SourceFile,LineNumberTable

# Rave third party libraries

-dontwarn org.codehaus.jackson.map.ext.JodaSerializers*
-dontwarn org.codehaus.jackson.map.ext.JodaDeserializers*
-dontwarn org.codehaus.jackson.map.ext.DOMSerializer
-dontwarn com.gorillagraph.cssengine.view.*
-dontwarn co.ravesocial.sdk.login.**
-dontwarn co.ravesocial.sdk.test.**
-keep class com.facebook.** { *; }
# == Start Google requirements
-keep class * extends java.util.ListResourceBundle {
        protected Object[][] getContents();
}
-keep public class com.google.android.gms.common.internal.safeparcel.SafeParcelable {
        public static final *** NULL;
}
-keepnames @com.google.android.gms.common.annotation.KeepName class *
-keepclassmembernames class * {
        @com.google.android.gms.common.annotation.KeepName *;
}
-keepnames class * implements android.os.Parcelable {
        public static final ** CREATOR;
}
# == End Google requirements

# == Start Rave Social SDK

# Keep internal plugins as they may be used optionally / dynamically
-keep class co.ravesocial.sdk.internal.plugin.** { *; }

# Keep all JSON mappable fields
-keep public class co.ravesocial.sdk.internal.net.action.** {
  public void set*(***);
  public *** get*();
}
-keep public class co.ravesocial.sdk.internal.net.** { *; }
-keep public class co.ravesocial.sdk.internal.dao.** { *; }
# Keep reflective mapper mixins
-keep class co.ravesocial.sdk.internal.net.servers.rave.RaveJsonMixInRegistry$* { *; }
# With Gradle 2.2, this is required to avoid a bad descriptor while dexing
-keep class org.codehaus.jackson.JsonLocation { *; }
# == End Rave Social SDK
-keep class com.crashlytics.android.Crashlytics { *; }

# Add any other SDK bits here

# BigfishScenePack
-keep class co.ravesocial.bigfishscenepack.BigfishEntity { *; }
-keep class co.ravesocial.bigfishscenepack.susi.** { *; }

Initializing the SDK#

Tip

If Rave does not initialize, check the log for exception messages about invalid or missing settings. See the SDK Logging section for more information on logging.

The main ScenePack class is named BigFishScenePack and is in the co.ravesocial.bigfishscenepack package. You can initialize it by calling .initializeScenePack(context), where the context is the Application context. If you are initializing in an Activity, you can obtain the application context via getApplicationContext().

RaveSocial is automatically initialized along with any ScenePack-specific options or integration features. We recommend initializing the SDK from the Application’s onCreate() method, like in the following example:

public class MyApplication extends Application
{
        @Override
        public void onCreate()
        {
                super.onCreate();
                BigFishScenePack.initializeScenePack(this);
        }
}

This initialization will contact the Rave servers and attempt to pull any app configuration data if available. There are many initialization options - some must be added before initalization, others after.

An exception will be thrown if any method in RaveSDK requiring initialization is called before the system is initialized. Please see the Rave Demo for examples of pre and post-init methods.

Following the ScenePack, the next most important class is the RaveSocial class. Located in co.ravesocial.sdk, it is the gateway to nearly every feature provided by Rave Social. For Android, RaveSocial requires two lifecycle calls which are onStart and onStop.

To make sure you have the required lifecycle calls integrated:

public class MyActivity extends Activity
{
    @Override
    public void onResume()
    {
        super.onResume();
        //...
        RaveSocial.onStart(this);
    }

    @Override
    public void onPause()
    {
        super.onPause();
        //...
        RaveSocial.onStop();
    }
}

Settings#

Rave’s settings can be set in any of the following: the RaveSettings class (programmatic), Android Manifest or JSON. Default app configuration data is held in a file located in res/raw by the name config.json. Here is an example template:

{
    "RaveSettings.General.ServerURL":"<rave server url including https>",
    "RaveSettings.General.ApplicationID":"<rave application id>",
    "RaveSettings.General.ConfigUpdateInterval": "3600",
    "RaveSettings.General.ContactsUpdateInterval": "21600",
    "RaveSettings.Facebook.ApplicationId":"<Facebook application id>",
    "RaveSettings.General.AllowForceDisconnect": false,
    "RaveSettings.Facebook.ReadPermissions": "public_profile,email",
    "RaveSettings.General.AutoCrossAppLogin": true,
    "RaveSettings.General.AutoGuestLogin": true,
    "RaveSettings.General.ThirdPartySource": "bigfishgames",
    "RaveSettings.General.AutoInstallConfigUpdates": true,
    "RaveSettings.General.LogLevel" : "Error"
}

Settings Priority and Overrides#

Programmatic settings have the highest priority (e.g. will always override), next priority is manifest, lowest priority is JSON. This gives you the ability to have config that works on both platforms that you can override keys per platform either in code or platform specific config (manifest). If Rave does not initialize, check the log for messages about invalid settings.

Attention

Rave will terminate your application with an exception if one or more required settings are missing

To initialize RaveSocial with a different json file change your initialization code as follows:

// this should be resolved based on the location of the config file you wish to read from
InputStream configInputStream;

BigFishScenePack.initializeWithConfig(application, configInputStream);

Available Settings#

Common Settings Between SDKs#

Note

Required settings are highlighted in bold in the table below.

Setting Key

Description

Default

RaveSettings.General.ApplicationID

Rave Application ID

RaveSettings.General.ServerURL

Rave Server URL, start with https://

RaveSettings.General.LogLevel

Rave Log level, “quiet, error, warn, info, verbose, debug” are valid options

“error”

RaveSettings.General.AutoSyncInterval

Rave automatic configuration sync interval in seconds, 0 = 0ff, valid {3600-86400}

21600

RaveSettings.General.AutoGuestLogin

Automatic guest login

true

RaveSettings.General.AutoCrossAppLogin

Automatic cross-app login

true

RaveSettings.General.AutoInstallConfigUpdates

Automatically install configuration updates after download

true

RaveSettings.General.AllowForceDisconnect

Allow resolving connect conflicts by forceably disconnecting previous account is allowed

false

RaveSettings.General.NetworkTimeout

Network timeout in ms, valid range is 0-60000

30000

RaveSettings.General.ContactsUpdateInterval

How often to update contacts in seconds, 0 = off, 3600-86400 is valid range

21600

RaveSettings.General.ConfigUpdateInterval

How often to check for configuration updates, 0 = off, 3600-86400 is valid range

21600

RaveSettings.General.ThirdPartySource

If integrating with a supported third-party system, what the source key is

RaveSettings.General.DefaultResourcesPath

Default resources path

RaveSettings.General.AutoMergeOnConnect (read-only)

Automatically merge users if there is a conflict

false

RaveSettings.General.AutoSyncFriends

Comma separated list of social providers for which friends will be automatically synced.

Facebook, Google, Phonebook

RaveSettings.Facebook.ApplicationId

Rave Facebook Application ID

RaveSettings.Facebook.ReadPermissions

Comma separated list of Facebook read permissions (e.g. public_profile,email…) omitting spaces. Please refer to Facebook documentation for further details

public_profile, email, user_friends

RaveSettings.Facebook.AlwaysUseLiveContacts

If Facebook contacts should always be kept current

false

RaveSettings.Google.ClientID

Google Client ID

RaveSettings.Google.BackendClientID

The web Google client ID configured in the portal

RaveSettings.Google.ReadPermissions

Comma separated list of Google read permissions (e.g. email,contacts…) omitting spaces. Please refer to Google documentation for further details

email,contacts

RaveSettings.DataMirror.Achievements

Plugins to enable achievements mirroring for

RaveSettings.DataMirror.Leaderboards

Plugins to enable leaderboards mirroring for

Android-only Settings#

Setting Key

Description

Default

Required

RaveSettings.Android.UseDialogOverlay RaveSettings.Android.SkipPermissionChecks

Bases Rave UI in a full screen dialog for compat Skips permission checks on initialization

false false

Integrating Third-party Social Providers#

Rave supports third party service providers via plugin architecture. All plugins are referenced by their “key name” in Rave APIs. A plugin will be automatically registered for you in your company’s scenepack. Please refer to the following chart for Rave’s stock plugin capabilities.

Service

Authentication

Contacts

Sharing

Data Mirroring

Facebook

Yes

Yes

Yes

No

Google

Yes

Yes

No

No

Phonebook

No

Yes

No

No

Gamecenter

No

No

No

Yes

Rave Social’s server infrastructure requires configuration of third-party credentials in order to communicate directly with the third party services. Please read and perform the following guides for the applicable social networks for your app and send the resulting credentials to your Rave Social support representative to enable the associated features.

Configure the Facebook App#

  1. Go to the Facebook Developers Console and log in with your Facebook credentials to access the developer App settings

  2. Click Create New App

  3. In the Display Name field, type in the name of your application

  4. (Optional) In the Namespace field, type in a unique application ID

  5. Select the category most appropriate for your application

  6. In the left sidebar, click the Settings button

  7. You will now need to add information for each platform your app is on:

    1. Click Add Platform

    2. Enter your Bundle ID and iPhone/iPad Store ID from your iTunes Connect page

    3. Enable Single Sign On and Deep Linking

    4. Click Save Changes

    1. Click Add Platform

    2. Enter your Package Name and the Class Name of your application’s start activity (e.g.: co.ravesocial.demo.DemoStartActivity)

    3. Enable Single Sign On and Deep Linking

    4. Enter Key Hashes for each Android key you plan on using for development and release. The Obtaining Key Hash and SHA-1 Fingerprint section describes how to get the necessary key hash value(s)

    5. Click Save Changes

  8. Configure your business mappings for all of your apps. Since Graph API v2.0, Facebook is issuing app-scoped user IDs for players’ Facebook UIs. By definition, this means the ID for the same person may be different between these apps.

Since Big Fish Games operates many Facebook Apps, in order to support use cases such as keeping track of which of player’s friends are playing Big Fish games, you need to map the same person’s ID between those apps. You can do this using Facebook’s Business Mapping API.

Before you use the Business Mapping API you will need to use Facebook Business Manager to create a new business, or associate your apps to an existing business in order for Facebook to determine the apps your business operates.

Note

Important

Facebook Graph API v2 went online on April 30, 2014. All FB apps created after this date will use Graph API v2 or newer.

Warning

Known Issue with Facebook Test Users and Cross-Play Functionality

Some Facebook Test Users have been observed to encounter issues with cross-play functionality due to a known issue in Facebook’s /me/ids_for_business API. In certain cases, the API response does not conform to the documented structure, specifically omitting critical information required for Rave to identify accounts signed in across the same business apps. As Rave relies on this API to enable cross-play and account reutilization, this issue may affect these functionalities.

To mitigate this problem, Rave disabled Facebook cross-play functionality for the affected test user accounts until Facebook resolves the issue on their end. Please note that this issue is specific to certain Facebook test users, and real Facebook user accounts remain unaffected.

Once your Facebook app is set up, find the AppID and AppSecret for the application you just created and copy them for use in the Rave Application Management Portal and for contacting Rave Social for support.

By default, Rave Social uses the latest Facebook Graph API supported by the native Facebook SDK linked to the application.

Keys to add to your Android or iOS project:

  • RaveSettings.Facebook.ApplicationId

Facebook’s app review process#

Facebook has a review process for apps requesting permissions beyond the basic set (public_profile, email and user_friends). Please refer to the Facebook documentation on review for more information on this process.

Note

Facebook SDK requires that the meta-data string “com.facebook.sdk.ApplicationId” and “com.facebook.sdk.ClientToken” is set in your AndroidManifest.xml. It’s critical that the Facebook Application ID is placed into the strings.xml file, not directly into the Manifest. Android casts any numbers in the meta-data to 32-bit integers, which does not work for Facebook, but when a string resource is referenced, it will remain as a string and not cast. See the included demo for an example.

Note

Facebook SDK automatically adds the Advertising ID Permission to your app. In some cases, you might want to opt out of including the Advertising ID permission in your app. For example, if the customers for your app are children and families, the Advertising ID Permission might not be relevant. For more information, see the Understand the Advertising ID Permission section in Facebook docs.

Important

Rave currently supports Android Facebook SDK version 15.1.0. While newer versions may work, they may not have been tested yet with your version of Rave.

Full Facebook setup instructions for Android can be found here:

https://developers.facebook.com/docs/android/getting-started

Configure Google Project#

  1. Access Google API Console:

  2. Configure OAuth Consent Screen:

    • In the left side bar, navigate to the OAuth consent screen page.

    • Ensure all information provided is complete and accurate.

  3. Create Android/iOS Client ID:

    • In the left side bar, navigate to the Credentials page.

    • If you don’t have already, you will now need to register a Client ID for iOS and one for each Android signing key you plan on using for development/release:

      1. Click Create credentials.

      2. Select OAuth client ID (Note: To create an OAuth client ID, you must first set a product name on the consent screen).

      3. Select iOS for the application type.

      4. Enter your Bundle ID.

      5. After creation, take note of the Client ID.

      1. Click Create credentials.

      2. Select OAuth client ID (Note: To create an OAuth ID, you must first set a product name on the consent screen).

      3. Select Android for the application type.

      4. Enter the Package Name and SHA-1 Fingerprint. The Obtaining Key Hash and SHA-1 Fingerprint section describes how to get the necessary SHA-1 fingerprint.

      5. Repeat this process to create a Client ID for each Android key (Development and Release).

  4. Creating Client ID for the Rave Backend Server:

    • In the left side bar, navigate to the Credentials page.

    • Click Create credentials

    • Select Web application for the application type

    • After creation, take note of the Client ID and the Client secret. You will need the Client ID and Client Secret for use in the Rave Application Management Portal and for contacting Rave Social for support.

  5. Configure the project:

    • Configure your Android or iOS project with new generated Client IDs, you will need to add a few config keys as per platform:

      • RaveSettings.Google.ClientID (The iOS Client ID)

      • RaveSettings.Google.BackendClientID (The Backend Client ID)

      • RaveSettings.Google.ClientID (The Backend Client ID)

      • RaveSettings.Google.BackendClientID (The Backend Client ID)

      Note

      Android requires the Backend Client ID for both settings.

Full Google setup instructions for Android can be found here:

https://developers.google.com/identity/sign-in/android/start-integrating

Obtaining Key Hash and SHA-1 Fingerprint#

Key Hash#

Facebook’s documentation on how to obtain your Key Hash is available here: https://developers.facebook.com/docs/android/getting-started#troubleshooting

To obtain your key hash, add the following code to your application main activity’s onCreate function. Remember to replace the package listed below with your actual package name or it won’t find the key.

// Add code to print out the key hash
try {
    PackageInfo info = getPackageManager().getPackageInfo(
        "com.facebook.samples.hellofacebook",
        PackageManager.GET_SIGNATURES);
        for (Signature signature : info.signatures) {
            MessageDigest md = MessageDigest.getInstance("SHA");
            md.update(signature.toByteArray());
            Log.d("KeyHash:", Base64.encodeToString(md.digest(), Base64.DEFAULT));
        }
    } catch (NameNotFoundException e) {
} catch (NoSuchAlgorithmException e) {
}

SHA-1 Fingerprint#

Google’s documentation on how to obtain your keystore’s SHA-1 fingerprint is available here: https://developers.google.com/+/quickstart/android

To obtain your SHA-1 fingerprint of the certificate run the Keytool utility in a terminal.

keytool -exportcert -alias androiddebugkey -keystore <path-to-debug-or-production-keystore> -list -v

Where Is My Default Debug Key for Android?#

  • key path is ~/.android/debug.keystore

  • the key alias is androiddebugkey

  • the password is android

Setting Keys in the Rave-enabled App#

Modify <Android Application>/res/raw/config.json

  • “RaveSettings.Google.ClientID” : “”

  • “RaveSettings.Facebook.ApplicationId” : “”,

Directly Logging In to Authentication Providers#

Using our loginWith API, you can directly invoke a login via Facebook, or Google. Please use the following constants:

  • Facebook

  • Google

RaveSocial.loginWith("Facebook", new RaveCompletionListener() {
    public void onComplete(RaveException exception) {
        // handle login response
    }
});

Checking Readiness of Authentication Providers#

Just like with the direct login API - you can also see if an authentication provider is ready to be used. “Readiness” indicates that a user has connected this social account to their Rave Social account and also that the token or local authentication for this provider was successful. Use all the same constants as direct login to check. If a plugin is not ready but you desire a ready status, use the matching connect convenience function in RaveSocial.

RaveSocial.checkReadinessOf("Facebook", new RaveReadinessListener() {
    public void onComplete(RaveReadyStatus readyStatus) {
        // handle result
    }
});

// connecting to Facebook if it fails a readiness check
RaveSocial.connectTo("Facebook", new RaveCompletionListener() {
    public void onComplete(RaveException exception) {
        if (exception != null) {
            // handle error
        } else {
            // success
        }
    }
});

Built-In Big Fish Game Personalization Experiences#

The BFC SDK comes equipped with a set of pre-built Big Fish Games experiences. They can be easily and quickly integrated into any Big Fish mobile game to provide a consistent experience for basic game personalization features like Player Login, and Player Profile Management.

Although these experiences by default reflect the look and feel of the Big Fish brand, they can be customized to fit the look and feel of individual games by changing the skin and layout of individual features.

See the Personalizing the Built-in Experiences section to find out how to personalize these experiences.

Player Login Experience#

The default Login experience allows the player to log in, and create a new gamer account via any of these methods:

  • Sign up with a new email address

  • Sign in with an email address associated with player’s Big Fish ID account

_images/player_login_experience1.png

In order to integrate this scene it’s important that the Facebook and Google apps used in the Rave integration are properly configured. Please see Integrating Third Party Authentication section for instructions on how to configure the social networks apps.

Sign up data is somtimes returned in certain regions for new users. See Getting COPPA or CASL Information from User Sign Up section for more on this.

To integrate the sign-up experience:

RaveSignUpEmailScene signUpScene = new RaveSignUpEmailScene(BigFishDemoStartActivity.this, null);
signUpScene.setSignUpListener(new BigFishSignUpListener() {
    @Override
    public void onSceneComplete(RaveCallbackResult result, BigFishSignUpData signUpData, RaveException exception) {
        if (result == RaveCallbackResult.RESULT_ERROR) {
          // handle error
        } else if (result == RaveCallbackResult.RESULT_CANCELED) {
          // handle canceled
        } else if (signUpData != null) {
          // handle the sign up data if needed (canada, us)
        } else if (result == RaveCallbackResult.RESULT_SUCCESSFUL) {
          // there is no sign up data returned for other regions
        }
    }
});
signUpScene.show();

To integrate the sign-in experience:

RaveLoginScene loginScene = new RaveLoginScene(BigFishDemoStartActivity.this);
loginScene.setSignUpListener(new BigFishSignUpListener() {
  // same as above
);
loginScene.show();

Registering and Handling Login Callbacks#

RaveSocial provides key Scene and Login status callbacks that a developer can register and listen to.

Login Status Notification#

The general Login Callback (not to be confused with the RaveLoginScene callback) is used to notify the developer that a login status change of some kind has occured. This is useful because it may indicate that some social features are now available.

RaveSocial.setLoginListener(new RaveLoginStatusListener() {
  @Override
  public void onLoginStatusChanged(RaveLoginStatus status, RaveException e) {
    if (e != null) {
      //handle errors here
    } else {
      if (RaveSocial.isLoggedInAsGuest()) {
        //handle guest access here
      }
      //post-login code here
    }
  }
});

Directly Logging In to Authentication Providers#

If using the built-in Big Fish Login experiences is not desired, developer can build completely custom login experience using Rave’s login APIs.

Using our loginWith API, you can directly invoke a login via Facebook or Google. Please use the following constants:

  • Facebook

  • Google

RaveSocial.loginWith("Facebook", new RaveCompletionListener() {
  @Override
  public void onComplete(RaveException exception) {
        if (exception != null) {
            // handle error
        } else {
                            // success
        }
  }
});

Checking Readiness of Authentication Providers#

Just like with the direct login API - you can also see if an authentication provider is ready to be used. “Readiness” indicates that a user has connected this social account to their Rave Social account and also that the token or local authentication for this social account was successful. Call convenience functions in RaveSocial to check a plugin’s readiness. If a plugin is not ready but you desire a ready status, use the matching connect methods in RaveSocial to establish a connection with the the desired plugin.

RaveSocial.checkReadinessOf("Facebook", new RaveReadinessListener() {
  @Override
  public void onComplete(RaveReadyStatus status) {
    //handle result
  }
});

RaveSocial.connectTo("Facebook", new RaveCompletionListener() {
  @Override
  public void onComplete(RaveException exception) {
    if (exception) {
      // handle error
    } else {
      // success
    }
  }
});

Player Profile Management Experience#

The profile management experience screen allows players to build out their game profile by adding a profile picture, email, and display name, as well as connecting various social networks to connect with friends.

This screen will also have a link to login or sign-up if the user hasn’t done so already.

To integrate the Profile Management experience:

RaveAccountInfoScene accountInfoScene = new RaveAccountInfoScene(BigFishDemoStartActivity.this);
accountInfoScene.setSignUpListener(new BigFishSignUpListener() {
  @Override
  public void onSceneComplete(RaveCallbackResult result, BigFishSignUpData signUpData, RaveException exception) {
      // handle any login or sign-up actions here
});
accountInfoScene.show();

Find Friends Experience#

The Find Friends screen allows the player to connect their Facebook and Google accounts, and their local Phonebook to find friends who are also playing Big Fish games.

As the player connects his social network account to his gamer account, Rave will keep track of which of player’s friends are also playing Big Fish games and will add those friends to the list of player’s gamer contacts. These friends will be available in games for in-game interactions such as sending gifts to them and for social leaderboards.

_images/find_friends_experience.png

To integrate the Find Friends experience:

FindFriendsScene scene = new FindFriendsScene(BigFishDemoStartActivity.this);
if( FindFriendsScene.shouldShow() ) {
  scene.show();
} else {
  // ends up here if all plugins are already connected and it is not necessary to show the scene
}

Getting COPPA or CASL Information from User Sign Up#

If you are in the US region and need information about a new user’s COPPA compliance, or are in the Canadian region and need information about whether the user has accepted newsletter sign-up, this data can be checked by setting a callback on RaveAccountInfoScene, RaveLoginScene and RaveSignUpEmailScene. Note that signUpData can be returned as null in certain situations.

The newsletter name for sign up can be set in the setting BigFishSettings.General.NewsletterName

An example usage:

RaveAccountInfoScene accountInfoScene = new RaveAccountInfoScene(BigFishDemoStartActivity.this);
accountInfoScene.setSignUpListener(new BigFishSignUpListener() {
  @Override
  public void onSceneComplete(RaveCallbackResult result, BigFishSignUpData signUpData, RaveException exception) {
    if (result == RaveCallbackResult.RESULT_ERROR) {
      // handle error
    }
    if (signUpData == null) {
      // no sign up data when canceled or other regions
    } else {
      // For Canada:
        // signUpData.acceptedNewsletter tells you if the user opted-in to receive newsletter
      // For US:
        // signUpData.passedCoppaCheck tells you if the user's age is COPPA Compliant
        // signUpData.birthYear will contain the user's year of birth
    }
});
accountInfoScene.show();

Personalizing the Built-in Experiences#

The built-in Big Fish game experiences reflect the look and feel of the Big Fish brand, but they can be customized to fit the look and feel of individual games by changing the skin and layout of individual components. The look and feel of the screens can be changed by modifying the resource files that were used to build the screens.

The Rave SDK UI framework allows for native Android and iOS UI to be generated using XML- and CSS-based UI definitions. An individual screen (called a Scene in the SDK) is a combination of XML and native code used to lay out and provide UI functionality. Scenes are generally used for full-screen or dialog-based UI layouts, such as Login or Account Management. Widgets are smaller UI building blocks, such as a button with specialized behavior.

Every built-in experience has at least one XML layout and at least one controlling class, called the Scene class. The Scene class is native code.

Scene Resources#

The scene XML can refer to resources in the local app configuration, such as images, fonts or other XML. Resources can be redefined dynamically via an app configuration bundle and distributed live using the Rave backend service. The default location for resources on Android is in the assets folder of the game or app. The default location in iOS is in the Scene Pack’s resource bundle. Both platforms can share the same resources.

Changing the Look and Feel#

In order to change the color scheme, the skin or individual text or images used in the creation of the built-in experience, the individual assets need to be created and replaced in the exact file structure used in the project. Once replaced the project needs to be restarted for changes to take effect.

Attention

It is important the file structure stays intact so that the SDK and the logic in the Scene class are able to find the assets. Failing to do so may result in an error or an app crash.

Changing Layout#

Since all UI elements in the built-in experiences are dynamically created from XML and CSS scene resource descriptions, only the XML and CSS files need to be modified to change the screen layout. Similarly to the look and feel changes, the project needs to be restarted for those changes to take effect.

Changing Functionality#

If using the built-in Big Fish game experiences is not appropriate for a game, you can build completely custom game UI by using Rave’s data APIs. These APIs expose all functionality available through the Rave system and are used to build the built-in experiences.

For example, instead of integrating the built-in Login screen, you can build a custom login UI by using Rave’s login APIs.

Remotely Updating the Look and Feel of the Experience#

Since all UI elements used in the built-in experiences are dynamically created from resource files, by changing the resource files the look and feel can be modified. Rave supports remote upgrades of these resources. The Rave SDK regularly queries the backend service to check for updated resource files. Resource bundles with new contents can be uploaded through the Rave Developer Portal.

To update UI resource files remotely:

  1. Copy the /resources folder included in the project (and the SDK distribution) to another location where it can be modified safely. Make appropriate changes to individual asset files, CSS and XML files without changing their location.

  2. Once done making changes, create a zip archive from the resources folder called resources.zip.

  3. Upload the file to the Rave Developer Portal. See REF GOES HERE for instructions.

Users and Identities#

At the core of Rave’s game personalization is the concept of a player’s gamer account. This account reflects the gamer identity of an individual person who maybe be playing several Big Fish games across many different devices, including iPad, iPhone, Android phones, and Android tablets.

Every Big Fish gamer account has a globally unique Rave ID, a 32-digit hex number, which can be used to uniquely identify the player for game logic purposes. This Rave ID is created when the player first begins playing a Big Fish game, even if they have not logged in with an explicit authentication method such as Facebook. We will refer to a user that has a Rave ID, but no authentication or personalized data associated with their account as an anonymous user. This Rave ID is persisted for the lifetime of that player’s account.

Later as the player continues to build out their gamer profile by adding a display name or email address to their account, the player will move to the “Personalized” state.

Once the player logs in with any of the available authentication methods, they will move to the “Authenticated” state. Today the available methods of authentication are Big Fish ID, Facebook and Google.

As the player plays more Big Fish games across more devices and continues to build out their profile by connecting additional social networks and additional pieces of personal information (e.g. a profile picture), these attributes are attached to their Rave ID and they can be accessed via the User API. The figure below gives a logical representation of a player’s account and all attributes associated with it.

Attribute

Description

UUID

A 32-digit hex number that acts as the Rave ID for the user. It is assigned when a user is created and is immutable. Note that although the value is immutable, multiple Rave accounts can be merged into a single account. Thus the primary UUID referencing a user may change over time

Account state

A user can be in one of three account states: anonymous, personalized, or authenticated. See Player Account States for more information.

Username

A unique username in the Rave system. It can be changed, but at any given time it must be unique. Given that it can be changed, it should not be used in place of the UUID to refer to users. It is intended for display purposes.

Display name

A non-unique display name for the user

Profile image URL

A URL for the user’s profile image

Email

User’s email address

Birthdate

User’s birthdate

Gender

User’s gender

FB UIDs

One or more Facebook UIDs can be associated with a user.

Google UID

The user’s Google UID if they have connected to Google.

Devices

A list of devices associated with the user

Sessions

A list of active sessions a user has. Each application/device combination where a user is using Rave requires an active session

Merged identities

A list of user accounts that have been merged in to this user account. See Merged IDs for more information.

User State Transitions#

A player’s Rave ID can change on a specific device when any of the following is true:

  • The device is reset when the player was in the “Anonymous” state

  • The player logs in to an account that was previously created on another device. This transitions the user on the curent device from the anonymous state to the authenticated state and the anonymous account they had been using on this device is automatically merged in to the account that they logged in to. A list of merged anonymous Rave IDs for an account and can be accessed via the User API.

  • The player opens game the first time after his account was merged with another account and the primary Rave ID was generated on the other device. See Merging for more information.

Player Account Identifiers#

As the player continues playing Rave-enabled games, over time they can add more information about themself and build out their gamer profile. They can connect his Facebook and Google accounts, create a display name and a username, as well as add a profile picture.

Social Network State#

Once the player connects Facebook, Google, or the local Phonebook to his account, he will be able to use social features, such as posting to someone’s Facebook wall, directly from the game and from the built in Big Fish Rave personalization experiences. However, this will only be true if there is an authentication token present from the particular social network on the device from which the player was connecting. If the developer starts playing on another device, or wipes the current device, then the token will not be available and the player will have to log into Facebook again. The social network readiness API lets the developer know whether the usage of the social network is currently available for the player. See Checking Readiness Of Social Networks section for more details.

Player Account States#

A player account will be in one of the following three states, which will affect their ability to use different Rave features.

  • Anonymous - The player hasn’t provided any information to identify their account

  • Personalized - The player shared personal information such as email, but didn’t associate any information to be able to securely identify himself in the game. Secure authenticating identities include Big Fish ID, Facebook and Google.

  • Authenticated - Player connected and logged in with one or more of these identities: Facebook, Google, Big Fish ID

Player Value Scopes#

It is possible to apply an application scope to a subset of a user’s attributes. For each application, the display name and profile image can be configured to either use global or app-scoped values. This behavior can be controlled with the User value scope setting for an application in the Rave portal (see the Configuring an Application section).

When the App scope option is selected for an application, the following behaviors are enabled:

  • Display names and profile images that are set in the application are only visible in that application

  • Display name and profile image values displayed in the application will either be the app-scoped values, if set, or the global values if no app-scoped values have been set.

  • If a user removes an app-scoped value that they have set, the value displayed in the application will become the global value.

When the default scope Global is selected, display name and profile image are shared across all other apps that have Global scope selected.

Merging#

As of Rave SDK v2.9, complete player account merging is supported.

When a user is logging in to apps and games using different social networks on different devices, the user will be identified initially as different distinct users and as a result, there will be multiple Rave IDs defined for this user. As Rave observes the associations between this user’s social networks, it will collect a list of the identities for this unique user by way of merging them under a single Rave ID.

Example: Bob logs in to a game on his iPad using Facebook. Later, Bob logs in to a different game on his Android device using Google. At this moment, Bob has 2 different accounts (one for the Facebook login on one device, another for the Google account on his other device). Now Bob decides to request some gifts from his friends using Facebook on his Android device which he had only logged in to using Google. At this point, Rave is able to identify that Bob has used two accounts and Bob’s accounts are now merged into a single identity with the previous identity stored safely and without loss. Bob’s single Rave account is unified and for all future logins, he will be identified under the one unique account.

How Merging Works#

When an anonymous or personalized user logs in to an existing Rave account, or any user connects to an existing Rave account while already authenticated, Rave will merge all data (social data such as friends list and game data such as leaderboard scores) from the currently logged in user to the existing Rave account of which the user is trying to connect or login as. The result is a single Rave ID which has all of the combined associations with social networks and combined data from both accounts. To the user, it will simply appear as though the login or connect action worked without issue.

Rave maintains the list of all Rave IDs merged into the current account. See Merged IDs for information.

The merge function is triggered when RaveSocial.connectTo is used to connect the current user using authentication data already associated with another Rave user account. The result of the merge is a single user which maintains the previous identity as well as a combined set of both user’s data. This feature is enabled by default. To disable this feature, disable the Rave setting RaveSettings.General.AutoMergeOnConnect.

In a user merge case, the source user (currently logged in) is merged into the target user (existing Rave user matching connect credentials). The source user is then logged out after the merge is complete and the newly merged-in-to target user is logged in. The currently logged in Rave ID will switch from the source user to the target user. Any devices logged in with the source user will also switch to the target user automatically. Any devices logged in as the target user will be unaffected except for the data updates.

Merged IDs#

Rave creates a new Rave ID for every new anonymous player session when the setting RaveSettings.General.AutoGuestLogin is enabled. When an anonymous player subsequently logs in via, for example, Facebook, the Rave ID from the anonymous session is merged into the authenticated account. Account merge also happens when a logged in player attempts to connect a social network account (ie. Facebook) that is already connected to another Rave ID. The account is merged and the other Rave ID is stored in the list of merged IDs for the player’s account.

Obtaining the list of merged identities is available via the API RaveUsersManager.fetchIdentities. Please refer to the platform SDK API documentation for more information on usage.

Merged Data#

When two users are merged together, the users data is also merged using the following rules:

  • Identity - The source user’s RaveID will be added to the target user’s identities.

  • Contacts - The target user will retain its contacts and add all contacts of the source user.

  • Facebook, Google and other associations - The target user will add the associations from the source user for all social networks.

  • Leaderboards - The target user will use the best high scores earned between both the source and target user.

  • Achievements - The target user will keep all unlocked achievements from both the source and target user.

  • Gifts - The target user will keep all gifts from both the source and target user.

Accessing the Current User#

Once you have successfully logged in you can access the current user

//  to access the current user use the following snippet:
RaveUser currentUser = RaveSocial.usersManager.getCurrent();

//  to update the current user use the following code:
RaveSocial.usersManager.updateCurrent(new RaveCompletionListener() {
    public void onComplete(RaveException exception) {
        if (exception != null) {
            //  handle the error condition
        } else {
            //  peform operations on RaveSocial.usersManager.getCurrent()
        }
    }
});

// to access the RaveID and other values for the current user use the following snippet:
//  access is also provided to the current user through RaveSocial
RaveUser currentUser = RaveSocial.usersManager.getCurrent();
String raveID = currentUser.getRaveId();

if (! currentUser.isGuest()) {
    //  perform some action if the user is or isn't a guest account
    String bfId = currentUser.getThirdPartyId();
    String fbId = currentUser.getFacebookId();
    // etc.
}

Finding Users#

Find a user by email

RaveSocial.usersManager.fetchUser(RaveUserReference.byEmail(email), new RaveUsersManager.RaveUserListener() {
    @Override
    public void onComplete(RaveUser user, RaveException exception) {
        if (exception != null) {
            // handle exception
            return;
        }
        // view, request friend, follow, block, unblock, etc
    }
});

Find a user by username

RaveSocial.usersManager.fetchUser(RaveUserReference.byUsername(username), new RaveUsersManager.RaveUserListener() {
    @Override
    public void onComplete(RaveUser user, RaveException exception) {
        if (exception != null) {
            // handle exception
            return;
        }
        // view, request friend, follow, block, unblock, etc
    }
});

Find a user by Rave ID

RaveSocial.usersManager.fetchUser(RaveUserReference.byRaveId(raveId), new RaveUsersManager.RaveUserListener() {
    @Override
    public void onComplete(RaveUser user, RaveException exception) {
        if (exception != null) {
            // handle exception
            return;
        }
        // view, request friend, follow, block, unblock, etc
    }
});

Blocking Users#

Block a user

RaveSocial.usersManager.blockUser(userReference, new RaveCompletionListener() {
    @Override
    public void onComplete(RaveException exception) {
        if (exception != null) {
            // handle exception
            return;
        }
    }
});

Unblock a user

RaveSocial.usersManager.unblockUser(raveId, new RaveCompletionListener() {
    @Override
    public void onComplete(RaveException exception) {
        if (exception != null) {
            // handle exception
            return;
        }
    }
});

List blocked users

RaveSocial.usersManager.fetchBlockedUsers(new RaveUsersManager.RaveUsersListener() {
    @Override
    public void onComplete(List<RaveUser> users, RaveException exception) {
        if (exception != null) {
            // handle exception
            return;
        }
    }
});

Two-Factor Authentication#

Rave’s two-factor authentication system is set up to work automatically with google’s Authenticator application. Rave offer’s three interfaces to implement in the RaveTwoFactorAuthenticationManager class.

RaveTwoFactorAuthenticationPolicy#

The two-factor autentication policy interface can be passed into the activation, deactivation, and challenge methods of the two-factor authentication manager class. It contains a single method to let Rave know what code the user entered from their authenticator application.

Attention

These policies are typically implemented and set at a native scene pack level, even when working with Unity projects.

In addition to the policies, two-factor authentication must be enabled for your application in the Rave portal for a user to be presented with a 2FA challenge when authenticating.

public interface RaveTwoFactorAuthenticationPolicy {
    /**
     * The listener is called after a user inputs a challenge code, this code is then sent back to the Rave server for verification.
     */
    interface RaveTwoFactorAuthenticationListener {
        void onComplete(String code);
    }
    /**
     * This method provides a structure for customization of two-factor authentiction flow. This can be implemented and set for activation, deactivation, or challenging a user on login.
     *
     * When implementing a custom activation, deactivation, or challenge policy, you can override the default UI that is shown to the user.
     * A default policy is provided that uses basic system UI for inputting the code they retrieve from the device.
     *
     * @param listener The UI should pass back the code the user enters in this callback for the manager to use.
     */
    void onPresentChallenge(RaveTwoFactorAuthenticationListener listener);
}

This policy can be implemented and passed into manager to show what UI is presented to the user when receiving a 2FA challenge, and allow them to enter a code that they can retrieve from their authenticator app.

There are three different policies that need to be set, and the same implementation can be used for all of them.

Activation Policy#

You can set the activation policy by calling:

RaveSocial.twoFactorAuthenticationManager.setActivationPolicy(new SomeTwoFactorAuthenticationActivationPolicy());

This activation policy is what will be presented to the user when they start the enableTwoFactorAuthentication, which is initiated when the following is called.

RaveSocial.twoFactorAuthenticationManager.enableTwoFactorAuthentication(new RaveTwoFactorAuthenticationManager.RaveActivationListener() {
    @Override
    public void onComplete(List<String> backupCodes, RaveException error) {
        if(error != null) {
            // Handle error
            return;
        }
        // Notify user to store list of backup codes in a safe place.
    }
});

This does several things. First, it retrieves a link and secret that is used to deep-link into the Google authenticator application and add the account to the list, all the user has to do from here is make a note of the code and input it in the dialog when navigating back to your application. As it does this, it also opens the dialog that is configured in the RaveTwoFactorAuthenticationPolicy that is set for the activation policy.

Deactivation Policy#

You can set the deactivation policy by calling:

RaveSocial.twoFactorAuthenticationManager.setDeactivationPolicy(new SomeTwoFactorAuthenticationDeactivationPolicy());

This deactivation policy is what will be presented to the user when attempting to remove 2FA from the users account, which is done via the following:

RaveSocial.twoFactorAuthenticationManager.disableTwoFactorAuthentication(new RaveCompletionListener() {
    @Override
    public void onComplete(RaveException exception) {
        if(exception != null) {
            // Handle error
        }
    }
});

Upon entering the code, two-factor authenticaiton will be removed from the account.

Challenge Policy#

The challenge policy is responsible for UI that will be displayed to the user when attempting to authenticate after enabling two-factor authentication for the account. It can be set with the following:

RaveSocial.twoFactorAuthenticationManager.setChallengePolicy(new SomeTwoFactorAuthChallengePolicy());

URL Handler#

There is also a URL handler interface that must be implemented to customize what is done when Rave receives a URL and secret for a user. The recommended flow is to open the URL in the native way, so that the user is directed to the Google authenticator application automatically. It can be encoded in a QR code as well, or allow for customization of UI to allow the user to navigate to the application themselves.

Friends and Followers#

Note

Friends and Followers functionality is currently under deprecation. Please contact the Rave Social support representative for additional info.

Rave Social has an advanced in-game social graph management system which makes it easy to establish connections between users to create a social graph around your apps. Rave supports both Friends (private, or two-way) and Followers (public, or one-way) relationship models, and the Friends lists and Followers lists can be configured to be app-specific, or shared across several apps.

Both relationship models use similar APIs and concepts but have key differences in how relationships are established and maintained.

Friends#

Friends are two-way relationships between users, which require one person to send a Friend request, and the other to accept that request to establish the relationship. A user can send a friend request to any other user and they may either accept or reject the request.

Followers#

Followers are one-way relationships between two users. A user can follow any other user without the requirement to first send them a request. It is possible for the other user to reciprocate and also follow the first user, but in a reciprocating following relationship, where two users follow each other, the outcome is still two independent relationships and not a Friend relationship. The only way to get a Friend, or two-way relationship is to use the Friends model.

Lists#

Every app in the Rave system can use one or more lists of Friends and Followers. By default Rave generates one list of Friends and one list of Followers at the time a Rave application is created. These lists are private to that app. Rave also creates global Friends and Follower lists, which are accessible to all of a publisher’s apps. A developer can create any number of custom lists on top of these four lists for their application. Every list can be either a Followers or Friends list, but not both. Lists are created in the Rave portal. Lists are independent - adding friends or followers for a user to a list does not add those relationships in any other list.

Scopes#

Each list is assigned a specific scope. Scope can be either Global or Application. A globally-scoped list is read-write permission across all applications for the publisher. Application-scoped lists are only accessible to a specific application. Other applications cannot access an application-scoped list that is not created for them.

Querying#

In order to get the most up to date list of relationships for a given list, each lists must be individually synced from the server to the client via a call to update* in the associated feature manager in the Rave SDK. To sync Friends, you would call the updateFriendsList method in RaveFriends. Once a list is synced, it can be queried in a number of ways using the query builder methods provided by the feature manager. To start a query in a Friends list, you would call the friendsListQuery method in RaveFriends, or to start a query in a Followers list, you would call the followersListQuery or followingListQuery in the RaveFollowersManager. Queries enable modern user experiences, such as autocomplete, partial data searches and pagination.

Friends and Followers classes#

RaveFriends / RaveFriendsManager - Provides all friends feature functions.

RaveFriend - A friend

RaveFollowers / RaveFollowersManager - Provides all follower/following feature functions.

RaveFollower - A follower or followee

ListQueryBuilder - A query builder which provides a list of friends or followers

SearchQueryBuilder - A query builder which provides a search filter within a ListQueryBuilder

Friends and Followers examples#

Update list of friends#

RaveSocial.friendsManager.updateFriendsList(listKey, new RaveCompletionListener() {
    public void onComplete(RaveException exception) {
        if (exception != null) {
            // handle error condition for updating the list
        } else {
            // handle the successful update of the list
        }
    }
});

Query all friends in list#

RaveSocial.friendsManager.friendsListQuery(listKey).get();

Query some friends in list#

This will query 5 friends starting at offset 10 in order of display name

RaveSocial.friendsManager.friendsListQuery(listKey).orderBy(RaveRelationship.ORDER_BY.DISPLAY_NAME).offset(10, 5).get();

Find user to request#

final RaveUserReference userReference = RaveUserReference.byEmail("myfriend@gmail.com");
RaveSocial.usersManager.fetchUser(userReference, new RaveUsersManager.RaveUserListener() {
        @Override
        public void onComplete(RaveUser user, RaveException exception) {
                if (exception != null) {
                        // show error message
                        return;
                }
                // send request, follow, block, etc
        }
});

Send friend request#

RaveSocial.friendsManager.sendFriendRequest(listKey, userReference, new RaveCompletionListener() {
        @Override
        public void onComplete(RaveException exception) {
                if (exception != null) {
                        // show error message
                        return;
                }
                // success!
        }
});

Accept friend request#

RaveSocial.friendsManager.acceptFriendRequest(listKey, raveId, new RaveCompletionListener() {
        @Override
        public void onComplete(RaveException exception) {
                if (exception != null) {
                        // show error message
                        return;
                }
                // success!
        }
});

Reject friend request#

RaveSocial.friendsManager.rejectFriendRequest(listKey, raveId, new RaveCompletionListener() {
        @Override
        public void onComplete(RaveException exception) {
                if (exception != null) {
                        // show error message
                        return;
                }
                // success!
        }
});

Update list of followers#

RaveSocial.followersManager.updateFollowersList(listKey, new RaveCompletionListener() {
        @Override
        public void onComplete(RaveException exception) {
                if (exception != null) {
                        // show error message
                        return;
                }
        }
});

Query followers#

RaveSocial.followersManager.followersListQuery(listKey).get();

Follow user#

RaveSocial.followersManager.followUser(listKey, userReference, new RaveCompletionListener() {
        @Override
        public void onComplete(RaveException exception) {
                if (exception != null) {
                        // show error message
                        return;
                }
                // success!
        }
});

Unfollow user#

RaveSocial.followersManager.unfollowUser(listKey, raveId, new RaveCompletionListener() {
        @Override
        public void onComplete(RaveException exception) {
                if (exception != null) {
                        // show error message
                        return;
                }
                // success!
        }
});

Account Conflict Resolution#

Attention

To avoid unwanted conflicts it is critical that each app in your portfolio uses a consistent business mapping with Facebook . If incorrectly configured users that could be identified as the same across your portfolio will be misidentified as different users potentially leading to account conflicts later.

There are two types of conflicts that can occur when attempting to attach credentials to a Rave account. In the simpler case where different credentials of the same kind are already associated with current account the user will be offered the opportunity to use the new credentials instead. In the case where the credentials are already associated with a different Rave account several things can happen depending on your integration:

  1. The default configuration will prompt the user to contact support.

  2. The next option is to configure RaveSettings.General.AllowForceDisconnect to true. This will prompt the user to confirm that the current credentials should be forcably connected to the current user and removed from the old user.

  3. Finally if the integration has set a merge policy then it will give you the opportunity to let the user choose whether or not to merge the current user with the user that already has these credentials associated. If so the current user will be merged into the foreign user. This cannot be undone and has implications across your portfolio so please consider carefully how best to implement this policy.

Rave supplies a default merge policy with your scene pack that provides a user merge dialog that you can customize or replace but you must explicitly set the provided policy as the current policy. By default no policy is set so merging is disabled.

Transitioning from Rave ID as a Save Game/Cloud Storage ID#

In the past you may have used Rave ID as a means to index user data stored on your own servers. There are downsides to this approach that you may have encountered including Rave ID changing for the current user. To create a more stable environment for data indexing we have created Application Data Keys.

Save Game/Cloud Storage ID with App Data Keys#

AppDataKeys provides a stable index for a given Rave user and application giving you the same key under most scenarios regardless of account changes. In the typical scenario the user’s Rave ID would be the index and would remain stable over the life of the application. Common scenarios include:

* Server-stored savegame keys
* Cloud storage indexing
* Any application data which can be accessed via a RaveID

When a merge between two accounts that have active sessions for your application should happen AppDataKeys provides an easy mechanism to resolve which key should be used to continue by giving your application a list of the possible index candidates. Your application can take that list, find indentifying information from your cloud storage and let the user choose or you can automatically chooose for them. For more information on AppDataKeys see Using App Data Keys for Save Game or Cloud Storage ID and AppDataKeys API.

Adding a Facebook (or other social provider) button to your App#

Using controllers#

Added in Rave 3.01, controllers implement common logic using a few APIs available in the Rave SDK in a way that makes it easy to attach an in-game button with just a thin layer connecting your UI with a Rave controller.

Contacts#

Adding Friends from Contacts Providers#

As a user connects to a social network, like Facebook, Rave automatically finds your friends that use Rave. No additional integration work is necessary. In the particular case of Facebook, when the Rave client notices that your Facebook friends have changed it will update your Rave friends through the backend. All of this is taken care of for you automatically once you have successfully logged in using Facebook, or some other authentication provider. A user’s phonebook will also automatically be searched for Rave friends when they are first logged in.

Rave Social’s contacts API allows the developer to manage a list of contacts associated with the current user and interact with contacts from all supported social media sources as well as the local device phonebook.

Automatic Syncing#

Rave will opportunistily update contacts based on a few settings and emergent SDK usage. Upon completion of connect, if RaveSettings.General.AutoSyncFriends includes the pluginKeyName for the social provider you’re using then, your contacts will sync automatically. Otherwise automatic syncing will be performed when updating contacts caches no more often than the time interval specified by RaveSettings.General.AutoSyncInterval.

RaveContact#

This class implements a single Rave contact. A Rave contact is stored on the server and can be retrieved using the RaveContactsManager. The Rave API will attempt to associate a contact on the server with an existing Rave user. Social networks associated with a Rave account will be used to automatically fetch the user’s friends. Those friends that have an associated Rave account are added as contacts.

In addition to Rave contacts stored on the server, a social network can also be used to temporarily fetch a list of the user’s friends. These are known as external contacts and are only available as a result set from a fetch operation. They are not sent or stored on the server, but can be used locally by the application.

Both Rave contacts and external contacts contain the following information, if available:

RaveId - Unique identifier for the user within the Rave API. If the Rave backend server is able to, it will associate contacts with existing Rave users. If the contact is an external contact, this function will return null

DisplayName - A contact’s chosen display name. Usually obtained from the source of the contact (FB, Google, etc…)

PictureURL - A URL to the contact’s profile picture

Source - A list of external sources where the contact was found or imported from. Sources include Rave, Facebook, Google, Phonebook, and Third Party

ThirdPartySouce - Name of the third party source this contact originated from. A third party source is typically customer-specific, and outside the standard list of supported social networks

Key - Unique identifier for the contact, even if the contact is an external contact and not associated with a Rave user

RaveContacts#

This class provides static, easy to use references to all functions in the RaveContactsManager.

RaveContactsManager#

This class implements all functions related to managing contacts in the Rave API. The manager stores contacts in a local cache that can be retrieved using the get family of functions. Before the local cache is used, it should first be updated, by retrieving information from the server, using the update family of functions. After the first update, contacts information can be quickly retrieved from the cache and updated from the server only as needed.

Contacts can be deleted from the Rave backend server and added in a few different ways:

  • Manually added by username. Username is any arbitrary string that is used to identify the contact. In other sources, the username can also be an email address.

  • Manually added by email, marked as a phonebook contact. Source of contact is set to phonebook.

  • Automatically sync contacts from the local phonebook to Rave.

  • Automatically sync contacts from Facebook to Rave.

In addition to Rave contacts, the RaveContactsManager can also “fetch” external contacts from Facebook, Google, and third party contact providers. This retrieves a list of contacts from the specified social network or third party, but does not store them on the server. This list can then be used for sharing, recommending, and gifting.

For get, update, and fetch, contacts can be filtered by All, Using current application, and Not using current application.

Attention

As of Facebook Graph API 2.0, Facebook will only return friends already using the current application instead of a full list of the user’s friends.

Usage Examples

Update and get a list of all of the current user’s contacts:

RaveSocial.contactsManager.updateAll(new RaveCompletionListener() {
    @Override
    public void onComplete(RaveException e) {
        if (exception == null) {
            for (RaveContact contact : RaveSocial.contactsManager.getAll()) {
                // Process contacts here
            }
        }
    }
});

Fetch a list of contacts from all attached social networks and filter them for only users already using the app. Then process each contact differently depending on if they are a Facebook or Google contact.

RaveSocial.contactsManager.fetchExternalFromAll(RaveContactsFilter.INCLUDE_ONLY_USING_APP, new RaveContactsListener() {
    @Override
    public void onComplete(List<RaveContact> contacts, RaveException exception) {
        if (exception == null) {
            for (RaveContact contact : contacts) {
                if(contact.isFacebook()) {
                    // Process Facebook external contacts
                } else if(contact.isGoogleIdentity()) {
                    // Process Google external contacts
                }
            }
        }
    }
});

Common Contacts Examples#

List All Contacts in One Pass#

RaveSocial.contactsManager.updateAll(new RaveCompletionListener() {
    @Override
    public void onComplete(RaveException exception) {
        if (exception != null) {
            // handle error
        }
        // process contacts through RaveSocial.contactsManager.getAll()
    }
});

Accessing the Cached Contacts#

Most update operations have a corresponding get that returns cached data

List<RaveContact> cachedContacts = RaveSocial.contactsManager.getAll();
// process cached contacts

Similarly you can call getFacebook/updateFacebook, getAllUsingThisApplication/ updateAllUsingThisApplication to update your Facebook friends and friends who are using this application respectively.

Getting a Random Selection of Contacts From the Game Community#

RaveSocial.usersManager.fetchRandomUsersForApp(appUuid, new RaveUsersListener() {
    public void onComplete(List<RaveUser> userPool, RaveException exception) {
        if (exception != null) {
            //  handle error condition
        } else if (userPool != null && userPool.size() > 0) {
            for (RaveUser user : userPool) {
                // display the user
                String displayName = user.getDisplayName();
                //  save the raveId for later
                String raveId = user.getRaveId();
                // potentially call addContactById later
            }
        }
    }
});

Adding a Contact#

RaveSocial.contactsManager.addContactsByUsername(usernames, new RaveCompletionListener() {
    public void onComplete(RaveException exception) {
        if (exception != null) {
            // handle error condition for adding the contact
        } else {
            // handle the successful addition of a contact
        }
    }
});

Blocking a Contact#

RaveSocial.contactsManager.deleteContact(raveId, new RaveCompletionListener() {
    public void onComplete(RaveException exception) {
        if (exception != null) {
            // handle error condition for removing the contact
        } else {
            // handle the successful removing of a contact
        }
    }
});

Updating Contacts#

RaveSocial.contactsManager.updateAll(new RaveCompletionListener() {
    public void onComplete(RaveException exception) {
        if (exception != null) {
            // handle error condition for updating the contacts
        } else {
            // process contacts with RaveSocial.contactsManager.getAll(), filter by any of the RaveContact fields,
            // including FB, Google, ThirdParty, etc
        }
    }
});

Login and Cross-App Login#

Rave makes it easy to provide a little-to-no-typing login experience for players of Big Fish games.

A game developer can integrate a built-in Big Fish branded Player Login experience (see Player Login Experience for details), or use Rave’s Login APIs for directly logging into services like Facebook, BFID and Google and create a completely custom login experience. See Directly Logging In to Authentication Providers section for details on the APIs

Once the player logs into one of Big Fish’s games on a given device, Rave will automatically log the player into other games. In order to do this Rave, stores some information about the player’s identity on the device and enables each subsequent Big Fish game the player opens on the device to access that information to seamlessly log the player into the game.

Logging out in any game, and reopening the game doesn’t cause the player to automatically log in.

For testing purposes Rave SDK provides a CAL (cross app login) tool as part of the SDK package. This tool allows the person testing the game and Rave SDK integration to use the tool to delete the CAL data from the phone, therefore disabling auto login functionality. Explicitly logging into any app recreates the CAL data, and stores it in the same place.

For more information on the CAL tool, see the Using the CAL tool section.

Android API 23 compatibility#

As of Android API level 23, runtime permissions are required for the Rave cross-app login feature to operate correctly. Rave fully supports runtime permissions with additional APIs. To use new API 23 support, set the android:targetSdkVersion in your manifest to 23 or above. A setting of 22 or lower will continue to use the install-time permission model of previous versions of Android.

Big Fish Games has a permission request flow which is accessible via a single API, BigFishScenePack.checkCrossAppLogin(). Call this after Rave is initialized and after your app activity has started.

BigFishScenePack.checkCrossAppLogin(new RaveCompletionListener() { ... });

To collect events for analytics on the API 23 flow, simply add a listener using BigFishScenePack.registerCALEventListener(BigFishScenePack.BFCALEventListener listener):

BigFishScenePack.registerCALEventListener(new BigFishScenePack.BFCALEventListener() {
                @Override
                public void onEvent(String eventKey) {
                        Log.i(TAG, "CAL Event " + eventKey);
                }
});

The CALEventListener will provide on of these eventKeys, available as constants in BigFishScenePack:

public static final String BF_CAL_EVENT_PROMPT_1_OKAY = "Prompt1_Okay";
public static final String BF_CAL_EVENT_PROMPT_1_NOTNOW = "Prompt1_NotNow";
public static final String BF_CAL_EVENT_PROMPT_2_OKAY = "Prompt2_Okay";
public static final String BF_CAL_EVENT_PROMPT_2_DONTSHOWAGAIN = "Prompt2_DontShowAgain";
public static final String BF_CAL_EVENT_PROMPT_3_OKAY = "Prompt3_Okay";
public static final String BF_CAL_EVENT_PROMPT_3_EXPLAIN = "Prompt3_Explain";
public static final String BF_CAL_EVENT_PERMISSION_REQUEST_1_GRANT = "Request1_Grant";
public static final String BF_CAL_EVENT_PERMISSION_REQUEST_1_DENY = "Request1_Deny";
public static final String BF_CAL_EVENT_PERMISSION_REQUEST_2_GRANT = "Request2_Grant";
public static final String BF_CAL_EVENT_PERMISSION_REQUEST_2_DENY = "Request2_Deny";

Achievements#

Rave Social’s achievements API allows the developer to retrieve and unlock achievements associated with the current game and user. Achievements are defined using the Rave portal.

Note

In order to use achievements in your application, you must define your achievements in the Rave Developer Portal. See the Achievements section in the portal documentation for instructions on how to create acheivements.

RaveAchievement#

This class implements a single Rave achievement, containing information about the achievement and the current user’s progress on it (locked or unlocked). The following fields are stored and accessible with a RaveAchievement:

Key - A unique key identifying the achievement

Name - A display name used when showing the achievement

Description - A longer form description of the achievement

ImageUrl - A URL to the icon or image representing this achievement

Unlocked - Whether or not the current player has unlocked (completed the requirements for) this achievement

RaveAchievements#

This class provides static, easy to use references to all functions in the RaveAchievementsManager.

RaveAchievementsManager#

This class implements all functions related to retrieving information about achievements in the Rave API. The manager stores achievements in a local cache that can be retrieved using the “get” family of functions. Before the local cache is used, it should first be updated by retrieving information from the server using the “update” family of functions. After the first update, achievements information can be quickly retrieved from the cache and updated from the server only as needed.

Common Achievements Examples#

List All Achievements#

RaveSocial.achievementsManager.updateAchievements(new RaveCompletionListener() {
    @Override
    public void onComplete(RaveException exception) {
        if (exception != null) {
            // handle error
        }
        // process achievements through RaveSocial.achievementsManager.getAchievements()
    }
});

Accessing the Cached Achievements#

Most update operations have a corresponding get that returns cached data

List<RaveAchievement> cachedAchievements = RaveSocial.achievementsManager.getAchievements()
// process cached achievements

Mark an Achievement as Unlocked#

Unlocking an achievement indicates that the current user has completed all requirements to obtain the specified achievement. An achievement is referenced by a string of its unique key

RaveSocial.achievementsManager.unlockAchievement(achievementKey, new RaveCompletionListener() {
    @Override
    public void onComplete(RaveException exception) {
        if (exception != null) {
            // handle error
        }
        // display message indicating successfully unlocked achievement
    }
});

Leaderboards#

The Rave Social leaderboards system allows for various ways to organize and access high score data for your users. The system is designed to not access the server until you tell it to update, caching the last accessed data until then for optimal performance that is customizable to any use case or connectivity situation. Note that when in anonymous mode, you cannot submit scores to leaderboards and leaderboards will not display your scores in them. Also, when you request adjacent scores for a user that doesn’t have a score you will receive data as if their score is the worst possible.

Note

In order to use leaderboards in your application, you must define your leaderboards in the Rave Developer Portal. See the Leaderboards and Tournaments / Timed Leaderboards section in the portal documentation for instructions on how to create leaderboards.

Leaderboards Concepts#

  • Sorter - The order of a given Leaderboard amongst other Leaderboards. The leaderboard designated “1” for Sorter will be shown first in a list of leaderboards, etc.

  • Is Ascending - sort order of what the best score is. Used to determine if a new score is best.

  • High Score - score for this leaderboard

  • Global Position - ranking over all users

  • Friends Position - ranking over just the user’s group of friends

Tournaments, or Timed Leaderboards#

Leaderboards can be reset on a given interval, such as hourly, daily, weeklu and monthly. They can also start and end on a given pre-defined schedule.

For information on how to configure a leaderboard reset interval and start and end date, see the Rave Developer Portal, Leaderboards and Tournaments / Timed Leaderboards section.

Android Leaderboard Examples#

Updating and Getting Leaderboards#

You can work with leaderboards and their scores after updating them at least once from the server. It is up to you how often you want to ask the server for updates beyond the first time. After the first call, even if the app is closed and reopened, cached information will be used until the next update request.

RaveSocial.leaderboardsManager.updateLeaderboards(new RaveCompletionListener() {
    @Override
    public void onComplete(RaveException e) {
        if (e != null) {
            // handle exception
        } else {
            List<RaveLeaderboard> leaderboards = RaveSocial.leaderboardsManager.getLeaderboards();

            //  you can get specific leaderboards
            RaveLeaderboard leaderboard = RaveSocial.leaderboardsManager.getLeaderboard("myLeaderboardKey");
        }
    }
});

Submitting Scores to a Leaderboard#

RaveSocial.leaderboardsManager.submitScore("myLeaderboardKey",234042,new RaveCompletionListener() {
    @Override
    public void onComplete(RaveException e) {
        if (e == null) {
            // score submitted OK
        }
    }
});

Getting the High Score and Position#

Before you can examine your score you will have to update the leaderboard for which you want detailed information:

// you can also update or get single leaderboards instead of all of them
RaveSocial.leaderboardsManager.updateLeaderboard("myLeaderboardKey", new RaveCompletionListener() {
    @Override
    public void onComplete(RaveException e) {
        if (e != null) {
            // handle exception
        } else {
        }
    }
});

You can easily get the high score and your ranking in a leaderboard: either globally or amongst your friends

RaveLeaderboard leaderboard = RaveSocial.leaderboardsManager.getLeaderboard("myLeaderboardKey");
Integer highScore = leaderboard.getHighScore();
Integer globalPosition = leaderboard.getGlobalPosition();
Integer friendsPosition = leaderboard.getFriendsPosition();

Note: these values will be null if you have not submitted a score

Getting Lists of Scores#

Since leaderboards for games can contain thousands of entries, there are various ways to get subsections of a given leaderboard. Each method has two versions: the global scores version and the scores just amongst your friends

Getting Scores By Absolute Page#

You can get scores in strict pages by specifying the page you want and the number of entries you want in each page. You can access the scores after calling the proper update function.

// for global scores
RaveSocial.leaderboardsManager.updateGlobalScores("myLeaderboardKey",1,10,new RaveCompletionListener() {
    @Override
    public void onComplete(RaveException e) {
        if (e == null) {
            List<RaveScore> scores = RaveSocial.leaderboardsManager.getGlobalScores("myLeaderboardKey",1,10);
        }
    }
});

// for scores amongst friends only
RaveSocial.leaderboardsManager.updateFriendsScores("myLeaderboardKey",1,10,new RaveCompletionListener() {
    @Override
    public void onComplete(RaveException e) {
        if (e == null) {
            List<RaveScore> scores = RaveSocial.leaderboardsManager.getFriendsScores("myLeaderboardKey",1,10);
        }
    }
});

Getting Scores By Nearby Page#

You can get the page of scores closest to the user’s high score

// for global scores
RaveSocial.leaderboardsManager.updateMyGlobalScores("myLeaderboardKey",10,new RaveCompletionListener() {
    @Override
    public void onComplete(RaveException e) {
        if (e == null) {
            List<RaveScore> scores = RaveSocial.leaderboardsManager.getMyGlobalScores("myLeaderboardKey",10);
        }
    }
});

// for scores amongst friends only
RaveSocial.leaderboardsManager.updateMyFriendsScores("myLeaderboardKey",10,new RaveCompletionListener() {
    @Override
    public void onComplete(RaveException e) {
        if (e == null) {
            List<RaveScore> scores = RaveSocial.leaderboardsManager.getMyFriendsScores("myLeaderboardKey",10);
        }
    }
});

Getting Scores Adjacent to the User Score#

You can get the scores nearest to a given user’s high score after you call the update function

// for global scores the 15 scores before and 15 scores after the user, if available
RaveSocial.leaderboardsManager.updateMyGlobalScoresAdjacent("myLeaderboardKey",10,new RaveCompletionListener() {
    @Override
    public void onComplete(RaveException e) {
        if (e == null) {
            List<RaveScore> scores = RaveSocial.leaderboardsManager.getMyGlobalScoresAdjacent("myLeaderboardKey",10);
        }
    }
});

// for scores amongst friends only, 15 before and 15 after the user, if available
RaveSocial.leaderboardsManager.updateMyFriendsScoresAdjacent("myLeaderboardKey",10,new RaveCompletionListener() {
    @Override
    public void onComplete(RaveException e) {
        if (e == null) {
            List<RaveScore> scores = RaveSocial.leaderboardsManager.getMyFriendsScoresAdjacent("myLeaderboardKey",10);
        }
    }
});

Getting Scores For Leaderboard From Previous Reset Intervals (ie. last week’s tournament)#

For leaderboards that have a defined Reset Frequency you might want to access the scores from a previous reset period

// Build leaderboard request. Set version to the leaderboard version you wish to retrieve.
RaveLeaderboardsRequest request = new LeaderboardsRequestBuilder().key("myLeaderboardKey").page(1).pageSize(50).version(1).update(true).build();
List<RaveScore> scores = RaveSocial.leaderboardsManager.getLeaderboardScores(request);

Sharing#

The Rave Social gifting system provides ways to get your game in front of new users via gifts and app sharing. By allowing players to send gifts to friends that have yet to install the game, Rave Social can incentivize new users to join in on the fun. Here is an overview of the sharing and promotion system.

Social networks, such as Facebook, provide a feature called a “Request” which, when used, will notify the recipient that their friend has requested them to join them by installing the app the request originated from. Rave integrates this feature along with Facebook and Google contact queries (known as external contacts) in a way that makes it extremely easy to add requests into your game, tie them to a gift, incentivize the social connection and award a gift to a new user. It’s important to note that to receive a gift, the new user must login using the same service that was used for the share. Rave keeps track of which pending gifts are associated with which external users (such as which Facebook user) and can only associate the new user once they have connected or logged in with that service.

Note

In order to use gifts or requests in your application, you must define your gifts that can be given or requested in the Rave Developer Portal. See the Gifts section in the portal documentation for instructions on how to create gifts.

Sharing Flow#

The process is:

  • Sender: Get a list of external contacts

  • Sender: Call the share with gift API

  • Recipient: Check to see if the app was ran from an external link and if a gift is available upon connection of an authentication provider

  • Recipient: Connect using the authentication provider

Sender: Getting the Contacts#

First we get a list of potential contacts the user could choose to send a Gift Share to. We can find contacts via all known contact providers, or just the provider the user logged in to Rave Social with

RaveSocial.contactsManager.fetchExternalFrom(RaveConstants.CONNECT_PLUGIN_FACEBOOK, RaveContactsFilter.INCLUDE_ALL, new RaveContactsListener() {
    @Override
    public void onComplete(List<RaveContact> contacts, RaveException exception) {
        if (exception != null) {
            // handle exception
        } else {
            // iterate the contacts
        }
    }
});

// or

RaveSocial.contactsManager.fetchExternalFromAll(RaveContactsFilter.INCLUDE_ALL, new RaveContactsListener() {
    @Override
    public void onComplete(List<RaveContact> contacts, RaveException exception) {
        if (exception != null) {
            // handle exception
        } else {
            // iterate the contacts
        }
    }
});

Sender: Sending the Gift Share#

There are a few ways to send a gift in Rave, but the main method used for user acquisition gifting is:

RaveSocial.giftsManager.sendGiftWithKeyToContactsAndShareVia(RaveConstants.CONNECT_PLUGIN_FACEBOOK, "life", contacts, "", "I just smashed my friends, can you beat it?", true, new RaveGiftAndShareResultListener() {
    @Override
    public void onComplete(List<RaveShareRequest> requests, List<RaveContactGiftResult> giftResults, RaveException exception) {
        if (exception != null) {
            // handle exception
        } else {
            // process results or handle success case
        }
    }
});

// or

RaveSocial.giftsManager.sendGiftWithKeyToContactsAndShare("life", contacts, "", "I just smashed my friends, can you beat it?", true, new RaveGiftAndShareResultListener() {
    @Override
    public void onComplete(List<RaveShareRequest> requests, List<RaveContactGiftResult> giftResults, RaveException exception) {
        if (exception != null) {
            // handle exception
        } else {
            // process results or handle success case
        }
    }
});

Receipient: Checking for the Gift Share#

Once the recipient has installed the app via the share link, you can check to see if it’s desireable to incentivize the login.

String source = RaveConstants.CONNECT_PLUGIN_FACEBOOK;
if (!RaveSocial.isProviderReady(source)) {
    RaveSocial.giftsManager.fetchGiftContentForShareInstall(source, new RaveGiftContentListener() {
    @Override
    public void onComplete(String key, String requestId, RaveException error) {
        if (requestId != null) {
            // we're here through facebook share
            if (key != null) {
                // There's a gifting pending once we login with facebook
                // Toast.makeText(Activity.this, "Gift pending for FB Request ID " + requestId, Toast.LENGTH_SHORT).show();
            } else {
                // Toast.makeText(Activity.this, "FB Request ID " + requestId, Toast.LENGTH_SHORT).show();
            }
        }
    }
    });
}

Receipient: Connecting to an authentication provider#

Log the user in to the authentication provider for the first time and a new Rave user will be created. New user acquired!

new RaveLoginScene().show();

// or

RaveSocial.connectTo(RaveConstants.CONNECT_PLUGIN_FACEBOOK, new RaveCompletionListener() {
    @Override
        public void onComplete(RaveException exception) {
    }
});

Gifting and Requests#

The Rave Social gifting system allows for players across social environments to interact in a tangible way that can either be used as just a social tool or as a monetizable or incentivized feature in your game. Players can request a gift from another player, which gives that player an opportunity to send back a gift. Gifts may be accepted or rejected by the recipient.

Gifting Concepts#

  • Gift Type - Any conceptual thing a user can give to another (life, heart, money, etc)

  • Gift Request - A request from one user to another asking for a gift

  • Gift - An instance of a gift type which can be accepted or rejected by the recipient

-.. note:: - In order to use gifts or requests in your application, you must define your gifts that can be given or requested in the Rave Developer Portal. See the Gifts section in the portal documentation for instructions on how to create gifts.

Android Gifting Examples#

Get Gift Types#

RaveSocial.giftsManager.updateGiftTypes(new RaveCompletionListener() {
    @Override
    public void onComplete(RaveException e) {
        if (e != null) {
            // handle exception
        } else {
            List<RaveGiftType> giftTypes = RaveSocial.giftsManager.getGiftTypes();
        }
    }
});

// you can also get gift types by their name
RaveGiftType type = RaveSocial.giftsManager.getGiftTypeByName("myGiftTypeKey");

Get Gifts#

RaveSocial.giftsManager.updateGifts(new RaveCompletionListener() {
    @Override
    public void onComplete(RaveException e) {
        if (e != null) {
            // handle exception
        } else {
            List<RaveGift> gifts = RaveSocial.giftsManager.getGifts();
        }
    }
});

Send Gift#

You can send a gift to other users of the same game, with a limit of 20 users per send call.

RaveSocial.giftsManager.sendGiftWithKeyToUsers(type.getKey(), userIds, new RaveGiftResultListener() {
    @Override
    public void onResult(List<String> succeeded, List<String> failed, List<String> errors, RaveException e) {
        if (e != null) {
            // handle exception
        } else {
            // optional - handle list of success and failed requests
        }
    }
});

You can bulk send gifts using the gift’s name as well. You can send to a list of user IDs, or contacts. Note that in the list of contacts version the users can be on external social networks such as Facebook

RaveSocial.giftsManager.sendGiftWithKeyToUsers("myGiftTypeKey", listOfUserIds, new RaveGiftResultListener() {...});
RaveSocial.giftsManager.sendGiftWithKeyToContacts("myGiftTypeKey", listOfContacts, new RaveGiftResultListener() {...});

Send Gift Request#

You can request a gift from other users of the same application, with a limit of 20 users per send call.

RaveSocial.giftsManager.requestGiftWithKeyFromUsers(type.getKey(), userIds, new RaveGiftResultListener() {
    @Override
    public void onResult(List<String> succeeded, List<String> failed, List<String> errors, RaveException e) {
        if (e != null) {
            // handle exception
        } else {
            // optional - handle list of success and failed requests
        }
    }
});

Get Gift Requests#

RaveSocial.giftsManager.updateGiftRequests(new RaveCompletionListener() {
    @Override
    public void onComplete(RaveException e) {
        if (e != null) {
            // handle exception
        } else {
            List<RaveGiftRequest> requests = RaveSocial.giftsManager.getGiftRequests();
        }
    }
});

Grant/Ignore Gift Request#

RaveSocial.giftsManager.grantGiftRequestById(giftRequest.getId(), new RaveCompletionListener() {
@Override
    public void onComplete(RaveException e) {
    }
});

RaveSocial.giftsManager.ignoreGiftRequestById(giftRequest.getId(), new RaveCompletionListener() {
@Override
    public void onComplete(RaveException e) {
    }
});

Accept/Reject Gift#

RaveSocial.giftsManager.acceptGiftById(gift.getId(), new RaveCompletionListener() {
    @Override
    public void onComplete(RaveException e) {
    }
});

RaveSocial.giftsManager.rejectGiftById(gift.getId(), new RaveCompletionListener() {
    @Override
    public void onComplete(RaveException e) {
    }
});

Sharing on social networks#

You can send a gift that simultaneously shares an install request via the plugin each contact is on. Currently the only supported service is Facebook, with others coming soon

// this will share via each contact's social network
RaveSocial.giftsManager.sendGiftWithKeyToContactsAndShare("myGiftTypeKey", myListOfContacts, "Hello There!", "Gifting this to you!", true, new RaveGiftAndShareResultListener() {...});

// this will share only to contacts who are through the given plugin (here, Facebook is used)
RaveSocial.giftsManager.sendGiftWithKeyToContactsAndShareVia("Facebook", "myGiftTypeKey", myListOfContacts, "Hello There!", "Gifting this to you via Facebook!", true, new RaveGiftAndShareResultListener() {...});

If you want to handle the details of the sharing process yourself instead of using the above functions, you can use the following

// the sender of the gift attaches gifts to requests
RaveSocial.giftsManager.attachGiftWithKey("myGiftTypeKey",myRequestsArray, new RaveCompletionListener() {...});

// if the receiver of the gift is a new user, they can fetch the gift from the sharing request result
RaveSocial.giftsManager.fetchGiftKeyForExternalId(sharingRequestResult,"Facebook",new RaveCompletionListener() {...});

// then the receiver can detach the fetched gift
RaveSocial.giftsManager.detachGiftTypeForExternalId(sharingRequestResultId,"Facebook",new RaveCompletionListener() {...});

For more information regarding this process see User Acquisition Process

Chat#

_images/RaveLayer.png

About Rave and Layer Integration#

Rave Social offers chat services with an out-of-the-box integration with Layer. Sign up for the Layer add-on to allow your users to send and receive messages, subscribe to chat channels and conversations, and view user online/offline statuses.

How it Works#

  1. Let your Rave Account Manager know that you’d like to sign up for the Layer add-on

  2. We configure your Layer app for you and ensure the link between your Layer and Rave applications

  3. We will provide you a Layer URL to add to your application’s Rave configuration files for the RaveSettings.Chat.LayerURL value.

That’s it. Rave SDK wraps Layer’s messaging APIs, so now that your Layer app is configured you can use the Rave SDK to add user to user messaging to your app.

For additional documentation see: https://docs.layer.com

Localization#

Resources can be localized for a region and language using standard ISO 639-1 codes. A localized resource is one that exists in a directory named with the language code or the language-region code pair, such as “en” or “en-us”. Beyond this, resources do not need to receive any special treatment, as any resource in a locale-specific directory will override the same resource in the default resource directory.

Creating Localized Content#

Localizing your project to other languages is done with JSON files.

In /resources/default/strings.json you will see the default translation file. Here you can define what strings will be displayed for any language that doesn’t have a more specific string in its own language. Usually this JSON is used for English, but you can make this whatever you want your default language to be. The format for each row is:

"key" : "translated language string",

Let’s look at a few rows from our default version of this file:

"Create your account" : "Create your account",
"OK" : "OK",
"RSEnterEmail" : "Enter the email address you use for your account. We'll email you a temporary password. <a href='http://www.ravesocial.co/help/index.html?rn=password'>Need Help?</a>",

The text to the left of the colon shows the key of the translation. Usually this is the English term in our existing code and XML files. The text to the right of the colon shows what will be substituted. Since this is for our English speaking users, often the string is the same as the key. Note that RSEnterEmail is a key. This is showing how you can put a shorter string in your code that can be substituted with something much longer in the translation file.

Localization Example#

Now let’s create a translation of the application. To localize to a language, simply copy the strings.json file from /resources/default to /resources/XX where XX is the ISO-639-1 code for the language that you are creating your localization for. In this example, the localization is for German, which has the country code de.

Now you can edit the value for each key to be translated as shown below:

"Create your account" : "Erstelle Dein Spielekonto",
"OK" : "OK",
"RSEnterEmail" : "Gib die E-Mail-Adresse ein, die Du für Dein Spielekonto verwendest hast. Wir werden Dir ein vorübergehendes Passwort schicken. <a href='http://www.ravesocial.co/help/index.html?rn=password'>Brauchst Du Hilfe?</a>",

Attention

Ensure that the last row in your JSON dictionary does not end with a comma. Strict JSON prohibits this.

When you build and run the application and set the target device’s language as German, any strings for which there are translated values will show up in German.

Upgrading the Rave SDK#

The Rave SDK will always preserve your current user’s RaveID and credentials on upgrade.

Version-specific Upgrade Notes#

v4.2.13 Upgrade Notes#

The deprecated method RaveContacts.setPhoneBookAutoUpdate was removed. Ensure you update your code to use the phonebook plugin instead.

v4.2.0 Upgrade Notes#

  • The SDK now handles all operations, including initialization, asynchronously. To adapt to this change, ensure that your codebase can handle asynchronous operations.

  • All SDK public method callbacks now execute within the same thread as the original calls, ensuring thread safety and predictable behavior. Review your callback implementations to ensure they remain compatible with this behavior.

  • If your application uses custom connect plugins, note that token storage v3 migration method has been removed, it now happens as part of the plugin token retrieval, so remove any calls to migrateV2TokenStorage.

  • Several settings have been deprecated as of version 2.8.0 and have now been removed from the SDK. To ensure your code works with the latest version, update your settings usage as follows:

Deprecated/Removed Setting

Replacement Setting

RaveSettings.RaveAndroidUseDialogOverlay

RaveSettings.Android.DialogOverlay

RaveSettings.RaveApplicationID

RaveSettings.General.ApplicationID

RaveSettings.RaveServerURL

RaveSettings.General.ServerURL

RaveSettings.RaveAutoSyncInterval

RaveSettings.General.AutoSyncInterval

RaveSettings.RaveAutoGuestLogin

RaveSettings.General.AutoGuestLogin

RaveSettings.RaveAutoCrossAppLogin

RaveSettings.General.AutoCrossAppLogin

RaveSettings.RaveLogLevel

RaveSettings.General.LogLevel

RaveSettings.RaveAllowForceDisconnect

RaveSettings.General.AllowForceDisconnect

RaveSettings.RaveAutoInstallConfigUpdates

RaveSettings.General.AutoInstallConfigUpdates

RaveSettings.RaveNetworkTimeout

RaveSettings.General.NetworkTimeout

RaveSettings.RaveConfigUpdateInterval

RaveSettings.General.ConfigUpdateInterval

RaveSettings.RaveThirdPartySource

RaveSettings.General.ThirdPartySource

RaveSettings.RaveDefaultResourcesPath

RaveSettings.General.DefaultResourcesPath

RaveSettings.RaveAutoSendGiftOnGrantedRequest

RaveSettings.General.AutoSendGiftOnGrantedRequest

RaveSettings.RaveSceneServerHost

RaveSettings.General.SceneServerHost

RaveSettings.RaveFBApplicationId

RaveSettings.Facebook.ApplicationId

RaveSettings.RaveFBReadPermissions

RaveSettings.Facebook.ReadPermissions

RaveSettings.RaveFBAlwaysUseLiveContacts

RaveSettings.Facebook.AlwaysLiveContacts

RaveSettings.RaveIOSBundleName

RaveSettings.IOS.BundleName

RaveSettings.RaveInitGameCenterOnStartUp

RaveSettings.IOS.InitGameCenterOnStartUp

RaveSettings.RaveIOSUseIDFAForDeviceID

RaveSettings.IOS.IDFAForDeviceID

v4.1.0 Upgrade Notes#

  • Android API 34 support has been added. Ensure your project targets API 34, update dependencies, and test for compatibility.

  • We replaced Facebook publishing with Facebook Share API. If your app relied on the publishing API, please update it accordingly.

  • The Twitter integration was completely removed. Make sure to remove any code related to Twitter integration, as it is no longer supported.

  • The RaveFriends, RaveFollowers, and user blocking methods convenience classes have been deprecated. Please refactor your code to replace the usage of RaveFriends and RaveFollowers with alternative approaches for similar functionality, such as contacts v1 methods.

  • The RaveSocial’s FileCripter has been removed. If your application relied on RaveSocial’s FileCripter, implement an alternative solution for file encryption and decryption.

v4.0.0 Upgrade Notes#

We increased the Android SDK min version, make sure now your app supports at least API 19.

Some of the util classes were removed from the core SDK, if your app was relying on that, please update accordingly.

The manifest permissions were also cleaned up to reduce the amount of permissions required for the SDK to work.

The following deprecated settings has been removed:

  • RaveSettings.General.DefaultNewUserName

  • RaveSettings.RaveFBAutoUpdateContactsOnConnect (replaced by RaveSettings.General.AutoSyncFriends)

  • RaveSettings.General.PhoneContactsUpdateInterval (replaced by RaveSettings.General.ContactsUpdateInterval)

  • RaveSettings.Google.ContactsUpdateInterval (replaced by RaveSettings.General.ContactsUpdateInterval)

  • RaveSettings.Facebook.ContactsUpdateInterval (replaced by RaveSettings.General.ContactsUpdateInterval)

v3.13.1 Upgrade Notes#

We removed the dependency on android-priority-jobqueue library in favor of WorkManager, the official deferred task library for Android.

If your project had previously included com.birbit:android-priority-jobqueue dependency as a Rave dependency you can safely remove it.

Add both androidx.security:security-crypto and androidx.work:work-runtime dependencies to your build.gradle.

v3.9.15 Upgrade Notes#

  • The SDK now handles all operations, including initialization, asynchronously. To adapt to this change, ensure that your codebase can handle asynchronous operations.

  • All SDK public method callbacks now execute within the same thread as the original calls, ensuring thread safety and predictable behavior. Review your callback implementations to ensure they remain compatible with this behavior.

v3.6.1 Upgrade Notes#

We removed all the dependencies on external storage from the Rave SDK for Android. That means unless your app requires external storage for some other reason, you should be able to remove the following permissions from your AndroidManifest.xml:

<uses-permission android:name=”android.permission.WRITE_EXTERNAL_STORAGE” /> <uses-permission android:name=”android.permission.READ_EXTERNAL_STORAGE” />

v3.5.1 Upgrade Notes#

The Rave Android SDK is now packaged in Android Archive (AAR) format. Remove any Rave submodules and jars from your project and compile the Rave AAR libraires by copying them from the SDK distribution ZIP into your project’s “libs” directory and adding the following to the dependencies section of your app’s build.gradle:

dependencies {
    ...
    compile(name: "RaveSocial", ext: "aar")
    compile 'com.facebook.android:facebook-android-sdk:4.25.0'
    compile(name: "RaveFacebookPlugin", ext: "aar")
    compile 'com.google.android.gms:play-services-identity:11.0.4'
    compile 'com.google.android.gms:play-services-auth:11.0.4'
    compile 'com.google.android.gms:play-services-plus:11.0.4'
    compile(name: "RaveGooglePlugin", ext: "aar")
    compile project(':BigFishScenePack')
    ...
}

Add a “flatDir” to the repositories section so the Gradle plugin can locate “libs” directory:

repositories {
    ...
    flatDir {
        dirs 'libs'
    }
    ...
}

If your project contains submodules for Facebook or Google SDKs you can remove them and let the Android Gradle Plugin resolve them.

For Unity projects, copy the Rave AAR libaries from the distribution ZIP into Assets/Plugins/Android/, or reimport the Rave Unity asset package. The Unity demo now builds and runs from within the Unity editor using the internal Android build system. Also, the Unity demo project now includes it’s own user.keystore for Android builds. Both store and key passwords are “bfcdemo”.

v3.01 Upgrade Notes#

There are minor but sweeping changes to some basic methods in the RaveSocial API. If you’re using the scene pack as the front-end to your integration you should be largely unaffected. If, however, you’re using login and other APIs directly there are some important changes to consider.

More listeners have been simplified to RaveCompletionListener. That means that success is represented by a null result for the exception. User cancellation is now representated by an instance of RaveCanceledException. Notable instances where the listener changed are RaveSocial.loginWith(), RaveSocial.connectTo(), RaveSocial.disconnectFrom().

Constants for referring to social network providers have been changed (e.g. Constants.SOCIAL_PROVIDER_FACEBOOK is now RaveConstants.CONNECT_PLUGIN_FACEBOOK). Some methods that referred to providers in their name now refer instead to plugins to more accurately reflect the extensible nature of Rave.

v2.8 Upgrade Notes#

Considerations for upgrading the Rave SDK for an Android project include changes to a number of scene listeners, removal of the Settings Scene, and minor changes to the gifting API.

  • NOTICE: Both Google and Facebook SDKs have been updated to their respective latest versions as of July 2014.

  • LoginSceneListener and AccountInfoSceneListener - onSceneComplete() - Additional boolean parameter canceled as well as some other parameters have been added. The canceled parameter is used to determine if a scene was successfully completed or canceled/backed out of.

  • SettingsScene - This scene has been completely removed and all of its functionality has been merged into RaveAccountInfoScene, which previously inherited its functionality

  • RaveGifts.sendGiftWithKeyToContactsAndShareVia() - The interactive boolean parameter for this function has been removed. The functionality it provided has been made automatic.

Additional considerations specific to Big Fish Games are listed below.

  • BigFishActivity.reportUserPicture() - This static function has been moved from BigFishActivity, which no longer exists in the scene pack, to BigFishScenePack.java.

  • BigFishMessageAlertDialogBuilder and all other dialog classes have been removed. Built-in platform dialogs are now the standard for all BigFish dialogs.

  • BigFishDialogScene.DismissHandler.onDismiss() - Additional boolean parameter canceled has been added. This additional parameter is used to determine if a scene was successfully completed or canceled/backed out of. o

Using Facebook Tokens From Previous Non-Rave Integration#

Rave will automatically find and use an active Facebook session on startup if the session was created using the default session storage in the Facebook SDK. If the session did not use default storage, Rave provides an API which can be used to set the token to use. When using the explicit token setting method, it should only be used once so an integrator should delete the token from local storage once handed off to Rave for initialization. Either method will result in an automatic login to Rave either for the existing user linked to the Facebook account or a new Rave user will be created and linked to the Facebook account.

Explicit Token Setting Method#

Use the AuthenticationManager to get the Facebook Login Provider and set the token directly:

FacebookLoginProvider fbLoginProvider = new FacebookLoginProvider(context);
fbLoginProvider.useTokenForRaveUpgrade(myToken);
RaveSocial.addLoginProvider(fbLoginProvider);

This must be called before Rave initialization. The easiest location to set this is usually in the ScenePack class unless Rave is being used without a ScenePack.

Note

The explicit token method only works on Android for users having the Facebook app installed.

SDK Logging#

Rave Social SDK can be configured to use any log level at run-time via RaveSettings, using the setting RaveSettings.General.LogLevel.

Available log levels are:

  • Quiet - No Logging - Default

  • Error - Only Errors

  • Warn - Warnings and Errors

  • Info - Info, Warnings and Errors

  • Verbose - Verbose Messages, Info, Warnings and Errors

  • Debug - Debug Messages and all others included

You may override the default value for debugging by changing the config.json, the application manifest, or by calling:

RaveSettings.set(RaveSettings.General.LogLevel, customLogLevel);

SDK Troubleshooting#

Unable to execute dex: method ID not in [0, 0xffff]: 65536#

Android has a limit of 64k methods in the DEX file format. Please visit the section on Optimizing Android for information on how to optimize your build to work around this issue.

Google reporting “an internal error has occured” on login/connect#

Google simply toasts “an internal error has occured” when the client configuration does not correctly match the cloud configuration. Check your Google cloud configuration and match your SHA-1 package.

Using the CAL tool#

The Rave Android CAL (Cross App Login) utility provides a way to view and clear data that the SDK uses to log a user in to multiple game installations on the device. There are multiple versions of data supported which allows for CAL between newer and older integrations of Rave. The version of the CAL utility is displayed on the bottom right corner of the screen. A single button allows for all versions of data to be totally cleared. Clearing the CAL data does not affect the local app data for any installed apps and any Rave-enabled app may re-create data once used again. Clearing CAL data is intended for use in a testing environment only, though it will also work with production data.

Android CAL Utility screenshot

A screenshot of the Android CAL Utility#

SDK Caching Policy#

The RaveSocial SDK implements a common pattern of cache utilization. The SDK accesses most data from caches and only fetches data directly from the back-end service in a small number of instances.. Thus, it is important to populate the cache before certain SDK operations. To this end each API manager has a series of paired methods for each cache it implements: an accessor named get<CacheName> and a method to update the cache named update<CacheName>. In most cases accessors will give direct cache access. Update methods all take a completion callback so that you are notified when it completes and whether the update failed. For example, RaveUsersManager provides cache accessor “getCurrent” and a cache update method “updateCurrent” that follow this pattern. Some managers also have keyed lookup access so that you can more easily look up specific subsets of data. For example, RaveUsersManager’s getUserByRaveId.