在应用中升级 Capacitor 至 3.0 版本
Capacitor 3 为生态系统带来了重要更新和令人兴奋的新功能。
将应用升级到 Capacitor 3 后,欢迎您在此讨论区分享任何反馈意见。我们期待听到您的声音!💖
如果您是插件开发者,希望将插件升级到更新的 Capacitor 版本,请参阅Capacitor 插件升级指南。
NodeJS 12+
Node 8 已停止支持。Node 10 将于 2021 年 4 月 30 日停止支持。Capacitor 3 需要 NodeJS 12 或更高版本。(推荐使用最新的 LTS 版本。)
Ionic CLI
如果您正在使用 Ionic CLI,官方对 Capacitor 3 的支持从版本 6.16.0 开始。我们建议此时通过 npm install -g @ionic/cli 升级到最新版本。
更新 Capacitor CLI 和 Core
npm install @capacitor/cli@latest-3 @capacitor/core@latest-3
ES2017+
Capacitor 3 现在针对 ES2017 环境构建,而非 ES5。插件模板也已更新为面向 ES2017,鼓励第三方插件更新其 目标环境。
除非您需要支持 IE11(Capacitor 官方不支持),否则此更改不应影响您的应用。
TypeScript 3.8+
Capacitor 3 使用了仅在 TS 3.8 或更高版本中可用的较新 TypeScript 语法。
Capacitor 配置变更
如果您已安装 TypeScript 3.8+,可以将 capacitor.config.json 迁移为名为 capacitor.config.ts 的强类型 TypeScript 配置文件。您可以继续使用 .json 文件,但 TypeScript 配置文件可能为您的团队提供更好的开发体验。以下是一个在 Capacitor 测试应用中使用的 capacitor.config.ts 文件示例。
/// <reference types="@capacitor/local-notifications" />
/// <reference types="@capacitor/push-notifications" />
/// <reference types="@capacitor/splash-screen" />
import { CapacitorConfig } from '@capacitor/cli';
const config: CapacitorConfig = {
appId: 'com.capacitorjs.app.testapp',
appName: 'capacitor-testapp',
webDir: 'build',
plugins: {
SplashScreen: {
launchAutoHide: false,
},
LocalNotifications: {
smallIcon: 'ic_stat_icon_config_sample',
iconColor: '#CE0B7C',
},
PushNotifications: {
presentationOptions: ['alert', 'sound'],
},
},
};
export default config;
官方插件
所有插件都已从 Capacitor 核心库中移除,并置于各自的 npm 包中。这有几个原因(参见 #3227),核心团队确信这是正确的方向。您可以像这样导入核心插件。
import { Camera } from '@capacitor/camera';
后台任务、权限和照片插件已被移除
- 后台任务:此插件似乎很少使用,且工作方式与大多数开发者的预期不符。核心团队将在未来重新设计后台功能。关注 #3032 获取更新。
- 权限:核心团队已实现了一种替代这种集中式方法的新方案,社区插件也可能采用(参见新的权限 API)。
- 照片:这个未记录的仅限 iOS 的插件已被移除。请使用
@capacitor-community/media。
可访问性、应用和模态框插件被拆分
- 可访问性
- VoiceOver 和 TalkBack 功能移至 屏幕阅读器
- 应用
- 模态框
将您的应用迁移到使用新的官方插件包
此变更需要您单独安装每个正在使用的插件。
- 在您的项目中搜索从
@capacitor/core的Plugins对象中提取的核心插件 - 查找对应的插件文档,请记住有些插件已被拆分
- 按照文档中每个插件的安装说明进行操作
- 将插件导入改为从插件包导入(参见插件导入)
- 遵循向后不兼容的插件变更中的任何说明
使用 Ionic Framework 吗?
Ionic Framework 使用了以下插件中的 API:
为了获得 Ionic Framework 的最佳用户体验,即使您没有在应用中导入这些插件,也应确保它们已安装:
npm install @capacitor/app @capacitor/haptics @capacitor/keyboard @capacitor/status-bar
插件导入
Plugins 对象已被弃用,但在 Capacitor 3 中将继续工作。Capacitor 插件应更新为使用新的插件注册 API(参见插件升级指南),这将允许它们直接从插件包导入。
未来,不应再使用来自 @capacitor/core 的 Plugins 对象。
// 旧方式
import { Plugins } from '@capacitor/core';
const { AnyPlugin } = Plugins;
首选直接从插件包导入插件,但插件必须更新以兼容 Capacitor 3 才能实现此操作。
// 新方式
import { AnyPlugin } from 'any-plugin';
```## 向后不兼容的插件变更
虽然多数插件 API 保持不变以简化迁移到 Capacitor 3 的过程,但部分插件仍需要代码更新和手动迁移。
- **无障碍功能** / **屏幕阅读器**
- `isScreenReaderEnabled()` 方法已更名为 `isEnabled()`
- `'accessibilityScreenReaderStateChange'` 事件已更名为 `'stateChange'`
- 在 Android 和 iOS 上,`speak()` 仅当屏幕阅读器当前处于活动状态时才生效。如需在屏幕阅读器无论是否激活时都能使用文本转语音功能,请使用 [`@capacitor-community/text-to-speech`](https://github.com/capacitor-community/text-to-speech)。
- **浏览器**
- `prefetch()` 已被移除。
- **设备**
- 应用信息已从 `getInfo()` 中移除(包括 `appVersion`、`appBuild`、`appId` 和 `appName`)。请使用 App 插件的 [`getInfo()`](/apis/app.md#getinfo) 来获取这些信息。
- `getInfo()` 中的 `uuid` 已被移除。请使用新的 `getId()` 函数。
- **触觉反馈**
- `HapticsNotificationType` 枚举的键已从大写改为驼峰命名法,以与其他枚举保持一致。
- **本地通知**
- 此插件现在使用新的权限 API。`requestPermission()` 已被移除,请改用 `requestPermissions()`。
- **推送通知**
- 此插件现在使用新的权限 API。`requestPermission()` 已被移除,请改用 `requestPermissions()`。
- **分享**
- `share()` 方法现在返回 `ShareResult` 而非 `any`
- `share()` 的返回值将不再包含 `completed`。如果未完成,则会拒绝(reject)而不是返回该字段。
- **存储**
- **需要数据迁移!** 内部存储机制已变更,需要进行数据迁移。已添加一个便捷方法:`migrate()`。为避免影响最终用户,请在调用任何其他方法之前先调用 `migrate()` 来更新你的应用。
- **文件系统**
- `stat()` 方法现在在所有平台上均返回以毫秒为单位的 ctime 和 mtime 时间戳。此前,iOS 返回的是以秒为单位的时间戳。
## 日志记录变更
Capacitor 3 中已弃用 `hideLogs` 配置选项。它已被新的 `loggingBehavior` 配置选项取代。详细信息可在[配置文档](/main/reference/config.md)中找到。
## iOS
Capacitor 3 支持 iOS 12+。需要 Xcode 12+。推荐使用 CocoaPods 1.8+。
### 更新 CocoaPods
建议将 CocoaPods 升级到最新的稳定版本。[CocoaPods 1.8](https://blog.cocoapods.org/CocoaPods-1.8.0-beta/) 切换到了使用 CDN,这意味着不再需要定期运行 `pod repo update`。
使用 `pod --version` 检查你的 CocoaPods 版本,并访问 [cocoapods.org](https://cocoapods.org) 获取安装说明。
### 将 iOS 部署目标设置为 12.0
请对你的 Xcode 项目和应用程序目标进行以下操作:打开 **Build Settings** 标签页。在 **Deployment** 部分下,将 **iOS Deployment Target** 更改为 **iOS 12.0**。
然后,打开 `ios/App/Podfile` 并将 iOS 版本更新为 12.0:
```diff
-platform :ios, '11.0'
+platform :ios, '12.0'
use_frameworks!
将 Swift 版本设置为 5
如果你的应用尚未使用 Swift 5,请在 Xcode 目标中打开 Build Settings 标签页,然后在 Swift Compiler - Language 部分下将 Swift Language Version 更改为 Swift 5。
将 public 文件夹移至 iOS 目标目录
在 Capacitor 3 中,建议将 ios/App/public 目录移动到 ios/App/App/public 中。这可以在 Xcode 中完成:
移除现有的 public 文件夹
- 展开
App项目下的文件树,然后展开App组,并选中public文件夹。 - 右键单击 Delete。当提示是删除文件夹还是仅移除引用时,选择 Move to Trash。

在新位置重新创建 public 文件夹
- 右键单击
App项目内的App组,然后单击 Add Files to "App"... - 保持默认选项(确保创建的是文件夹引用,而不是分组,并且添加到
App目标)。 - 单击 New Folder,将其命名为 "public"。
- 单击 Create,然后单击 Add。

在 Xcode 中看起来可能相同,但现在新的 public 文件夹应该相对于 App 组,而不是项目根目录。
将新的 public 文件夹加入 gitignore
在 ios/.gitignore 中,将忽略路径从 App/public 更改为 App/App/public。此文件夹包含你的 Web 资产副本,不应提交。
App/build
App/Pods
-App/public
+App/App/public
App/Podfile.lock
xcuserdata
更新 Capacitor iOS 平台
npm install @capacitor/ios@latest-3
npx cap sync ios
在应用程序事件中将 CAPBridge 切换为 ApplicationDelegateProxy
在 ios/App/App/AppDelegate.swift 中,更新以下内容:
func application(_ app: UIApplication, open url: URL, options: [UIApplication.OpenURLOptionsKey: Any] = [:]) -> Bool {
// Called when the app was launched with a url. Feel free to add additional processing here,
// but if you want the App API to support tracking app url opens, make sure to keep this call
- return CAPBridge.handleOpenUrl(url, options)
+ return ApplicationDelegateProxy.shared.application(app, open: url, options: options)
}
func application(_ application: UIApplication, continue userActivity: NSUserActivity, restorationHandler: @escaping ([UIUserActivityRestoring]?) -> Void) -> Bool {
// Called when the app was launched with an activity, including Universal Links.
// Feel free to add additional processing here, but if you want the App API to support
// tracking app url opens, make sure to keep this call
- return CAPBridge.handleContinueActivity(userActivity, restorationHandler)
+ return ApplicationDelegateProxy.shared.application(application, continue: userActivity, restorationHandler: restorationHandler)
}
移除 USE_PUSH 编译条件
如果使用了推送通知功能,请在 ios/App/App/AppDelegate.swift 中更新以下内容:
- #if USE_PUSH
func application(_ application: UIApplication, didRegisterForRemoteNotificationsWithDeviceToken deviceToken: Data) {
NotificationCenter.default.post(name: Notification.Name(CAPNotifications.DidRegisterForRemoteNotificationsWithDeviceToken.name()), object: deviceToken)
}
func application(_ application: UIApplication, didFailToRegisterForRemoteNotificationsWithError error: Error) {
NotificationCenter.default.post(name: Notification.Name(CAPNotifications.DidFailToRegisterForRemoteNotificationsWithError.name()), object: error)
}
-#endif
如果未使用推送通知,你可以移除整个代码块
- #if USE_PUSH
-
- func application(_ application: UIApplication, didRegisterForRemoteNotificationsWithDeviceToken deviceToken: Data) {
- NotificationCenter.default.post(name: Notification.Name(CAPNotifications.DidRegisterForRemoteNotificationsWithDeviceToken.name()), object: deviceToken)
- }
-
- func application(_ application: UIApplication, didFailToRegisterForRemoteNotificationsWithError error: Error) {
- NotificationCenter.default.post(name: Notification.Name(CAPNotifications.DidFailToRegisterForRemoteNotificationsWithError.name()), object: error)
- }
-
-#endif
```### 从硬编码的 `CAPNotifications` 切换到 `NSNotification` 扩展
在 `ios/App/App/AppDelegate.swift` 文件中,更新以下内容:
```diff
override func touchesBegan(_ touches: Set<UITouch>, with event: UIEvent?) {
super.touchesBegan(touches, with: event)
let statusBarRect = UIApplication.shared.statusBarFrame
guard let touchPoint = event?.allTouches?.first?.location(in: self.window) else { return }
if statusBarRect.contains(touchPoint) {
- NotificationCenter.default.post(CAPBridge.statusBarTappedNotification)
+ NotificationCenter.default.post(name: .capacitorStatusBarTapped, object: nil)
}
}
func application(_ application: UIApplication, didRegisterForRemoteNotificationsWithDeviceToken deviceToken: Data) {
- NotificationCenter.default.post(name: Notification.Name(CAPNotifications.DidRegisterForRemoteNotificationsWithDeviceToken.name()), object: deviceToken)
+ NotificationCenter.default.post(name: .capacitorDidRegisterForRemoteNotifications, object: deviceToken)
}
func application(_ application: UIApplication, didFailToRegisterForRemoteNotificationsWithError error: Error) {
- NotificationCenter.default.post(name: Notification.Name(CAPNotifications.DidFailToRegisterForRemoteNotificationsWithError.name()), object: error)
+ NotificationCenter.default.post(name: .capacitorDidFailToRegisterForRemoteNotifications, object: error)
}
忽略 DerivedData
将 DerivedData 添加到 ios/.gitignore 文件中。这是 Capacitor CLI 存放 iOS 原生构建产物的地方。
App/Pods
App/App/public
App/Podfile.lock
+DerivedData
xcuserdata
# Capacitor 使用的 Cordova 插件
Android
Capacitor 3 支持 Android 5+(现在也支持 Android 11)。需要 Android Studio 4+。
更新 Capacitor Android 平台
npm install @capacitor/android@latest-3
npx cap sync android
切换到自动加载 Android 插件
在 Capacitor 3 中,推荐自动加载 Android 插件。在 MainActivity.java 中,可以移除 onCreate 方法。当你添加或移除通过 npm 安装的插件时,不再需要编辑此文件。
public class MainActivity extends BridgeActivity {
- @Override
- public void onCreate(Bundle savedInstanceState) {
- super.onCreate(savedInstanceState);
-
- // 初始化 Bridge
- this.init(savedInstanceState, new ArrayList<Class<? extends Plugin>>() {{
- // 你安装的额外插件放在这里
- add(Plugin1.class);
- add(Plugin2.class);
- }});
- }
}
如果你的应用包含专门为你的应用构建的自定义插件,你仍然需要在 onCreate 中注册这些插件:
public class MainActivity extends BridgeActivity {
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
+ registerPlugin(PluginInMyApp.class);
}
}
将 Gradle 更新到 7.0
我们现在建议在 Capacitor 项目中使用 Gradle 7.0。在 Android Studio 中,打开文件菜单,然后点击项目结构。在项目部分,将Gradle 版本更改为 7.0,Android Gradle 插件版本更改为 4.2.0。然后点击 确定。
你可能需要评估项目结构对话框的建议部分中推荐的 Android 包更新。
更新 Android 变量
在 android/variables.gradle 文件中,你可以更新以下变量:
ext {
minSdkVersion = 21
- compileSdkVersion = 29
- targetSdkVersion = 29
+ compileSdkVersion = 30
+ targetSdkVersion = 30
+ androidxActivityVersion = '1.2.0'
- androidxAppCompatVersion = '1.1.0'
+ androidxAppCompatVersion = '1.2.0'
+ androidxCoordinatorLayoutVersion = '1.1.0'
- androidxCoreVersion = '1.2.0'
- androidxMaterialVersion = '1.1.0-rc02'
- androidxBrowserVersion = '1.2.0'
- androidxLocalbroadcastmanagerVersion = '1.0.0'
- androidxExifInterfaceVersion = '1.2.0'
- firebaseMessagingVersion = '20.1.2'
- playServicesLocationVersion = '17.0.0'
+ androidxCoreVersion = '1.3.2'
+ androidxFragmentVersion = '1.3.0'
- junitVersion = '4.12'
- androidxJunitVersion = '1.1.1'
- androidxEspressoCoreVersion = '3.2.0'
+ junitVersion = '4.13.1'
+ androidxJunitVersion = '1.1.2'
+ androidxEspressoCoreVersion = '3.3.0'
cordovaAndroidVersion = '7.0.0'
}
Capacitor 3 支持 Android 11 (API 30),因此你可以将 SDK 目标更新到 30。将 compileSdkVersion 和 targetSdkVersion 更改为 30。
新增了 androidxActivityVersion 变量,添加它并设置值为 1.2.0。
可以将 androidxAppCompatVersion 更新为 1.2.0。
新增了 androidxCoordinatorLayoutVersion 变量,添加它并设置值为 1.1.0。
可以将 androidxCoreVersion 更新为 1.3.2。
androidxMaterialVersion 变量被 Action Sheet 和 Camera 插件使用,如果不使用这些插件可以移除。如果使用,请查看 Camera 文档 和 Action Sheet 文档。
androidxBrowserVersion 变量被 Browser 插件使用,如果不使用该插件可以移除。如果使用,请查看 文档。
androidxLocalbroadcastmanagerVersion 变量可以移除。
androidxExifInterfaceVersion 变量被 Camera 插件使用,如果不使用该插件可以移除。如果使用,请查看 文档。
firebaseMessagingVersion 变量被 Push Notifications 插件使用,如果不使用该插件可以移除。如果使用,请查看 文档。
playServicesLocationVersion 变量被 Geolocation 插件使用,如果不使用该插件可以移除。如果使用,请查看 文档。
新增了 androidxFragmentVersion 变量,添加它并设置值为 1.3.0。
可以将 junitVersion 更新为 4.13.1。
可以将 androidxJunitVersion 更新为 1.1.2。
可以将 androidxEspressoCoreVersion 更新为 3.3.0。### 移除未使用和冗余的权限
根据您使用的插件情况,可以选择性地从应用的 AndroidManifest.xml 文件中移除未使用的权限。新版 Capacitor 应用中的清单文件 默认只包含 INTERNET 权限,因为现在权限都是在插件安装时自动添加的。请按照以下步骤移除未使用的权限:
- 确定您的应用所使用的插件
- 参考官方插件文档中每个插件的安装说明,查看各插件所需的权限
- 在您应用的
AndroidManifest.xml文件中,保留插件所需的权限,移除未使用的权限
例如,Haptics 和 Network 插件现在已将安装时所需的权限包含在它们自己的 AndroidManifest.xml 文件中,这些文件最终会与您应用的清单文件合并。因此,您可以安全地从您应用的 AndroidManifest.xml 文件中移除这些插件的权限:
<!-- 权限 -->
<uses-permission android:name="android.permission.INTERNET" />
- <!-- Network API -->
- <uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />
- <!-- Vibration API -->
- <uses-permission android:name="android.permission.VIBRATE" />
</manifest>