内购中断此测试员的购买流程

中断此测试员的购买流程
此测试员在沙盒环境中于设备上进行的购买尝试将被更新的条款与条件中断。此功能可以测试 App 对中断情况的响应,以确保购买流程顺畅。
在此流程中,测试员的购买尝试将被中断,除非您取消选中上方的复选框,或测试员在其 iOS 设备上同意条款与条件。

点 “取消” 和 点 “好” 都会报错:
source:IAPSource.AppStore
code:purchase_error
message:SKErrorDomain
details:{NSLocalizedDescription: 发生未知错误, NSUnderlyingError: {domain: ASDServerErrorDomain, userInfo: {NSLocalizedDescription: Apple 媒體服務條款與約定已更改}, code: 3038}}

同意协议后,走回调票据 进入 PurchaseStatus.purchased 状态

flutter一键打包ipa、apk安装包 上传蒲公英

经验证,flutter build iOS打出的ipa包太大,用xcodebuild打包正常,支持设置代码混淆。iOS如果因为签名原因打包失败,先用Xcode正常打一次就行。

直接上脚本:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
## 计时
SECONDS=0

# 打包类型 1:android 2:ios any:其它全部
platform=0

# Xcode12开始需要设置导出ipa的名字
project_name="flutter_easy_example"
## 蒲公英 APIKey https://www.pgyer.com/account/api
pgyer_api_key=""
## 蒲公英 下载地址后缀
pgyer_subfix_url=""
## 蒲公英 安装密码
pgyer_pwd=""

# 不使用代码混淆
#obfuscate=""
# 开启代码混淆
obfuscate="--obfuscate --split-debug-info=app"

# 选择打包类型
read -n1 -p "设置打包类型 1:android 2:ios any:其它全部 (5s后自动执全部打包) [1/2/any]? " -t 5 answer
platform=${answer}

echo "清理 build"
find . -d -name "build" | xargs rm -rf
flutter clean

echo "开始获取 packages 插件资源"
flutter packages get

# iOS
build_ios() {
cd ios
project=`find . -name *.xcodeproj | awk -F "[/.]" '{print $(NF-1)}'`

## true or false 默认true
workspace_flag="true"

## Release or Debug 默认Release
configuration="Release"

## Bitcode开关 默认打开
compileBitcode=true

## 签名方式 默认自动签名,如果打包失败,先用Xcode打一次就正常了
signingStyle="automatic"

## 签名方式
### development
### ad-hoc
### app-store
### enterprise
methodStyle="ad-hoc"

## 打包导出目录
path_app="../app"

## 工作目录 build目录在.gitignore添加忽略
path_build="build"

path_archive="${path_build}/${project}.xcarchive"

path_export_options="${path_build}/ExportOptions.plist"

if [ -d "${path_build}" ]
then
echo "目录${path_build}已存在"
else
echo "创建目录${path_build}"
mkdir -pv "${path_build}"
fi

funcExpertOptionFile() {
if [ -f "$path_export_options" ]
then
rm -rf "$path_export_options"
fi

/usr/libexec/PlistBuddy -c "Add :compileBitcode bool $compileBitcode" "$path_export_options"
/usr/libexec/PlistBuddy -c "Add :signingStyle string $signingStyle" "$path_export_options"
/usr/libexec/PlistBuddy -c "Add :method string $methodStyle" "$path_export_options"
}

## 创建ExportOptions.plist文件
funcExpertOptionFile

if $workspace_flag
then
## 清理工程
xcodebuild clean -workspace ${project}.xcworkspace \
-scheme ${project} \
-configuration ${configuration}

## 归档
xcodebuild archive -workspace ${project}.xcworkspace \
-scheme ${project} \
-configuration ${configuration} \
-archivePath ${path_archive}
else
## 清理工程
xcodebuild clean -project ${project}.xcworkspace \
-scheme ${project} \
-configuration ${configuration}

## 归档
xcodebuild archive -project ${project}.xcworkspace \
-scheme ${project} \
-configuration ${configuration} \
-archivePath ${path_archive}
fi

## 判断归档结果
if [ -d "${path_archive}" ]
then
echo "** Finished archive. Elapsed time: ${SECONDS}s **"
echo
else
exit 1
fi

## 导出ipa
xcodebuild -exportArchive \
-archivePath ${path_archive} \
-exportPath ${path_app} \
-exportOptionsPlist ${path_export_options}

## ipa路径
file_ipa="${path_app}/${project}-$(date "+%Y%m%d%H%M").ipa"
if [[ -n "${project_name}" ]]
then
mv "${path_app}/${project_name}.ipa" "${file_ipa}"
else
mv "${path_app}/${project}.ipa" "${file_ipa}"
fi

## 判断导出ipa结果
if [ -f "${file_ipa}" ]
then
echo "** Finished export. Elapsed time: ${SECONDS}s **"
rm -rf "$path_build"
echo $file_ipa
say "iOS打包成功"

if [[ -n "${pgyer_api_key}" ]]
then
#上传到pgyer
echo "正在上传到蒲公英..."
echo
curl -F "file=@${file_ipa}" -F "_api_key=${pgyer_api_key}" -F "buildInstallType=2" -F "buildPassword=${pgyer_pwd}" -F "buildUpdateDescription=脚本自动上传" https://www.pgyer.com/apiv2/app/upload
# rm -rf ${file_ipa}
echo
say "iOS上传蒲公英成功"
echo
if [[ -n "${pgyer_subfix_url}" ]]
then
open https://www.pgyer.com/${pgyer_subfix_url}
fi
else
open $path_app
fi
else
echo "遇到报错了😭, 打开Xcode查找错误原因"
say "iOS打包失败"
exit 1
fi

echo "------------------------------------------------------------------------------"
echo "🎉 Congrats"

echo "🚀 ${project} successfully published"
echo "📅 Finished. Elapsed time: ${SECONDS}s"
echo "🌎 https://octmon.github.io"
echo "👍 Tell your friends!"
echo "------------------------------------------------------------------------------"

echo

cd ..
}

##==================================apk==================================
if [[ ${platform} -ne 2 ]]; then
echo "开始build apk"
flutter build apk $obfuscate --release --verbose #--no-codesign
echo "build apk已完成"

file_apk=android-$(date "+%Y%m%d%H%M").apk

cp -r build/app/outputs/apk/release/app-release.apk app/$file_apk

if [[ -f app/${file_apk} ]]
then
say "android打包成功"

if [[ -n "${pgyer_api_key}" ]]
then
#上传到pgyer
echo "正在上传到蒲公英..."
echo
curl -F "file=@app/${file_apk}" -F "_api_key=${pgyer_api_key}" -F "buildInstallType=2" -F "buildPassword=${pgyer_pwd}" -F "buildUpdateDescription=脚本自动上传" https://www.pgyer.com/apiv2/app/upload
# rm -rf app/${file_ipa}
echo
say "android上传蒲公英成功"
echo
if [[ -n "${pgyer_subfix_url}" ]]
then
open https://www.pgyer.com/${pgyer_subfix_url}
fi
else
open app
fi
else
echo "遇到报错了😭, 打开Android Studio查找错误原因"
say "android打包失败"
fi

echo "📅 Finished. Elapsed time: ${SECONDS}s"
fi
##==================================apk==================================

##==================================ipa==================================
if [[ ${platform} -ne 1 ]]; then
echo "开始build ios"
flutter build ios $obfuscate --release --verbose #--no-codesign
echo "build ios已完成"

build_ios
fi
##==================================ipa==================================

flutter配置多个环境

复制一份默认的flutter环境,并修改文件夹为:flutter_dev

打开终端输入:

1
open .zshrc

在文本编辑里加入flutter_dev环境:

1
2
3
4
5
6
export PATH=$PATH:~/Library/Android/sdk/platform-tools;
export PATH=~/Library/Android/flutter/bin:$PATH
export PUB_HOSTED_URL=https://pub.flutter-io.cn
export FLUTTER_STORAGE_BASE_URL=https://storage.flutter-io.cn

alias flutter_dev=~/Library/Android/flutter_dev/bin/flutter

保存之后,新建Shell窗口验证默认flutter环境,输入:

1
flutter doctor

结果:

1
2
3
4
5
6
7
8
9
10
Doctor summary (to see all details, run flutter doctor -v):
[✓] Flutter (Channel stable, v1.12.13+hotfix.10-pre.1, on Mac OS X 10.15.5
19F101, locale zh-Hans-CN)
[✓] Android toolchain - develop for Android devices (Android SDK version 29.0.3)
[✓] Xcode - develop for iOS and macOS (Xcode 11.4.1)
[✓] Android Studio (version 4.0)
[✓] VS Code (version 1.45.1)
[✓] Connected device (1 available)

• No issues found!

验证flutter_dev环境,输入:

1
flutter_dev doctor

结果:

1
2
3
4
5
6
7
8
9
10
11
[✓] Flutter (Channel dev, 1.19.0-3.0.pre, on Mac OS X 10.15.5 19F101, locale
zh-Hans-CN)

[✓] Android toolchain - develop for Android devices (Android SDK version 29.0.3)
[✓] Xcode - develop for iOS and macOS (Xcode 11.4.1)
[✓] Chrome - develop for the web
[✓] Android Studio (version 4.0)
[✓] VS Code (version 1.45.1)
[✓] Connected device (4 available)

• No issues found!

flutter中使用 Future.wait 一次执行多个异步操作

用法:

1
2
3
4
5
6
7
Future.wait([
PackageInfoUtil.init(),
SharedPreferencesUtil.init(),
]).then((e) {
log("init:", e);
callback();
});

执行结果:

1
flutter: init: => [Instance of 'PackageInfo', Instance of 'SharedPreferences']

Hello World

Welcome to Hexo! This is your very first post. Check documentation for more info. If you get any problems when using Hexo, you can find the answer in troubleshooting or you can ask me on GitHub.

Quick Start

Create a new post

1
$ hexo new "My New Post"

More info: Writing

Run server

1
$ hexo server

More info: Server

Generate static files

1
$ hexo generate

More info: Generating

Deploy to remote sites

1
$ hexo deploy

More info: Deployment