Setting up EasyAR Sense for Android

This article shows how to setup EasyAR non-Unity Android projects using EasyAR package.

If you want to run EasyAR non-Unity Android sample, please read this instead.

Pre-Requirements

  • JDK 1.8

  • Android SDK with Build Tools at least version 30.0.3

  • Android NDK r22

It is recommended to install the latest version of NDK and SDK

You can use EasyAR in Eclipse or Android Studio.

EasyAR Sense have both Java and C++ API, and support Kotlin, you can choose your favorite language.

Import EasyAR Sense for Android

Configuration may be different when using different IDEs. Here we will introduce the configuration details when using Android Studio 2.2 and later with gradle.

Using Java only API

  • Put EasyAR.aar to app/libs or explicitly specified folder in your gradle settings.

Using both Java and C++ API

  • Put EasyAR.jar to app/libs or explicitly specified folder in your gradle settings.

  • Put armeabi-v7a and/or arm64-v8a to app/src/main/jniLibs or explicitly specified folder in your gradle settings.

  • Put easyar folder from include to app/src/main/jni or explicitly specified folder in your Android.mk or CMakeLists.txt.

You can get more details about arm64-v8a support from About Android arm64-v8a.

Gradle Configuration for EasyAR Sense -- Java API

Nothing special.

Gradle Configuration for EasyAR Sense -- C++ API

You may reference Google official article for this.

Makefile / CMakeLists

Here we only describe how to write Android.mk, if you prefer CMake, you can reference Google official article.

  1. prebuilt library

include $(CLEAR_VARS)
# make sure this path is available for libEasyAR.so
LOCAL_PATH := $(LOCAL_PATH_TOP)/../jniLibs/$(TARGET_ARCH_ABI)
LOCAL_MODULE := EasyAR
LOCAL_SRC_FILES := libEasyAR.so
include $(PREBUILT_SHARED_LIBRARY)
  1. link libEasyAR.so

    GLESv2 is required.

LOCAL_LDLIBS += -lGLESv2
LOCAL_SHARED_LIBRARIES += EasyAR

External Native Build

android {
    externalNativeBuild {
        ndkBuild {
            path 'src/main/jni/Android.mk'
        }
    }
}

If you prefer CMake, you can reference Google official article.

Specify ABIs

android {
    defaultConfig {
        ndk {
            abiFilters 'armeabi-v7a', 'arm64-v8a'
        }
    }
}

If you need only one of armeabi-v7a or arm64-v8a, keep that one in the above.

Warning: Since August 1, 2019, Google Play Store requires that an application with armeabi-v7a be committed with support for arm64-v8a. (Support 64-bit architectures)

Add Permissions in AndroidManifest

EasyAR require the following permissions, missing permissions may cause initialize fail.

android.permission.CAMERA android.permission.INTERNET

Add them to AndroidManifest like this.

<manifest xmlns:android="http://schemas.android.com/apk/res/android" package="cn.easyar.samples.helloar" >
    <uses-permission android:name="android.permission.CAMERA" />
    <uses-permission android:name="android.permission.INTERNET" />
</manifest>

Initialize EasyAR

Use cn.easyar.Engine.initialize to initialize EasyAR. You can add the initialization into your activity like this.

protected void onCreate() {
    Engine.initialize(this, key);
}

Other Code

What is left is to write EasyAR logics and other code. You can refer to EasyAR samples for more details.

260 character path limit on Windows

On Windows, if any file in the project (including temporary files generated in the build process) has a path of longer than 260 characters, Android Studio may fail the build. Reduce the directory path length to workaround this problem.

ARCore

If you use ARCore, please refer to its official documentation to configure AndroidManifest and build.gradle.

In spite of that, it is neccessary to call the following line before initialization of EasyAR.

System.loadLibrary("arcore_sdk_c");

For an ARCore version before v1.19.0, it will not be detected on Android 11. This is caused by Android 11 restriction on application visibility and it is needed to be declared in Android.manifest.

<queries>
    <package android:name="com.google.ar.core" /> <!-- remove this line after updating to ARCore v1.19.0 or later -->
</queries>

Obfuscation

If obfuscation is to be applied to Java code, please exclude namespace cn.easyar. EasyAR Sense uses JNI to access Java classes by name, and will have undefined behavior when they are renamed.

If you use ProGuard, you can add

-keep class cn.easyar.** { *; }

Or more precisely,

-dontwarn javax.annotation.Nonnull
-dontwarn javax.annotation.Nullable
-keepattributes *Annotation*

-keep class cn.easyar.RefBase { native <methods>; }
-keepclassmembers class cn.easyar.* {
    <fields>;
    protected <init>(long, cn.easyar.RefBase);
}
-keep,allowobfuscation interface cn.easyar.FunctorOf* { *; }

-keep class cn.easyar.Buffer { native <methods>; }
-keep class cn.easyar.Engine { native <methods>; }
-keep class cn.easyar.JniUtility { native <methods>; }

-keep class cn.easyar.engine.** { *; }
-keep class cn.easyar.CameraParameters
-keep interface cn.easyar.FunctorOfVoidFromInputFrame

This ProGuard rule is included in the aar library.

Scoped Storage

Scoped Storage in Android 10 and Android 11 will affect some APIs.

Specifically, external storage path /sdcard, excluding media storage paths like /sdcard/Movies can not be accessed. On Android 10 (ant not on Android 11), MediaStore is the only way to access media storage paths.

APIs that require passing into file paths, such as recording, can not access media storage paths on Android 10. This is not the case on Android 11.

For simplicity, we can opt-out scoped storage for Android 10 with android:requestLegacyExternalStorage="true". Or we can access internal storage instead and do file exchange between internal storage and media storage paths with MediaStore.

Android Gradle plugin

NDK r22 defaults to use LLD linker, which need to be used with llvm-strip, and is not compatible with strip in Android Gradle Plugin before 4.0.

Update to Android Gradle Plugin 4.0 or later, or use doNotStrip option in packagingOptions to disable stripping.