插件概述 #

一、插件系统简介 #

1.1 什么是插件 #

Capacitor插件是封装原生功能的模块,允许JavaScript代码调用iOS、Android和Web平台的原生能力。插件提供了统一的API接口,屏蔽了平台差异。

text
┌─────────────────────────────────────────────────────────────┐
│                      JavaScript API                          │
│                    (统一的调用接口)                           │
├─────────────────────────────────────────────────────────────┤
│                       Plugin Layer                           │
│  ┌───────────────┐  ┌───────────────┐  ┌───────────────┐   │
│  │  iOS Plugin   │  │Android Plugin │  │   Web Plugin  │   │
│  │   (Swift)     │  │    (Java)     │  │ (TypeScript)  │   │
│  └───────────────┘  └───────────────┘  └───────────────┘   │
├─────────────────────────────────────────────────────────────┤
│                    Native Platform APIs                      │
│  ┌───────────────┐  ┌───────────────┐  ┌───────────────┐   │
│  │   iOS SDK     │  │ Android SDK   │  │  Web APIs     │   │
│  └───────────────┘  └───────────────┘  └───────────────┘   │
└─────────────────────────────────────────────────────────────┘

1.2 插件类型 #

类型 说明 示例
官方插件 Capacitor团队维护 @capacitor/camera
社区插件 社区开发者贡献 capacitor-plugin-biometric
自定义插件 项目内部开发 @mycompany/custom-plugin
Cordova插件 兼容Cordova生态 cordova-plugin-geolocation

1.3 插件优势 #

优势 说明
跨平台一致 统一的JavaScript API
类型安全 完整的TypeScript支持
按需加载 只加载需要的插件
易于扩展 可开发自定义插件
原生性能 直接调用原生API

二、插件架构 #

2.1 插件结构 #

text
@capacitor/plugin-name/
├── dist/                    # 编译输出
│   ├── esm/                 # ES模块
│   ├── cjs/                 # CommonJS模块
│   └── definitions.d.ts     # 类型定义
│
├── src/
│   ├── definitions.ts       # 接口定义
│   ├── index.ts             # 入口文件
│   ├── web.ts               # Web实现
│   └── index.ts             # 导出
│
├── ios/
│   ├── Sources/
│   │   └── PluginName/
│   │       ├── PluginName.h
│   │       └── PluginName.m
│   └── PluginName.podspec   # CocoaPods配置
│
├── android/
│   └── src/
│       └── main/
│           ├── java/com/example/plugin/
│           │   └── PluginName.java
│           └── AndroidManifest.xml
│
├── package.json
├── tsconfig.json
└── README.md

2.2 插件接口定义 #

typescript
// src/definitions.ts
export interface MyPlugin {
    // 方法定义
    doSomething(options: DoSomethingOptions): Promise<DoSomethingResult>;
    
    // 事件监听
    addListener(eventName: 'myEvent', listener: (data: MyEventData) => void): Promise<void>;
    
    // 移除监听
    removeAllListeners(): Promise<void>;
}

// 选项接口
export interface DoSomethingOptions {
    param1: string;
    param2?: number;
}

// 结果接口
export interface DoSomethingResult {
    success: boolean;
    data?: any;
}

// 事件数据接口
export interface MyEventData {
    message: string;
    timestamp: number;
}

2.3 插件注册 #

typescript
// src/index.ts
import { registerPlugin } from '@capacitor/core';
import type { MyPlugin } from './definitions';
import { MyPluginWeb } from './web';

// 注册插件
const MyPlugin = registerPlugin<MyPlugin>('MyPlugin', {
    web: () => import('./web').then(m => new m.MyPluginWeb())
});

export * from './definitions';
export { MyPlugin };

三、官方插件 #

3.1 核心插件列表 #

插件 功能 平台支持
@capacitor/camera 相机与相册 iOS, Android, Web
@capacitor/geolocation 地理定位 iOS, Android, Web
@capacitor/storage 本地存储 iOS, Android, Web
@capacitor/device 设备信息 iOS, Android, Web
@capacitor/network 网络状态 iOS, Android, Web
@capacitor/push-notifications 推送通知 iOS, Android
@capacitor/local-notifications 本地通知 iOS, Android
@capacitor/share 系统分享 iOS, Android, Web
@capacitor/clipboard 剪贴板 iOS, Android, Web
@capacitor/haptics 触觉反馈 iOS, Android
@capacitor/status-bar 状态栏 iOS, Android
@capacitor/splash-screen 启动画面 iOS, Android
@capacitor/keyboard 键盘控制 iOS, Android
@capacitor/browser 浏览器 iOS, Android, Web
@capacitor/app 应用信息 iOS, Android, Web
@capacitor/filesystem 文件系统 iOS, Android, Web
@capacitor/preferences 偏好设置 iOS, Android, Web
@capacitor/action-sheet 操作菜单 iOS, Android, Web
@capacitor/dialog 对话框 iOS, Android, Web
@capacitor/toast 提示消息 iOS, Android, Web

3.2 安装官方插件 #

bash
# 安装相机插件
npm install @capacitor/camera

# 安装地理位置插件
npm install @capacitor/geolocation

# 安装存储插件
npm install @capacitor/preferences

# 同步原生项目
npx cap sync

3.3 使用官方插件 #

typescript
// 相机插件
import { Camera, CameraResultType } from '@capacitor/camera';

async function takePhoto() {
    const photo = await Camera.getPhoto({
        quality: 90,
        allowEditing: true,
        resultType: CameraResultType.Uri
    });
    
    return photo.webPath;
}

// 地理位置插件
import { Geolocation } from '@capacitor/geolocation';

async function getCurrentPosition() {
    const position = await Geolocation.getCurrentPosition();
    return {
        latitude: position.coords.latitude,
        longitude: position.coords.longitude
    };
}

// 存储插件
import { Preferences } from '@capacitor/preferences';

async function saveData(key: string, value: string) {
    await Preferences.set({ key, value });
}

async function getData(key: string) {
    const { value } = await Preferences.get({ key });
    return value;
}

四、社区插件 #

4.1 查找社区插件 #

4.2 常用社区插件 #

插件 功能
@capacitor-community/firebase-analytics Firebase分析
@capacitor-community/firebase-crashlytics Firebase崩溃报告
@capacitor-community/sqlite SQLite数据库
@capacitor-community/http HTTP请求
@capacitor-community/stripe Stripe支付
@capacitor-community/facebook-login Facebook登录
@capacitor-community/google-signin Google登录
@capacitor-community/admob AdMob广告
@capacitor-community/appcenter App Center
@capacitor-community/intercom Intercom客服

4.3 安装社区插件 #

bash
# 安装Firebase分析
npm install @capacitor-community/firebase-analytics

# 安装SQLite
npm install @capacitor-community/sqlite

# 同步
npx cap sync

五、Cordova插件兼容 #

5.1 兼容性说明 #

Capacitor支持大多数Cordova插件,但推荐优先使用Capacitor原生插件。

5.2 安装Cordova插件 #

bash
# 安装Cordova插件
npm install cordova-plugin-device-name

# 同步
npx cap sync

5.3 使用Cordova插件 #

typescript
// 声明全局变量
declare global {
    interface Window {
        device: any;
    }
}

// 使用
if (window.device) {
    console.log('Device name:', window.device.name);
}

5.4 兼容性检查 #

bash
# 检查插件兼容性
npx cap plugin:check

六、插件开发基础 #

6.1 创建插件项目 #

bash
# 使用Capacitor CLI创建插件
npm init @capacitor/plugin my-plugin

# 按提示输入信息
# ? Plugin NPM name: @mycompany/my-plugin
# ? Plugin id: my-plugin
# ? Plugin description: My custom Capacitor plugin
# ? Plugin git repository: 
# ? Plugin author: 
# ? Plugin license: MIT
# ? Package type: npm

6.2 插件项目结构 #

text
my-plugin/
├── src/
│   ├── definitions.ts       # 接口定义
│   ├── index.ts             # 入口
│   └── web.ts               # Web实现
│
├── ios/
│   ├── Sources/
│   │   └── MyPlugin/
│   │       ├── MyPlugin.swift
│   │       └── MyPlugin.m
│   └── MyPlugin.podspec
│
├── android/
│   └── src/main/
│       └── java/com/mycompany/myplugin/
│           └── MyPlugin.java
│
├── package.json
├── tsconfig.json
├── rollup.config.js
└── README.md

6.3 定义插件接口 #

typescript
// src/definitions.ts
import type { PluginListenerHandle } from '@capacitor/core';

export interface MyPlugin {
    // 基本方法
    echo(options: { value: string }): Promise<{ value: string }>;
    
    // 带选项的方法
    doSomething(options: DoSomethingOptions): Promise<DoSomethingResult>;
    
    // 事件监听
    addListener(
        eventName: 'myEvent',
        listener: (data: MyEventData) => void
    ): Promise<PluginListenerHandle>;
    
    // 移除所有监听器
    removeAllListeners(): Promise<void>;
}

export interface DoSomethingOptions {
    param1: string;
    param2?: number;
    flag?: boolean;
}

export interface DoSomethingResult {
    success: boolean;
    message: string;
    data?: any;
}

export interface MyEventData {
    type: string;
    payload: any;
}

6.4 Web实现 #

typescript
// src/web.ts
import { WebPlugin } from '@capacitor/core';
import type { MyPlugin, DoSomethingOptions, DoSomethingResult, MyEventData } from './definitions';

export class MyPluginWeb extends WebPlugin implements MyPlugin {
    async echo(options: { value: string }): Promise<{ value: string }> {
        return { value: options.value };
    }
    
    async doSomething(options: DoSomethingOptions): Promise<DoSomethingResult> {
        console.log('doSomething called with:', options);
        
        // Web实现逻辑
        return {
            success: true,
            message: 'Operation completed',
            data: { input: options }
        };
    }
    
    // 触发事件示例
    notifyEvent(data: MyEventData) {
        this.notifyListeners('myEvent', data);
    }
}

6.5 插件注册 #

typescript
// src/index.ts
import { registerPlugin } from '@capacitor/core';
import type { MyPlugin } from './definitions';

const MyPlugin = registerPlugin<MyPlugin>('MyPlugin', {
    web: () => import('./web').then(m => new m.MyPluginWeb())
});

export * from './definitions';
export { MyPlugin };

七、插件使用模式 #

7.1 Promise模式 #

typescript
// 最常用的异步调用模式
const result = await MyPlugin.doSomething({
    param1: 'value',
    param2: 123
});

console.log(result.success);

7.2 事件监听模式 #

typescript
// 添加监听器
const listener = await MyPlugin.addListener('myEvent', (data) => {
    console.log('Event received:', data);
});

// 移除监听器
await listener.remove();

// 移除所有监听器
await MyPlugin.removeAllListeners();

7.3 回调模式 #

typescript
// 某些插件支持回调
MyPlugin.watchPosition({}, (position) => {
    console.log('Position:', position);
});

// 清除监听
await MyPlugin.clearWatch();

八、插件权限 #

8.1 iOS权限配置 #

xml
<!-- ios/App/App/Info.plist -->
<key>NSCameraUsageDescription</key>
<string>需要访问相机来拍照</string>

<key>NSPhotoLibraryUsageDescription</key>
<string>需要访问相册来选择照片</string>

<key>NSLocationWhenInUseUsageDescription</key>
<string>需要获取您的位置信息</string>

8.2 Android权限配置 #

xml
<!-- android/app/src/main/AndroidManifest.xml -->
<uses-permission android:name="android.permission.CAMERA" />
<uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE" />
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
<uses-permission android:name="android.permission.ACCESS_FINE_LOCATION" />

8.3 运行时权限请求 #

typescript
import { Camera } from '@capacitor/camera';

// 请求权限
async function requestCameraPermission() {
    const permission = await Camera.requestPermissions();
    
    if (permission.camera === 'granted') {
        // 权限已授予
        const photo = await Camera.getPhoto();
    } else {
        // 权限被拒绝
        console.log('Camera permission denied');
    }
}

九、插件调试 #

9.1 控制台日志 #

typescript
// 在插件中添加日志
export class MyPluginWeb extends WebPlugin implements MyPlugin {
    async doSomething(options: DoSomethingOptions): Promise<DoSomethingResult> {
        console.log('[MyPlugin] doSomething called:', options);
        
        // ... 实现逻辑
        
        console.log('[MyPlugin] doSomething result:', result);
        return result;
    }
}

9.2 原生调试 #

iOS:

swift
// Swift日志
print("[MyPlugin] doSomething called with: \(options)")

Android:

java
// Java日志
Log.d("MyPlugin", "doSomething called with: " + options.toString());

9.3 Web调试 #

typescript
// 开发模式下启用详细日志
if (import.meta.env.DEV) {
    const originalCall = MyPlugin.doSomething;
    MyPlugin.doSomething = async (options) => {
        console.time('doSomething');
        const result = await originalCall(options);
        console.timeEnd('doSomething');
        return result;
    };
}

十、插件最佳实践 #

10.1 API设计原则 #

原则 说明
一致性 遵循官方插件的命名和风格
简洁性 提供简单易用的API
类型安全 完整的TypeScript类型定义
错误处理 清晰的错误信息和错误码
文档完善 提供详细的使用文档

10.2 错误处理 #

typescript
// 定义错误类型
export class MyPluginError extends Error {
    constructor(
        message: string,
        public code: string,
        public data?: any
    ) {
        super(message);
        this.name = 'MyPluginError';
    }
}

// 使用
async doSomething(options: DoSomethingOptions): Promise<DoSomethingResult> {
    if (!options.param1) {
        throw new MyPluginError('param1 is required', 'INVALID_ARGUMENT');
    }
    
    try {
        // 执行操作
        return { success: true, message: 'OK' };
    } catch (error) {
        throw new MyPluginError(
            error.message,
            'OPERATION_FAILED',
            { originalError: error }
        );
    }
}

10.3 版本兼容 #

typescript
// 检查API可用性
async checkAvailability(): Promise<boolean> {
    try {
        await MyPlugin.echo({ value: 'test' });
        return true;
    } catch {
        return false;
    }
}

十一、总结 #

11.1 插件系统要点 #

要点 说明
统一API 跨平台一致的JavaScript接口
类型安全 完整的TypeScript支持
按需加载 只加载需要的平台实现
易于扩展 可开发自定义插件

11.2 下一步 #

了解插件概述后,让我们学习 官方插件 的详细使用!

最后更新:2026-03-28