NativeScript 插件系统 #
插件概述 #
NativeScript 插件扩展了核心功能,提供对原生 API 的访问和额外的 UI 组件。
┌─────────────────────────────────────────────────────────────┐
│ 插件类型 │
├─────────────────────────────────────────────────────────────┤
│ │
│ JavaScript 插件 │
│ ├── 纯 JavaScript 实现 │
│ └── 无需原生代码 │
│ │
│ 原生插件 │
│ ├── iOS: Swift/Objective-C │
│ ├── Android: Kotlin/Java │
│ └── 通过桥接访问原生 API │
│ │
│ UI 插件 │
│ ├── 自定义 UI 组件 │
│ └── 封装原生视图 │
│ │
└─────────────────────────────────────────────────────────────┘
安装插件 #
使用 npm 安装 #
# 安装插件
ns plugin add @nativescript/camera
# 或使用 npm
npm install @nativescript/camera
插件命名规范 #
@nativescript/xxx 官方插件
nativescript-xxx 社区插件
@scope/nativescript-xxx 作用域插件
清理和重建 #
# 清理项目
ns clean
# 重新添加平台
ns platform remove android
ns platform add android
常用官方插件 #
@nativescript/camera #
相机功能:
ns plugin add @nativescript/camera
import { Camera } from '@nativescript/camera';
// 请求权限
await Camera.requestPermissions();
// 拍照
const image = await Camera.takePicture({
width: 300,
height: 300,
keepAspectRatio: true,
saveToGallery: true
});
// 从相册选择
const image = await Camera.pickFromGallery({
width: 300,
height: 300,
keepAspectRatio: true
});
@nativescript/geolocation #
地理位置:
ns plugin add @nativescript/geolocation
import { Geolocation } from '@nativescript/geolocation';
// 请求权限
await Geolocation.enableLocationRequest();
// 获取当前位置
const location = await Geolocation.getCurrentLocation({
desiredAccuracy: Accuracy.high,
maximumAge: 5000,
timeout: 10000
});
console.log('Latitude:', location.latitude);
console.log('Longitude:', location.longitude);
// 监听位置变化
const watchId = Geolocation.watchLocation(
(location) => {
console.log('New location:', location);
},
(error) => {
console.error('Error:', error);
},
{
desiredAccuracy: Accuracy.high,
updateDistance: 10,
minimumUpdateTime: 1000
}
);
// 停止监听
Geolocation.clearWatch(watchId);
@nativescript/social-share #
社交分享:
ns plugin add @nativescript/social-share
import { SocialShare } from '@nativescript/social-share';
// 分享文本
SocialShare.shareText('Hello, World!');
// 分享图片
SocialShare.shareImage(image);
// 分享 URL
SocialShare.shareUrl('https://example.com', 'Example Site');
@nativescript/local-notifications #
本地通知:
ns plugin add @nativescript/local-notifications
import { LocalNotifications } from '@nativescript/local-notifications';
// 请求权限
await LocalNotifications.requestPermission();
// 发送通知
LocalNotifications.schedule([{
id: 1,
title: 'Notification Title',
body: 'Notification body text',
at: new Date(Date.now() + 5000)
}]);
// 监听通知点击
LocalNotifications.addOnMessageReceivedCallback((notification) => {
console.log('Notification received:', notification);
});
@nativescript/secure-storage #
安全存储:
ns plugin add @nativescript/secure-storage
import { SecureStorage } from '@nativescript/secure-storage';
const secureStorage = new SecureStorage();
// 存储数据
await secureStorage.set({
key: 'token',
value: 'my-secret-token'
});
// 获取数据
const token = await secureStorage.get({
key: 'token'
});
// 删除数据
await secureStorage.remove({
key: 'token'
});
// 清空所有
await secureStorage.removeAll();
@nativescript/firebase #
Firebase 集成:
ns plugin add @nativescript/firebase
import { firebase } from '@nativescript/firebase-core';
import '@nativescript/firebase-auth';
import '@nativescript/firebase-firestore';
// 初始化
firebase.initializeApp();
// 认证
const auth = firebase.auth();
await auth.signInWithEmailAndPassword(email, password);
// 数据库
const db = firebase.firestore();
const snapshot = await db.collection('users').get();
社区插件 #
nativescript-oauth2 #
OAuth 2.0 认证:
ns plugin add nativescript-oauth2
import { TnsOAuthClient, TnsOAuthClientLogin } from 'nativescript-oauth2';
const client = new TnsOAuthClient('google');
client.loginWithCompletion((result, error) => {
if (error) {
console.error('Login failed:', error);
} else {
console.log('Access token:', result.accessToken);
}
});
nativescript-image-cache #
图片缓存:
ns plugin add nativescript-image-cache
<NSImage src="https://example.com/image.jpg"
stretch="aspectFill" />
nativescript-pdf-view #
PDF 查看:
ns plugin add nativescript-pdf-view
<PDFView src="~/document.pdf"
load="onPdfLoaded" />
自定义插件开发 #
创建插件项目 #
# 创建插件目录
mkdir nativescript-my-plugin
cd nativescript-my-plugin
# 初始化 npm
npm init -y
# 创建目录结构
mkdir -p platforms/android
mkdir -p platforms/ios
插件结构 #
nativescript-my-plugin/
├── platforms/
│ ├── android/
│ │ └── src/main/
│ │ └── java/com/example/
│ │ └── MyPlugin.java
│ └── ios/
│ └── MyPlugin.swift
├── index.d.ts # TypeScript 定义
├── index.ts # JavaScript 入口
├── package.json
└── README.md
JavaScript 入口 #
// index.ts
import { Application } from '@nativescript/core';
export class MyPlugin {
static echo(value: string): string {
if (global.isAndroid) {
return com.example.MyPlugin.echo(value);
} else {
return MyPlugin.echo(value);
}
}
static async doSomething(): Promise<string> {
return new Promise((resolve, reject) => {
// 原生实现
});
}
}
TypeScript 定义 #
// index.d.ts
export class MyPlugin {
static echo(value: string): string;
static doSomething(): Promise<string>;
}
Android 实现 #
// platforms/android/src/main/java/com/example/MyPlugin.java
package com.example;
public class MyPlugin {
public static String echo(String value) {
return "Echo: " + value;
}
}
iOS 实现 #
// platforms/ios/MyPlugin.swift
import Foundation
@objc(MyPlugin)
class MyPlugin: NSObject {
@objc static func echo(_ value: String) -> String {
return "Echo: \(value)"
}
}
package.json 配置 #
{
"name": "nativescript-my-plugin",
"version": "1.0.0",
"main": "index",
"typings": "index.d.ts",
"nativescript": {
"platforms": {
"android": "8.0.0",
"ios": "8.0.0"
}
},
"dependencies": {
"@nativescript/core": "^8.0.0"
}
}
原生 API 访问 #
直接访问 iOS API #
import { Utils } from '@nativescript/core';
// 获取 iOS 版本
const version = Utils.ios.MajorVersion;
// 访问 UIKit
const window = Utils.ios.getter(UIApplication, UIApplication.sharedApplication).keyWindow;
// 调用原生方法
const alert = UIAlertController.alertControllerWithTitleMessagePreferredStyle(
"Title",
"Message",
UIAlertControllerStyle.Alert
);
直接访问 Android API #
import { Utils, Application } from '@nativescript/core';
// 获取 Android 版本
const version = android.os.Build.VERSION.SDK_INT;
// 获取 Context
const context = Application.android.context;
// 调用原生方法
const intent = new android.content.Intent(
context,
com.example.MyActivity.class
);
context.startActivity(intent);
插件调试 #
调试模式 #
# 启动调试
ns debug android
ns debug ios
日志输出 #
console.log('Debug message');
console.warn('Warning message');
console.error('Error message');
原生日志 #
# Android 日志
adb logcat | grep NativeScript
# iOS 日志
# 在 Xcode 控制台查看
插件发布 #
准备发布 #
# 构建
npm run build
# 测试
npm test
# 检查
npm publish --dry-run
发布到 npm #
# 登录 npm
npm login
# 发布
npm publish
# 发布 beta 版本
npm publish --tag beta
README 模板 #
# NativeScript My Plugin
## Installation
ns plugin add nativescript-my-plugin
## Usage
```typescript
import { MyPlugin } from 'nativescript-my-plugin';
const result = MyPlugin.echo('Hello');
API #
echo(value: string): string #
Echoes the input value.
License #
MIT
## 最佳实践
### 插件设计原则
┌─────────────────────────────────────────────────────────────┐ │ 插件设计原则 │ ├─────────────────────────────────────────────────────────────┤ │ │ │ 1. 简洁 API │ │ 提供简单易用的接口 │ │ │ │ 2. 跨平台一致性 │ │ iOS 和 Android 行为一致 │ │ │ │ 3. 错误处理 │ │ 统一的错误处理机制 │ │ │ │ 4. 类型定义 │ │ 提供完整的 TypeScript 定义 │ │ │ │ 5. 文档完善 │ │ 详细的使用说明和示例 │ │ │ │ 6. 版本兼容 │ │ 说明兼容的 NativeScript 版本 │ │ │ └─────────────────────────────────────────────────────────────┘
### 权限处理
```typescript
import { Application } from '@nativescript/core';
export class PermissionHelper {
static async requestCameraPermission(): Promise<boolean> {
if (global.isAndroid) {
return await this.requestAndroidPermission(
android.Manifest.permission.CAMERA
);
} else {
return await this.requestIOSPermission('camera');
}
}
private static async requestAndroidPermission(permission: string): Promise<boolean> {
return new Promise((resolve) => {
Application.android.on(Application.android.activityRequestPermissionsEvent, (args) => {
resolve(args.grantResults[0] === android.content.pm.PackageManager.PERMISSION_GRANTED);
});
(Application.android.foregroundActivity || Application.android.startActivity)
.requestPermissions([permission], 0);
});
}
}
下一步 #
现在你已经掌握了插件系统,接下来学习 网络请求,了解如何进行 API 调用!