在 Android 应用中启用 AR

让 AR 功能在您的新应用或现有应用中使用增强现实功能。

将应用配置为 AR 必备或 AR 可选

为了节省个别设备上的空间,所有 AR 功能都会存储在名为“面向 AR 的 Google Play 服务”的应用中,并由 Play 商店单独更新。使用 AR 功能的 Android 应用通过 ARCore SDK 与 Google Play 服务进行 AR 通信。支持 AR 功能的应用可以通过以下两种方式进行配置:AR 必备AR 可选。此标识决定了该应用如何与 AR 应用的 Google Play 服务进行交互。

如果没有 ARCore,所需的 AR 应用将无法正常运行。这需要 ARCore 支持的设备安装了 AR 版 Google Play 服务。

  • Google Play 商店仅在支持 ARCore 的设备上提供 AR 必备应用。
  • 当用户安装 AR 必备应用时,Google Play 商店会自动在其设备上安装适用于 AR 的 Google Play 服务。不过,如果 Google Play 服务面向 AR 的版本已过时或已被手动卸载,您的应用仍必须执行额外的运行时检查

AR 可选应用使用 ARCore 增强现有功能。它具有可选的 AR 功能,这些功能仅在安装了 AR 服务的 ARCore 支持设备上激活。

  • AR 可选应用可在不支持 ARCore 的设备上安装和运行。
  • 当用户安装 AR 可选应用时,Google Play 商店不会自动为设备安装 AR 专用 Google Play 服务。
AR 必备AR(可选)
AR 功能使用情况 您的应用需要 ARCore 来实现基本功能。 ARCore 增强了应用的功能。您的应用可以在没有 ARCore 支持的情况下运行。
Play 商店公开范围 您的应用仅列在支持 ARCore 的设备上的 Play 商店中。 您的应用遵循常规的商品详情展示流程
“面向 AR 的 Google Play 服务”安装方法 Play 商店会随应用一起安装“面向 AR 的 Google Play 服务”。 您的应用使用 ArCoreApk.requestInstall() 下载并安装 ARCore。
Android minSdkVersion 要求 Android 7.0(API 级别 24) Android 7.0(API 级别 24)
必须使用 ArCoreApk.checkAvailability() 检查 ARCore 支持和安装状态
必须使用 ArCoreApk.requestInstall() 安装“面向 AR 的 Google Play 服务”

如需将应用设为 AR 必备或 AR 可选,请更新您的 AndroidManifest.xml 以添加以下条目:

AR 必备

<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>

AR(可选)

<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>

然后,修改应用的 build.gradle 以指定 minSdkVersion 至少为 24

 android {
     defaultConfig {
         …
         minSdkVersion 24
     }
 }

添加 build 依赖项

如需将 ARCore 添加到您的 Android Studio 项目,请执行以下操作:

  1. 确保项目的 build.gradle 文件包含 Google 的 Maven 代码库。

    allprojects {
        repositories {
            google()
            …
        }
    }
    
  2. 将最新的 ARCore 库作为依赖项添加到应用的 build.gradle 文件中。

    dependencies {
        …
        implementation 'com.google.ar:core:1.33.0'
    }
    

执行运行时检查

在运行时,执行以下操作以确保应用上的 AR 功能能够顺畅运行。

检查 ARCore 是否受支持

AR 必备应用和 AR 可选应用都应使用 ArCoreApk.checkAvailability() 来确定当前设备是否支持 ARCore。在不支持 ARCore 的设备上,应用应停用 AR 相关功能并隐藏关联的界面元素。

Kotlin

override fun onCreate(savedInstanceState: Bundle?) {
  super.onCreate(savedInstanceState)

  // Enable AR-related functionality on ARCore supported devices only.
  maybeEnableArButton()
  …
}

fun maybeEnableArButton() {
  val availability = ArCoreApk.getInstance().checkAvailability(this)
  if (availability.isTransient) {
    // Continue to query availability at 5Hz while compatibility is checked in the background.
    Handler().postDelayed({
      maybeEnableArButton()
    }, 200)
  }
  if (availability.isSupported) {
    mArButton.visibility = View.VISIBLE
    mArButton.isEnabled = true
  } else { // The device is unsupported or unknown.
    mArButton.visibility = View.INVISIBLE
    mArButton.isEnabled = false
  }
}

Java

@Override
protected void onCreate(Bundle savedInstanceState) {
  super.onCreate(savedInstanceState);

  // Enable AR-related functionality on ARCore supported devices only.
  maybeEnableArButton();
  …
}

void maybeEnableArButton() {
  ArCoreApk.Availability availability = ArCoreApk.getInstance().checkAvailability(this);
  if (availability.isTransient()) {
    // Continue to query availability at 5Hz while compatibility is checked in the background.
    new Handler().postDelayed(new Runnable() {
      @Override
      public void run() {
        maybeEnableArButton();
      }
    }, 200);
  }
  if (availability.isSupported()) {
    mArButton.setVisibility(View.VISIBLE);
    mArButton.setEnabled(true);
  } else { // The device is unsupported or unknown.
    mArButton.setVisibility(View.INVISIBLE);
    mArButton.setEnabled(false);
  }
}

即使“面向 AR 的 Google Play 服务”是随 AR 必备应用一起安装的,用户也可以使用不受支持的设备安装 AR。使用 ArCoreApk.checkAvailability() 检查是否支持 ARCore 可确保实现一致的体验。

ArCoreApk.checkAvailability() 可能需要查询网络资源来确定设备是否支持 ARCore。在此期间,它将返回 UNKNOWN_CHECKING。为了减少感知延迟时间和弹跳次数,应用应在其生命周期的早期阶段调用一次 ArCoreApk.checkAvailability() 以启动查询,并忽略返回值。这样一来,在可能显示进入 AR 的界面元素时,便可立即提供缓存的结果。

检查是否已安装面向 AR 的 Google Play 服务

AR 必备和 AR 可选应用在创建 ARCore 会话之前都必须调用 ArCoreApk.requestInstall(),以检查是否(仍然)安装了适用于 AR 的兼容 Google Play 服务版本,并确保已下载所有必需的 ARCore 设备配置文件数据。

Kotlin

// requestInstall(Activity, true) will triggers installation of
// Google Play Services for AR if necessary.
var mUserRequestedInstall = true

override fun onResume() {
  super.onResume()

  // Check camera permission.
  …

  // Ensure that Google Play Services for AR and ARCore device profile data are
  // installed and up to date.
  try {
    if (mSession == null) {
      when (ArCoreApk.getInstance().requestInstall(this, mUserRequestedInstall)) {
        ArCoreApk.InstallStatus.INSTALLED -> {
          // Success: Safe to create the AR session.
          mSession = Session(this)
        }
        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
          return
        }
      }
    }
  } catch (e: UnavailableUserDeclinedInstallationException) {
    // Display an appropriate message to the user and return gracefully.
    Toast.makeText(this, "TODO: handle exception " + e, Toast.LENGTH_LONG)
        .show()
    return
  } catch (…) {
    …
    return  // mSession remains null, since session creation has failed.
  }
  …
}

Java

// requestInstall(Activity, true) will trigger installation of
// Google Play Services for AR if necessary.
private boolean mUserRequestedInstall = true;

@Override
protected void onResume() {
  super.onResume();

  // Check camera permission.
  …

  // Ensure that Google Play Services for AR and ARCore device profile data are
  // installed and up to date.
  try {
    if (mSession == null) {
      switch (ArCoreApk.getInstance().requestInstall(this, mUserRequestedInstall)) {
        case INSTALLED:
          // Success: Safe to create the AR session.
          mSession = new Session(this);
          break;
        case 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;
          return;
      }
    }
  } catch (UnavailableUserDeclinedInstallationException e) {
    // Display an appropriate message to the user and return gracefully.
    Toast.makeText(this, "TODO: handle exception " + e, Toast.LENGTH_LONG)
        .show();
    return;
  } catch (…) {
    …
    return;  // mSession remains null, since session creation has failed.
  }
  …
}

请求相机权限

AR 可选应用和 AR 必备应用都必须确保相机权限已授予,然后才能创建 AR 会话。

Kotlin

override fun onResume() {
  super.onResume()

  // ARCore requires camera permission to operate.
  if (!CameraPermissionHelper.hasCameraPermission(this)) {
    CameraPermissionHelper.requestCameraPermission(this)
    return
  }

  …
}

Java

@Override
protected void onResume() {
  super.onResume();

  // ARCore requires camera permission to operate.
  if (!CameraPermissionHelper.hasCameraPermission(this)) {
    CameraPermissionHelper.requestCameraPermission(this);
    return;
  }

  …
}

您的 AR activity 还必须实现 onRequestPermissionsResult()

Kotlin

override fun onRequestPermissionsResult(
  requestCode: Int,
  permissions: Array<String>,
  results: IntArray
) {
  super.onRequestPermissionsResult(requestCode, permissions, results)
  if (!CameraPermissionHelper.hasCameraPermission(this)) {
    Toast.makeText(this, "Camera permission is needed to run this application", Toast.LENGTH_LONG)
      .show()
    if (!CameraPermissionHelper.shouldShowRequestPermissionRationale(this)) {
      // Permission denied with checking "Do not ask again".
      CameraPermissionHelper.launchPermissionSettings(this)
    }
    finish()
  }
}

Java

@Override
public void onRequestPermissionsResult(int requestCode, String[] permissions, int[] results) {
  super.onRequestPermissionsResult(requestCode, permissions, results);
  if (!CameraPermissionHelper.hasCameraPermission(this)) {
    Toast.makeText(this, "Camera permission is needed to run this application", Toast.LENGTH_LONG)
        .show();
    if (!CameraPermissionHelper.shouldShowRequestPermissionRationale(this)) {
      // Permission denied with checking "Do not ask again".
      CameraPermissionHelper.launchPermissionSettings(this);
    }
    finish();
  }
}

遵守用户隐私要求

若要在 Play 商店中发布您的应用,请确保您的应用符合 ARCore 的用户隐私要求

后续步骤