在您的插件中将 Capacitor 更新到 3.0
对于正在更新到 Capacitor 3 的插件,有几个必需的和推荐的更改。
规划核心 API
目前,核心团队很难在不影响插件的情况下对 Capacitor 的内部进行更改。因为 Capacitor 2 中的大多数类和方法对于 iOS 和 Android 都是公开的,所以我们观察到我们对被认为是内部的 Capacitor API 的使用不符合预期。
在 Capacitor 3 开发期间,我们将评估这个问题并创建插件的官方公共 API,该 API 将在此处记录。
Android
使用新的 @CapacitorPlugin 注解
@NativePlugin 注解已弃用。我们现在建议使用新的 @CapacitorPlugin 注解,它将允许新的权限 API。
name 属性相同。requestCodes 和 permissionRequestCode 属性被删除。permissions 属性需要替换为 @Permission 注解列表,每个注解包含一个清单字符串列表及其相应的 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 并删除了手动定义的请求代码。插件不应该提供请求代码并覆盖 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();
+ // do something with the result data
+ call.resolve("Success!");
+ }
+}
使用 WebColor.parseColor() 而不是 Color.parseColor()
Android 使用 ARGB 格式解析带有 alpha 通道的十六进制颜色字符串,而在 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已弃用。使用类型访问器之一来检查值。- 任何采用默认值的访问器现在都需要非可选默认值,但返回非可选结果。这可能会更改局部变量的可选项,但应该减少强制解包的使用,这是 Swift 中的反模式。
- 关于日期和 null 值的行为略有变化并有更好的文档记录。在此处查找更多信息。
- Obj-C 便利访问器已分离以避免与 Swift 实现冲突。如果您在 Obj-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'
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:表示功能不能或不会实现,或者可能在将来实现
阅读更多关于 Web、iOS 和 Android 的错误处理。
采用新的权限 API
在 3.0 之前,预期插件会在使用功能之前自动请求权限。例如,地理位置插件会在第一次请求用户位置时自动请求权限,然后在授予权限或拒绝权限时继续适当地进行。
Capacitor 3 的一个目标是让应用开发人员能够随时请求或检查权限,并控制和何时向用户显示提示。这通过允许应用以各种方式响应用户的选择,在用户体验中提供了更大的灵活性。
继续自动请求权限完全可以,但我们鼓励您也采用新的权限模式,以便为应用开发人员提供对权限的控制。