pindo 5.10.6 → 5.10.8

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (75) hide show
  1. checksums.yaml +4 -4
  2. data/lib/pindo/base/funlog.rb +12 -1
  3. data/lib/pindo/base/pindocontext.rb +3 -0
  4. data/lib/pindo/command/android/autobuild.rb +62 -9
  5. data/lib/pindo/command/android/build.rb +6 -6
  6. data/lib/pindo/command/android/debug.rb +9 -9
  7. data/lib/pindo/command/deploy/build.rb +2 -4
  8. data/lib/pindo/command/deploy/cert.rb +4 -5
  9. data/lib/pindo/command/deploy/configproj.rb +3 -3
  10. data/lib/pindo/command/deploy/confusecode.rb +1 -1
  11. data/lib/pindo/command/deploy/confuseproj.rb +1 -1
  12. data/lib/pindo/command/deploy/pem.rb +3 -4
  13. data/lib/pindo/command/dev/autobuild.rb +1 -1
  14. data/lib/pindo/command/dev/build.rb +1 -1
  15. data/lib/pindo/command/dev/feishu.rb +1 -1
  16. data/lib/pindo/command/gplay/pullconfig.rb +48 -0
  17. data/lib/pindo/command/gplay.rb +6 -5
  18. data/lib/pindo/command/ios/adhoc.rb +6 -5
  19. data/lib/pindo/command/ios/autobuild.rb +24 -24
  20. data/lib/pindo/command/ios/build.rb +7 -6
  21. data/lib/pindo/command/ios/debug.rb +1 -0
  22. data/lib/pindo/command/ipa/import.rb +2 -3
  23. data/lib/pindo/command/ipa/output.rb +2 -3
  24. data/lib/pindo/command/jps/upload.rb +6 -5
  25. data/lib/pindo/command/unity/apk.rb +19 -2
  26. data/lib/pindo/command/unity/autobuild.rb +58 -63
  27. data/lib/pindo/command/unity/initpack.rb +1 -1
  28. data/lib/pindo/command/unity/ipa.rb +17 -14
  29. data/lib/pindo/command/unity/pack.rb +1 -1
  30. data/lib/pindo/command/unity/upload.rb +1 -1
  31. data/lib/pindo/command/unity/web.rb +2 -2
  32. data/lib/pindo/command/utils/icon.rb +1 -1
  33. data/lib/pindo/command/utils/renewcert.rb +1 -2
  34. data/lib/pindo/command/utils/renewproj.rb +9 -10
  35. data/lib/pindo/command/web/autobuild.rb +2 -2
  36. data/lib/pindo/command/web/run.rb +1 -1
  37. data/lib/pindo/command.rb +2 -1
  38. data/lib/pindo/module/android/android_build_config_helper.rb +267 -35
  39. data/lib/pindo/module/android/android_build_helper.rb +300 -0
  40. data/lib/pindo/module/android/android_project_helper.rb +279 -0
  41. data/lib/pindo/module/android/gp_compliance_helper.rb +33 -87
  42. data/lib/pindo/module/android/gradle_helper.rb +524 -255
  43. data/lib/pindo/module/android/java_env_helper.rb +633 -0
  44. data/lib/pindo/module/android/keystore_helper.rb +1118 -0
  45. data/lib/pindo/module/appselect.rb +109 -0
  46. data/lib/pindo/module/appstore/appstore_in_app_purchase.rb +1 -1
  47. data/lib/pindo/module/build/{buildhelper.rb → build_helper.rb} +1 -2
  48. data/lib/pindo/module/build/{commonconfuseproj.rb → confuse_xcodeproj.rb} +2 -2
  49. data/lib/pindo/module/cert/cert_helper.rb +245 -0
  50. data/lib/pindo/module/cert/keychain_helper.rb +152 -0
  51. data/lib/pindo/module/cert/pem_helper.rb +67 -0
  52. data/lib/pindo/module/cert/xcodecerthelper.rb +2 -2
  53. data/lib/pindo/module/{build/unityhelper.rb → unity/unity_helper.rb} +0 -17
  54. data/lib/pindo/module/xcode/{xcodereshandler.rb → res/xcode_res_handler.rb} +1 -1
  55. data/lib/pindo/module/xcode/{xcodebuildconfig.rb → xcode_build_config.rb} +7 -6
  56. data/lib/pindo/module/xcode/{xcodebuildhelper.rb → xcode_build_helper.rb} +4 -3
  57. data/lib/pindo/module/xcode/{xcodehelper.rb → xcode_project_helper.rb} +4 -2
  58. data/lib/pindo/module/xcode/{xcodereshelper.rb → xcode_res_helper.rb} +12 -9
  59. data/lib/pindo/version.rb +185 -7
  60. data/lib/pindo.rb +14 -9
  61. metadata +24 -23
  62. data/lib/pindo/module/android/apk_helper.rb +0 -138
  63. data/lib/pindo/module/android/base_helper.rb +0 -964
  64. data/lib/pindo/module/android/build_helper.rb +0 -128
  65. data/lib/pindo/module/android/so_helper.rb +0 -18
  66. data/lib/pindo/module/cert/certhelper.rb +0 -246
  67. data/lib/pindo/module/cert/keychainhelper.rb +0 -150
  68. data/lib/pindo/module/cert/pemhelper.rb +0 -65
  69. /data/lib/pindo/module/android/{androidreshelper.rb → android_res_helper.rb} +0 -0
  70. /data/lib/pindo/module/appstore/{iap_tier.json → appstore_iap_tier.json} +0 -0
  71. /data/lib/pindo/module/build/{swarkhelper.rb → swark_helper.rb} +0 -0
  72. /data/lib/pindo/module/build/{versionhelper.rb → version_helper.rb} +0 -0
  73. /data/lib/pindo/module/cert/{provisioninghelper.rb → provisioning_helper.rb} +0 -0
  74. /data/lib/pindo/module/unity/{nugethelper.rb → nuget_helper.rb} +0 -0
  75. /data/lib/pindo/module/xcode/{xcoderesconstant.rb → res/xcode_res_constant.rb} +0 -0
@@ -1,964 +0,0 @@
1
- module Pindo
2
- module BaseAndroidHelper
3
-
4
- def get_build_tools
5
- # 获取 gem 资源文件路径
6
-
7
- pindo_dir ||= File.expand_path(ENV['PINDO_DIR'] || '~/.pindo')
8
- pindo_common_configdir ||= File.join(pindo_dir, "pindo_common_config")
9
- tools_dir = File.join(pindo_common_configdir, 'android_tools')
10
-
11
- # 如果开发环境找不到,尝试在 gem 安装目录找
12
- unless File.directory?(tools_dir)
13
- raise "缺少必要的构建工具: #{tools_dir},请执行pindo setup更新pindo配置"
14
- end
15
-
16
- # 检查必要的工具是否存在
17
- required_tools = {
18
- bundle_tool: 'bundletool.jar',
19
- gradlew: 'gradlew',
20
- gradle_wrapper: 'gradle-wrapper.jar'
21
- }
22
-
23
- tools = {}
24
- required_tools.each do |key, filename|
25
- path = File.join(tools_dir, filename)
26
- unless File.exist?(path)
27
- raise "缺少必要的构建工具: #{filename},请执行pindo setup更新pindo配置"
28
- end
29
- tools[key] = path
30
- end
31
-
32
- tools
33
- end
34
-
35
- # 查找正确的 Java 命令 (Java 11+)
36
- def find_java_command
37
- # 检查 JAVA_HOME 环境变量
38
- if ENV['JAVA_HOME'] && File.exist?(File.join(ENV['JAVA_HOME'], 'bin', 'java'))
39
- java_path = File.join(ENV['JAVA_HOME'], 'bin', 'java')
40
- # 验证 Java 版本
41
- if verify_java_version(java_path)
42
- return java_path
43
- end
44
- end
45
-
46
- # 尝试常见的 Java 路径
47
- common_java_paths = [
48
- '/usr/libexec/java_home', # macOS
49
- '/usr/bin/java',
50
- '/usr/local/bin/java',
51
- '/opt/homebrew/bin/java', # macOS Homebrew
52
- '/usr/local/opt/openjdk/bin/java' # macOS Homebrew OpenJDK
53
- ]
54
-
55
- common_java_paths.each do |java_path|
56
- if File.exist?(java_path)
57
- # 对于 macOS 的 java_home,需要特殊处理
58
- if java_path.include?('java_home')
59
- java_home_output = `#{java_path} 2>/dev/null`.strip
60
- if !java_home_output.empty?
61
- actual_java_path = File.join(java_home_output, 'bin', 'java')
62
- if File.exist?(actual_java_path) && verify_java_version(actual_java_path)
63
- return actual_java_path
64
- end
65
- end
66
- elsif verify_java_version(java_path)
67
- return java_path
68
- end
69
- end
70
- end
71
-
72
- # 如果都找不到,返回默认的 java 命令
73
- 'java'
74
- end
75
-
76
- # 验证 Java 版本是否满足要求 (Java 11+)
77
- def verify_java_version(java_path)
78
- begin
79
- version_output = `"#{java_path}" -version 2>&1`
80
- if version_output =~ /version "(\d+)/
81
- major_version = $1.to_i
82
- return major_version >= 11
83
- end
84
- rescue
85
- # 如果执行失败,返回 false
86
- end
87
- false
88
- end
89
-
90
- # 检查并确保 Java 版本符合要求 (Java 11+)
91
- def ensure_java_version_compliance
92
- # puts "\e[36m=== Java 版本检测 ===\e[0m"
93
-
94
- # 检查 Unity Editor 中的 JDK 版本(仅检测,不自动替换)
95
- # if check_and_update_unity_jdk
96
- # puts "\e[32m✓ Unity Editor JDK 已更新为 Java 11+\e[0m"
97
- # end
98
-
99
- # 仅检测Unity Editor JDK版本,不进行替换
100
- unity_root_paths = find_unity_editor_paths
101
- if unity_root_paths.any?
102
- # puts "\e[36m=== Unity Editor JDK 版本检测 ===\e[0m"
103
- unity_root_paths.each do |unity_root|
104
- # 构建JDK路径
105
- jdk_path = build_jdk_path_from_unity_root(unity_root)
106
- puts "\e[33m[DEBUG] 检查Unity路径: #{unity_root} -> JDK路径: #{jdk_path}\e[0m" if ENV['PINDO_DEBUG']
107
-
108
- if File.exist?(jdk_path)
109
- java_cmd = File.join(jdk_path, "bin", "java")
110
- if File.exist?(java_cmd)
111
- version_output = `"#{java_cmd}" -version 2>&1`
112
- if version_output =~ /version "(\d+)/
113
- major_version = $1.to_i
114
- if major_version >= 11
115
- # puts "\e[32m✓ Unity Editor JDK 版本 #{major_version} 符合要求: #{jdk_path}\e[0m"
116
- else
117
- puts "\e[33m⚠ Unity Editor JDK 版本 #{major_version} 不符合要求 (需要 Java 11+): #{jdk_path}\e[0m"
118
- end
119
- else
120
- puts "\e[33m⚠ 无法解析Unity Editor JDK版本: #{jdk_path}\e[0m"
121
- end
122
- else
123
- puts "\e[33m⚠ Unity Editor JDK中未找到java命令: #{jdk_path}\e[0m"
124
- end
125
- else
126
- puts "\e[33m⚠ Unity Editor JDK路径不存在: #{jdk_path}\e[0m"
127
- end
128
- end
129
- else
130
- puts "\e[33m⚠ 未找到Unity Editor安装路径\e[0m"
131
- end
132
-
133
- # 查找当前可用的 Java 命令
134
- current_java = find_java_command
135
- # puts "当前 Java 命令: #{current_java}"
136
-
137
- # 验证当前 Java 版本
138
- if verify_java_version(current_java)
139
- version_output = `"#{current_java}" -version 2>&1`
140
- if version_output =~ /version "(\d+)/
141
- major_version = $1.to_i
142
- # puts "\e[32m✓ Java 版本 #{major_version} 符合要求 (需要 Java 11+)\e[0m"
143
- return true
144
- end
145
- end
146
-
147
- puts "\e[31m✗ 当前 Java 版本不符合要求,需要 Java 11+\e[0m"
148
- puts "\e[33m请手动安装 Java 11 或更高版本:\e[0m"
149
- puts " • macOS: brew install openjdk@11"
150
- puts " • 或下载: https://adoptium.net/"
151
- puts " • 或使用 SDKMAN: sdk install java 11.0.21-tem"
152
-
153
- # 注释掉自动安装 Java 11 的逻辑
154
- # puts "\e[33m正在尝试自动安装和配置 Java 11...\e[0m"
155
- # if install_java_11
156
- # puts "\e[32m✓ Java 11 安装成功\e[0m"
157
- # return true
158
- # else
159
- # puts "\e[31m✗ Java 11 自动安装失败\e[0m"
160
- # puts "\e[33m请手动安装 Java 11 或更高版本:\e[0m"
161
- # puts " • macOS: brew install openjdk@11"
162
- # puts " • 或下载: https://adoptium.net/"
163
- # puts " • 或使用 SDKMAN: sdk install java 11.0.21-tem"
164
- # return false
165
- # end
166
-
167
- return false
168
- end
169
-
170
- # 自动安装 Java 11
171
- def install_java_11
172
- begin
173
- # 检查是否在 macOS 上
174
- if RbConfig::CONFIG['host_os'] =~ /darwin/
175
- return install_java_11_macos
176
- else
177
- puts "\e[33m当前系统不是 macOS,请手动安装 Java 11\e[0m"
178
- return false
179
- end
180
- rescue => e
181
- puts "\e[31m安装 Java 11 时出错: #{e.message}\e[0m"
182
- return false
183
- end
184
- end
185
-
186
- # 在 macOS 上安装 Java 11
187
- def install_java_11_macos
188
- puts "\e[36m在 macOS 上安装 Java 11...\e[0m"
189
-
190
- # 方法1: 使用 Homebrew 安装
191
- if system("which brew > /dev/null 2>&1")
192
- puts "使用 Homebrew 安装 OpenJDK 11..."
193
- if system("brew install openjdk@11")
194
- # 设置 JAVA_HOME
195
- java_home_path = `brew --prefix openjdk@11`.strip
196
- if !java_home_path.empty? && File.directory?(java_home_path)
197
- java_bin_path = File.join(java_home_path, "bin", "java")
198
- if File.exist?(java_bin_path)
199
- # 设置环境变量
200
- ENV['JAVA_HOME'] = java_home_path
201
- puts "\e[32m✓ 已设置 JAVA_HOME: #{java_home_path}\e[0m"
202
- return true
203
- end
204
- end
205
- else
206
- puts "\e[33mHomebrew 安装 OpenJDK 11 失败\e[0m"
207
- end
208
- else
209
- puts "\e[33m未找到 Homebrew,跳过 Homebrew 安装方式\e[0m"
210
- end
211
-
212
- # 方法2: 使用 SDKMAN 安装
213
- if system("which sdk > /dev/null 2>&1")
214
- puts "使用 SDKMAN 安装 Java 11..."
215
- if system("sdk install java 11.0.21-tem")
216
- # 设置环境变量
217
- sdkman_home = ENV['SDKMAN_DIR'] || File.expand_path("~/.sdkman")
218
- java_home_path = File.join(sdkman_home, "candidates", "java", "11.0.21-tem")
219
- if File.directory?(java_home_path)
220
- ENV['JAVA_HOME'] = java_home_path
221
- puts "\e[32m✓ 已设置 JAVA_HOME: #{java_home_path}\e[0m"
222
- return true
223
- end
224
- else
225
- puts "\e[33mSDKMAN 安装 Java 11 失败\e[0m"
226
- end
227
- else
228
- puts "\e[33m未找到 SDKMAN,跳过 SDKMAN 安装方式\e[0m"
229
- end
230
-
231
- # 方法3: 下载并安装 Adoptium OpenJDK
232
- puts "尝试下载并安装 Adoptium OpenJDK 11..."
233
- return install_adoptium_java_11
234
- end
235
-
236
- # 下载并安装 Adoptium OpenJDK 11
237
- def install_adoptium_java_11
238
- begin
239
- # 创建临时目录
240
- temp_dir = Dir.mktmpdir("java_install_")
241
-
242
- # 下载 URL (macOS x64)
243
- download_url = "https://github.com/adoptium/temurin11-binaries/releases/download/jdk-11.0.21%2B9/OpenJDK11U-jdk_x64_mac_hotspot_11.0.21_9.tar.gz"
244
- tar_file = File.join(temp_dir, "openjdk11.tar.gz")
245
-
246
- puts "下载 OpenJDK 11..."
247
- if system("curl -L -o \"#{tar_file}\" \"#{download_url}\"")
248
- puts "解压 OpenJDK 11..."
249
- if system("tar -xzf \"#{tar_file}\" -C \"#{temp_dir}\"")
250
- # 查找解压后的目录
251
- jdk_dir = Dir.glob(File.join(temp_dir, "jdk-11*")).first
252
- if jdk_dir && File.directory?(jdk_dir)
253
- # 尝试安装到用户目录而不是系统目录
254
- user_install_dir = File.expand_path("~/.pindo/java11")
255
- if system("mkdir -p \"#{File.dirname(user_install_dir)}\" && mv \"#{jdk_dir}\" \"#{user_install_dir}\"")
256
- # 设置环境变量
257
- ENV['JAVA_HOME'] = user_install_dir
258
- puts "\e[32m✓ 已安装并设置 JAVA_HOME: #{user_install_dir}\e[0m"
259
- return true
260
- else
261
- puts "\e[33m无法安装到用户目录,尝试系统目录...\e[0m"
262
- # 回退到系统目录
263
- install_dir = "/usr/local/openjdk11"
264
- if system("sudo mkdir -p /usr/local && sudo mv \"#{jdk_dir}\" \"#{install_dir}\"")
265
- # 设置环境变量
266
- ENV['JAVA_HOME'] = install_dir
267
- puts "\e[32m✓ 已安装并设置 JAVA_HOME: #{install_dir}\e[0m"
268
- return true
269
- else
270
- puts "\e[31m无法安装到系统目录,需要管理员权限\e[0m"
271
- end
272
- end
273
- else
274
- puts "\e[31m解压后未找到 JDK 目录\e[0m"
275
- end
276
- else
277
- puts "\e[31m解压 OpenJDK 11 失败\e[0m"
278
- end
279
- else
280
- puts "\e[31m下载 OpenJDK 11 失败\e[0m"
281
- end
282
-
283
- return false
284
- rescue => e
285
- puts "\e[31m下载安装 OpenJDK 11 失败: #{e.message}\e[0m"
286
- return false
287
- ensure
288
- # 清理临时目录
289
- FileUtils.rm_rf(temp_dir) if temp_dir && File.directory?(temp_dir)
290
- end
291
- end
292
-
293
- # 检查并更新 Unity Editor 中的 JDK 版本
294
- def check_and_update_unity_jdk
295
- return false unless RbConfig::CONFIG['host_os'] =~ /darwin/
296
-
297
- puts "\e[36m=== Unity Editor JDK 版本检测 ===\e[0m"
298
-
299
- # 查找 Unity Editor 安装路径
300
- unity_paths = find_unity_editor_paths
301
- if unity_paths.empty?
302
- puts "\e[33m未找到 Unity Editor 安装路径\e[0m"
303
- return false
304
- end
305
-
306
- updated_any = false
307
- unity_paths.each do |unity_path|
308
- # 根据不同的 Unity 路径结构构建 JDK 路径
309
- jdk_path = build_jdk_path_from_unity_root(unity_path)
310
-
311
- if File.directory?(jdk_path)
312
- puts "检查 Unity Editor JDK: #{jdk_path}"
313
- if check_and_replace_unity_jdk(jdk_path)
314
- updated_any = true
315
- end
316
- else
317
- # OpenJDK 目录不存在,尝试创建并安装 Java 11
318
- puts "OpenJDK 目录不存在: #{jdk_path}"
319
- puts "正在创建 OpenJDK 目录并安装 Java 11..."
320
-
321
- if create_and_install_openjdk(jdk_path)
322
- puts "\e[32m✓ OpenJDK 目录创建并安装 Java 11 成功\e[0m"
323
- updated_any = true
324
- else
325
- puts "\e[31m✗ OpenJDK 目录创建并安装 Java 11 失败\e[0m"
326
- end
327
- end
328
- end
329
-
330
- updated_any
331
- end
332
-
333
- # 创建 OpenJDK 目录并安装 Java 11
334
- def create_and_install_openjdk(jdk_path)
335
- begin
336
- # 创建 OpenJDK 目录(使用 sudo 权限)
337
- puts "\e[33m需要管理员权限来创建 OpenJDK 目录,请输入密码...\e[0m"
338
- if system("sudo mkdir -p \"#{jdk_path}\"")
339
- puts "创建 OpenJDK 目录: #{jdk_path}"
340
- else
341
- puts "\e[31m✗ 创建 OpenJDK 目录失败\e[0m"
342
- return false
343
- end
344
-
345
- # 查找或安装 Java 11
346
- java11_path = find_java11_installation
347
- unless java11_path && File.directory?(java11_path)
348
- puts "\e[33m未找到系统中的 Java 11 安装,正在自动下载...\e[0m"
349
-
350
- # 自动下载并安装 Java 11
351
- if install_java_11
352
- java11_path = find_java11_installation
353
- unless java11_path && File.directory?(java11_path)
354
- puts "\e[31m✗ Java 11 自动安装失败\e[0m"
355
- return false
356
- end
357
- puts "\e[32m✓ Java 11 自动安装成功\e[0m"
358
- else
359
- puts "\e[31m✗ Java 11 自动安装失败\e[0m"
360
- return false
361
- end
362
- end
363
-
364
- puts "找到 Java 11 安装路径: #{java11_path}"
365
-
366
- # 复制 Java 11 到 OpenJDK 目录(使用 sudo 权限)
367
- puts "正在复制 Java 11 到 OpenJDK 目录..."
368
- if system("sudo cp -R \"#{java11_path}\"/* \"#{jdk_path}\"/")
369
- puts "\e[32m✓ Java 11 复制成功\e[0m"
370
-
371
- # 验证安装
372
- java_bin = File.join(jdk_path, "bin", "java")
373
- if File.exist?(java_bin)
374
- version_output = `"#{java_bin}" -version 2>&1`
375
- if version_output =~ /version "(\d+)/
376
- version = $1.to_i
377
- if version >= 11
378
- puts "\e[32m✓ Unity Editor JDK 安装成功,版本: #{version}\e[0m"
379
- return true
380
- else
381
- puts "\e[31m✗ 安装的 JDK 版本 #{version} 不符合要求\e[0m"
382
- return false
383
- end
384
- end
385
- end
386
-
387
- return true
388
- else
389
- puts "\e[31m✗ Java 11 复制失败\e[0m"
390
- return false
391
- end
392
-
393
- rescue => e
394
- puts "\e[31m创建并安装 OpenJDK 时出错: #{e.message}\e[0m"
395
- return false
396
- end
397
- end
398
-
399
- # 查找 Unity Editor 安装路径
400
- def find_unity_editor_paths
401
- unity_paths = []
402
-
403
- # 1. 检查全局 Unity PlaybackEngines 路径(最常见)
404
- global_playback_engines = "/Applications/Unity/PlaybackEngines"
405
- if File.directory?(global_playback_engines)
406
- unity_paths << "/Applications/Unity"
407
- end
408
-
409
- # 2. 检查 Unity Hub 中的多个版本(支持 2021.3.* 版本范围)
410
- unity_hub_patterns = [
411
- "/Applications/Unity/Hub/Editor/2021.3.*/PlaybackEngines"
412
- ]
413
-
414
- unity_hub_patterns.each do |pattern|
415
- Dir.glob(pattern).each do |playback_engines_path|
416
- # Unity Hub 版本:/Applications/Unity/Hub/Editor/2022.3.15f1/PlaybackEngines
417
- unity_root = playback_engines_path.gsub("/PlaybackEngines", "")
418
- unity_paths << unity_root
419
- end
420
- end
421
-
422
- # 3. 检查其他常见的 Unity 安装路径
423
- other_pattern = "/Applications/Unity/*/PlaybackEngines"
424
- Dir.glob(other_pattern).each do |playback_engines_path|
425
- # 其他 Unity 版本:/Applications/Unity/2022.3.15f1/PlaybackEngines
426
- unity_root = playback_engines_path.gsub("/PlaybackEngines", "")
427
- unity_paths << unity_root
428
- end
429
-
430
- unity_paths.uniq
431
- end
432
-
433
- # 根据 Unity 根路径构建 JDK 路径
434
- def build_jdk_path_from_unity_root(unity_path)
435
- # 1. 全局 Unity 路径
436
- if unity_path == "/Applications/Unity"
437
- return "/Applications/Unity/PlaybackEngines/AndroidPlayer/OpenJDK"
438
- end
439
-
440
- # 2. Unity Hub 路径(包含版本号)
441
- if unity_path.include?("/Unity/Hub/Editor/")
442
- # 检查是否有 PlaybackEngines 目录
443
- playback_engines_path = File.join(unity_path, "PlaybackEngines")
444
- if File.directory?(playback_engines_path)
445
- return File.join(playback_engines_path, "AndroidPlayer", "OpenJDK")
446
- end
447
- end
448
-
449
- # 3. 其他 Unity 版本路径
450
- if unity_path.include?("/Unity/") && !unity_path.include?("/Hub/")
451
- # 检查是否有 PlaybackEngines 目录
452
- playback_engines_path = File.join(unity_path, "PlaybackEngines")
453
- if File.directory?(playback_engines_path)
454
- return File.join(playback_engines_path, "AndroidPlayer", "OpenJDK")
455
- end
456
- end
457
-
458
- # 4. 默认尝试
459
- File.join(unity_path, "PlaybackEngines", "AndroidPlayer", "OpenJDK")
460
- end
461
-
462
- # 检查并替换 Unity Editor 中的 JDK
463
- def check_and_replace_unity_jdk(jdk_path)
464
- begin
465
- # 检查当前 JDK 版本
466
- java_bin = File.join(jdk_path, "bin", "java")
467
- if File.exist?(java_bin)
468
- version_output = `"#{java_bin}" -version 2>&1`
469
- if version_output =~ /version "(\d+)/
470
- current_version = $1.to_i
471
- puts "Unity Editor JDK 当前版本: #{current_version}"
472
-
473
- if current_version >= 11
474
- puts "\e[32m✓ Unity Editor JDK 版本 #{current_version} 符合要求\e[0m"
475
- return false
476
- else
477
- puts "\e[31m✗ Unity Editor JDK 版本 #{current_version} 不符合要求,需要 Java 11+\e[0m"
478
- return replace_unity_jdk_with_java11(jdk_path)
479
- end
480
- end
481
- else
482
- puts "\e[31m✗ Unity Editor JDK 中未找到 java 可执行文件\e[0m"
483
- return replace_unity_jdk_with_java11(jdk_path)
484
- end
485
-
486
- return false
487
- rescue => e
488
- puts "\e[31m检查 Unity Editor JDK 时出错: #{e.message}\e[0m"
489
- return false
490
- end
491
- end
492
-
493
- # 替换 Unity Editor 中的 JDK 为 Java 11
494
- def replace_unity_jdk_with_java11(jdk_path)
495
- begin
496
- puts "\e[33m正在替换 Unity Editor JDK 为 Java 11...\e[0m"
497
-
498
- # 查找系统中的 Java 11
499
- java11_path = find_java11_installation
500
- unless java11_path && File.directory?(java11_path)
501
- puts "\e[33m未找到系统中的 Java 11 安装,正在自动下载...\e[0m"
502
-
503
- # 自动下载并安装 Java 11
504
- if install_java_11
505
- java11_path = find_java11_installation
506
- unless java11_path && File.directory?(java11_path)
507
- puts "\e[31m✗ Java 11 自动安装失败\e[0m"
508
- return false
509
- end
510
- puts "\e[32m✓ Java 11 自动安装成功\e[0m"
511
- else
512
- puts "\e[31m✗ Java 11 自动安装失败\e[0m"
513
- return false
514
- end
515
- end
516
-
517
- puts "找到 Java 11 安装路径: #{java11_path}"
518
-
519
- # 备份原始 JDK(使用 sudo 权限)
520
- backup_path = "#{jdk_path}_backup_#{Time.now.strftime('%Y%m%d_%H%M%S')}"
521
- puts "备份原始 JDK 到: #{backup_path}"
522
- puts "\e[33m需要管理员权限来备份和替换 Unity Editor JDK,请输入密码...\e[0m"
523
-
524
- if system("sudo cp -R \"#{jdk_path}\" \"#{backup_path}\"")
525
- puts "\e[32m✓ 原始 JDK 备份成功\e[0m"
526
- else
527
- puts "\e[31m✗ 原始 JDK 备份失败\e[0m"
528
- return false
529
- end
530
-
531
- # 删除原始 JDK 内容(使用 sudo 权限)
532
- puts "删除原始 JDK 内容..."
533
- if system("sudo rm -rf \"#{jdk_path}/*\"")
534
- puts "\e[32m✓ 原始 JDK 内容删除成功\e[0m"
535
- else
536
- puts "\e[31m✗ 原始 JDK 内容删除失败\e[0m"
537
- return false
538
- end
539
-
540
- # 复制 Java 11 到 Unity JDK 目录(使用 sudo 权限)
541
- puts "复制 Java 11 到 Unity JDK 目录..."
542
- if system("sudo cp -R \"#{java11_path}\"/* \"#{jdk_path}/\"")
543
- puts "\e[32m✓ Java 11 复制成功\e[0m"
544
-
545
- # 验证替换结果
546
- new_java_bin = File.join(jdk_path, "bin", "java")
547
- if File.exist?(new_java_bin)
548
- version_output = `"#{new_java_bin}" -version 2>&1`
549
- if version_output =~ /version "(\d+)/
550
- new_version = $1.to_i
551
- if new_version >= 11
552
- puts "\e[32m✓ Unity Editor JDK 已成功替换为 Java #{new_version}\e[0m"
553
- return true
554
- else
555
- puts "\e[31m✗ 替换后的 JDK 版本仍然不符合要求: #{new_version}\e[0m"
556
- end
557
- end
558
- end
559
- else
560
- puts "\e[31m✗ Java 11 复制失败\e[0m"
561
- return false
562
- end
563
-
564
- return false
565
- rescue => e
566
- puts "\e[31m替换 Unity Editor JDK 时出错: #{e.message}\e[0m"
567
- return false
568
- end
569
- end
570
-
571
- # 查找系统中的 Java 11 安装
572
- def find_java11_installation
573
- # 检查常见的 Java 11 安装路径
574
- java11_paths = [
575
- # Homebrew 安装路径
576
- "/opt/homebrew/opt/openjdk@11",
577
- "/usr/local/opt/openjdk@11",
578
- # SDKMAN 安装路径
579
- File.expand_path("~/.sdkman/candidates/java/11.0.21-tem"),
580
- File.expand_path("~/.sdkman/candidates/java/11.0.20-tem"),
581
- # 系统安装路径
582
- "/Library/Java/JavaVirtualMachines/openjdk-11.jdk/Contents/Home",
583
- "/Library/Java/JavaVirtualMachines/adoptopenjdk-11.jdk/Contents/Home",
584
- # Pindo 安装的 Java 11
585
- File.expand_path("~/.pindo/java11")
586
- ]
587
-
588
- java11_paths.each do |path|
589
- if File.directory?(path)
590
- java_bin = File.join(path, "bin", "java")
591
- if File.exist?(java_bin)
592
- # 验证版本
593
- version_output = `"#{java_bin}" -version 2>&1`
594
- if version_output =~ /version "(\d+)/
595
- version = $1.to_i
596
- if version >= 11
597
- return path
598
- end
599
- end
600
- end
601
- end
602
- end
603
-
604
- nil
605
- end
606
-
607
- def modify_il2cpp_config(project_path)
608
- # 设置Il2CppOutputProject可执行权限
609
- system("chmod", "-R", "777",
610
- File.join(project_path, "unityLibrary/src/main/Il2CppOutputProject"))
611
-
612
- il2cpp_config_path = File.join(project_path, "unityLibrary/src/main/Il2CppOutputProject/IL2CPP/libil2cpp/il2cpp-config.h")
613
- content = File.read(il2cpp_config_path)
614
- content.gsub!("il2cpp::vm::Exception::Raise", "//il2cpp::vm::Exception::Raise")
615
- File.write(il2cpp_config_path, content)
616
- end
617
-
618
- def remove_desktop_google_service(project_path)
619
- # 删除google-services-desktop.json
620
- desktop_google_service_path = File.join(project_path,
621
- "unityLibrary/src/main/assets/google-services-desktop.json")
622
- File.delete(desktop_google_service_path) if File.exist?(desktop_google_service_path)
623
- end
624
-
625
- # def get_app_name(project_path)
626
- # strings_xml_path = File.join(project_path, "app/src/main/res/values/strings.xml")
627
-
628
- # unless File.exist?(strings_xml_path)
629
- # strings_xml_path = File.join(project_path, "unityLibrary/src/main/res/values/strings.xml")
630
- # unless File.exist?(strings_xml_path)
631
- # return nil
632
- # end
633
- # end
634
-
635
- # xml_content = File.read(strings_xml_path)
636
- # doc = Nokogiri::XML(xml_content)
637
- # doc.at_xpath("//string[@name='app_name']")&.text
638
- # end
639
-
640
- def get_main_module(project_path)
641
- settings_gradle_path = File.join(project_path, "settings.gradle")
642
- settings_gradle_kts_path = File.join(project_path, "settings.gradle.kts")
643
-
644
- # 优先使用 settings.gradle.kts,如果不存在则使用 settings.gradle
645
- if File.exist?(settings_gradle_kts_path)
646
- settings_gradle_path = settings_gradle_kts_path
647
- elsif !File.exist?(settings_gradle_path)
648
- return nil
649
- end
650
-
651
- content = File.read(settings_gradle_path)
652
- # 兼容 include ':app' 和 include(":app")
653
- modules = content.scan(/include\s*\(?\s*['\"]?([:\w\-]+)['\"]?\s*\)?/).flatten
654
-
655
- main_module = modules.find do |m|
656
- module_name = m.split(':').last
657
- gradle_path = File.join(project_path, module_name, "build.gradle")
658
- gradle_kts_path = File.join(project_path, module_name, "build.gradle.kts")
659
-
660
- # 优先使用 build.gradle.kts,如果不存在则使用 build.gradle
661
- if File.exist?(gradle_kts_path)
662
- gradle_path = gradle_kts_path
663
- end
664
-
665
- if File.exist?(gradle_path)
666
- gradle_content = File.read(gradle_path)
667
- gradle_content.include?("apply plugin: 'com.android.application") ||
668
- gradle_content.include?("id 'com.android.application") ||
669
- (gradle_content.include?("plugins {") && gradle_content.include?("com.android.application"))
670
- end
671
- end
672
- return nil unless main_module
673
-
674
- module_name = main_module.split(':').last
675
- File.join(project_path, module_name)
676
- end
677
-
678
- def get_keystore_config(project_path, debug = false)
679
- main_module = get_main_module(project_path)
680
- return nil unless main_module
681
-
682
- gradle_kts_path = File.join(main_module, "build.gradle.kts")
683
- gradle_path = File.join(main_module, "build.gradle")
684
-
685
- if File.exist?(gradle_kts_path)
686
- puts "KTS 项目,读取 #{File.basename(gradle_kts_path)} 文件"
687
- get_keystore_config_kts(gradle_kts_path, project_path, debug)
688
- elsif File.exist?(gradle_path)
689
- puts "Groovy 项目,读取 #{File.basename(gradle_path)} 文件"
690
- get_keystore_config_groovy(gradle_path, project_path, debug)
691
- else
692
- puts "未找到 build.gradle 或 build.gradle.kts 文件"
693
- nil
694
- end
695
- end
696
-
697
- # 处理 Kotlin DSL (build.gradle.kts)
698
- def get_keystore_config_kts(gradle_kts_path, project_path, debug)
699
- content = File.read(gradle_kts_path)
700
- puts "读取 #{File.basename(gradle_kts_path)} 文件"
701
- signing_configs_block = extract_signing_configs_kts(content)
702
- # puts "==== signingConfigs block ===="
703
- # puts signing_configs_block
704
- # puts "==============================" if signing_configs_block
705
- return nil unless signing_configs_block
706
-
707
- config_type = debug ? 'debug' : 'release'
708
- config_block = extract_config_block_kts(signing_configs_block, config_type)
709
- # puts "==== config_block ===="
710
- # puts config_block
711
- # puts "=====================" if config_block
712
- return nil unless config_block
713
-
714
- config_block = remove_kts_comments(config_block)
715
- ext_values = get_ext_values(project_path)
716
- store_file, store_password, key_alias, key_password = extract_keystore_fields_kts(config_block, ext_values)
717
- store_file = fix_store_file_path(store_file, project_path)
718
- keystore_config = {
719
- store_file: store_file,
720
- store_password: store_password,
721
- key_alias: key_alias,
722
- key_password: key_password
723
- }
724
- if keystore_config.values.any?(&:nil?)
725
- puts "警告: 部分 keystore 配置为 nil: #{keystore_config}"
726
- end
727
- keystore_config
728
- end
729
-
730
- # 处理 Groovy DSL (build.gradle)
731
- def get_keystore_config_groovy(gradle_path, project_path, debug)
732
- content = File.read(gradle_path)
733
- puts "读取 #{File.basename(gradle_path)} 文件"
734
- signing_configs_block = extract_signing_configs_groovy(content)
735
- # puts "==== signingConfigs block ===="
736
- # puts signing_configs_block
737
- # puts "==============================" if signing_configs_block
738
- return nil unless signing_configs_block
739
-
740
- config_type = debug ? 'debug' : 'release'
741
- config_block = extract_config_block_groovy(signing_configs_block, config_type)
742
- # puts "==== config_block ===="
743
- # puts config_block
744
- # puts "=====================" if config_block
745
- return nil unless config_block
746
-
747
- config_block = remove_groovy_comments(config_block)
748
- ext_values = get_ext_values(project_path)
749
- store_file, store_password, key_alias, key_password = extract_keystore_fields_groovy(config_block, ext_values)
750
- store_file = fix_store_file_path(store_file, project_path)
751
- keystore_config = {
752
- store_file: store_file,
753
- store_password: store_password,
754
- key_alias: key_alias,
755
- key_password: key_password
756
- }
757
- if keystore_config.values.any?(&:nil?)
758
- puts "警告: 部分 keystore 配置为 nil: #{keystore_config}"
759
- end
760
- keystore_config
761
- end
762
-
763
- # --- 工具方法 ---
764
- def extract_signing_configs_kts(content)
765
- # 提取 signingConfigs { ... },支持多层嵌套
766
- match = content.match(/signingConfigs\s*\{([\s\S]*?)^\}/m)
767
- match ? match[1] : nil
768
- end
769
-
770
- def extract_signing_configs_groovy(content)
771
- # 提取 signingConfigs { ... },支持多层嵌套
772
- match = content.match(/signingConfigs\s*\{([\s\S]*?)^\}/m)
773
- match ? match[1] : nil
774
- end
775
-
776
- def extract_config_block_kts(signing_configs_block, config_type)
777
- # 支持 create("xxx") { ... }
778
- all_blocks = signing_configs_block.scan(/create\(["']?([A-Za-z0-9_]+)["']?\)\s*\{([\s\S]*?)^\s*\}/m)
779
- # 优先 release/debug/Android_Sign/自定义名
780
- priority_names = [config_type, "Android_Sign", "release", "debug"]
781
- config_block = nil
782
- priority_names.each do |name|
783
- block = all_blocks.find { |n, b| n == name && b.include?("storeFile") }
784
- if block
785
- config_block = block[1]
786
- break
787
- end
788
- end
789
- # 没找到就取第一个有 storeFile 的块
790
- if config_block.nil?
791
- all_blocks.each do |name, block|
792
- if block.include?("storeFile")
793
- config_block = block
794
- break
795
- end
796
- end
797
- end
798
- config_block
799
- end
800
-
801
- def extract_config_block_groovy(signing_configs_block, config_type)
802
- # 支持 xxx { ... }
803
- all_blocks = signing_configs_block.scan(/([A-Za-z0-9_]+)\s*\{([\s\S]*?)^\s*\}/m)
804
- priority_names = [config_type, "Android_Sign", "release", "debug"]
805
- config_block = nil
806
- priority_names.each do |name|
807
- block = all_blocks.find { |n, b| n == name && b.include?("storeFile") }
808
- if block
809
- config_block = block[1]
810
- break
811
- end
812
- end
813
- if config_block.nil?
814
- all_blocks.each do |name, block|
815
- if block.include?("storeFile")
816
- config_block = block
817
- break
818
- end
819
- end
820
- end
821
- config_block
822
- end
823
-
824
- def remove_kts_comments(block)
825
- # 去除 // 注释
826
- block.lines.reject { |line| line.strip.start_with?("//") }.join
827
- end
828
-
829
- def remove_groovy_comments(block)
830
- # 去除 // 和 /* ... */ 注释
831
- block = block.gsub(/\/\*[\s\S]*?\*\//, "")
832
- block.lines.reject { |line| line.strip.start_with?("//") }.join
833
- end
834
-
835
- # 通用字段递归解析
836
- def extract_keystore_fields_common(fields, ext_values)
837
- fields.map { |val| extract_var_or_value(val, ext_values) }
838
- end
839
-
840
- def extract_keystore_fields_groovy(config_block, ext_values)
841
- # 只处理 groovy 语法
842
- store_file = config_block[/storeFile\s+file\(["']?([^\)"']+)["']?\)/, 1]
843
- store_password = config_block[/storePassword\s+["']?([^\)"']+)["']?/, 1]
844
- key_alias = config_block[/keyAlias\s+["']?([^\)"']+)["']?/, 1]
845
- key_password = config_block[/keyPassword\s+["']?([^\)"']+)["']?/, 1]
846
- extract_keystore_fields_common([store_file, store_password, key_alias, key_password], ext_values)
847
- end
848
-
849
- def extract_keystore_fields_kts(config_block, ext_values)
850
- # 只处理 kts 语法
851
- store_file = config_block[/storeFile\s*=\s*file\(["']?([^\)"']+)["']?\)/, 1] ||
852
- config_block[/storeFile\s*=\s*rootProject\.file\(["']?([^\)"']+)["']?\)/, 1]
853
- store_password = config_block[/storePassword\s*=\s*["']?([^\)"']+)["']?/, 1]
854
- key_alias = config_block[/keyAlias\s*=\s*["']?([^\)"']+)["']?/, 1]
855
- key_password = config_block[/keyPassword\s*=\s*["']?([^\)"']+)["']?/, 1]
856
- extract_keystore_fields_common([store_file, store_password, key_alias, key_password], ext_values)
857
- end
858
-
859
- def extract_var_or_value(val, ext_values, depth=0)
860
- return nil if val.nil? || val.empty? || depth > 5
861
- # 匹配 ${KEY}、$KEY、"${KEY}"、'${KEY}'
862
- if val =~ /^\$\{?([A-Za-z0-9_]+)\}?$/
863
- key = $1
864
- v = ext_values[key]
865
- v ? extract_var_or_value(v, ext_values, depth+1) : nil
866
- elsif val =~ /^"?\$\{([A-Za-z0-9_]+)\}"?$/
867
- key = $1
868
- v = ext_values[key]
869
- v ? extract_var_or_value(v, ext_values, depth+1) : nil
870
- else
871
- val
872
- end
873
- end
874
-
875
- def resolve_var(val, ext_values, depth=0)
876
- return val if val.nil? || depth > 5
877
- if ext_values[val]
878
- resolve_var(ext_values[val], ext_values, depth+1)
879
- else
880
- val
881
- end
882
- end
883
-
884
- def fix_store_file_path(store_file, project_path)
885
- return nil if store_file.nil? || store_file.empty?
886
- # 兼容 $rootDir、${rootDir}、project.rootDir、rootProject.file
887
- store_file = store_file.gsub(/^\$?\{?rootDir\}?\/?/, project_path + "/")
888
- store_file = store_file.gsub(/^project\.rootDir\/?/, project_path + "/")
889
- store_file = store_file.gsub(/^rootProject\.file\(['"](.+?)['"]\)/, project_path + '/\\1')
890
- store_file = File.expand_path(store_file, project_path) unless File.exist?(store_file)
891
- store_file
892
- end
893
-
894
- # 新增方法:从 ext 配置文件中获取变量值
895
- def get_ext_values(project_path)
896
- ext_values = {}
897
-
898
- ext_files = [
899
- File.join(project_path, "buildScripts/cfg/ext_signing.gradle"),
900
- File.join(project_path, "buildScripts/cfg/ext_signing.gradle.kts"),
901
- File.join(project_path, "gradle.properties"),
902
- File.join(project_path, "local.properties")
903
- ]
904
-
905
- ext_files.each do |file_path|
906
- next unless File.exist?(file_path)
907
-
908
- content = File.read(file_path)
909
-
910
- # 支持 ext.KEY = "VALUE"
911
- content.scan(/ext\.(\w+)\s*=\s*["']([^"']+)["']/m).each do |key, value|
912
- ext_values[key] = value
913
- end
914
-
915
- # 支持 ext["KEY"] = "VALUE"
916
- content.scan(/ext\[\s*["'](\w+)["']\s*\]\s*=\s*["']([^"']+)["']/m).each do |key, value|
917
- ext_values[key] = value
918
- end
919
-
920
- # 支持 KEY = "VALUE"
921
- content.scan(/^(\w+)\s*=\s*["']([^"']+)["']/m).each do |key, value|
922
- ext_values[key] = value
923
- end
924
- end
925
-
926
- ext_values
927
- end
928
-
929
- def unity_android_project?(project_path)
930
- # 检查 unityLibrary 模块是否存在
931
- unity_library_path = File.join(project_path, "unityLibrary")
932
- return false unless File.directory?(unity_library_path)
933
-
934
- # 检查 unityLibrary 的 build.gradle 或 build.gradle.kts 是否存在
935
- unity_gradle_path = File.join(unity_library_path, "build.gradle")
936
- unity_gradle_kts_path = File.join(unity_library_path, "build.gradle.kts")
937
- if File.exist?(unity_gradle_kts_path)
938
- unity_gradle_path = unity_gradle_kts_path
939
- elsif !File.exist?(unity_gradle_path)
940
- return false
941
- end
942
-
943
- # 检查 build.gradle 中是否包含 Unity 特有的配置
944
- content = File.read(unity_gradle_path)
945
- content.include?("com.android.library") && content.include?("BuildIl2Cpp")
946
- end
947
-
948
- def find_android_subproject(project_path)
949
- android_dir = File.join(project_path, "Unity")
950
- return nil unless File.directory?(android_dir)
951
-
952
- main_module = get_main_module(android_dir)
953
- return nil unless main_module
954
-
955
- src_main = File.join(main_module, "src/main")
956
- return nil unless File.directory?(src_main)
957
-
958
- manifest = File.join(src_main, "AndroidManifest.xml")
959
- return nil unless File.exist?(manifest)
960
-
961
- android_dir
962
- end
963
- end
964
- end