将插件中的 Capacitor 升级至 3.0
对于需要升级到 Capacitor 3 的插件,有几项必需和推荐的更改。
为核心 API 制定规划
目前,核心团队难以在不影响插件的情况下对 Capacitor 的内部机制进行修改。由于 Capacitor 2 中的大多数类和方法在 iOS 和 Android 上都是公开的,我们观察到了一些不期望出现的 Capacitor API 使用方式,这些 API 我们本打算作为内部接口。
在 Capacitor 3 的开发过程中,我们将评估这个问题,并为插件创建一个官方的公开 API,相关文档将记录在此。
Android
使用新的 @CapacitorPlugin 注解
@NativePlugin 注解已弃用。我们现在推荐使用新的 @CapacitorPlugin 注解,它将支持新的权限 API。
name 属性保持不变。requestCodes 和 permissionRequestCode 属性已被移除。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,并移除了手动定义的请求码。插件不应再提供请求码并重写 handleOnActivityResult 或 handleRequestPermissionsResult,而应使用 @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 中,将 compileSdkVersion 和 targetSdkVersion 的默认值更改为 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 上的方法相对变化不大,只是现在需要 使用可选链:
-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 变更
除了引用从 strong 变为 weak 之外,bridge 本身的 API 也已更新(现在通过更正式的协议公开)。许多属性和方法已重命名,但在可能的情况下,通过保留和弃用旧接口提供了向后兼容支持。Xcode 在大多数情况下能够自动建议较新的替代方案。你应该迁移所有现有代码,以便你的插件可以在没有编译器警告的情况下构建。

CAPPluginCall 参数
Capacitor 在 CAPPluginCall 上包含一组便捷方法(getString、getDate 等),用于访问从 JavaScript 传递给插件方法的数据。这些方法在 Capacitor 3 中已更新。
get()已被移除。如果你想直接访问参数,请读取options字典。hasOption已弃用。使用其中一个类型化的访问器来检查值。- 任何接受默认值的访问器现在都需要一个非可选的默认值,但会返回一个非可选 的结果。这可能会改变你局部变量的可选性,但应该减少强制展开(force unwrapping)的使用,这在 Swift 中是一种反模式。
- 关于日期和空值的行为略有改变,并有了更好的文档记录。在此处查看更多信息。
- Objective-C 的便捷访问器已被拆分出来,以避免与 Swift 实现冲突。如果你在 Objective-C 中工作,需要单独导入它们,方法是添加
#import <Capacitor/CAPBridgedJSTypes.h>到你的.m文件中。
PluginCall 和 CAPPluginCall 的变更### 使用 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'