返回博客首页
← 所有文章

使用 NativeScript 增强您的 Capacitor 开发

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

假设您有一个 Web 应用程序,并且您希望今天将其部署到移动应用商店。您可以使用 Capacitor 来完成此操作。如果您使用过 Ionic 来构建您的 UI,那么您可能处于更好的位置,因为两者都是由同一个团队制作的,并且配合得很好。

NativeScript 也与两者配合得很好,为您提供了更多选择来解决您的移动开发挑战。

在 2021 年 2 月,我们 宣布了 NativeScript for Capacitor 的公开测试版,我们非常感谢我们收到的所有反馈。它使我们能够修复一些关键细节,并改进您如何使用它来解决您自己的挑战。

NativeScript for Capacitor 1.0

随着 最近宣布 Capacitor 3,我们发布了 NativeScript for Capacitor 1.0,并且已经开始享受它的乐趣。

开发团队按其语言技能划分(或部门化)的情况并不少见,这会造成沟通、理解方面的隔阂,并需要编写更多文档,这些文档需要团队维护和理解。这为您的开发堆栈增加了另一层,您或团队中的某个人有一天需要调试、改进或仅仅更新它。例如,一个平台 API 团队(Objective C、Swift、Java、Kotlin 等)通常会围绕一组特定的平台 API 功能创建一个包装器/插件,并公开一个新的 API,然后将其提供给 Web 开发人员以用于那些确切的平台需求。

NativeScript 允许本地平台开发人员与 Web 开发团队在同一个代码库中,甚至在同一个 IDE 中协同工作。根据我们的经验,我们发现 Web 开发人员通过使用 JavaScript(通常是他们的首选语言)以及使用 NativeScript 的能力来使用平台源代码文档来解决现实世界的日常挑战,从而成为更好的本地平台开发人员。

  • 如果您是 Web 开发人员,您现在有能力直接接触您的本地设备平台 API。
  • 如果您是本地平台 API 开发人员,您现在有能力提供以 Web 开发团队的首选语言 JavaScript 说话的解决方案。

这使两个部门能够共同解决日常挑战;提高团队对影响项目开发的所有 API 的理解和沟通。

要将其用于您今天的 Ionic + Capacitor 开发,它全部都包含在一个方便的 npm 包中

yarn add @nativescript/capacitor

或者,如果您使用的是 npm:npm install @nativescript/capacitor

在此处查看更多文档

一些示例

让我们看一下在您的 Capacitor 应用程序中以编程方式设置设备屏幕亮度(该应用程序可能正在使用 Ionic 与 Angular、React 或 Vue,而现在可以使用 NativeScript)的 Android 示例。

// change Android screen brightness
const context = native.androidCapacitorActivity;
if (!android.provider.Settings.System.canWrite(context)) {
  const intent = new android.content.Intent(android.provider.Settings.ACTION_MANAGE_WRITE_SETTINGS);
  intent.setData(android.net.Uri.parse("package:" + context.getPackageName()));
  intent.addFlags(android.content.Intent.FLAG_ACTIVITY_NEW_TASK);
  context.startActivity(intent);
}

if (android.provider.Settings.System.canWrite(context)) {
  android.provider.Settings.System.putInt(context.getContentResolver(), android.provider.Settings.System.SCREEN_BRIGHTNESS, value * 100);
}

🚨 新的质量保证错误票证

我们收到了有关在用户导航到应用程序中的“电影模式”功能时旧版 Android 设备发生崩溃的报告,在该功能中我们应该预期看到屏幕亮度自动增加到至少 80%。

哦,等等,您的意思是 Android API 级别 22 及以下使用不同的 API 来设置屏幕亮度?!

通常,这种意外会需要平台 API 开发人员对插件进行更改,然后需要重新构建、版本提升,然后重新发布,以便 Web 开发团队获得修改。

我们更喜欢能够这样做

// change Android screen brightness (including API level 22 and below)
const context = native.androidCapacitorActivity;
if (android.os.Build.VERSION.SDK_INT < 23) {
  const attr = context.getWindow().getAttributes();
  attr.screenBrightness = value;
  context.getWindow().setAttributes(attr);
} else {
  if (!android.provider.Settings.System.canWrite(context)) {
    const intent = new android.content.Intent(android.provider.Settings.ACTION_MANAGE_WRITE_SETTINGS);
    intent.setData(android.net.Uri.parse("package:" + context.getPackageName()));
    intent.addFlags(android.content.Intent.FLAG_ACTIVITY_NEW_TASK);
    context.startActivity(intent);
  }

  if (android.provider.Settings.System.canWrite(context)) {
    android.provider.Settings.System.putInt(context.getContentResolver(), android.provider.Settings.System.SCREEN_BRIGHTNESS, value * 100);
  }
}

完成并继续前进。

NativeScript 从一开始(大约在 2014 年)就使用 TypeScript 编写,因此您在 NativeScript 中处理的每个 API 都严格针对直接从平台 API 映射出来的定义进行类型化。这些类型化通过 @nativescript/types 提供。每个平台标记为公开可用的 API 都旨在用于开发,因此映射到您可以用 TypeScript 代码库中使用的严格类型化结构。

让我们最后再看一下 iOS 例子,该例子用于执行相同的操作,设置屏幕亮度

UIScreen.mainScreen.brightness = .8;

就这些吗?我的意思是,我不需要插件来做这个?

好吧,一个 @nativescript/capacitor,就像获得了数百个插件一样。

从您的 Web 组件使用平台 API

只需从 @nativescript/capacitor 导入 native 对象,您就可以从一个全新的角度解决现实世界的开发挑战,而无需离开您的 Web 组件

import { native } from '@nativescript/capacitor';

native.UIScreen.mainScreen.brightness.set(.8);

嗯?

native 对象是一个 JavaScript 代理,它只在从平台设备运行时上下文执行时处于活动状态,这为您提供了极大的灵活性,可以快速访问所有那些平台 API,甚至无需离开您的 Web 组件。这意味着当本地对象在独立的 Web 浏览器中执行时,它只是处于非活动状态,对 Web 浏览器部署没有任何影响。

这很强大。但是,我们鼓励使用更强大的东西……

为良好的项目组织创建平台 API 帮助程序

大多数 JavaScript 开发人员习惯于为良好的组合开发增长创建纯方法。我们鼓励使用 NativeScript 做同样的事情。

也许更简单的是为需要处理的任何数量的平台 API 行为定义自己的本地帮助程序方法。

例如,让我们为上面的屏幕亮度执行此操作

/**
 * Adjust iOS and Android screen brightness
 */
native.setScreenBrightness = (value: number) => {
  if (native.isAndroid) {
    const context = native.androidCapacitorActivity;
    if (android.os.Build.VERSION.SDK_INT < 23) {
      const attr = context.getWindow().getAttributes();
      attr.screenBrightness = value;
      context.getWindow().setAttributes(attr);
    } else {
      if (!android.provider.Settings.System.canWrite(context)) {
        const intent = new android.content.Intent(
          android.provider.Settings.ACTION_MANAGE_WRITE_SETTINGS
        );
        intent.setData(
          android.net.Uri.parse("package:" + context.getPackageName())
        );
        intent.addFlags(android.content.Intent.FLAG_ACTIVITY_NEW_TASK);
        context.startActivity(intent);
      }

      if (android.provider.Settings.System.canWrite(context)) {
        android.provider.Settings.System.putInt(
          context.getContentResolver(),
          android.provider.Settings.System.SCREEN_BRIGHTNESS,
          value * 100
        );
      }
    }
  } else {
    UIScreen.mainScreen.brightness = value;
  }
};

然后,只需在您需要以编程方式调整移动设备屏幕亮度的任何时候在您的 Ionic 组件中使用它即可

native.setScreenBrightness(.8);

等一下,这不是为 Web 开发团队创建新的 API 吗?

可以通过注释、通过 TypeScript 导入智能感知自动注释、维护、修改、重构、重新集成到您的 Web 应用程序中以及在不离开您自己的代码库的情况下清晰理解的一种 API。那么,当然。但是,本地平台 API 开发人员 Web 开发人员可以随时控制它,无需任何延迟,并且它是严格类型检查的,允许随着时间的推移轻松地重构和改进。

您创建的自定义本地帮助程序方法的严格类型化是 native-custom.d.ts 的用途,您会发现插件将其添加到您的代码库中,例如

  • native-custom.d.ts:
declare module '@nativescript/capacitor' {
  export interface customNativeAPI extends nativeCustom {}
}

/**
 * Define your own custom strongly typed native helpers here.
 */
export interface nativeCustom {
  openNativeModalView: () => void;

  // For the example above we can just add strong typing for it here:
  setScreenBrightness: (value: number) => void;
}

插件附带一个简单的示例,为您提供执行此操作的指导。您可以在其中根据项目的需要添加任意数量的自定义本地帮助程序方法。

OpenJS 演示文稿和其他视频学习

您可以观看来自 OpenJS World 2021 的一个有趣的演示文稿。

https://www.youtube.com/watch?v=OInjFvniccU

您还可以观看由 beeman.dev 提供的 BLS035 集。

https://www.youtube.com/watch?v=AHcL_UbnnPY

帮助塑造未来

NativeScript 已在 OpenJS 基金会 毕业,我们致力于一个透明的开源未来。您可以通过多种有益的方式做出贡献

随时与我们一起庆祝 JavaScript 开发的奇迹和乐趣。