[Huawei Developers] John Wo:
More information like this, you can visit HUAWEI Developer Forum

​

Introduction

AR Engine has support to detect objects in the real world is called "Environment tracking" and with it you can records illumination, plane, image, object, surface, and other environmental information to help your apps merge virtual objects into scenarios in the physical world.

What is HUAWEI AR Engine?

HUAWEI AR Engine is a platform for building augmented reality (AR) apps on Android smartphones. It is based on the HiSilicon chipset, and integrates AR core algorithms to provide basic AR capabilities such as motion tracking, environment tracking, body tracking, and face tracking, allowing your app to bridge virtual world with the real world, for a brand new visually interactive user experience.

Currently, HUAWEI AR Engine provides three types of capabilities, including motion tracking, environment tracking, and human body and face tracking.

[IMG="https://communityfile-dre.op.hicloud.com/FileServer/getFile/cmtybbs/002/216/213/2640052000002216213.20200904175331.21715326582390171724078678926102:50510917114646:2800:A3A73A7293BA10DA2CBDDD2C15AF2C1D5311CAA480C0302DBDDFC74FF85F02A6.jpg"]https://communityfile-dre.op.hicloud.com/FileServer/getFile/cmtybbs/002/216/213/2640052000002216213.20200904175331.21715326582390171724078678926102:50510917114646:2800:A3A73A7293BA10DA2CBDDD2C15AF2C1D5311CAA480C0302DBDDFC74FF85F02A6.jpg[/IMG]

Example Android Application

For this example we will work on Environment tracking so we can detect surfaces, like a table or a floor.

Development Process

[IMG="https://communityfile-dre.op.hicloud.com/FileServer/getFile/cmtybbs/002/216/213/2640052000002216213.20200904175358.47139979565536496091533765070387:50510917114646:2800:42CB3BCA7B7929DE87A14FDDEF821153637A6252079CAB7DC94C9F25224DBFFD.jpg"]https://communityfile-dre.op.hicloud.com/FileServer/getFile/cmtybbs/002/216/213/2640052000002216213.20200904175358.47139979565536496091533765070387:50510917114646:2800:42CB3BCA7B7929DE87A14FDDEF821153637A6252079CAB7DC94C9F25224DBFFD.jpg[/IMG]

Creating an App

Create an app following instructions in Creating an AppGallery Connect Project and Adding an App to the Project.

Platform: Android

Device: Mobile phone

App category: App or Game

Integrating HUAWEI AR Engine SDK

Before development, integrate the HUAWEI AR Engine SDK via the Maven repository into your development environment.

Open the build.gradle file in the root directory of your Android Studio project.

// Top-level build file where you can add configuration options common to all sub-projects/modules.
buildscript {
repositories {
google()
jcenter()
maven {url 'https://developer.huawei.com/repo/'}
}
dependencies {
classpath "com.android.tools.build:gradle:4.0.1"
classpath 'com.huawei.agconnect:agcp:1.3.2.301'
// NOTE: Do not place your application dependencies here; they belong
// in the individual module build.gradle files
}
}

allprojects {
repositories {
maven {url 'https://developer.huawei.com/repo/'}
google()
jcenter()
}
}

task clean(type: Delete) {
delete rootProject.buildDir
}

Open the build.gradle file in the app directory of your project

apply plugin: 'com.android.application'

android {
compileSdkVersion 30
buildToolsVersion "30.0.1"

defaultConfig {
applicationId "com.vsm.myarapplication"
minSdkVersion 27
targetSdkVersion 30
versionCode 1
versionName "1.0"

testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner"
}

buildTypes {
release {
minifyEnabled false
proguardFiles getDefaultProguardFile('proguard-android-optimize.txt'), 'proguard-rules.pro'
}
}
}

dependencies {
implementation fileTree(dir: "libs", include: ["*.jar"])
implementation 'androidx.appcompat:appcompat:1.2.0'
implementation 'androidx.constraintlayout:constraintlayout:2.0.1'
testImplementation 'junit:junit:4.12'
//
implementation 'com.huawei.agconnect:agconnect-core:1.4.1.300'
//
implementation 'com.huawei.hms:arenginesdk:2.13.0.4'
//
implementation 'de.javagl:obj:0.3.0'
androidTestImplementation 'androidx.test.ext:junit:1.1.2'
androidTestImplementation 'androidx.test.espresso:espresso-core:3.3.0'

}
apply plugin: 'com.huawei.agconnect'

We create our Main Activity:

<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
tools:context=".MainActivity">

<android.opengl.GLSurfaceView
android:id="@+id/surfaceview"
android:layout_width="fill_parent"
android:layout_height="fill_parent"
android:layout_gravity="top" />
<TextView
android:id="@+id/wordTextView"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="TextView"
android:textColor="@color/red"
tools:layout_editor_absoluteX="315dp"
tools:layout_editor_absoluteY="4dp" />

<TextView
android:id="@+id/searchingTextView"
android:layout_width="match_parent"
android:layout_height="47dp"
android:layout_alignParentStart="true"
android:layout_alignParentTop="true"
android:layout_marginStart="2dp"
android:layout_marginTop="59dp"
android:layout_marginBottom="403dp"
android:gravity="center"
android:text="Please move the mobile phone slowly to find the plane"
android:textColor="#ffffff"
tools:layout_editor_absoluteX="0dp"
tools:layout_editor_absoluteY="512dp" />

<TextView
android:id="@+id/plane_other"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="@string/plane_other"
android:visibility="gone"
android:rotation="180"
android:textColor="#ff2211"
tools:layout_editor_absoluteX="315dp"
tools:layout_editor_absoluteY="4dp" />
<TextView
android:id="@+id/plane_floor"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="@string/plane_floor"
android:visibility="gone"
android:rotation="180"
android:textColor="#ff2211"
tools:layout_editor_absoluteX="315dp"
tools:layout_editor_absoluteY="4dp" />
<TextView
android:id="@+id/plane_wall"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="@string/plane_wall"
android:visibility="gone"
android:rotation="180"
android:textColor="#ff2211"
tools:layout_editor_absoluteX="315dp"
tools:layout_editor_absoluteY="4dp" />
<TextView
android:id="@+id/plane_table"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="@string/plane_table"
android:visibility="gone"
android:rotation="180"
android:textColor="#ff2211"
tools:layout_editor_absoluteX="315dp"
tools:layout_editor_absoluteY="4dp" />
<TextView
android:id="@+id/plane_seat"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="@string/plane_seat"
android:visibility="gone"
android:rotation="180"
android:textColor="#ff2211"
tools:layout_editor_absoluteX="315dp"
tools:layout_editor_absoluteY="4dp" />
<TextView
android:id="@+id/plane_ceiling"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="@string/plane_ceiling"
android:visibility="gone"
android:rotation="180"
android:textColor="#ff2211"
tools:layout_editor_absoluteX="315dp"
tools:layout_editor_absoluteY="4dp" />

</RelativeLayout>

AR Engine is not for all devices, so first we need to validate if the device support AR Engine and is aviable, here is the list of devices supported

[IMG="https://communityfile-dre.op.hicloud.com/FileServer/getFile/cmtybbs/002/216/213/2640052000002216213.20200904172439.07731851173075371629372732240852:50510917114646:2800:EE1EF3DDB8E4BC2096A652532BE0B9130635665D72611713EB0F0CC2C4A7BDFA.png"]https://communityfile-dre.op.hicloud.com/FileServer/getFile/cmtybbs/002/216/213/2640052000002216213.20200904172439.07731851173075371629372732240852:50510917114646:2800:EE1EF3DDB8E4BC2096A652532BE0B9130635665D72611713EB0F0CC2C4A7BDFA.png[/IMG]

private boolean arEngineAbilityCheck() {
boolean isInstallArEngineApk = AREnginesApk.isAREngineApkReady(this);
if (!isInstallArEngineApk && isRemindInstall) {
Toast.makeText(this, "Please agree to install.", Toast.LENGTH_LONG).show();
finish();
}
Log.d(TAG, "Is Install AR Engine Apk: " + isInstallArEngineApk);
if (!isInstallArEngineApk) {
startActivity(new Intent(this, ConnectAppMarketActivity.class));
isRemindInstall = true;
}
return AREnginesApk.isAREngineApkReady(this);
}

private void setMessageWhenError(Exception catchException) {
if (catchException instanceof ARUnavailableServiceNotInstalledException) {
startActivity(new Intent(getApplicationContext(), ConnectAppMarketActivity.class));
} else if (catchException instanceof ARUnavailableServiceApkTooOldException) {
message = "Please update HuaweiARService.apk";
} else if (catchException instanceof ARUnavailableClientSdkTooOldException) {
message = "Please update this app";
} else if (catchException instanceof ARUnSupportedConfigurationException) {
message = "The configuration is not supported by the device!";
} else {
message = "exception throw";
}
}

On our MainActivity.java we call the surface detection

package com.vsm.myarapplication;

import androidx.appcompat.app.AppCompatActivity;

import android.content.Intent;
import android.opengl.GLSurfaceView;
import android.os.Bundle;
import android.util.Log;
import android.view.GestureDetector;
import android.view.MotionEvent;
import android.view.View;
import android.widget.Toast;

import com.huawei.hiar.ARConfigBase;
import com.huawei.hiar.AREnginesApk;
import com.huawei.hiar.ARSession;
import com.huawei.hiar.ARWorldTrackingConfig;
import com.huawei.hiar.exceptions.ARCameraNotAvailableException;
import com.huawei.hiar.exceptions.ARUnSupportedConfigurationException;
import com.huawei.hiar.exceptions.ARUnavailableClientSdkTooOldException;
import com.huawei.hiar.exceptions.ARUnavailableServiceApkTooOldException;
import com.huawei.hiar.exceptions.ARUnavailableServiceNotInstalledException;
import com.vsm.myarapplication.common.ConnectAppMarketActivity;
import com.vsm.myarapplication.common.DisplayRotationManager;
import com.vsm.myarapplication.common.PermissionManager;
import com.vsm.myarapplication.rendering.WorldRenderManager;

import java.util.concurrent.ArrayBlockingQueue;

public class MainActivity extends AppCompatActivity {

private static final String TAG = MainActivity.class.getSimpleName();
private static final int MOTIONEVENT_QUEUE_CAPACITY = 2;
private static final int OPENGLES_VERSION = 2;
private ARSession mArSession;
private GLSurfaceView mSurfaceView;
private WorldRenderManager mWorldRenderManager;
private GestureDetector mGestureDetector;
private DisplayRotationManager mDisplayRotationManager;
private ArrayBlockingQueue<GestureEvent> mQueuedSingleTaps = new ArrayBlockingQueue<>(MOTIONEVENT_QUEUE_CAPACITY);
private String message = null;
private boolean isRemindInstall = false;

@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
// AR Engine requires the camera permission.
PermissionManager.checkPermission(this);
mSurfaceView = findViewById(R.id.surfaceview);
mDisplayRotationManager = new DisplayRotationManager(this);
initGestureDetector();
mSurfaceView.setPreserveEGLContextOnPause(true);
mSurfaceView.setEGLContextClientVersion(OPENGLES_VERSION);
// Set the EGL configuration chooser, including for the number of
// bits of the color buffer and the number of depth bits.
mSurfaceView.setEGLConfigChooser(8, 8, 8, 8, 16, 0);

mWorldRenderManager = new WorldRenderManager(this, this);
mWorldRenderManager.setDisplayRotationManage(mDisplayRotationManager);
mWorldRenderManager.setQueuedSingleTaps(mQueuedSingleTaps);

mSurfaceView.setRenderer(mWorldRenderManager);
mSurfaceView.setRenderMode(GLSurfaceView.RENDERMODE_CONTINUOUSLY);
}

private void initGestureDetector() {
mGestureDetector = new GestureDetector(this, new GestureDetector.SimpleOnGestureListener() {
@Override
public boolean onDoubleTap(MotionEvent motionEvent) {
onGestureEvent(GestureEvent.createDoubleTapEvent(motionEvent));
return true;
}

@Override
public boolean onSingleTapConfirmed(MotionEvent motionEvent) {
onGestureEvent(GestureEvent.createSingleTapConfirmEvent(motionEvent));
return true;
}

@Override
public boolean onDown(MotionEvent motionEvent) {
return true;
}

@Override
public boolean onScroll(MotionEvent e1, MotionEvent e2, float distanceX, float distanceY) {
onGestureEvent(GestureEvent.createScrollEvent(e1, e2, distanceX, distanceY));
return true;
}
});

mSurfaceView.setOnTouchListener(new View.OnTouchListener() {
@Override
public boolean onTouch(View v, MotionEvent event) {
return mGestureDetector.onTouchEvent(event);
}
});
}
private void onGestureEvent(GestureEvent e) {
boolean offerResult = mQueuedSingleTaps.offer(e);
if (offerResult) {
Log.i(TAG, "Successfully joined the queue.");
} else {
Log.i(TAG, "Failed to join queue.");
}
}
@Override
protected void onResume() {
Log.i(TAG, "onResume");
super.onResume();
Exception exception = null;
message = null;
if (mArSession == null) {
try {
if (!arEngineAbilityCheck()) {
finish();
return;
}
mArSession = new ARSession(getApplicationContext());
ARWorldTrackingConfig config = new ARWorldTrackingConfig(mArSession);
config.setFocusMode(ARConfigBase.FocusMode.AUTO_FOCUS);
config.setSemanticMode(ARWorldTrackingConfig.SEMANTIC_PLANE);
mArSession.configure(config);
mWorldRenderManager.setArSession(mArSession);
} catch (Exception capturedException) {
Log.e(TAG,capturedException.toString());
exception = capturedException;
setMessageWhenError(capturedException);
}
if (message != null) {
stopArSession(exception);
return;
}
}
try {
mArSession.resume();
} catch (ARCameraNotAvailableException e) {
Toast.makeText(this, "Camera open failed, please restart the app", Toast.LENGTH_LONG).show();
mArSession = null;
return;
}
mDisplayRotationManager.registerDisplayListener();
mSurfaceView.onResume();
}

@Override
protected void onPause() {
Log.i(TAG, "onPause start.");
super.onPause();
if (mArSession != null) {
mDisplayRotationManager.unregisterDisplayListener();
mSurfaceView.onPause();
mArSession.pause();
}
Log.i(TAG, "onPause end.");
}

@Override
protected void onDestroy() {
Log.i(TAG, "onDestroy start.");
if (mArSession != null) {
mArSession.stop();
mArSession = null;
}
super.onDestroy();
Log.i(TAG, "onDestroy end.");
}

private boolean arEngineAbilityCheck() {
boolean isInstallArEngineApk = AREnginesApk.isAREngineApkReady(this);
if (!isInstallArEngineApk && isRemindInstall) {
Toast.makeText(this, "Please agree to install.", Toast.LENGTH_LONG).show();
finish();
}
Log.d(TAG, "Is Install AR Engine Apk: " + isInstallArEngineApk);
if (!isInstallArEngineApk) {
startActivity(new Intent(this, ConnectAppMarketActivity.class));
isRemindInstall = true;
}
return AREnginesApk.isAREngineApkReady(this);
}

private void setMessageWhenError(Exception catchException) {
if (catchException instanceof ARUnavailableServiceNotInstalledException) {
startActivity(new Intent(getApplicationContext(), ConnectAppMarketActivity.class));
} else if (catchException instanceof ARUnavailableServiceApkTooOldException) {
message = "Please update HuaweiARService.apk";
} else if (catchException instanceof ARUnavailableClientSdkTooOldException) {
message = "Please update this app";
} else if (catchException instanceof ARUnSupportedConfigurationException) {
message = "The configuration is not supported by the device!";
} else {
message = "exception throw";
}
}
private void stopArSession(Exception exception) {
Log.i(TAG, "stopArSession start.");
Toast.makeText(this, message, Toast.LENGTH_LONG).show();
Log.e(TAG, "Creating session error", exception);
if (mArSession != null) {
mArSession.stop();
mArSession = null;
}
Log.i(TAG, "stopArSession end.");
}

}

[IMG="https://communityfile-dre.op.hicloud.com/FileServer/getFile/cmtybbs/002/216/213/2640052000002216213.20200904175426.38191434233307595738305641191139:50510917114646:2800:4D9D549479DAA87126B6E0425A2E2D94D088BC5E6B21B0E85FE3B67C4CA05D9A.gif"]https://communityfile-dre.op.hicloud.com/FileServer/getFile/cmtybbs/002/216/213/2640052000002216213.20200904175426.38191434233307595738305641191139:50510917114646:2800:4D9D549479DAA87126B6E0425A2E2D94D088BC5E6B21B0E85FE3B67C4CA05D9A.gif[/IMG]

Conclusion

We can detect surfaces for multiple purposes in a simple way.

Documentation:

https://developer.huawei.com/consumer/en/doc/development/HMSCore-Guides/introduction-0000001050130900

Codelab:

https://developer.huawei.com/consumer/en/codelab/HWAREngine/index.html#0

Code Sample:

https://github.com/spartdark/hms-arengine-myarapplication