在 Android NDK 應用程式中啟用 AR

只要啟用 AR,即可在現有或新的應用程式中使用擴增實境功能。

將應用程式設為必要的 AR 或 AR 選用功能

為了節省個別裝置的儲存空間,所有 AR 功能都儲存在名為 Google Play 服務 - AR 適用的應用程式中,該應用程式會由 Play 商店另行更新。使用 AR 功能的 Android 應用程式會透過 ARCore SDK 與 Google Play 服務 - AR 通訊。支援 AR 功能的應用程式可以透過兩種方式設定:「AR 要求」和「AR 選用」。此類別會決定應用程式與 Google Play 服務 - AR 應用程式的互動方式。

AR 要求應用程式無法在沒有 ARCore 的情況下運作。必須使用支援 ARCore 的裝置,且已安裝 Google Play 服務 - AR。

  • Google Play 商店只會在支援 ARCore 的裝置上提供必要的 AR 應用程式。
  • 使用者安裝 AR 要求的應用程式後,Google Play 商店會自動在裝置上安裝 Google Play 服務 - AR 適用。不過,即使 Google Play 適用的 AR 服務版本過舊或使用者已手動解除安裝,應用程式仍須執行其他執行階段檢查

AR 選用應用程式會使用 ARCore 強化現有功能。這款遊戲包含選用的 AR 功能,但只有支援 ARCore 且已安裝「Google Play 服務 - AR 適用」的裝置才能啟用。

  • AR 選用應用程式可以在不支援 ARCore 的裝置上安裝及執行。
  • 使用者安裝 AR 選用應用程式時,Google Play 商店不會自動在裝置上安裝 Google Play 服務 - AR 適用。
需要 ARAR 選用
AR 功能使用情形 您的應用程式需要有 ARCore 才能使用基本功能。 ARCore 可強化應用程式的功能。您的應用程式可在不支援 ARCore 的情況下執行。
Play 商店瀏覽權限 您的應用程式只會在支援 ARCore 的裝置的 Play 商店中列出。 應用程式符合一般商店資訊程序
Google Play 服務 - AR 安裝方式 Play 商店會同時安裝您的應用程式適用的 Google Play 服務 - AR。 應用程式使用 ArCoreApk.requestInstall() 下載並安裝 ARCore。
Android minSdkVersion 需求 Android 7.0 (API 級別 24) Android 4.4 (API 級別 19) 版本,但如要執行任何 AR 功能,則至少需要 Android 7.0 (API 級別 24)
必須使用 ArCoreApk_checkAvailability()ArCoreApk_checkAvailabilityAsync() 才能檢查 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,指定至少 24minSdkVersion

 android {
     defaultConfig {
         …
         minSdkVersion 24
     }
 }

新增建構依附元件

  1. 確認專案的 build.gradle 檔案包含 Google 的 Maven 存放區。

    allprojects {
        repositories {
            google()
            …
        }
    }
    
  2. 在模組的 build.gradle 檔案中新增自訂工作,以從 ARCore AAR 檔案擷取內含的原生資料庫。如此一來,就能直接在 C 或 C++ 專案中參照這些程式庫。

  3. app/build 目錄中,定義要擷取原生資料庫的目錄變數。

  4. 建立 Gradle 設定以存放資料和擷取工作。

    /*
    The ARCore AAR library contains native shared libraries that are
    extracted before building to a temporary directory.
    */
    def arcore_libpath = "${buildDir}/arcore-native"
    
    // Create a configuration to mark which aars to extract .so files from
    configurations { natives }
    
  5. 建立工作,以便從 AAR 檔案複製原生資料庫,並將其新增至建構依附元件。

    // Extracts the shared libraries from AARs in the native configuration
    // so that NDK builds can access these libraries.
    task extractNativeLibraries() {
       // Extract every time.
       outputs.upToDateWhen { false }
    
       doFirst {
            configurations.natives.files.each { f ->
                copy {
                    from zipTree(f)
                    into arcore_libpath
                    include "jni/**/*"
                }
            }
        }
    }
    
    tasks.whenTaskAdded {
        task-> if (task.name.contains("external") && !task.name.contains("Clean")) {
            task.dependsOn(extractNativeLibraries)
        }
    }
    
  6. 設定原生建構旗標,將位置傳送至外部建構工具。

    // From the sample app.
    externalNativeBuild {
        cmake {
            cppFlags "-std=c++11", "-Wall"
            arguments "-DANDROID_STL=c++_static",
                    "-DARCORE_LIBPATH=${arcore_libpath}/jni",
                    "-DARCORE_INCLUDE=${project.rootDir}/../../libraries/include"
        }
    }
    
  7. 新增 Java 和原生資料庫的依附元件。

    dependencies {
         ...
         // Add Java and native dependencies to the ARCore library.
         implementation 'com.google.ar:core:1.33.0'
         natives 'com.google.ar:core:1.33.0'
         ...
    }
    
  8. 參照 CMakeLists.txt 中的原生資料庫。

    # Import the ARCore library.
    add_library(arcore SHARED IMPORTED)
    set_target_properties(arcore PROPERTIES IMPORTED_LOCATION
                  ${ARCORE_LIBPATH}/${ANDROID_ABI}/libarcore_sdk_c.so
                  INTERFACE_INCLUDE_DIRECTORIES ${ARCORE_INCLUDE}
    )
    

執行執行階段檢查

在執行階段執行下列作業,確保應用程式的 AR 功能運作順暢。

檢查是否支援 ARCore

AR 必要和 AR 選用應用程式均應使用 ArCoreApk_checkAvailability()ArCoreApk_checkAvailabilityAsync(),判斷目前裝置是否支援 ARCore。在不支援 ARCore 的裝置上,應用程式應停用 AR 相關功能,並隱藏相關的 UI 元素。

Android NDK 應用程式可能會使用 Java ArCoreApk 類別檢查相容性及管理原生 C ARCore Session API 中的安裝作業。視應用程式的結構而定,這可能會比使用 ArCoreApk_ 函式更容易,因為需要處理大量的錯誤處理和使用者介面互動。

void maybeEnableArButton(JNIEnv env, jobject context) {
  // Likely called from Activity.onCreate() of an activity with AR buttons.
  ArAvailability availability
  ArCoreApk_checkAvailability(env, context, &availability);
  if (availability == AR_AVAILABILITY_UNKNOWN_CHECKING) {
    // Set a timer to call maybeEnableArButton() again after about 200ms.
  }
  if (availability == AR_AVAILABILITY_SUPPORTED_NOT_INSTALLED ||
      availability == AR_AVAILABILITY_SUPPORTED_APK_TOO_OLD ||
      availability == AR_AVAILABILITY_SUPPORTED_INSTALLED) {
    // Show or enable the AR button.
  } else {
    // Hide or disable the AR button.
  }
}
雖然系統會一併安裝「Google Play 服務 - AR 適用」並安裝必要的 AR 應用程式,但如果使用者的裝置不支援這項功能,則可能從外部來源安裝應用程式。使用 ArCoreApk_checkAvailability()ArCoreApk_checkAvailabilityAsync() 檢查 ARCore 支援情形,確保提供一致的體驗。

ArCoreApk_checkAvailability() 可能需要查詢網路資源,才能判斷裝置是否支援 ARCore。在這段期間,系統會傳回 AR_AVAILABILITY_UNKNOWN_CHECKING。為縮短感知延遲時間和彈出的時間,應用程式應在生命週期的早期一次呼叫 ArCoreApk_checkAvailability() 來啟動查詢 (忽略傳回的值)。如此一來,在顯示 AR 進入 UI 元素時,就會立即使用快取結果。

檢查是否已安裝「Google Play 服務 - AR 適用」

使用 AR 必要和 AR 選用應用程式前,都必須使用 ArCoreApk.requestInstall() 建立 ARCore 工作階段,檢查是否已安裝相容的「Google Play 服務 - AR 適用」版本,並確認已下載所有必要的 ARCore 裝置設定檔資料。

// Tracks if an installation request has already been triggered.
bool install_requested_;

void nativeOnCreate() {
  // Do other setup here.

  install_requested_ = false;
}

void nativeOnResume(JNIEnv env, jobject activity) {
  if (ar_session_ == null) {
    bool user_requested_install = !install_requested_;

    ArInstallStatus install_status;
    // Ensure that Google Play Services for AR and ARCore device profile data are
    // installed and up to date.
    ArStatus error = ArCoreApk_requestInstall(
        env, activity, user_requested_install, &install_status);
    if (error != AR_SUCCESS) {
      // Inform user of error.
      return;
    }

    switch (install_status) {
      case AR_INSTALL_STATUS_INSTALLED:
        break;
      case AR_INSTALL_STATUS_INSTALL_REQUESTED:
        // When this method returns AR_INSTALL_STATUS_INSTALL_REQUESTED:
        // 1. This activity will be paused.
        // 2. The user is prompted 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. This activity is resumed. The next invocation of
        //    ArCoreApk_requestInstall() will either return
        //    AR_INSTALL_STATUS_INSTALLED or throw an exception if the
        //    installation or update did not succeed.
        install_requested_ = true;
        return;
    }

    // Request camera permissions.

    error = ArSession_create(env, context, &ar_session_);
    if (error != AR_SUCCESS) {
      // Inform user of error.
      return;
    }

    // Configure the ARCore session.
  }

  // Normal onResume behavior.
}

遵守使用者隱私權規定

如要在 Play 商店中發布應用程式,請確認您的應用程式符合 ARCore 的「使用者隱私權規定」。

後續步驟