ARCore
ARCore 是 Google 的增强现实体验构建平台。ARCore 利用不同的 API 让手机能够感知其环境、理解现实世界并与信息互动。
设备支持
并不是所有的设备都支持ARCore,首先需要Android 7.0 或更高版本,其次需要安装适用于 AR 的 Google Play 服务。
国内手机
在国内的手机上一般是没有Google Play的,但是部分设备可以安装适用于 AR 的 Google Play 服务,这样就可以运行ARCore。
具体哪些设备支持可以查看官方文档:developers.google.cn/ar/devices#...
当我们在这些设备上运行官方提供的hello ar demo的时候就会自动安装或更新Google Play Services for AR(我的华为手机会一直卡在更新,去应用商店中进行更新即可)。
模拟器
也可以使用Android模拟器来运行ARCore,首先要求:
- Android Studio 3.1 或更高版本。
- Android 模拟器 27.2.9 或更高版本。
还需要在Android SDK中在相应 Android 版本下,选择:
Google APIs Intel x86 Atom System Image API Level 27 或更高版本。
然后创建一个虚拟机,运行 API 级别 27 或更高版本 的 x86
或 x86_64
系统映像,注意仅支持基于 x86 的 Android 模拟器架构。目前不支持其他架构,例如 arm64-v8a
、armeabi-v7
。
在虚拟机的高级选项(Show Advanced Settings )中将后置摄像头(Camera Back )设置为 VirtualScene。
注意:因为只能用x86架构,所以M1版本的mac上就不能使用,因为其上只能运行arm架构的虚拟机。
快速入门
下载官方提供的demo:github.com/google-ar/a...
bash
git clone https://github.com/google-ar/arcore-android-sdk.git
然后打开其中hello_ar_kotlin项目,运行起来。
应用启动后,如果设备上没有Google Play Services for AR或者版本低,就会下载或更新安装。如果符合条件,则会进入AR场景。
进入AR场景后会先扫描环境来寻找surface,这就涉及到一个基本概念:环境理解。我们来看看官方解释。
ARCore 会通过检测特征点和平面来不断改进对现实世界环境的理解。
ARCore 可以查找看起来位于常见水平或垂直表面(例如桌子或墙)上的聚类特征点,并将这些表面作为几何平面提供给您的应用。****ARCore 也可以确定每个几何平面的边界,并将该信息提供给您的应用。您可以使用这些信息将虚拟对象置于平坦的表面上。
由于 ARCore 使用特征点来检测平面,因此可能无法正确检测没有纹理的平坦表面(例如白墙)。
简单来说就是ARCore会分析摄像头返回的图像,会试图找出图像中的平面,然后将这些平台提供给开发者来进行处理。
当扫描完后,就可以看到用白线和点标志出来的平面,这样我们就可以在平面上放置虚拟物品,点击右上角选择Instant Placement,然后在点击屏幕就可以在相应的位置放置一个三维 ARCore 兵。如下:
启用ARCore
AR必备和AR可选
首先先来了解一下什么是AR必备和AR可选。
官方对这个解释的很详细,大家可以参考developers.google.cn/ar/develop/...
这里我简单说说。
如果一个APP是AR必备的,那么只有那些支持ARCore的设备才能在GooglePlay中找到它,而且安装APP的同时GooglePlay会自动安装面向 AR 的 Google Play 服务;AR可选则没有上面这两个特点。
所以这个设定其实是针对GooglePlay的,在国内可以忽略不计的。根据我的测试,即使APP设置了AR必备,一样可以安装到非支持设备并且可以正常启动,只是AR功能无法使用。
所以无论应用是否是AR必备的,都必须使用ArCoreApk.checkAvailability()
来检查 ARCore 支持和安装状态,对于不支持的设备要不起用AR相关功能。
另外要注意,AR必备要求minSdkVersion是24及以上,AR可选则要求19及以上。
配置
如何配置AR必备和AR可选?
AR必备
首先在AndroidManifest.xml中添加:
xml
<uses-permission android:name="android.permission.CAMERA" />
<!-- Limits app visibility in the Google Play Store to ARCore supported devices
(https://developers.google.com/ar/devices). -->
<uses-feature android:name="android.hardware.camera.ar" />
<application ...>
...
<!-- "AR Required" app, requires "Google Play Services for AR" (ARCore)
to be installed, as the app does not include any non-AR features. -->
<meta-data android:name="com.google.ar.core" android:value="required" />
</application>
然后配置minSdkVersion为24及以上就可以了。
AR可选
首先在AndroidManifest.xml中添加:
xml
<uses-permission android:name="android.permission.CAMERA" />
<!-- If your app was previously AR Required, don't forget to remove the
`<uses-feature android:name="android.hardware.camera.ar" />` entry, as
this would limit app visibility in the Google Play Store to only
ARCore supported devices. -->
<application ...>
...
<!-- "AR Optional" app, contains non-AR features that can be used when
"Google Play Services for AR" (ARCore) is not available. -->
<meta-data android:name="com.google.ar.core" android:value="optional" />
</application>
然后配置minSdkVersion为19及以上就可以了。
添加ARCore
最新的 ARCore 库作为依赖项添加到应用 的 build.gradle
文件中:
gradle
dependencies {
...
implementation 'com.google.ar:core:1.33.0'
}
运行时检查
检查是否支持ARCore
上面说过无论是AR必备还是AR可选,都需要用 ArCoreApk.checkAvailability()
来检查设备是否支持 ARCore,如果不支持就需要停用或隐藏相关的AR功能。
由于checkAvailability
是需要查询网络资源来确定是否支持,所以应该在应用早期调用一次,因为checkAvailability
可以缓存结果,这样后续再执行的时候可以直接使用缓存结果即可。
所以我们在Application中先执行一次:
kotlin
override fun onCreate() {
super.onCreate()
ArCoreApk.getInstance().checkAvailability(this)
}
然后在相关的页面再进行检查,代码如下
kotlin
fun checkAr(){
val arEnable = ArCoreApk.getInstance().checkAvailability(activity)
if(arEnable.isTransient){
Handler().postDelayed({checkAr()}, 200)
}
else if(arEnable.isSupported){
//支持,显示ar相关功能
}
else{
//不支持arcore,隐藏ar相关功能
}
}
请求相机权限
创建AR会话前需要请求相机权限,否则会话会创建失败,代码如下:
kotlin
activity?.let{
if(ContextCompat.checkSelfPermission(it, Manifest.permission.CAMERA) == PackageManager.PERMISSION_DENIED){
ActivityCompat.requestPermissions(it, arrayOf(Manifest.permission.CAMERA), 0)
return
}
...
}
为了防止用户拒绝权限后导致无法使用,还应该在onRequestPermissionsResult
中判断用户拒绝了权限就弹窗提示用户,指引用户去设置页面开启权限,这里就不放代码了。
检查是否已安装面向 AR 的 Google Play 服务
在创建AR会话前还要检查是否已安装面向 AR 的 Google Play 服务,或者确保是最新版本,代码如下:
kotlin
fun installARCore(){
activity?.let{
if(ContextCompat.checkSelfPermission(it, Manifest.permission.CAMERA) == PackageManager.PERMISSION_DENIED){
ActivityCompat.requestPermissions(it, arrayOf(Manifest.permission.CAMERA), 0)
return
}
try {
if (mSession == null) {
when(ArCoreApk.getInstance().requestInstall(it, mUserRequestedInstall)){
ArCoreApk.InstallStatus.INSTALLED -> {
mSession = Session(it)
//创建会话成功,可以使用AR
}
ArCoreApk.InstallStatus.INSTALL_REQUESTED -> {
// When this method returns `INSTALL_REQUESTED`:
// 1. ARCore pauses this activity.
// 2. ARCore prompts the user to install or update Google Play
// Services for AR (market://details?id=com.google.ar.core).
// 3. ARCore downloads the latest device profile data.
// 4. ARCore resumes this activity. The next invocation of
// requestInstall() will either return `INSTALLED` or throw an
// exception if the installation or update did not succeed.
mUserRequestedInstall = false
}
}
}
else{
//创建会话成功,可以使用AR
}
}
catch (e: UnavailableUserDeclinedInstallationException) {
//用户先前拒绝安装(有可能是无法安装,有可能是取消了)
Log.e("arcore", "install fial", e)
}
catch (e : Exception){
Log.e("arcore", "install fial", e)
}
}
}
当没有安装相关服务的时候,会自动安装面向 AR 的 Google Play 服务;如果发现版本低则会更新(不过我这更新一直不成功,在应用商店中手动更新成功的)。
当检查成功直接创建AR会话,就可以使用AR相关功能了。
一般在onResume
来执行检查,这样当安装完成后返回可以继续创建会话。
kotlin
override fun onResume() {
super.onResume()
installARCore()
}
这里注意因为创建AR会话前需要相机权限,所以在最前面申请了相机权限,如果没有相机权限则创建会话的时候会报错UnavailableDeviceNotCompatibleException
上面我们通过ArCoreApk.checkAvailability()
来检查设备是否支持 ARCore,也可以将两个检查联动起来,ArCoreApk.checkAvailability()
的返回值有多种状态,可以通过状态来判断是否需要检查服务,改动后代码如下:
kotlin
fun checkAr(){
val arEnable = ArCoreApk.getInstance().checkAvailability(activity)
if(arEnable.isTransient){
Handler().postDelayed({checkAr()}, 200)
}
else if(arEnable.isSupported){
when(arEnable){
ArCoreApk.Availability.SUPPORTED_INSTALLED -> {
mSession = Session(activity)
}
ArCoreApk.Availability.SUPPORTED_APK_TOO_OLD, ArCoreApk.Availability.SUPPORTED_NOT_INSTALLED -> {
installARCore()
}
}
}
else{
Log.d("arcore", "不支持arcore")
}
}
如果设备支持且已经安装最新版本的服务,则直接创建会话;否则支持但是没安装或者版本比较旧,则执行安装即可。
ARCore会话
这样我们就成功在项目中启用了ARCore,并且创建了AR会话,所有 AR 流程(例如运动跟踪、环境理解和光照估算)都发生在 ARCore 会话中。创建会话后可以通过Config来配置会话,如下:
kotlin
session = Session(this)
val config = Config(session)
...
session.configure(config)
关闭
Session 拥有大量原生堆内存。如果未显式关闭会话,则可能导致应用耗尽原生内存并崩溃。当不再需要 AR 会话时,调用 close() 以释放资源。可以在onDestroy() 中调用 close():
总结
这样我们就可以开始通过ARCore开发AR功能了,不过因为ARCore不是sdk而是帮助sdk渲染对象的引擎,如果使用它来进行开发还要非常熟悉openGL。
为此Google提供了Sceneform SDK让开发者可以很轻松的构建AR应用,但是很遗憾的是Sceneform与VR sdk的命运是一样的,github上的开源项目最后的提交已经是两年前了。
不过因为使用起来比较简单,所以我们可以先用Sceneform来了解一下AR。
后面我会先用几篇文章来介绍一下Sceneform SDK,让大家简单了解一下AR。至于ARCore的后续文章,需要我深入学习一下openGL再来完成,目前我简单看了一下ARCore的示例,不熟练掌握openGL真的是寸步难行。