返回博客首页
← 所有文章

NativeScript 预览快速入门 - 手电筒 🔦

2022年9月9日 — 作者:技术指导委员会 (TSC)

NativeScript 预览通过在世界上最流行的编程语言 JavaScript 中提供平台 API,实现了加速原生移动开发的概念。这让你如虎添翼。能够绕过本地开发限制,直接尝试原生 API 并获得即时反馈,这彻底改变了游戏规则!

为了说明这种新的工作流程,我们将提供一个“Hello World”类型的示例,只需几行代码即可切换手机的手电筒开关。

演示

要快速了解 NativeScript 预览的工作原理,你可以在我们的主页上阅读相关内容:此链接

简而言之,你需要下载设备上的 NativeScript 预览应用,然后扫描 StackBlitz 项目中的二维码,将应用程序推送到你的手机。然后,当你编辑应用程序时,这些更改将实时推送到你的手机。非常酷!

我们想要演示的示例在下面的链接中,让我们开始吧!

演示

设置

在你浏览应用程序时,有一些值得注意的细节需要说明。我们想要指出 NativeScript 特定的部分,以便你了解编写移动应用程序需要多少(或少)代码。

应用模块

为了赋予我们的 Angular 应用程序原生功能,我们首先需要将 NativeScriptModule 连接到我们的主模块。

我们通过从 '@nativescript/angular' 导入 NativeScriptModule,然后将其添加到 NgModule 配置对象中的导入中来实现这一点。

import { NgModule, NO_ERRORS_SCHEMA } from '@angular/core'
import { NativeScriptModule } from '@nativescript/angular'

import { AppRoutingModule } from './app-routing.module'
import { AppComponent } from './app.component'
import { TorchComponent } from './torch.component'

@NgModule({
  bootstrap: [AppComponent],
  imports: [NativeScriptModule, AppRoutingModule],
  declarations: [AppComponent, TorchComponent],
  providers: [],
  schemas: [NO_ERRORS_SCHEMA],
})
export class AppModule {}

路由模块

我们大胆地假设每个非平凡的应用程序都将拥有多个路由,因此我们也将更新我们的路由模块。这将遵循声明路由的标准约定,唯一的区别是我们正在导入并在 NgModule 配置对象中初始化 NativeScriptRouterModule

import { NgModule } from '@angular/core'
import { Routes } from '@angular/router'
import { NativeScriptRouterModule } from '@nativescript/angular'

import { TorchComponent } from './torch.component'

const routes: Routes = [
  { path: '', redirectTo: '/torch', pathMatch: 'full' },
  { path: 'torch', component: TorchComponent },
]

@NgModule({
  imports: [NativeScriptRouterModule.forRoot(routes)],
  exports: [NativeScriptRouterModule],
})
export class AppRoutingModule {}

手电筒

TorchComponent 完全是 Angular 的构造,当你考虑到你获得的回报时,这真是令人难以置信。在下面的代码片段中,我们有一个基本的按钮,它响应 tap 事件并调用 toggle

<GridLayout>
  <Button
    text="Toggle Torch"
    class="btn-primary"
    width="300"
    (tap)="toggle()"
  ></Button>
</GridLayout>

在组件类中,我们调用 toggleDeviceTorch 并传入本地 enabled state。那么手电筒是如何激活的呢?这就是事情变得更有趣的地方。

import { Component } from '@angular/core';
import { toggleDeviceTorch } from './torch';

@Component({
  selector: 'ns-torch',
  templateUrl: './torch.component.html',
})
export class TorchComponent {
  enabled = false;

  toggle() {
    this.enabled = !this.enabled;
    toggleDeviceTorch(this.enabled);
  }
}

请注意,我们正在从 ./torch 导入 toggleDeviceTorch,这将是我们旅程中的下一站。

切换

./torch 目录中,我们有三个文件。首先,我们有一个 index.d.ts,它基本上是一个类型定义文件。然后,我们有 index.android.tsindex.ios.ts,这对于 NativeScript 的新手开发者来说可能是一个“啊哈”时刻。不可避免的问题出现了,iOS 和 Android 之间的逻辑在哪里切换?好问题,答案是 NativeScript 在幕后为你处理了这一切。它将生成特定于平台的包并自动修剪针对其他平台的代码。

export declare function toggleDeviceTorch(enable: boolean);

我们不会深入探讨特定于平台的 API 细节,但让我们快速浏览一下 toggleDeviceTorch 的 iOS 和 Android 版本。

iOS 手电筒

请注意,每个平台的实现都遵循 TypeScript 定义,这使得能够在平台之间无缝切换。也就是说,我们正在实例化一个 AVCaptureDevice 实例并将该引用存储为 device。从这里,我们可以检查设备是否具有手电筒,以防万一我们在模拟器上运行。如果是,我们将解锁设备以进行配置,并根据 enable 参数,打开或关闭手电筒。只需几行代码就能做到这一点,真是不错!

export function toggleDeviceTorch(enable: boolean) {
  const device = AVCaptureDevice.defaultDeviceWithMediaType(AVMediaTypeVideo);
  if (device?.hasTorch) {
    device.lockForConfiguration();
    if (enable) {
      device.setTorchModeOnWithLevelError(1.0);
    } else {
      device.torchMode = AVCaptureTorchMode.Off;
    }
    device.unlockForConfiguration();
  }
}

我们鼓励每个人查看平台文档并将 NativeScript 与原生 API 进行比较。你可以在此处查看 iOS 文档:这里

Android 手电筒

Android 版本更加简洁,但遵循类似的原理。我们获取对 Android 应用程序上下文 的引用,然后使用该上下文获取对相机服务的引用。从那里,我们获取对相机本身的引用,然后根据 enable 属性调用 setTorchMode 打开或关闭。

import { Utils } from '@nativescript/core';

export function toggleDeviceTorch(enable: boolean) {
    const appContext = Utils.android.getApplicationContext();
    const cameraManager = appContext.getSystemService(
      android.content.Context.CAMERA_SERVICE
    );
    const camera = cameraManager.getCameraIdList()[0];
    cameraManager.setTorchMode(camera, enable);
}

你可以在此处查看 Android 文档:这里

总结

当开发者体验到从 StackBlitz 到设备的实时更新并意识到原生平台 API 触手可及的力量时,这是一个美好的时刻。目标是使丰富的平台开发感觉与你已经熟悉的任何 JavaScript 应用程序开发一样自然。

希望你喜欢这个手电筒演示。