基本命令
npm install -g cordova ios-deploy
- 如果要运行在
xcode
需要用xcode
打开项目名.xcworkspace
文件
1 | 创建工程 |
目录结构
编译后
*-Info.plist
在Resources
目录下如果要添加配置到
*-Info.plist
文件里可以在config.xml
里面的platform ios
添加,不过添加完成后需要重新cordova platform remove ios && cordova platform add ios
,否则可能出现错误doc.find is not a function1
2
3
4
5
6
7
8
9
10
11<platform name="ios">
<!--下面这个配置可以避免NSURLConnection finished with error - code -1004问题-->
<edit-config file="*-Info.plist" mode="merge" target="NSAppTransportSecurity">
<dict>
<key>NSAllowsArbitraryLoadsInWebContent</key>
<true/>
<key>NSAllowsArbitraryLoads</key>
<true/>
</dict>
</edit-config>
</platform>
使用Vue作前端
VUE配置步骤
初始化一个
vue
工程,vue init webpack project-name
在
vue/index.html
的head
中添加内容:1
2
3<meta http-equiv="Content-Security-Policy" content="default-src ‘self’ data: gap: https://ssl.gstatic.com ‘unsafe-eval’; style-src ‘self’ ‘unsafe-inline’; media-src *; img-src ‘self’ data: content:; connect-src ‘self’ ws:;">
<script type="text/javascript" src="cordova.js"></script>修改build配置,在
config/index.js
中修改如下配置1
2
3
4build: {
index: path.resolve(__dirname, ‘../www/index.html’), // 指向cordova的www目录
assetsRoot: path.resolve(__dirname, ‘../www’),
}
依赖管理Pod
- 转为iOS工程提供的第三方库的依赖管理工具
- 如果发现执行这些命令后仍然缺少依赖,可以去看看fetch.json文件里面有没有缺失那个包,如果缺失了尝试删除fetch.json文件再次安装npm包和pod包试试
1 | sudo sudo # 安装pod管理工具 |
移动端常用配置
添加App logo
Android
- 在
resources
目录中添加logo文件resources/logo.png
- 只需要在
config.xml
中添加<icon src="resources/logo.png" platform="android" width="57" height="57" density="mdpi"/>
即可(与name
同一级)
Ios
首先需要生成各个尺寸的logo图片,否则没有的就不会展示自定义的icon,可以在App Icon Generator生成对应平台的所有尺寸图片,它会生成一个针对XCode的压缩包,我们可以将所有的图片提取到
resources/ios
目录下在
config.xml
的ios配置中添加如下的icon属性1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22<platform name="ios">
<icon src="resources/ios/180.png" width="180" height="180"/>
<icon src="resources/ios/20.png" width="20" height="20"/>
<icon src="resources/ios/60.png" width="60" height="60"/>
<icon src="resources/ios/120.png" width="120" height="120"/>
<icon src="resources/ios/76.png" width="76" height="76"/>
<icon src="resources/ios/152.png" width="152" height="152"/>
<icon src="resources/ios/40.png" width="40" height="40"/>
<icon src="resources/ios/80.png" width="80" height="80"/>
<icon src="resources/ios/57.png" width="57" height="57"/>
<icon src="resources/ios/114.png" width="114" height="114"/>
<icon src="resources/ios/72.png" width="72" height="72"/>
<icon src="resources/ios/144.png" width="144" height="144"/>
<icon src="resources/ios/167.png" width="167" height="167"/>
<icon src="resources/ios/29.png" width="29" height="29"/>
<icon src="resources/ios/58.png" width="58" height="58"/>
<icon src="resources/ios/87.png" width="87" height="87"/>
<icon src="resources/ios/50.png" width="50" height="50"/>
<icon src="resources/ios/100.png" width="100" height="100"/>
<icon src="resources/ios/167.png" width="167" height="167"/>
<icon src="resources/ios/1024.png" width="1024" height="1024"/>
</platform>然后
cordova prepare
后打开Xcode,在左侧目录项目名->Resources->Images.xcassets->AppIcon
可以看到我们所有的图标,然后选中整个AppIcon框后,右侧可以勾选对应的平台,选择了后就可以把对应的图片拖到对应尺寸的框里,如果有重复的,可以直接Cmd + C
进行复制,不能用鼠标复制。需要保证所有的框都装了icon并且没有感叹号
config.xml配置
1 | <preference name="android-minSdkVersion" value="14"/> <!--设置安卓的minSDK--> |
异形屏处理
现在流行水滴屏、刘海屏、曲面屏、瀑布屏或者其他的异形屏/凹槽,可能会造成屏幕上下左右出现不规则的区域(或者多出来一块、white bar)
我们需要在
App.vue
中添加一个全局的padding使我们的内容全都在中间,目前有四个参数来分别代表上下左右四个地方的安全区域距离边界的距离1
2
3
4
5
6
7
8
9// 首先需要修改index.html中的viewport,添加vieport-fit=cover
<meta name="viewport" content="width=device-width, initial-scale=1.0, shrink-to-fit=no, viewport-fit=cover">
// 然后需要将app的样式修改一下,将页面主体限定在安全区域内
#app {
height:100vh;
width:100vw;
padding: env(safe-area-inset-top) env(safe-area-inset-right) env(safe-area-inset-bottom) env(safe-area-inset-left);
}如果有
position:absolute; bottom:0
这样的absolute/fixed组件,建议在不同屏幕上看一下,可能需要改为bottom:env(safe-area-inset-bototm)
,否则可能仍然会跑到异形的地方去(注意背景色的不同)
常用插件推荐
很多插件的官方文档都不写插件在使用的时候的命名空间在哪里,可以尝试一下方法找一下,找不到还有一个可能是插件没有注入进来,可以尝试rm然后重新add一下插件
1
2
3
4
5
6
7if (window.plugins) {
console.log('window.plugins', Object.keys(window.plugins))
}
if (window.cordova.plugins) {
console.log('window.cordova.plugins', Object.keys(window.cordova.plugins))
}
console.log(Object.keys(window))
branch-cordova-sdk
- deeplink插件
- 官方集成文档
- 如果配置成功后依然不work,可能需要重新
cordova build ios
一下 - 默认情况下,在桌面打开分享地址会是发送SMS的页面,可以在branch后台设置里面的Desktop Redirects中修改的,一种是
Branch-hosted SMS Landing Page
(发送SMS,但是这个发送SMS必须发邮件给他们才会给你开通,否则会报错This app is blocked from sending SMS messages),一种是Custom Landing Page
- 如果
+clicked_branch_link
一直为false
,可能是因为该link没有在后端创建,正常情况下,deeplink需要在后端创建,但是如果我们不需要对该link做什么运营相关的事情,可以直接在后台手动创建Quick Links
右上角直接Create
一个即可,这样改link打开才会是+clicked_branch_link=true
- APP ID Prefix就是apple developer的Team ID
cordova-plugin-app-version
- 获取当前APP版本的插件,使用很简单的啦
cordova-plugin-console
- 只有很老的版本才需要了,现在可以直接使用
console.log
进行日志的输出,需要注意的是,必须先引入cordova.js
才行,否则依然无法看到日志输出
cordova-plugin-device
获取平台设备信息,ionic
不需要使用插件,直接import { Platform } from "ionic-angular"
cordova-plugin-facebook-connect
Facebook登陆插件,安装完成后得去
platforms/ios
目录执行一下pod repo update && pod install
安装facebook SDK,这样使用:需要注意的是,如果获取不到邮箱地址,可能的原因是邮箱没有认证
test user
如果出现There was a problem logging you in.
错误,不知道为啥,尝试换成添加真实用户为测试用户试试
1 | window.facebookConnectPlugin.login(['public_profile', 'email'], userData => { |
cordova-plugin-firebasex
firebase插件,包含(cloud messaging等多个firebase的功能),如果对firebase的证书配置还不熟悉,可以现在其example项目上进行测试,它的example里还有命令行工具,不过它打印的错误信息不够详细,还是用firebase-admin-node好一点,具体的使用方式和证书等配置可以在firebase手册中查看
cordova-plugin-geolocation
如果xcode里面有warning:
No NSLocationAlwaysUsageDescription or NSLocationWhenInUseUsageDescription key is defined in the Info.plist file.
表示没有正确配置NSLocationWhenInUseUsageDescription
选项下面是两种获取地理信息的声明,需要选择一种在
config.xml
中添加,添加完后记得重新编译(可能需要remove ios再添加才行):1
2
3
4
5
6
7<edit-config target="NSLocationWhenInUseUsageDescription" file="*-Info.plist" mode="merge">
<string>need location access to find things nearby</string>
</edit-config>
<edit-config target="NSLocationAlwaysAndWhenInUseUsageDescription" file="*-Info.plist" mode="merge">
<string>need location access to find things nearby</string>
</edit-config>
cordova-plugin-nativestorage
如果不能使用可以直接安装仓库里面的最新代码
1
2cordova plugin remove cordova-plugin-nativestorage
cordova plugin add https://github.com/TheCocoaProject/cordova-plugin-nativestorage
cordova-plugin-purchase
- 内购插件
- apple这边的设置参考Setup for iOS and macOS,包括创建bundle id,在apple store创建产品,以及创建沙盒账户。注意,sandbox账户必须退出机器本身的apple id,但又不能直接在机器本身apple id那里进行登录,只能在app里面点击支付弹出登录框的时候进行登录
- 需要注意的是在你的device上面必须在app store里面退出当前的账户,但是不用登录沙盒账户,在购买的时候会提示你登录。另外,必须先填写Tax Forms and Contacts,否则你的产品一直处于
invalid
的状态 - 使用文档可以参考Ionic In App Purchase 2,注意cordova这边直接用是这样
window.store
cordova-plugin-googleplus
Google登陆插件,只不过需要获取很多的账号相关的信息,实际的登陆只需要下面这样做即可。
REVERSED_CLIENT_ID
需要在firebase
的Project settings
的app中获取,需要下载GoogleService-Info.plist
,包含在里面的。安装完成后需要确保REVERSED_CLIENT_ID
被加入到XCode
中的Resources/项目名-Info.plist
中的URL types
中,其中URL-identifier=REVERSED_CLIENT_ID
,URL Schemes[0]=com.googleusercontent.apps.xxxxxxx
,如果没有可以手动添加:WEB_APPLICATION_CLIENT_ID
可以在firebase
里新建一个web app
取其ID或者直接在上面的GoogleService-Info.plist
取GOOGLE_APP_ID
Android
端的webClientId
参数则是firebase
的android app
的google-services.json
中的client.oauth_client.client_id
(如果登录时返回一个错误码10有可能就是这个client id没有填对,或者是下面的fingerprints没有被添加到firebase里面去)Android
端现在可以不用google-service.json
文件了(如果有用到firebase还是需要的,否则会出现错误:No matching client found for package name),但是需要这样做- 本地生成一个SHA1的key:
keytool -exportcert -alias androiddebugkey -keystore ~/.android/debug.keystore -list -v
,这里的~/.android/debug.keystore
是keytool
的地址,安装了Android Studio
就自动有的 - 在
Firebase -> Project Overview -> Project settings -> General
新建Android apps
,并将上一步生成的SHA1添入到该APP下的SHA certificate fingerprints
中 - 如果是要发布到
play store
,会在上传bundle
的时候给App重新签名,我们需要在google play console -> Setup -> App integrity
中的SHA-1 certificate fingerprint
上传到上一步的firebase
后台中,否则本地测试ok,但是传上去点击登录的时候却没有反应
- 本地生成一个SHA1的key:
1 | window.plugins.googleplus.isAvailable(avail => { |
cordova-plugin-qrscanner
inoic
官方推荐的一个二维码扫描插件,不过也没找到更好的了,我给改了bug。它默认是全屏的,如果要更改为局部扫描,我觉得得修改源代码,不直接取body
。还有一个问题是推出扫描时,背景颜色居然没有改过来,我在js代码里改的,所以我是这样用的:
1 | mounted() { |
cordova-plugin-sign-in-with-apple
Apple ID登陆插件
- 需要在apple开发者后台给指定Bundle ID添加
Sign In with Apple
权限,使用同样非常简单,如果要获取email可以使用jwt-decode
去 - 如果是Angular项目,需要将
SignInWithApple
加入到app.module.ts
中去,否则可能出现NullInjectorError: No provider for Sign in with Apple
错误 - 如果用户选择隐藏邮箱,你是肯定获取不到真实邮箱的,不要挣扎了
- 需要注意的是对于
ionic 4.x
版本,不能用官方的方式来安装,需要安装的是ionic cordova plugin add cordova-plugin-sign-in-with-apple && npm install @ionic-native/sign-in-with-apple
,然后不需要去providers
中声明,也不需要用this.signInWithApple
,直接用cordova.plugins.SignInWithApple.signin
即可,调用方法也得按下面这种
1 | window.cordova.plugins.SignInWithApple.signin( |
cordova-plugin-splashscreen
启动屏配置插件
cordova-spotify
Cordova的Spotify插件
如果是安卓,建议安装我fork的这个cordova-spotify-oauth,否则可能不起作用
插件开发Tips
- 我不开发插件,但是很多很小众的插件,经常需要我们修改一下,所以还是需要学习一点插件开发的知识
IOS开发常用流程
方法定义: 需要在
src/ios/*.h
中这样定义:1
2
3
4
5
6
7
8#import <Cordova/CDV.h>
@interface CordovaAppleMusic : CDVPlugin
- (void) requestToken:(CDVInvokedUrlCommand*)command;
- (void) requestAuthorization:(CDVInvokedUrlCommand*)command;
@end方法实现,需要在
src/ios/*.m
中实现1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20// 此方法来自于CordovaAppleMusic Plugin,是使用OC写的
- (void)requestToken:(CDVInvokedUrlCommand*)command
{
NSString* callbackId = [command callbackId];
NSString* developerToken = [[command arguments] objectAtIndex:0]; // 如果方法有参数可以这样获取参数
SKCloudServiceController *serviceController = [[SKCloudServiceController alloc] init];
[serviceController requestUserTokenForDeveloperToken:developerToken completionHandler:^(NSString * _Nullable userToken, NSError * _Nullable error) {
if (error != nil) {
NSLog(@"userToken_Error :%@", error);
// 返回正确响应
CDVPluginResult* result = [CDVPluginResult resultWithStatus:CDVCommandStatus_ERROR messageAsString:error.description];
[self.commandDelegate sendPluginResult:result callbackId:callbackId];
}
else{
// 返回错误响应
CDVPluginResult* result = [CDVPluginResult resultWithStatus:CDVCommandStatus_OK messageAsString:userToken];
[self.commandDelegate sendPluginResult:result callbackId:callbackId];
}
}];
}最后在
www/*.js
中暴露方法给JS1
2
3
4
5
6
7
8
9var exec = require('cordova/exec');
module.exports = {
requestAuthorization: function (successCallback, errorCallback) { // 无参数的方法
exec(successCallback, errorCallback, "AppleMusic", "requestAuthorization", []);
},
requestToken: function (developerToken, successCallback, errorCallback) { // 带参数的方法
exec(successCallback, errorCallback, "AppleMusic", "requestToken", [developerToken]);
},
}
TroubleShooting
- 应用启动一直白屏: 网上有很多解决方法,都试过,我最后的解决方法是把系统语言切换成英文解决了
- pod: Command failed with exit code 31: 尝试执行一下
pod repo update
,如果是Apple Silicon
,那么需要使用arch -x86_64 zsh
- 删除
node_module
可以解决的一些问题:- Cannot find module ‘./elementtree’
- Current working directory is not a Cordova-based project.: 可能是
www
目录不见了 - new Date(‘2020-04-29 00:00:00’)输出Invalid Date: 目前我个人只在ios上复现过,vue直接运行没问题,但是真机上却是
Invalid Date
,用moment代替吧 - ‘GoogleService-Info.plist’ was not found in your Cordova project root folder: 如果是这样,首先检查是否有该文件,如果确实有还是报错,那么可以在
XCode
中手动添加,右键项目的Resource->Add Files to "项目名"
选择GoogleService-Info.plist
即可 - 开启应用显示The connection to the server was unsuccessful: 可以在
config.xml
中添加<preference name="loadUrlTimeoutValue" value="60000" />
具体原因不知道为啥,至少能用 - File google-services.json is missing: 从
firebase
下载google-services.json
文件,然后复制到platforms/android/app
下面去 - package IInAppBillingService does not exist: AlexDisler/cordova-plugin-inapppurchase插件报的错,这个插件已经被
archived
了,不建议使用,修复可以尝试mkdir -p platforms/android/app/src/main/aidl/com/android/vending/billing && cp platforms/android/src/com/android/vending/billing/IInAppBillingService.aidl platforms/android/app/src/main/aidl/com/android/vending/billing/
- 编译安卓的时候报错Cannot read property ‘version’ of null: 尝试删除重新生成目录
cordova platform rm android && cordova platform add android
- **Cannot find ‘GIDConfiguration’ / No type or protocol named ‘GIDSignInDelegate’**没什么特别的办法,自己尝试不同的Google或者firebase的pod版本吧,太难了
- script error: js的错误,如果能在vue那边调试最好在那边调试,在cordova这边的话基本调试不了,只能自己加断点或者日志了
- 修改Andorid的Gradle的版本:可以直接在
android\gradle\wrapper\gradle-wrapper.properties
里面修改,但是这样每次cordova build后又恢复了,还有个办法是在cordova之前设置一个环境变量指定版本即可:export CORDOVA_ANDROID_GRADLE_DISTRIBUTION_URL=https://services.gradle.org/distributions/gradle-6.7.1-all.zip
- A problem was found with the configuration of task ‘:app:injectCrashlyticsMappingFileIdDebug’ (type ‘InjectMappingFileIdTask’) : 这个问题我就是将gradle的版本从7.1.1降到6.7.1解决的
- build An exception has occurred in the compiler (1.8.0_302). Please file a bug against the Java compiler via the Java bug reporting page: 应该是android sdk版本的问题,我这边用系统默认的sdk不行,但是用android studio却可以,那么我直接设置为android studio的sdk路径即可:
export JAVA_HOME="/Applications/Android Studio.app/Contents/jre/Contents/Home