通过Google ARCore来认识AR是什么

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 或更高版本x86x86_64 系统映像,注意仅支持基于 x86 的 Android 模拟器架构。目前不支持其他架构,例如 arm64-v8aarmeabi-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真的是寸步难行。

相关推荐
恋猫de小郭27 分钟前
Flutter Widget Preview 功能已合并到 master,提前在体验毛坯的预览支持
android·flutter·ios
断剑重铸之日1 小时前
Android自定义相机开发(类似OCR扫描相机)
android
随心最为安1 小时前
Android Library Maven 发布完整流程指南
android
岁月玲珑2 小时前
【使用Android Studio调试手机app时候手机老掉线问题】
android·ide·android studio
还鮟6 小时前
CTF Web的数组巧用
android
小蜜蜂嗡嗡7 小时前
Android Studio flutter项目运行、打包时间太长
android·flutter·android studio
aqi007 小时前
FFmpeg开发笔记(七十一)使用国产的QPlayer2实现双播放器观看视频
android·ffmpeg·音视频·流媒体
zhangphil9 小时前
Android理解onTrimMemory中ComponentCallbacks2的内存警戒水位线值
android
你过来啊你9 小时前
Android View的绘制原理详解
android
移动开发者1号12 小时前
使用 Android App Bundle 极致压缩应用体积
android·kotlin