跳到主要内容
版本:v5

在您的插件中将 Capacitor 更新到 3.0

对于正在更新到 Capacitor 3 的插件,有几个必需和推荐的更改。

规划核心 API

目前,核心团队很难在不潜在影响插件的情况下对 Capacitor 的内部结构进行更改。由于 Capacitor 2 中大多数类和方法对 iOS 和 Android 都是公开的,我们观察到用户对我们视为内部使用的 Capacitor API 进行了不当使用。

在 Capacitor 3 的开发过程中,我们将评估这个问题并创建一个官方的公开 API 供插件使用,该 API 将 在此处记录

Android

使用新的 @CapacitorPlugin 注解

@NativePlugin 注解已被弃用。我们现在建议使用新的 @CapacitorPlugin 注解,它将支持 新的权限 API

name 属性保持不变。requestCodespermissionRequestCode 属性已被移除。permissions 属性需要替换为 @Permission 注解列表,每个注解包含一组清单字符串及其对应的 alias,在新的权限 API 在您的插件中实现之前,您可以暂时省略 alias

-@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 并移除了手动定义的请求码。插件不再需要提供请求码并重写 handleOnActivityResulthandleRequestPermissionsResult,而是应该使用 @ActivityCallback@PermissionCallback 注解提供回调方法。这些回调可以在启动新的 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 将带 alpha 通道的十六进制颜色字符串解析为 ARGB,而在 iOS 和 Web 中则解析为 RGBA。如果您在跨平台共享带 alpha 通道的颜色,请务必使用新的 WebColor 工具类。WebColor.parseColor() 的工作方式类似于原生 Android 的 Color.parseColor() 函数,但将字符串解析为 RGBA 格式。

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

如果您的颜色没有 alpha 通道,两个函数将返回相同的结果。

更改默认的 compileSdkVersion 和 targetSdkVersion 为 30

android/build.gradle 中将 compileSdkVersiontargetSdkVersion 的默认值更改为 30

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.presentVC(myViewController, animated: true, completion: nil)
+bridge?.presentVC(myViewController, animated: true, completion: nil)

此更改的最大影响是桥接器的所有返回值也将是可选的。安全处理和展开可选值可能需要额外步骤

if bridge?.isSimEnvironment {
// 错误:无法编译。布尔值是可选类型(因为 `bridge` 是可选的)
// 必须在其可以被评估之前进行解包。
}
if bridge?.isSimEnvironment == true {
// 中性:对布尔值使用显式比较是可行的,但可能不适用于所有数据类型。
}
if let isSim = bridge?.isSimEnvironment, isSim {
// 良好:在检查值之前使用可选绑定解包可选值。
}

桥接器更改

除了引用从 strong 变为 weak 之外,桥接器本身的 API 也已更新(现在通过更正式的协议暴露)。许多属性和方法已重命名,但尽可能保留了旧接口并标记为弃用,以保持向后兼容。在大多数情况下,Xcode 会自动建议新的替代方案。您应该迁移任何现有代码,以便您的插件可以在没有编译器警告的情况下构建。

Xcode 自动更正建议

CAPPluginCall 参数

Capacitor 包含一系列便捷方法(getStringgetDate 等),用于在 CAPPluginCall 上访问从 JavaScript 传递到插件方法的数据。这些已在 Capacitor 3 中更新。

  • get() 已被移除。如果您想直接访问参数,请读取 options 字典。
  • hasOption 已被弃用。请使用类型化的访问器之一来检查值。
  • 任何接受默认值的访问器现在需要非可选默认值,但返回非可选结果。这可能会改变局部变量的可选性,但应减少强制解包的使用,这在 Swift 中是一种反模式。
  • 关于日期和空值的行为略有更改并有了更好的文档。在此处查找更多信息
  • Obj-C 便捷访问器已被分离,以避免与 Swift 实现冲突。如果您使用 Obj-C,您需要通过将 #import <Capacitor/CAPBridgedJSTypes.h> 添加到您的 .m 文件来单独导入它们。

PluginCallCAPPluginCall 的更改

使用 resolve()reject()

我们认为 resolve()reject() 更好地反映了插件方法预期的类 Promise 流程。即使在回调风格的插件方法中,也应优先使用它们而不是 success()error()(现已弃用)。

无参数的 resolve() 现在解析为 undefined

以前,不带参数调用 resolve() 会导致向 JavaScript 层发送一个空对象。由于这与 JavaScript 的 Promise.resolve() 的行为不同,从 Capacitor 3 开始,将发送 undefined

保存调用

save() 方法已被弃用,并添加了替代属性 keepAlive。保存调用的推荐模式已记录在案,以澄清行为。在此处阅读更多信息

将 iOS 部署目标设置为 12.0

对插件 Xcode 项目和插件目标执行以下操作:打开 Build Settings 选项卡。在 Deployment 部分下,将 iOS Deployment Target 更改为 iOS 12.0

然后,打开 ios/Podfile 并将 iOS 版本更新为 12.0:

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

最后,打开 pluginName.podspec 并将 iOS 版本更新为 12.0:

-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 并将 Swift 版本更新为 5.1:

-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 的错误处理。

采用新的权限 API

在 3.0 之前,预期插件在功能使用前会自动请求权限。例如,地理位置插件会在首次请求用户位置时自动请求权限,然后根据权限被授予或拒绝继续适当操作。

Capacitor 3 的目标之一是让应用开发者能够随时请求或检查权限,并控制用户提示的呈现方式和时机。这通过允许应用以多种方式响应用户的选择,为用户体验提供了更大的灵活性。

继续自动请求权限是完全可以的,但我们鼓励您也采用新的权限模式,以便为应用开发者提供对权限的控制。

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