Skip to main content

Getting Started

Pre-requisites

Install a Perl distribution (ie Strawberry Perl) and ensure perl.exe is in your path.

Android SDK/NDK Versions

The mod.io Android SDK is built against NDK version r25b and supports the arm64-v8a ABI. To install the correct NDK, open Android Studio, go to the SDK Manager and install the following:

  • SDK Platforms
    • Android 14.0 ("UpsideDownCake") (API 34)
  • SDK Tools (tick Show Package Details to see all these)
    • Android SDK Build Tools - 34.0.0
    • NDK - 25.1.8937393
    • Android SDK Command-line Tools - latest
    • CMake 3.22.1

Compiling for Android

Currently, the mod.io SDK can only be used from native Android applications being built with CMake on Windows. There is no support for the AGDE for Visual Studio. mod.io SDK method calls are not available from Java. You can follow the CMake Integration documentation for how to configure your native CMake project to use the SDK.

Initializing the Android SDK

Prior to initializing the mod.io SDK via Modio::InitializeAsync, you have to pass a few initialization parameters to the SDK for Android specific support.

  1. #include "ModioAndroid.h". The next three android specific function calls require this header.

  2. Pass mod.io the JNI VM, an optional reference to the global ClassLoader, and specify whether to use external storage for downloaded mods using Modio::InitializeAndroidJNI(vm, nullptr, true);. Generally you should do this in your JNI_OnLoad method.

    • If you don't provide a reference to the native classloader, the SDK will attempt to discover and create one itself.
    • The bUseExternalStorageForMods parameter (defaults to true) determines whether downloaded mods should be stored in external storage. Set this to false if you want to use internal storage instead.
  3. Pass mod.io a reference to your native main Activity using Modio::SetGlobalActivity(JavaObject);. You can do this either in a native event from Java, or anytime in your startup process if you have a reference to the native activity cached.

  4. Call Modio::InitializeAndroid(); for mod.io to initialize and setup its JNI bindings.

Authentication

There are two ways that you can perform Google SSO, either via a server-side auth code which the mod.io service will exchange for an ID Token, or directly using an ID token.

Sever Auth Code

Obtain a Server Auth Code from Google Play Games Services (v1 only) or the Google Sign-In Client library, ensuring you request Email access and the Profile scope.

GoogleSignInOptions signInOptions = new GoogleSignInOptions.Builder(GoogleSignInOptions.DEFAULT_GAMES_SIGN_IN)
.requestScopes(new Scope(Scopes.PROFILE))
.requestEmail()
.requestServerAuthCode(OAUTH_CLIENT_ID)
.build();

You can then show the Google Sign-In Intent to prompt users to consent to the OAuth scopes you are requesting, and obtain the server auth code in the callback.

    SignInClient = GoogleSignIn.getClient(this, signInOptions);
startActivityForResult(SignInClient.getSignInIntent(), RC_SIGN_IN);

@Override
protected void onActivityResult(int requestCode, int resultCode, Intent intent) {
if (requestCode == RC_SIGN_IN) {
Task<GoogleSignInAccount> task = GoogleSignIn.getSignedInAccountFromIntent(intent);

try {
GoogleSignInAccount account = task.getResult(ApiException.class);
serverSideAuthCode = account.getServerAuthCode();
}
}
}

Once you receive the Server Auth Code, you can authenticate using Modio::AuthenticateUserExternalAsync, passing Modio::AuthenticationProvider::GoogleServerSideToken as the authentication provider. This indicates to mod.io that this is a server side token that should be exchanged for an ID Token by the backend.

Ensure that you have configured your OAuth client ID and secret on your games authentication providers page.

You can read more about Google Play Services sign-in at https://developers.google.com/games/services/common/concepts/v1/sign-in

ID Token

You can also directly request an ID Token using Google Credential Manager, and use this to authenticate.

Once you receive the ID Token, you can authenticate using Modio::AuthenticateUserExternalAsync, passing Modio::AuthenticationProvider::GoogleIDToken as the authentication provider. This indicates to mod.io that this is is an ID token that can be directly used.

Marketplace

You can set up your Android game so users can purchase creator credits through the Google Play Store, and the mod.io platform will verify those purchases and grant associated entitlements to the user. To enable this, first follow these steps to configure entitlements for your game.

Next, integrate the Google Play Billing Library into your game to query for your In-App Products (IAPs) and make purchases.

With the above points completed, you can now call the Mod.io SDK's RefreshEntitlementsAsync function, which will initiate a backend request to Google to verify a purchase and grant the associated entitlements (virtual currency) to the user's account. Note that the user must be signed in via Google's SSO (see previous section Authentication).

The RefreshEntitlementsAsync function must be called after a successful Google Play purchase, as you must pass through the json receipt from the purchase. As the Google Play Billing Library is implemented in Java, you will need to pass this json receipt from Java to C++ via a JNI call. Then you can call RefreshEntitlementsAsync, adding the json receipt to the EntitlementParams object.

The following is an example of how to implement this. See the GUITest sample in the SDK for a complete working example.

Java:

@Override
public void onPurchasesUpdated(BillingResult billingResult, List<Purchase> purchases) {
if (billingResult.getResponseCode() == BillingClient.BillingResponseCode.OK && purchases != null) {
// Successful purchase
for (Purchase purchase : purchases) {
// Get the json receipt
String jsonReceipt = purchase.getOriginalJson();

// Pass it to C++
nativeOnPurchaseSuccess(jsonReceipt);
}
} else {
// Handle failed purchase
}
}

// Native callback
private native void nativeOnPurchaseSuccess(String jsonReceipt);

C++:

extern "C"
{
JNIEXPORT void Java_com_modio_gui_1test_BillingHelper_nativeOnPurchaseSuccess(JNIEnv* env, jclass clazz, jstring jsonReceipt)
{
const char* receipt = env->GetStringUTFChars(jsonReceipt, nullptr);

Modio::EntitlementParams EntitlementParams;
EntitlementParams.ExtendedParameters.emplace(Modio::Detail::Constants::APIStrings::Receipt, receipt);
Modio::RefreshUserEntitlementsAsync(
EntitlementParams,
[](Modio::ErrorCode ec, Modio::Optional<Modio::EntitlementConsumptionStatusList> entitlementList) {
if (ec)
{
// Handle error
}
else
{
// Get the number of entitlements
int entitlementCount = entitlementList.value().GetTotalResultCount();
Modio::Detail::Logger().Log(Modio::LogLevel::Info, Modio::LogCategory::Test,
"Number of entitlements returned: {}", entitlementCount);

// Get information about each entitlement
for (int index = 0; index < entitlementCount; index++)
{
size_t i = static_cast<size_t>(index);
Modio::Detail::Logger().Log(Modio::LogLevel::Info, Modio::LogCategory::Test,
"Entitelement Id : {} , Consumed : {} , ProductId : {} ",
entitlementList.value()[i].TransactionId,
entitlementList.value()[i].EntitlementConsumed,
entitlementList.value()[i].SkuId);
}
}
});

env->ReleaseStringUTFChars(jsonReceipt, receipt);
}
}