如何在 NativeScript 中使用原生 API?

Posted

技术标签:

【中文标题】如何在 NativeScript 中使用原生 API?【英文标题】:How to use native APIs in NativeScript? 【发布时间】:2019-07-17 23:08:14 【问题描述】:

我正在构建一个需要使用本机 API 的应用程序,但事实证明,使用这些 API 非常困难,因为许多参数在 TypeScript 中没有明确的类比,缺少定义等等。人们如何使用 NativeScript 实际构建?

例如,我正在尝试使用 Apple 的 Secure Enclave 在this 页面之后生成一个公私密钥对。这些 sn-ps 是用 Swift 编写的(我认为),所以打字稿中不存在语法的许多方面。经过数小时的反复试验,我提出了不会导致错误的论点。但是我得到的privateKey 值为空。

可能有几十或一百种不同的参数排列我可以尝试,它们sort 等同于 Swift 代码......这不可能是人们在 NativeScript 上构建的方式吗?我到处找,我在 NativeScript Slack 上问过,我读过帖子......

tns create
(choose Angular and hello-world)
npm install --save-dev tns-platform-declarations

在项目根目录中添加reference.d.ts。将以下内容放入其中:

/// <reference path="./node_modules/tns-platform-declarations/ios.d.ts" />
/// <reference path="./node_modules/tns-platform-declarations/android.d.ts" />

更新tsconfig.json,使paths 看起来像这样:

"~/*": ["src/*", "./node_modules/tns-core-modules/*", "./node_modules/*"]

app.component.html 修改为只有一个按钮

<Button (tap)="onTap()"></Button>

修改app.component.ts添加按钮代码:

    onTap() 
        const access = SecAccessControlCreateWithFlags(
            kCFAllocatorDefault,
            kSecAttrAccessibleWhenUnlockedThisDeviceOnly,
           SecAccessControlCreateFlags.kSecAccessControlPrivateKeyUsage,
            new interop.Pointer(0)
        );
        const attributes = 
            kSecAttrKeyType: 'type',
            kSecAttrKeySizeInBits: '256',
            kSecAttrTokenID: kSecAttrTokenIDSecureEnclave,
            kSecPrivateKeyAttrs: 
                kSecAttrIsPermanent: 'true',
                kSecAttrApplicationTag: '<# a tag #>',
                kSecAttrAccessControl: 'access',
            ,
        ;
        const privateKey = SecKeyCreateRandomKey(attributes as any, new interop.Pointer(0));
        console.info(privateKey);
    

我确信我对 Swift 代码的解释(如上所示)存在很多问题。一个解决方案会很好。但我真正的问题是人们如何实际使用 Angular(意思是 NativeScript)进行构建?我不能只是猜测这些参数在 typescript 中应该是什么!

预期结果:

privateKey 不为空,访问原生 API 的明智方式?

【问题讨论】:

你可以开始查看 Nativescript Documentation 然后搜索具有类似 iOS 实现的插件 Geolocation 【参考方案1】:

是的,根据类型准确地解释要写什么并不总是那么容易,因此它确实归结为通过搜索 iOS 运行时存储库(在测试、问题甚至是代码库本身)。即使是我们当中最优秀的人,也可能会时不时地“发疯”。

浏览 Apple API 文档时,最好将语言设置为 Obj-C(因为它是生成 TypeScript 类型的运行时)。

如果您已经熟悉如何调用 API(即您已经设法让它事先在本机应用程序中工作),它也会有很大帮助。是的,这对 Swift 开发人员来说是一个艰难的领域。

猜测一下,您需要清理您的attributes 字典。我参考了“Generating New Cryptographic Keys”文档(链接如下),以更好地了解要输入的值。这里是一个尝试:

const access: any = SecAccessControlCreateWithFlags(
    kCFAllocatorDefault,
    kSecAttrAccessibleWhenUnlockedThisDeviceOnly,
    SecAccessControlCreateFlags.kSecAccessControlPrivateKeyUsage,
    new interop.Pointer(0)
);

const myTag: NSData = NSString.alloc().initWithString("com.example.keys.mykey")
                      .dataUsingEncoding(NSUTF8StringEncoding);

// Will be marshalled into the necessary NSDictionary<any, any> type
const attributes: any = 
    kSecAttrKeyType: kSecAttrKeyTypeECSECPrimeRandom,
    kSecAttrKeySizeInBits: 256,
    kSecAttrTokenID: kSecAttrTokenIDSecureEnclave,
    kSecPrivateKeyAttrs: 
        kSecAttrIsPermanent: true, // Hopefully marshalls to "YES" if appropriate
        kSecAttrApplicationTag: myTag,
        kSecAttrAccessControl: access,
    ,
;

const privateKey: any = SecKeyCreateRandomKey(attributes, new interop.Pointer(0));
console.info(privateKey);

注意:我还没有运行代码。它很可能仍然是错误的..!

参考资料:

苹果文档:Storing Keys in the Secure Enclave 生成新的加密密钥:Storing Keys in the Secure Enclave

但我真正的问题是人们实际上是如何使用 Angular 进行构建的?我不能只是猜测这些参数在 typescript 中应该是什么!

Angular 没有涉及到这一点;对于所有的 NativeScript 风格,访问本机 API 的方式都是相同的。 NativeScript 的各种非核心风格只是用于以不同方式管理 UI(即以声明方式)。

TypeScript 类型对编写内容提供了相当好的指导,但要弄清楚如何解释它确实需要一些额外的经验。部分问题在于 Obj-C 不能完美地映射到 TypeScript,但我想说 NativeScript 团队在这方面做得非常出色。

如果这一切看起来太难以克服,您可以制作一个原生模块,用 Obj-C(或 Swift)编写,然后将简单的 API 绑定暴露给您的原生模块。但是,如果您也决定走这条路,预计会遇到学习曲线!

如果您遇到更多问题,我建议您在Slack forums 的#ios 频道中发帖。那里有一些专业人士从里到外都了解这种黑暗艺术,他们非常乐意提供帮助;这只是在正确的时间抓住它们的问题。

如果这篇文章对任何人有所帮助,我会通过 NativeScript here 提供各种不同的 iOS API 调用示例 sn-ps - 尽管我之前没有处理过来自此安全框架的 API。

【讨论】:

非常感谢您的回答。这非常有帮助!

以上是关于如何在 NativeScript 中使用原生 API?的主要内容,如果未能解决你的问题,请参考以下文章

如何在不使用本机代码的情况下要求用户在 NativeScript 上启用蓝牙

Nativescript-vue原生iOS导航按钮在ActionBar上设置标题后消失

如何在对应OS上的Nativescript中集成平台依赖的SDK

有哪些像 Nativescript 这样的技术项目,在某种意义上是原生平台到 Javascript+原生反射代理绑定?

NativeScript-Vue 中的分组 UITableView

如何将 NativeScript 与 Angular CLI 集成