はじめに
AndroidのスマートフォンでAR(拡張現実)を表示できるアプリを作ってみようと思う。
Androidで動作するARアプリを作る場合はGoogle公式のARCoreを使用するのが有力な候補だと思うが、このARCoreをクロスプラットフォームアプリを作成できるFlutterで使えるようにしたい。
有り難いことに、FlutterでARCoreを使用するための「arcore_flutter_plugin」というパッケージがpubで公開されており、さらにこのパッケージを使用したサンプルも公式のGithubで公開されているので、まずはこのサンプルをAndroid上で動かすことを目標とする。
iPhoneでARアプリを作成したい場合
[Flutter開発]FlutterとARKitを組み合わせてARアプリを作成してみる という記事も作成しているので、こちらを参考にしてほしい。
環境情報
開発環境
- Windows 10 Home
- Android Studio
3.4.2
- Flutter
1.7.8+hotfix.4
- arcore_flutter_plugin
端末環境
- Pixel2(Emulator)
Android 8.1 Oreo
作成手順
新規のFlutterプロジェクトを作成
新規のFlutterプロジェクトを作成する。名前は「flutter_arcore_test_app」としてみた。
arcore_flutter_pluginのインストール
Flutterプロジェクトを作成できたら、pubspec.yamlを開いてarcore_flutter_pluginの記述を追加する。
dependencies:
flutter:
sdk: flutter
# The following adds the Cupertino Icons font to your application.
# Use with the CupertinoIcons class for iOS style icons.
cupertino_icons: ^0.1.2
arcore_flutter_plugin: ^0.0.2+1 #この行を追加
main.dartを開き、「Get Dependenceis」を押してarcore_flutter_pluginをインストールする。
main.dartの書き換え
main.dartを以下の内容に書き換える。
import 'package:arcore_flutter_plugin/arcore_flutter_plugin.dart';
import 'package:flutter/material.dart';
import 'package:vector_math/vector_math_64.dart' as vector;
class HelloWorld extends StatefulWidget {
@override
_HelloWorldState createState() => _HelloWorldState();
}
class _HelloWorldState extends State<HelloWorld> {
ArCoreController arCoreController;
@override
Widget build(BuildContext context) {
return MaterialApp(
home: Scaffold(
appBar: AppBar(
title: const Text('Hello World'),
),
body: ArCoreView(
onArCoreViewCreated: _onArCoreViewCreated,
),
),
);
}
void _onArCoreViewCreated(ArCoreController controller) {
arCoreController = controller;
_addSphere(arCoreController);
_addCylindre(arCoreController);
_addCube(arCoreController);
}
void _addSphere(ArCoreController controller) {
final material = ArCoreMaterial(
color: Color.fromARGB(120, 66, 134, 244), texture: "earth.jpg");
final sphere = ArCoreSphere(
materials: [material],
radius: 0.1,
);
final node = ArCoreNode(
shape: sphere,
position: vector.Vector3(0, 0, -1.5),
);
controller.add(node);
}
void _addCylindre(ArCoreController controller) {
final material = ArCoreMaterial(
color: Colors.red,
reflectance: 1.0,
);
final cylindre = ArCoreCylinder(
materials: [material],
radius: 0.5,
height: 0.3,
);
final node = ArCoreNode(
shape: cylindre,
position: vector.Vector3(0.0, -0.5, -2.0),
);
controller.add(node);
}
void _addCube(ArCoreController controller) {
final material = ArCoreMaterial(
color: Color.fromARGB(120, 66, 134, 244),
metallic: 1.0,
);
final cube = ArCoreCube(
materials: [material],
size: vector.Vector3(0.5, 0.5, 0.5),
);
final node = ArCoreNode(
shape: cube,
position: vector.Vector3(-0.5, 0.5, -3.5),
);
controller.add(node);
}
@override
void dispose() {
arCoreController.dispose();
super.dispose();
}
}
AndroidManifest.xmlにエントリを追加する
/android/app/src/main/AndroidManifest.xml
を開き、以下のエントリを追加する。
<!-- "AR Required" apps must declare minSdkVersion ≥ 24 -->
<uses-sdk android:minSdkVersion="24" />
<uses-permission android:name="android.permission.CAMERA" />
<!-- Indicates that app requires ARCore ("AR Required"). Ensures app is only
visible in the Google Play Store on devices that support ARCore.
-->
<uses-feature android:name="android.hardware.camera.ar" />
<application>
…
<!-- Indicates that app requires ARCore ("AR Required"). Causes Google
Play Store to download and install ARCore when the app is installed.
-->
<meta-data android:name="com.google.ar.core" android:value="required" />
</application>
エントリを追加すると、AndroidManifest.xmlは以下のようになる。
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="xxx.xxxxx.flutter_arcore_test_app">
<!-- io.flutter.app.FlutterApplication is an android.app.Application that
calls FlutterMain.startInitialization(this); in its onCreate method.
In most cases you can leave this as-is, but you if you want to provide
additional functionality it is fine to subclass or reimplement
FlutterApplication and put your custom class here. -->
<!-- "AR Required" apps must declare minSdkVersion ≥ 24 -->
<uses-sdk android:minSdkVersion="24" />
<uses-permission android:name="android.permission.CAMERA" />
<!-- Indicates that app requires ARCore ("AR Required"). Ensures app is only
visible in the Google Play Store on devices that support ARCore.
-->
<uses-feature android:name="android.hardware.camera.ar" />
<application
android:name="io.flutter.app.FlutterApplication"
android:label="flutter_arcore_test_app"
android:icon="@mipmap/ic_launcher">
<activity
android:name=".MainActivity"
android:launchMode="singleTop"
android:theme="@style/LaunchTheme"
android:configChanges="orientation|keyboardHidden|keyboard|screenSize|locale|layoutDirection|fontScale|screenLayout|density|uiMode"
android:hardwareAccelerated="true"
android:windowSoftInputMode="adjustResize">
<!-- This keeps the window background of the activity showing
until Flutter renders its first frame. It can be removed if
there is no splash screen (such as the default splash screen
defined in @style/LaunchTheme). -->
<meta-data
android:name="io.flutter.app.android.SplashScreenUntilFirstFrame"
android:value="true" />
<intent-filter>
<action android:name="android.intent.action.MAIN"/>
<category android:name="android.intent.category.LAUNCHER"/>
</intent-filter>
</activity>
<!-- Indicates that app requires ARCore ("AR Required"). Causes Google
Play Store to download and install ARCore when the app is installed.
-->
<meta-data android:name="com.google.ar.core" android:value="required" />
</application>
</manifest>
ビルドの依存関係を確認
プロジェクトのbuild.gradleを確認
/android/gradle/build.gradle
を開き、allprojectsにgoogleのレポジトリ指定が含まれていることを確認。
allprojects {
repositories {
google()
jcenter()
}
}
アプリのbuild.gradleにARCoreとSceneformの依存関係を追加
/android/app/build.gradle
に以下の記述を追加する。
android {
// compileSdkVersionの指定はもともとあるはず
compileSdkVersion 28
// 省略
// compileOptionsの指定は追加する
compileOptions {
sourceCompatibility 1.8
targetCompatibility 1.8
}
// defaultConfigのminSdkVersion指定を24に書き換える
defaultConfig {
// 省略
minSdkVersion 24
// 省略
}
// 省略
}
// もともとあるdependenciesの指定に以下の3行を追加する
dependencies {
// 省略
implementation 'com.google.ar.sceneform.ux:sceneform-ux:1.8.0'
implementation 'com.google.ar.sceneform:core:1.8.0'
implementation 'com.google.ar:core:1.8.0'
}
AndroidXを有効にする
/android/gradle.properties
を開き、useAndroidXがtrueであることを確認しておく。
org.gradle.jvmargs = -Xmx1536M
android.useAndroidX = true
android.enableJetifier = true
実行してみる
ARCoreに対応している実機
ARCoreは、Android 7.0(Nougat)以降であることが動作前提となっているが、これを満たしていてもすべてのAndroid端末でARCoreが動作するわけではないところに注意が必要。
以下にARCoreが動作することを確認できている端末の一覧が公開されているので、持っているAndroid端末がこのリストに載っていれば実機で動作確認ができる。
ARCore supported devices
ARCore対応のAndroid端末を持っていなかったり、そもそもiPhoneユーザだという方は、大人しくAndroidエミュレータで動作確認をすることになる。
エミュレータで実行してみる
仮想端末の用意
GoogleのAndroid端末「Pixel2」を選択し、OSは「Android 8.1 Oreo」のシステムイメージを使用した。
カメラエミュレータでの実行結果
作成したFlutterプロジェクトをエミュレータで実行するとまずはアプリが起動し、写真の撮影とビデオの保存を許可するかどうか聞いてくるのでALLOW(許可)をタップする。
アプリに3Dの部屋が映し出され、円柱と立方体のARオブジェクトが表示される。
この3Dの部屋はエミュレータでカメラ映像を使用するときにデフォルトで表示されるもののようで、Altキーを押すとカメラのアングル変更や移動もできるようになっている。(ただし操作は結構難しい)
行いたいカメラ操作 | キー入力 |
---|---|
カメラアングルを右に向ける | [Alt]キー + 右方向にスワイプ |
カメラアングルを左に向ける | [Alt]キー + 左方向にスワイプ |
カメラアングルを上に向ける | [Alt]キー + 上方向にスワイプ |
カメラアングルを下に向ける | [Alt]キー + 下方向にスワイプ |
カメラ位置を前に進める | [Alt]キー + [w]キー |
カメラ位置を後ろに進める | [Alt]キー + [s]キー |
カメラ位置を右に進める | [Alt]キー + [d]キー |
カメラ位置を左に進める | [Alt]キー + [a]キー |
カメラ位置を上げる | [Alt]キー + [e]キー |
カメラ位置を下げる | [Alt]キー + [q]キー |
まとめ
ARCoreの面白いところは、対応端末がAndroid端末だけでなくiOS端末も含まれているところだ。
FlutterにARKitとARCoreを組み合わせれば、Android向けとiOS向けのARアプリを同じコードベースで開発できるのではないかと期待していたが、ARCoreがiOS端末もカバーするのならARKitを使用しなくてもよいのかもしれない。(Apple純正のARKitに対して、ARCoreのiOS対応が見劣りしなければの話ではあるが)
[Flutter開発]FlutterとARKitを組み合わせてARアプリを作成してみる という記事でiOS向けのARサンプルアプリを実行するところまでできているので、次のステップとしてはFlutterの強みを生かして同一のコードベースからAndroid・iOSの双方のアプリをビルドできるようにしてみたいと考えている。
参考URL
arcore_flutter_pluginのパッケージ及びソース配布
pub.dev (arcore_flutter_plugin)
Github (arcore_flutter_plugin)
arcore_flutter_pluginの使用方法を紹介した公式記事
ARCore Flutter Plugin: configurations
ARCore Flutter Plugin: add object on the plane