跳到主要内容
版本:v4

将插件升级至 Capacitor 3.0

对于需要升级到 Capacitor 3 的插件,这里列出了一些必要的和推荐的改动项。

核心 API 规划

当前核心团队在修改 Capacitor 内部实现时,很难避免对插件造成影响。由于 Capacitor 2 中大部分类和方法的 iOS/Android 实现都是公开的,我们观察到部分插件存在不符合预期的 API 使用情况。

在 Capacitor 3 开发过程中,我们将评估这个问题并创建官方的插件公共 API,相关文档将在此处发布

Android 部分

使用新的 @CapacitorPlugin 注解

@NativePlugin 注解已弃用,推荐改用新的 @CapacitorPlugin 注解以支持新版权限 API

name 属性保持不变。移除了 requestCodespermissionRequestCode 属性。permissions 属性需要替换为 @Permission 注解列表,每个注解包含一组 manifest 字符串及其对应的 alias(在实现新版权限 API 前可暂不设置别名)。

-@NativePlugin(
+@CapacitorPlugin(
name = "FooBar",
- requestCodes = {
- FooBarPlugin.REQUEST_SOME_METHOD,
- FooBarPlugin.REQUEST_SOME_OTHER_METHOD
- },
- permissionRequestCode = FooBarPlugin.REQUEST_ALL_PERMISSIONS,
- permissions = { Manifest.permission.FOO, Manifest.permission.BAR }
+ permissions = {
+ @Permission(strings = { Manifest.permission.FOO }, alias = "foo"),
+ @Permission(strings = { Manifest.permission.BAR }, alias = "bar")
+ })
)
public class FooBarPlugin extends Plugin {
static final int REQUEST_SOME_METHOD = 10051;
static final int REQUEST_SOME_OTHER_METHOD = 10052;

Android 请求码调整

Capacitor 3.0 实现了 AndroidX Activity Result API 并移除了手动定义的请求码。现在应该使用 @ActivityCallback@PermissionCallback 注解提供回调方法,而非覆盖 handleOnActivityResulthandleRequestPermissionsResult。启动新 Activity 或权限请求时可以引用这些回调。

-static final int IMAGE_REQUEST = 10052;

@PluginMethod
public void chooseImage(PluginCall call) {
Intent intent = new Intent(Intent.ACTION_PICK);
intent.setType("image/*");
- startActivityForResult(call, intent, IMAGE_REQUEST);
+ startActivityForResult(call, intent, "chooseImageResult");
}

+@ActivityCallback
+private void chooseImageResult(PluginCall call, ActivityResult result) {
+ if (result.getResultCode() == Activity.RESULT_CANCELED) {
+ call.reject("Activity canceled");
+ } else {
+ Intent data = result.getData();
+ // 处理返回数据
+ call.resolve("Success!");
+ }
+}

使用 WebColor.parseColor() 替代 Color.parseColor()

Android 将带透明通道的十六进制颜色字符串解析为 ARGB 格式,而 iOS 和 Web 端则解析为 RGBA 格式。如需跨平台共享带透明通道的颜色值,请使用新的 WebColor 工具类。WebColor.parseColor() 功能类似 Android 原生 Color.parseColor(),但会按 RGBA 格式解析字符串。

String colorStringWithAlpha = "#FF000088"; // 半透明红色
int color = WebColor.parseColor(colorStringWithAlpha);

如果颜色值不带透明通道,两个方法将返回相同结果。

将 compileSdkVersion 和 targetSdkVersion 默认值改为 30

修改 android/build.gradle 文件:

android {
- compileSdkVersion project.hasProperty('compileSdkVersion') ? rootProject.ext.compileSdkVersion : 29
+ compileSdkVersion project.hasProperty('compileSdkVersion') ? rootProject.ext.compileSdkVersion : 30
defaultConfig {
minSdkVersion project.hasProperty('minSdkVersion') ? rootProject.ext.minSdkVersion : 21
- targetSdkVersion project.hasProperty('targetSdkVersion') ? rootProject.ext.targetSdkVersion : 29
+ targetSdkVersion project.hasProperty('targetSdkVersion') ? rootProject.ext.targetSdkVersion : 30
...
}
...
}

iOS 部分

弱引用调整

Capacitor 3 优化了对象关系以修复内存泄漏问题。现在插件对上层对象的引用变为 weak,在 Swift 中表现为可选类型。最常见的场景是访问 bridge 属性,该变化同样适用于 webView 等其他属性。调用 bridge 方法时需要使用可选链式调用:

-bridge.presentVC(myViewController, animated: true, completion: nil)
+bridge?.presentVC(myViewController, animated: true, completion: nil)

最大变化是 bridge 的所有返回值都变为可选类型。正确处理可选值解包需要额外步骤

if bridge?.isSimEnvironment {
// 错误:无法编译。布尔值现在是可选类型(因为bridge为可选)
// 必须先解包才能使用
}
if bridge?.isSimEnvironment == true {
// 中性方案:显式比较可选布尔值可行,但不适用所有数据类型
}
if let isSim = bridge?.isSimEnvironment, isSim {
// 最佳实践:先通过可选绑定解包,再使用值
}

Bridge API 变更

除了引用类型从 strong 变为 weak 外,bridge API 也进行了更新(现在通过更正式的协议暴露)。许多属性和方法已重命名,但仍通过保留旧接口提供向后兼容。Xcode 在大多数情况下会自动建议新名称替代方案。建议迁移现有代码以消除编译警告。

Xcode自动修正建议

CAPPluginCall 参数方法

Capacitor 提供了一系列便捷方法(getStringgetDate 等)来访问从 JavaScript 传入插件方法的数据,这些方法在 3.0 版本有所更新:

  • 移除了 get() 方法,如需直接访问参数可读取 options 字典
  • hasOption 已弃用,建议使用类型化访问器检查值是否存在
  • 所有带默认值的访问器现在要求必须提供非可选的默认值,并返回非可选结果
  • 日期和空值的处理逻辑略有调整,详见文档
  • Objective-C 的便捷访问器已拆分以避免冲突,需在 .m 文件中添加 #import <Capacitor/CAPBridgedJSTypes.h>

PluginCallCAPPluginCall 变更

使用 resolve()reject()

我们推荐使用 resolve()reject() 来更好地体现插件方法的 Promise 式流程。即使在回调式插件方法中也应优先使用它们,而非已弃用的 success()error()

无参 resolve() 现在返回 undefined

此前无参调用 resolve() 会向 JavaScript 层返回空对象。为保持与 JavaScript Promise.resolve() 行为一致,Capacitor 3 将改为返回 undefined

保存调用

sava() 方法已弃用,新增 keepAlive 属性作为替代。我们完善了保存调用的推荐模式文档,详见此处

设置 iOS 最低部署版本为 12.0

在 Xcode 项目中依次操作:打开 Build Settings 标签页,在 Deployment 部分将 iOS Deployment Target 改为 iOS 12.0

然后修改 ios/Podfile

-platform :ios, '11.0'
+platform :ios, '12.0'
use_frameworks!

最后更新 pluginName.podspec

-s.ios.deployment_target  = '11.0'
+s.ios.deployment_target = '12.0'

设置 Swift 版本为 5

在 Xcode 目标的 Build Settings 标签页中,找到 Swift Compiler - Language 部分,将 Swift Language Version 改为 Swift 5

然后更新 pluginName.podspec

-s.swift_version = '4.2'
+s.swift_version = '5.1'

Web 部分

插件注册

registerWebPlugin(MyPlugin) 方法已弃用。推荐使用新的 registerPlugin 方法并惰性加载 web(可选 electron)插件:

import { registerPlugin } from '@capacitor/core';
import type { CoolPlugin } from './definitions';

const MyCoolPlugin = registerPlugin<CoolPlugin>('MyCoolPlugin', {
web: () => import('./web').then(m => new m.MyCoolPluginWeb()),
// electron: () => ("./electron").then(m => new m.MyCoolPluginElectron())
});

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

设置 TypeScript 输出目标为 es2017

如果使用 TypeScript 开发 Web 插件,建议在 tsconfig.json 中将编译目标设置为 es2017

错误处理优化

我们建议插件作者使用 Capacitor 3 新增的错误码:

  • Unavailable:表示功能当前不可用
  • Unimplemented:表示功能无法或不会实现,或可能在将来实现

查阅各平台错误处理指南:WebiOSAndroid

采用新版权限接口

3.0 版本前,插件通常会在功能使用前自动请求权限。例如 Geolocation 插件在首次请求用户位置时自动申请权限,然后根据授权结果继续流程。

Capacitor 3 的目标之一是让应用开发者能够随时检查或请求权限,并控制用户提示的展示时机。这通过丰富的用户体验设计,让应用能以多种方式响应用户选择。

虽然自动请求权限仍可正常工作,但我们鼓励采用新的权限模式以给予应用开发者更多控制权。

了解如何在插件中实现权限 API ›