Using EOS SDK on Android

How to implement EOS SDK in an Android project with Android Studio

This guide explains how to add the Epic Online Services (EOS) SDK to an Android Studio project, how to ensure that your build system recognizes the SDK, and how to handle Android-specific initialization of the SDK.

1. Required Setup

This guide assumes that you already have an Android Studio project that can build C/C++ code with the Android NDK. If you do not have a project set up, follow the guides at https://developer.android.com/ndk/guides to get started. This guide also assumes that you use Gradle to build your project. Other build tools should also work, but are not officially supported.

The EOS SDK requires libc++_shared to be bundled with your app. If it is your desired Standard Template Library (STL), refer to developer.android.com/ndk/guides/cpp-support#selecting_a_c_runtime for information about how to bundle it in your .apk or .aab.

If you are using a different STL you will still need to bring in the associated libc++_shared library for your NDK release. You can find the .so files in your ndk folder at sources\cxx-stl\llvm-libc++\libs{arch}\. These will need to be included in the final build through your build tool.

2. Adding EOS SDK to Your Android Studio Project

The SDK download from the Developer Portal provides a zip file containing the following artifacts:

  • An include folder containing all headers exposed from the EOS SDK.

  • A lib folder containing EOS SDK .so files built for arm64-v8a and armeabi-v7a that can be used when building your app.

  • The EOSSDK.aar file, which will automatically bundle the correct library with your app and add both required permissions and accompanying java code into your project.

Regardless of which build system you use, you will need to bring EOSSDK.aar into your project as a module. To do that, complete the following steps:

  1. Click File > New > New Moduleā€¦

    Select New Module in the File menu

  2. Select Import .JAR/.AAR Package from the list of options and click Next.

    Select Import .JAR/.AAR Package

  3. Select the .aar file from the extracted zip file. The Subproject Name should automatically fill in to say "EOSSDK". If not, set it manually or choose an alternate name. EOSSDK should now show up as an imported module in your project.

  4. Open your app's build.gradle file, which will be located inside the EOSSDK folder.

    EOSSDK appears in the project with the build.gradle file.

  5. In the dependencies block add implementation 'androidx.security:security-crypto.." and implementation project(":EOSSDK"). The dependencies block should then read as follows:

    build.gradle

    dependencies {

    implementation `android.appcompat.appcompat:1.1.0`
    implementation `androidx.constraintlayout:constraintlayout:1.1.3`
    implementation 'androidx.security:security-crypto.."
    implementation project(":EOSSDK")

The SDK is now imported into your project and will be included in your builds! The .aar file will automatically handle bringing the correct .so file into the .apk/.aab during the build process.

The following sections will explain how to directly integrate the C libraries within the SDK.

3. Including the SDK With Your Build System

You can add the EOS SDK to your project using either CMake or ndk-build, which are both officially supported build systems that can be used with the NDK. This section will provide information about how to bring the SDK into your project using these build systems.

Using EOS With CMake

If you are using CMake in your project, you should have a CMakeLists.txt file in your project. To bring the EOS SDK into your NDK project you will need to let CMake know where the library is located.

CMakeLists.txt

add_library(EOSSDK SHARED IMPORTED)

set(EOSSDKDIR PUT_PATH_TO_EXPANDED_ZIP_HERE)

set_property(TARGET EOSSDK PROPERTY IMPORTED_LOCATION ${EOSSDKDIR}/lib/${ANDROID_ABI}/libEOSSDK.so)
set_property(TARGET EOSSDK PROPERTY INTERFACE_INCLUDE_DIRECTORIES ${EOSSDKDIR}/include/)

If you expanded the zip in the same directory as the CMakeLists.txt, it would look like this:

CMakeLists.txt

add_library(EOSSDK SHARED IMPORTED)

set(EOSSDKDIR ${CMAKE_SOURCE_DIR})

set_property(TARGET EOSSDK PROPERTY IMPORTED_LOCATION ${EOSSDKDIR}/lib/${ANDROID_ABI}/libEOSSDK.so)
set_property(TARGET EOSSDK PROPERTY INTERFACE_INCLUDE_DIRECTORIES ${EOSSDKDIR}/include/)

Finally, make sure the EOS SDK is linked with the appropriate library in your project. In an Android Studio C++ project created in the New Project Wizard, that would look like this:

CMakeLists.txt

target_link_libraries( # Specifies the target library.
                      native-lib
                      #Links the target library to the EOSSDK
                       EOSSDK

                      # Links the target library to the log library
                      # included in the NDK.
                      ${log-lib} )

At this point, sync gradle and you should be able to import EOS SDK symbols into your C++ project and move to the Android-Specific Initialize Options section.

For more information about using CMake, refer to https://developer.android.com/ndk/guides/cmake.

Using EOS With ndk-build

If you are using ndk-build for your project, you will need to add EOS SDK as a module to your Android.mk file. A basic Android.mk file would look like this:

Android.mk

LOCAL_PATH := $(call my-dir)

include $(CLEAR_VARS)

LOCAL_MODULE    := hello-jni
LOCAL_SRC_FILES := hello-jni.c
LOCAL_LDLIBS    := -llog -landroid

include $(BUILD_SHARED_LIBRARY)

This file defines a hello-jni module with a single .c file as its source. You need to define a similar module in this file for EOS SDK, such as the following:

Android.mk

include $(CLEAR_VARS)
LOCAL_MODULE := eossdk
LOCAL_SRC_FILES := $(LOCAL_PATH)/lib/$(TARGET_ARCH_ABI)/libEOSSDK.so
LOCAL_EXPORT_C_INCLUDES := $(LOCAL_PATH)/include
include $(PREBUILT_SHARED_LIBRARY)

In this example, the zip file was inflated in the same folder as the Android.mk file. If you prefer the files elsewhere you can replace the LOCAL_PATH with the correct path instead.

To use the EOS SDK module from the hello-jni module, you will need to link them. You can do this by adding the sdk as a LOCAL_SHARED_LIBRARIES entry. Additionally, we need to make sure c++_shared is also referenced.

Android.mk

include $(CLEAR_VARS)
LOCAL_MODULE    := hello-jni
LOCAL_SRC_FILES := hello-jni.c
LOCAL_SHARED_LIBRARIES := eossdk c++_shared
LOCAL_LDLIBS    := -llog -landroid
include $(BUILD_SHARED_LIBRARY)

At this point, the hello-jni module should have access to the exported symbols from the EOS SDK!

The full demo Android.mk file is provided below. This will need to be adapted for your specific use case.

Android.mk

LOCAL_PATH := $(call my-dir)

include $(CLEAR_VARS)
LOCAL_MODULE := eossdk
LOCAL_SRC_FILES := $(LOCAL_PATH)/lib/$(TARGET_ARCH_ABI)/libEOSSDK.so
LOCAL_EXPORT_C_INCLUDES := $(LOCAL_PATH)/include
include $(PREBUILT_SHARED_LIBRARY)

include $(CLEAR_VARS)
LOCAL_MODULE    := hello-jni
LOCAL_SRC_FILES := hello-jni.c
LOCAL_SHARED_LIBRARIES := eossdk c++_shared
LOCAL_LDLIBS    := -llog -landroid
include $(BUILD_SHARED_LIBRARY)

For more information about ndk-build, refer to https://developer.android.com/ndk/guides/ndk-build.

4. Android-Specific System Initialize Options

The EOS SDK requires platform-specific System Initialize Options for Android to function properly. These options are defined as EOS_Android_InitializeOptions, and require a reference to the JavaVM as well as optional directory paths for disk access.

For EOS SDK Java side to function, you need to pass the application context to it as follows:

EOSSDK.init(getApplicationContext());

In the login example we do this in onCreate of MainActivity class.

To get the correct values for these options, we suggest passing in the associated values over JNI. With a reference to a JNIEnv* you can access the JavaVM easily.

JavaVM* VM = nullptr;

env->GetJavaVM(&VM);

Here is an example of a full initialization of the EOS SDK on Android. This will need to be adapted for specific use-cases.

extern "C" JNIEXPORT jstring JNICALL
Java_com_example_eossdk_Documentation_initializeSdk( JNIEnv* env,
  jobject /* this */, jstring internalPath, jstring externalPath)
{
  EOS_InitializeOptions SDKOptions = { 0 };
  SDKOptions.ApiVersion = EOS_INITIALIZE_API_LATEST;
  SDKOptions.ProductName = "EOSDocumentationExample";
  SDKOptions.ProductVersion = "0.1";

  JavaVM* VM = nullptr;
  env->GetJavaVM(&VM);
  const char* androidInternalPath = env->GetStringUTFChars(internalPath, nullptr);
  const char* androidExternalPath = env->GetStringUTFChars(externalPath, nullptr);

  static EOS_Android_InitializeOptions JNIOptions = { 0 };
  JNIOptions.ApiVersion = EOS_ANDROID_INITIALIZEOPTIONS_API_LATEST;
  JNIOptions.VM = VM;

  JNIOptions.OptionalInternalDirectory = androidInternalPath;
  JNIOptions.OptionalExternalDirectory = androidExternalPath;

  SDKOptions.SystemInitializeOptions = &JNIOptions;

  EOS_EResult InitResult = EOS_Initialize(&SDKOptions);
  if(InitResult != EOS_EResult::EOS_Success){
     return env->NewStringUTF("Error when initializing");
  }
  return env->NewStringUTF("Initialized successfully");
}