开发准备
====

#### 硬件要求

开发者可根据实际的开发语言，选择对应接口判断当前设备是否支持AR Engine。接口的调用参考如下方式：

ArkTS（[arViewController.isARTypeSupported](https://developer.huawei.com/consumer/cn/doc/harmonyos-references/arengine-api-arviewcontroller#arviewcontrollerisartypesupported)）：

import { arEngine, arViewController } from '@kit.AREngine';

let ret: boolean = arViewController.isARTypeSupported(arEngine.ARFeatureType.ARENGINE\_FEATURE\_TYPE\_FACE);

C/C++（[HMS\_AREngine\_CheckSupported](https://developer.huawei.com/consumer/cn/doc/harmonyos-references/arengine-capi-arengine#hms_arengine_checksupported)）：

#include "ar/ar\_engine\_core.h"

auto ret = HMS\_AREngine\_CheckSupported(ARENGINE\_FEATURE\_TYPE\_FACE);

若对应接口返回错误码为801或ARENGINE\_ERROR\_DEVICE\_NOT\_SUPPORTED，则表示AR Engine不支持当前设备。

#### 环境搭建

请参考[应用开发准备](https://developer.huawei.com/consumer/cn/doc/harmonyos-guides/application-dev-overview)完成基本准备工作。

#### 申请权限

在开发AR应用时，需要先申请相机相关权限，确保应用拥有访问相机硬件及其他功能的权限，需要的权限如下表。在申请权限前，请保证符合[权限使用的基本原则](https://developer.huawei.com/consumer/cn/doc/harmonyos-guides/app-permission-mgmt-overview#权限使用的基本原则)。

*   使用相机拍摄前，需要申请**ohos.permission.CAMERA**相机权限。
    
*   当需要使用加速计感知设备运动状态时，需要申请**ohos.permission.ACCELEROMETER**加速计权限。
    
*   当需要陀螺仪感知设备位姿信息时，需要申请**ohos.permission.GYROSCOPE**陀螺仪权限。
    

#### 前置准备

推荐使用[组件导航(Navigation) (推荐)](https://developer.huawei.com/consumer/cn/doc/harmonyos-guides/arkts-navigation-navigation)作为页面路由，使用[Navigation](https://developer.huawei.com/consumer/cn/doc/harmonyos-references/ts-basic-components-navigation)的[页面生命周期](https://developer.huawei.com/consumer/cn/doc/harmonyos-guides/arkts-navigation-navdestination#页面生命周期)所示方法。

开发者需先创建首页，通过首页选择进入AR Engine场景。

1.  导入所需模块。
    
    import { abilityAccessCtrl, PermissionRequestResult } from '@kit.AbilityKit';
    import { BusinessError } from '@kit.BasicServicesKit';
    
2.  创建一个基础的页面，具体可参考[组件导航(Navigation) (推荐)](https://developer.huawei.com/consumer/cn/doc/harmonyos-guides/arkts-navigation-navigation)。
    
    @Entry
    @Component
    struct Selector {
      pageInfo: NavPathStack = new NavPathStack();
    
      build(): void {
        Navigation(this.pageInfo) {
    
        }
        .mode(NavigationMode.Stack)
        .hideTitleBar(true)
        .hideBackButton(true)
        .hideToolBar(true)
      }
    }
    
3.  创建sampleButton，封装Button及权限校验功能，使用@Builder装饰，并配置routerMap进行页面跳转。
    
    @Entry
    @Component
    struct Selector {
      pageInfo: NavPathStack = new NavPathStack();
      private hasPermission: boolean = false;
      @State context: Context = this.getUIContext().getHostContext() as Context;
    
      build(): void {
        // ...
      }
    
      @Builder
      sampleButton(sampleName: string): void {
        Button(sampleName, { type: ButtonType.Normal, stateEffect: true })
          .borderRadius(8)
          .width('50%')
          .height('5%')
          .onClick(async () => {
            if (!this.hasPermission) {
              this.hasPermission = await requestPermissionOnSetting(this.context);
              if (!this.hasPermission) {
                return;
              }
            }
            this.pageInfo.clear();
            this.pageInfo.pushDestinationByName(sampleName, null).catch((error: BusinessError) => {
              console.error(\`\[pushDestinationByName\]failed. Code: ${error.code}.\`);
            });
          })
      }
    }
    
4.  创建requestPermissionOnSetting方法用于校验在进入AR场景时是否已经获取相机权限。
    
    struct Selector {
      // ...
    }
    
    async function requestPermissionOnSetting(context: Context): Promise<boolean> {
      let requestResult: boolean = false;
      let atManager: abilityAccessCtrl.AtManager = abilityAccessCtrl.createAtManager();
      await atManager.requestPermissionOnSetting(context, \['ohos.permission.CAMERA'\])
        .then((data: abilityAccessCtrl.GrantStatus\[\]) => {
          console.info('data:' + JSON.stringify(data));
          if (data\[0\] === abilityAccessCtrl.GrantStatus.PERMISSION\_GRANTED) {
            requestResult = true;
          }
        })
        .catch((err: BusinessError) => {
          console.error('data:' + JSON.stringify(err));
        })
      return requestResult;
    }
    
5.  在页面上创建按钮，用于进入AR场景。
    
    build(): void {
      Navigation(this.pageInfo) {
        Column() {
          this.sampleButton('ARWorld'); // 进入ARWorld场景
        }
        .justifyContent(FlexAlign.SpaceEvenly)
        .width('100%')
        .height('100%')
      }
      .mode(NavigationMode.Stack)
      .hideTitleBar(true)
      .hideBackButton(true)
      .hideToolBar(true)
    }
    
6.  在onAppear中配置应用首次启动时的权限校验方法requestPermissionOnFirstStartup。
    
    struct Selector {
      // ...
      build(): void {
        Navigation(this.pageInfo) {
          Column() {
            this.sampleButton('ARWorld');
          }
          .justifyContent(FlexAlign.SpaceEvenly)
          .width('100%')
          .height('100%')
        }
        .onAppear(() => {
          this.requestPermissionOnFirstStartup();
        })
        .mode(NavigationMode.Stack)
        .hideTitleBar(true)
        .hideBackButton(true)
        .hideToolBar(true)
      }
    
      @Builder
      sampleButton(sampleName: string): void {
        // ...
      }
    
      private requestPermissionOnFirstStartup(): void {
        abilityAccessCtrl.createAtManager()
          .requestPermissionsFromUser(this.context, \['ohos.permission.CAMERA'\])
          .then((data: PermissionRequestResult) => {
            let grantStatus: number\[\] = data.authResults;
            if (grantStatus\[0\] === 0) {
              this.hasPermission = true;
              console.info('Succeeded in getting requestPermission.');
            } else {
              this.hasPermission = false;
              console.error('Failed to get requestPermission, user rejected.');
            }
          })
          .catch((err: BusinessError) => {
            console.error(\`Failed to request permissions from user. Code is ${err.code}, message is ${err.message}.\`);
          })
      }
    }