Как создать простое приложение для Android с дополненной реальностью?
Дополненная реальность прошла долгий путь от научно-фантастических историй до научной реальности. При такой скорости технического прогресса, вероятно, не так уж и далеко, когда мы также сможем манипулировать цифровыми данными в этом реальном физическом мире, как это сделал Тони Старк в своей лаборатории. Когда мы накладываем такую информацию, как звук, текст, изображение на наш реальный мир, а также можем взаимодействовать с ним через специальный носитель, то есть дополненную реальность. Всемирно известное приложение Pokemon GO - еще один пример приложения дополненной реальности. Давайте сделаем очень простое приложение дополненной реальности в Android Studio с использованием JAVA . Это приложение показывает изготовленную на заказ или загруженную 3D-модель с помощью камеры телефона. Ниже приведен образец GIF, чтобы понять, что мы собираемся делать в этой статье.
Терминологии
- ARCore: Согласно Google, ARCore - это платформа для дополненной реальности. ARCore действительно помогает телефону ощущать окружающую среду и взаимодействовать с окружающим миром. ARCore в основном использует 3 ключевых принципа - отслеживание движения, понимание окружающей среды и оценка освещенности . Вот список телефонов, поддерживающих ARCore, предоставленный Google.
- Sceneform: Согласно Google, Sceneform - это трехмерная структура, которая помогает разработчикам создавать приложения ARCore, не зная много об OpenGL. Sceneform имеет множество функций, таких как проверка разрешения камеры, управление 3D-активами и многое другое.
Пошаговая реализация
Шаг 1. Создайте новый проект
Чтобы создать новый проект в Android Studio, обратитесь к разделу «Как создать / запустить новый проект в Android Studio».
Note:
- Select Java as the programming language.
- Note the location where the app is getting saved because we need that path later.
- Choose ‘Minimum SDK‘ as ‘API 24: Android 7.0(Nougat)‘
Шаг 2: Получение 3D-модели
Scenform 1.16.0 поддерживает только файлы glTF. glTF означает формат передачи GL. Теперь файлы .glb представляют собой двоичную версию формата передачи GL. Эти типы файлов 3D-моделей используются в VR, AR, поскольку они поддерживают движение и анимацию.
- Для 3D-модели необходимо получить файл .glb.
- Есть два способа: вы можете взять 3D-модель, загрузить из Интернета или сделать ее самостоятельно .
- Если вы хотите загрузить его из Интернета, перейдите в этот потрясающий репозиторий 3D-моделей от Google, poly и найдите любой файл glb . Загрузите любой из них для своего проекта.
- ИЛИ, получите программное обеспечение для компьютерной 3D-графики и сделайте 3D-модель самостоятельно.
- Я использовал Blender, который можно загрузить совершенно бесплатно, и сделал 3d модель текста GEEKS FOR GEEKS. Получите этот файл отсюда.
- Экспортируйте модель в виде файла .glb в определенную папку, и имя файла должно содержать small_letters или числа .
- Вернитесь в Android Studio.
- На левой панели щелкните правой кнопкой мыши каталог res. Перейдите в Новый> Каталог ресурсов Android . Появится окно.
- Измените тип ресурса : на Raw . Щелкните ОК . Необработанная папка создается в каталоге res.
- Скопируйте файл . glb из того каталога, в котором вы его сохранили, и вставьте в исходную папку.
Шаг 3: загрузка и настройка SceneForm 1.16.0
Что ж, для приложений AR нам нужен Sceneform SDK. SceneForm 1.15.0 очень известен, но в последнее время я столкнулся с некоторыми ошибками плагина при установке плагина «Google Sceneform Tools (бета)» в последней версии Android Studio 4.1. Итак, я использую SDK Sceneform 1.16.0 и настраиваю его вручную.
- Перейдите по этой ссылке GitHub.
- Загрузите файл «sceneform-android-sdk-1.16.0.zip ».
- Извлеките папки «sceneformsrc» и « sceneformux », в которых вы создали свой проект. («E: android ARApp» для меня)
- Перейти в Android Studio
- Перейдите в Gradle Scripts> settings.gradle (Настройки проекта)
- Добавьте эти строки:
// this will add sceneformsrc folder into your project
include ‘:sceneform’
project(‘:sceneform’).projectDir = new File(‘sceneformsrc/sceneform’)
// this will add sceneformux folder into your project
include ‘:sceneformux’
project(‘:sceneformux’).projectDir = new File(‘sceneformux/ux’)
- После этого перейдите в Gradle Scripts> build.gradle (Module: app)
- Добавьте эту строку в блок зависимостей.
api project(“:sceneformux”)
- Затем в том же файле внутри блока «android» и сразу после блока «buildTypes» добавьте следующие строки (если его еще нет):
// to support java 8 in your project
compileOptions {
sourceCompatibility JavaVersion.VERSION_1_8
targetCompatibility JavaVersion.VERSION_1_8
}
- После всех этих изменений нажмите « Синхронизировать сейчас » во всплывающем окне выше. Теперь файловая структура Android будет выглядеть так.
- Затем перейдите в приложение> манифесты> AndroidManifest.xml
- Добавьте эти строки перед блоком «приложение »:
XML
<!--This permits the user to access Camera--> < uses-permission android:name = "android.permission.CAMERA" /> <!--This helps to check a specific feature in the phone's hardware, here it is OpenGlES version. Sceneform needs OpenGLES Version 3.0 or later--> < uses-feature android:glEsVersion = "0x00030000" android:required = "true" /> <!--Indicates that this app requires Google Play Services for AR. Limits app visibility in the Google Play Store to ARCore supported devices--> < uses-feature android:name = "android.hardware.camera.ar" android:required = "true" /> |
- После этого добавьте эту строку перед блоком «активность ».
XML
<!-- ARCore need to be installed, as the app does not include any non-AR features. For an "AR Optional" app, specify "optional" instead of "required".--> < meta-data android:name = "com.google.ar.core" android:value = "required" /> |
Ниже приведен полный код файла AndroidManifest.xml.
XML
<? xml version = "1.0" encoding = "utf-8" ?> package = "com.wheic.arapp" > <!--This helps to permit the user to access Camera--> < uses-permission android:name = "android.permission.CAMERA" /> <!--This helps to check a specific feature in the phone's hardware, here it is OpenGl ES version 3--> < uses-feature android:glEsVersion = "0x00030000" android:required = "true" /> <!--Here it is checking for AR feature in phone camera--> < uses-feature android:name = "android.hardware.camera.ar" android:required = "true" /> < application android:allowBackup = "true" android:icon = "@mipmap/ic_launcher" android:label = "@string/app_name" android:roundIcon = "@mipmap/ic_launcher_round" android:supportsRtl = "true" android:theme = "@style/Theme.ARApp" > < meta-data android:name = "com.google.ar.core" android:value = "required" /> < activity android:name = ".MainActivity" > < intent-filter > < action android:name = "android.intent.action.MAIN" /> < category android:name = "android.intent.category.LAUNCHER" /> </ intent-filter > </ activity > </ application > </ manifest > |
Шаг 4: Исправление ошибок
А теперь немного скучно. Скачанные папки sceneformsrc и sceneformux содержат некоторый файл java, который импортирует классы java из более старой версии android.support. Итак, теперь, если вы создадите проект, вы увидите много ошибок из-за этого. Теперь вы можете перенести свой проект на новую версию Androidx . Теперь вы можете найти способ перенести весь проект на Androidx или изменить импорт вручную один за другим. Я знаю, что это скучно, но хорошие вещи приходят к тем, кто ждет, правда?
- Перейдите в Build> Rebuild Project.
- Вы найдете множество ошибок. Итак, в разделе «Сборка» дважды щелкните ошибку импорта пакета. Откроется код с выделенным разделом ошибок.
- Вам нужно изменить только три типа пути импорта, указанные ниже, всякий раз, когда вы видите, что первый из них изменит его на второй:
- android.support.annotation. -> androidx.annotation.
- androidx.core.app -> androidx.fragment.app.
- android.support.v7.widget. -> androidx.appcompat.widget.
- Вы должны продолжать это до тех пор, пока ошибки не исчезнут.
Шаг 5: Работа с activity_main.xml файл
- Перейдите в файл res> layout> activity_main.xml.
- Вот код этого XML-файла:
XML
<? xml version = "1.0" encoding = "utf-8" ?> < androidx.constraintlayout.widget.ConstraintLayout android:layout_width = "match_parent" android:layout_height = "match_parent" tools:context = ".MainActivity" > <!--This is the fragment that will be used as AR camera--> < fragment android:id = "@+id/arCameraArea" android:name = "com.google.ar.sceneform.ux.ArFragment" android:layout_width = "match_parent" android:layout_height = "match_parent" app:layout_constraintBottom_toBottomOf = "parent" app:layout_constraintEnd_toEndOf = "parent" app:layout_constraintStart_toStartOf = "parent" app:layout_constraintTop_toTopOf = "parent" /> </ androidx.constraintlayout.widget.ConstraintLayout > |
- ArFragment сам по себе содержит множество функций, например, он просит вас загрузить ARCore, если он еще не установлен в вашем телефоне, или запрашивает разрешение камеры, если оно еще не предоставлено. Так что лучше всего здесь использовать ArFragment.
- После написания этого кода пользовательский интерфейс приложения будет выглядеть так:
Шаг 6: Работа с файлом MainActivity.java
- Перейдите в java> com.wheic.arapp (ваш может отличаться) > MainActivity.java
- В классе MainActivity сначала мы должны создать объект ArFragment.
Джава
// object of ArFragment Class private ArFragment arCam; |
- Теперь давайте создадим функцию проверки оборудования вне функции onCreate () . Эта функция проверит, соответствует ли оборудование вашего телефона всем системным требованиям для запуска этого приложения AR. Он собирается проверить:
- Версия API запущенного Android> = 24, что означает Android Nougat 7.0
- Версия OpenGL> = 3.0
- Их наличие обязательно для запуска приложений AR с использованием ARCore и Sceneform. Вот код этой функции:
Джава
public static boolean checkSystemSupport(Activity activity) { // checking whether the API version of the running Android >= 24 // that means Android Nougat 7.0 if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N) { String openGlVersion = ((ActivityManager) Objects.requireNonNull(activity.getSystemService(Context.ACTIVITY_SERVICE))).getDeviceConfigurationInfo().getGlEsVersion(); // checking whether the OpenGL version >= 3.0 if (Double.parseDouble(openGlVersion) >= 3.0 ) { return true ; } else { Toast.makeText(activity, "App needs OpenGl Version 3.0 or later" , Toast.LENGTH_SHORT).show(); activity.finish(); return false ; } } else { Toast.makeText(activity, "App does not support required Build Version" , Toast.LENGTH_SHORT).show(); activity.finish(); return false ; } } |
- Сначала внутри функции onCreate () нам нужно проверить оборудование телефона. Если он вернет истину, то остальная часть функции будет выполнена.
- Теперь ArFragment связан с соответствующим идентификатором, используемым в activity_main.xml .
Джава
// ArFragment is linked up with its respective id used in the activity_main.xml arCam = (ArFragment) getSupportFragmentManager().findFragmentById(R.id.arCameraArea); |
- Вызывается onTapListener , чтобы показать трехмерную модель, когда мы нажимаем на экран.
- Внутри setOnTapArPlaneListener создается объект Anchor. Якорь действительно помогает вывести виртуальные объекты на экран и заставить их оставаться в том же положении и ориентации в пространстве.
- Теперь класс ModelRenderable используется с множеством функций . Этот класс используется для рендеринга загруженной или созданной 3D-модели путем присоединения ее к AnchorNode.
- Функция setSource () помогает получить исходный код 3d модели.
- Функция setIsFilamentGltf () проверяет, является ли это файлом glb.
- Функция build () отображает модель.
- Функция вызывается внутри функции thenAccept () для получения модели путем присоединения AnchorNode к ModelRenderable.
- Функция exceptionally () генерирует исключение, если что-то пойдет не так при построении модели.
Джава
arCam.setOnTapArPlaneListener((hitResult, plane, motionEvent) -> { clickNo++; // the 3d model comes to the scene only the first time we tap the screen if (clickNo == 1 ) { Anchor anchor = hitResult.createAnchor(); ModelRenderable.builder() .setSource( this , R.raw.gfg_gold_text_stand_2) .setIsFilamentGltf( true ) .build() .thenAccept(modelRenderable -> addModel(anchor, modelRenderable)) .exceptionally(throwable -> { AlertDialog.Builder builder = new AlertDialog.Builder( this ); builder.setMessage( "Somthing is not right" + throwable.getMessage()).show(); return null ; }); } }); |
- Теперь посмотрим, что находится в функции addModel ():
- Он принимает два параметра: первый - это Anchor, а второй - ModelRenderable.
- Создается объект AnchorNode. Это корневой узел сцены. AnchorNode автоматически позиционируется в мире на основе привязки.
- TransformableNode помогает пользователю взаимодействовать с 3D-моделью, например изменять положение, изменять размер, вращать и т. Д.
Джава
private void addModel(Anchor anchor, ModelRenderable modelRenderable) { // Creating a AnchorNode with a specific anchor AnchorNode anchorNode = new AnchorNode(anchor); // attaching the anchorNode with the ArFragment anchorNode.setParent(arCam.getArSceneView().getScene()); TransformableNode transform = new TransformableNode(arCam.getTransformationSystem()); // attaching the anchorNode with the TransformableNode transform.setParent(anchorNode); // attaching the 3d model with the TransformableNode that is // already attached with the node transform.setRenderable(modelRenderable); transform.select(); } |
Вот полный код файла MainActivity.java. Комментарии добавляются внутри кода для более подробного понимания кода.
Джава
import android.app.Activity; import android.app.ActivityManager; import android.app.AlertDialog; import android.content.Context; import android.os.Build; import android.os.Bundle; import android.widget.Toast; import androidx.appcompat.app.AppCompatActivity; import com.google.ar.core.Anchor; import com.google.ar.sceneform.AnchorNode; import com.google.ar.sceneform.rendering.ModelRenderable; import com.google.ar.sceneform.ux.ArFragment; import com.google.ar.sceneform.ux.TransformableNode; import java.util.Objects; public class MainActivity extends AppCompatActivity { // object of ArFragment Class private ArFragment arCam; // helps to render the 3d model // only once when we tap the screen private int clickNo = 0 ; public static boolean checkSystemSupport(Activity activity) { // checking whether the API version of the running Android >= 24 // that means Android Nougat 7.0 if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N) { String openGlVersion = ((ActivityManager) Objects.requireNonNull(activity.getSystemService(Context.ACTIVITY_SERVICE))).getDeviceConfigurationInfo().getGlEsVersion(); // checking whether the OpenGL version >= 3.0 if (Double.parseDouble(openGlVersion) >= 3.0 ) { return true ; } else { Toast.makeText(activity, "App needs OpenGl Version 3.0 or later" , Toast.LENGTH_SHORT).show(); activity.finish(); return false ; } } else { Toast.makeText(activity, "App does not support required Build Version" , Toast.LENGTH_SHORT).show(); activity.finish(); return false ; } } @Override protected void onCreate(Bundle savedInstanceState) { super .onCreate(savedInstanceState); setContentView(R.layout.activity_main); if (checkSystemSupport( this )) { // ArFragment is linked up with its respective id used in the activity_main.xml arCam = (ArFragment) getSupportFragmentManager().findFragmentById(R.id.arCameraArea); arCam.setOnTapArPlaneListener((hitResult, plane, motionEvent) -> { clickNo++; // the 3d model comes to the scene only // when clickNo is one that means once if (clickNo == 1 ) { Anchor anchor = hitResult.createAnchor(); ModelRenderable.builder() .setSource( this , R.raw.gfg_gold_text_stand_2) .setIsFilamentGltf( true ) .build() .thenAccept(modelRenderable -> addModel(anchor, modelRenderable)) .exceptionally(throwable -> { AlertDialog.Builder builder = new AlertDialog.Builder( this ); builder.setMessage( "Somthing is not right" + throwable.getMessage()).show(); return null ; }); } }); } else { return ; } } private void addModel(Anchor anchor, ModelRenderable modelRenderable) { // Creating a AnchorNode with a specific anchor AnchorNode anchorNode = new AnchorNode(anchor); // attaching the anchorNode with the ArFragment anchorNode.setParent(arCam.getArSceneView().getScene()); // attaching the anchorNode with the TransformableNode TransformableNode model = new TransformableNode(arCam.getTransformationSystem()); model.setParent(anchorNode); // attaching the 3d model with the TransformableNode // that is already attached with the node model.setRenderable(modelRenderable); model.select(); } } |
Вывод: запуск на физическом устройстве
Наконец, мы создали простое приложение дополненной реальности с помощью Android Studio. Вы можете проверить этот проект по этой ссылке на GitHub.