Module: Pindo::KeystoreHelper

Defined in:
lib/pindo/module/android/keystore_helper.rb

Class Method Summary collapse

Class Method Details

.apply_keystore_config(project_dir, build_type = "debug") ⇒ Boolean

将签名配置应用到 Android 工程新策略:

  1. 从 buildTypes 中找到 debug/release 引用的 signingConfig 名称

  2. 检查该 signingConfig 配置是否存在且完整

  3. 如果不完整,用 Pindo 配置更新该 signingConfig

  4. 不修改 buildTypes 中的引用名称

Parameters:

  • project_dir (String)

    项目目录

  • build_type (String) (defaults to: "debug")

    构建类型 “debug” 或 “release”

Returns:

  • (Boolean)

    是否成功

Raises:

  • (ArgumentError)


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

def apply_keystore_config(project_dir, build_type = "debug")
  raise ArgumentError, "项目目录不能为空" if project_dir.nil?
  raise ArgumentError, "build_type 必须是 debug 或 release" unless ["debug", "release"].include?(build_type)

  # 查找主模块的 build.gradle
  main_module = Pindo::AndroidProjectHelper.get_main_module(project_dir)
  unless main_module
    Funlog.error("无法找到主模块")
    return false
  end

  gradle_file = find_gradle_file(main_module)
  unless gradle_file
    Funlog.error("无法找到 build.gradle 文件")
    return false
  end

  puts "检查并配置 keystore 签名..."

  # 获取签名配置并拷贝 keystore 文件到项目
  sign_config = get_android_sign_config
  if sign_config && sign_config[build_type]
    # 拷贝文件并更新配置路径
    copy_keystore_to_project(project_dir, build_type, sign_config[build_type])
  end

  # 根据文件类型选择处理方法,传递修改后的配置
  if gradle_file.end_with?(".kts")
    ensure_keystore_config_kts(gradle_file, project_dir, build_type, sign_config)
  else
    ensure_keystore_config_groovy(gradle_file, project_dir, build_type, sign_config)
  end
end

.get_android_sign_configHash?

从 PindoConfig 统一配置中读取 Android 签名配置

Returns:

  • (Hash, nil)

    签名配置哈希,包含 debug 和 release 配置



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

def get_android_sign_config
  begin
    # 使用 PindoConfig 单例获取配置
    pindo_config = Pindoconfig.instance

    # 从 pindo_user_config_json 中获取 android_sign_config
    android_sign_config = pindo_config.pindo_user_config_json["android_sign_config"]

    if android_sign_config.nil? || android_sign_config.empty?
      Funlog.warning("配置中未找到 android_sign_config")
      return nil
    end

    # 验证配置结构
    unless validate_sign_config(android_sign_config)
      Funlog.error("android_sign_config 配置格式不正确")
      return nil
    end

    # 解析文件路径
    android_sign_config = resolve_keystore_paths(android_sign_config)

    return android_sign_config

  rescue => e
    Funlog.error("读取签名配置失败: #{e.message}")
    return nil
  end
end

.get_keystore_config_from_project(project_path, debug = false) ⇒ Hash?

从工程的 build.gradle 中读取已有的 keystore 配置

Parameters:

  • project_path (String)

    项目路径

  • debug (Boolean) (defaults to: false)

    是否为 debug 构建

Returns:

  • (Hash, nil)

    keystore 配置哈希



104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
# File 'lib/pindo/module/android/keystore_helper.rb', line 104

def get_keystore_config_from_project(project_path, debug = false)
  main_module = Pindo::AndroidProjectHelper.get_main_module(project_path)
  return nil unless main_module

  gradle_kts_path = File.join(main_module, "build.gradle.kts")
  gradle_path     = File.join(main_module, "build.gradle")

  if File.exist?(gradle_kts_path)
    puts "KTS 项目,读取 #{File.basename(gradle_kts_path)} 文件"
    get_keystore_config_kts(gradle_kts_path, project_path, debug)
  elsif File.exist?(gradle_path)
    puts "Groovy 项目,读取 #{File.basename(gradle_path)} 文件"
    get_keystore_config_groovy(gradle_path, project_path, debug)
  else
    puts "未找到 build.gradle 或 build.gradle.kts 文件"
    nil
  end
end

.resolve_keystore_paths(config) ⇒ Hash

解析 keystore 文件路径

Parameters:

  • config (Hash)

    签名配置

Returns:

  • (Hash)

    解析后的配置



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

def resolve_keystore_paths(config)
  # 使用 PindoConfig 获取配置目录
  pindo_config = Pindoconfig.instance
  pindo_common_config_dir = pindo_config.pindo_common_configdir

  resolved_config = {}

  ["debug", "release"].each do |build_type|
    next if config[build_type].nil?

    cfg = config[build_type].dup
    store_file = cfg["storeFile"]

    # 如果是相对路径,则基于 pindo_common_config 目录解析
    unless store_file.start_with?("/")
      cfg["storeFile"] = File.join(pindo_common_config_dir, store_file)
    end

    # 验证文件是否存在
    unless File.exist?(cfg["storeFile"])
      Funlog.warning("Keystore 文件不存在: #{cfg["storeFile"]}")
    end

    resolved_config[build_type] = cfg
  end

  resolved_config
end

.validate_sign_config(config) ⇒ Boolean

验证签名配置格式

Parameters:

  • config (Hash)

    签名配置

Returns:

  • (Boolean)

    是否有效



44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
# File 'lib/pindo/module/android/keystore_helper.rb', line 44

def validate_sign_config(config)
  return false unless config.is_a?(Hash)

  # 至少需要有 debug 或 release 配置
  return false if config["debug"].nil? && config["release"].nil?

  # 验证每个配置的必需字段
  ["debug", "release"].each do |build_type|
    next if config[build_type].nil?

    cfg = config[build_type]
    required_fields = ["storeFile", "storePassword", "keyAlias", "keyPassword"]

    required_fields.each do |field|
      if cfg[field].nil? || cfg[field].to_s.empty?
        Funlog.error("#{build_type} 配置缺少必需字段: #{field}")
        return false
      end
    end
  end

  true
end