Module: Pindo::ApkHelper

Includes:
BaseAndroidHelper
Included in:
AndroidBuildHelper
Defined in:
lib/pindo/module/android/apk_helper.rb

Instance Method Summary collapse

Methods included from BaseAndroidHelper

#build_jdk_path_from_unity_root, #check_and_replace_unity_jdk, #check_and_update_unity_jdk, #create_and_install_openjdk, #ensure_java_version_compliance, #extract_config_block_groovy, #extract_config_block_kts, #extract_keystore_fields_common, #extract_keystore_fields_groovy, #extract_keystore_fields_kts, #extract_signing_configs_groovy, #extract_signing_configs_kts, #extract_var_or_value, #find_android_subproject, #find_java11_installation, #find_java_command, #find_unity_editor_paths, #fix_store_file_path, #get_build_tools, #get_ext_values, #get_keystore_config, #get_keystore_config_groovy, #get_keystore_config_kts, #get_main_module, #install_adoptium_java_11, #install_java_11, #install_java_11_macos, #modify_il2cpp_config, #remove_desktop_google_service, #remove_groovy_comments, #remove_kts_comments, #replace_unity_jdk_with_java11, #resolve_var, #unity_android_project?, #verify_java_version

Instance Method Details

#build_aab(project_path, debug) ⇒ Object



132
133
134
135
136
# File 'lib/pindo/module/android/apk_helper.rb', line 132

def build_aab(project_path, debug)
  Dir.chdir(project_path) do
    system("./gradlew bundle#{debug ? 'Debug' : 'Release'}")
  end
end

#build_apk(project_path, debug) ⇒ Object

Raises:

  • (ArgumentError)


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
# File 'lib/pindo/module/android/apk_helper.rb', line 8

def build_apk(project_path, debug)
  raise ArgumentError, "项目路径不能为空" if project_path.nil? || project_path.empty?

  # 构建 AAB 文件
  unless build_aab(project_path, debug)
    raise RuntimeError, "AAB 构建失败"
  end

  # 获取必要的配置信息
  main_module = get_main_module(project_path)
  raise ArgumentError, "无法找到主模块" unless main_module

  keystore_config = get_keystore_config(project_path, debug)
  raise ArgumentError, "无法从 build.gradle 中获取 keystore 信息" unless keystore_config

  bundle_tool = get_build_tools[:bundle_tool]
  raise ArgumentError, "找不到 bundletool" unless File.exist?(bundle_tool)

  # 准备输出路径
  build_type = debug ? 'debug' : 'release'
  main_module_name = File.basename(main_module)
  output_dir = File.join(project_path, "build/apks")

  # 清理已存在的文件
  FileUtils.rm_rf(output_dir)
  FileUtils.mkdir_p(output_dir)

  # 构建路径配置
  paths = {
    output_apks: File.join(output_dir, "app.apks"),
    bundle: File.join(main_module, "build/outputs/bundle/#{build_type}/#{main_module_name}-#{build_type}.aab"),
    universal_apk: File.join(output_dir, "universal.apk")
  }

  # 检查 bundle 文件是否存在
  unless File.exist?(paths[:bundle])
    raise RuntimeError, "找不到 AAB 文件: #{paths[:bundle]}"
  end

  # --- Google Play 合规检测 (包含包体积、Target SDK、ELF对齐检测) ---
  begin
    compliance_result = Pindo::GPComplianceHelper.check_aab_compliance(paths[:bundle])
    
    # 合规检测结果已在 gp_compliance_helper.rb 中输出,这里只做简单的状态提示
    if compliance_result.compliant?
      puts "\e[32m\e[1m✓ AAB 包符合 Google Play 最新合规要求,可以正常提交\e[0m"
    else
      puts "\e[31m\e[1m✗ AAB 包不符合 Google Play 提交标准,需要修复合规问题才能提交!!!\e[0m"
    end
    
    # 添加合规检测说明
    puts "\e[36m\e[1m📋 合规检测说明:\e[0m"
    puts "\e[33m  • 仅供测试用的包可以忽略合规检测问题\e[0m"
    puts "\e[33m  • 提交至 Google Play 的正式用包必须处理所有合规检测问题\e[0m"
    puts "\e[33m  • 建议在正式发布前解决所有合规问题以确保顺利上架\e[0m"
    
  rescue => e
    puts "\e[31mGoogle Play 合规检测失败: #{e.message}\e[0m"
    puts "\e[33m建议手动检查包体积、Target SDK 版本和共享库对齐情况\e[0m"
  end
  # --- END ---

  # puts "解析 keystore 配置"
  ks = keystore_config[:store_file]
  # puts "读取 keystore path = #{ks}"
  ks_pass = keystore_config[:store_password]
  # puts "读取 keystore pass = #{ks_pass}"
  key_alias = keystore_config[:key_alias]
  # puts "读取 key alias = #{key_alias}"
  key_pass = keystore_config[:key_password]
  # puts "读取 key pass = #{key_pass}"

  # 构建 APK
  # 确保使用正确的 Java 版本 (Java 11+)
  java_cmd = find_java_command
  
  # 验证 Java 版本
  unless verify_java_version(java_cmd)
    raise RuntimeError, "Java 版本不符合要求,bundletool 需要 Java 11+,当前使用的 Java: #{java_cmd}"
  end
  
  # 使用数组形式构建命令,正确处理包含空格的路径
  bundletool_cmd = [
    java_cmd, "-jar", bundle_tool, "build-apks",
    "--bundle=#{paths[:bundle]}",
    "--output=#{paths[:output_apks]}",
    "--ks=#{ks}",
    "--ks-pass=pass:#{ks_pass}",
    "--ks-key-alias=#{key_alias}",
    "--key-pass=pass:#{key_pass}",
    "--mode=universal"
  ]
  
  # 验证关键文件是否存在
  unless File.exist?(paths[:bundle])
    raise RuntimeError, "AAB 文件不存在: #{paths[:bundle]}"
  end
  
  unless File.exist?(ks)
    raise RuntimeError, "Keystore 文件不存在"
  end

  unless system(*bundletool_cmd)
    # 检查是否是 Java 版本问题
    if java_cmd == 'java'
      raise RuntimeError, "APKS 构建失败。可能是 Java 版本不兼容,bundletool 需要 Java 11+,请检查 JAVA_HOME 环境变量或安装正确的 Java 版本"
    else
      raise RuntimeError, "APKS 构建失败。使用的 Java 命令: #{java_cmd}"
    end
  end

  # 解压 APKs 文件
  unless system("unzip", "-o", paths[:output_apks], "-d", output_dir)
    raise RuntimeError, "APKS 解压失败"
  end

  # 返回生成的 APK 路径
  unless File.exist?(paths[:universal_apk])
    raise RuntimeError, "未找到生成的 APK 文件"
  end

  paths[:universal_apk]
end