Module: Pindo::AndroidResHelper
- Extended by:
- Executable
- Defined in:
- lib/pindo/module/android/android_res_helper.rb
Constant Summary collapse
- ANDROID_ICON_DENSITIES =
Android icon 各密度尺寸定义
{ 'mdpi' => 48, 'hdpi' => 72, 'xhdpi' => 96, 'xxhdpi' => 144, 'xxxhdpi' => 192 }.freeze
Class Method Summary collapse
-
.clean_old_icons(res_dir: nil) ⇒ Boolean
清理所有旧的 icon 文件和自定义配置.
-
.create_icon_for_density(icon_name: nil, new_icon_dir: nil, density: nil, size: nil) ⇒ Hash
创建单个密度的Android icon(同时生成方形和圆形命名).
-
.create_icons(icon_name: nil, new_icon_dir: nil) ⇒ Hash
创建所有密度的Android icons.
-
.install_icon(proj_dir: nil, new_icon_dir: nil) ⇒ Boolean
安装Android icon到项目中(完全标准化方案).
-
.update_manifest_to_standard(manifest_path: nil) ⇒ Boolean
更新 AndroidManifest.xml 为标准配置.
Methods included from Executable
capture_command, executable, execute_command, which, which!
Class Method Details
.clean_old_icons(res_dir: nil) ⇒ Boolean
清理所有旧的 icon 文件和自定义配置
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 |
# File 'lib/pindo/module/android/android_res_helper.rb', line 112 def self.clean_old_icons(res_dir:nil) return false unless res_dir && File.directory?(res_dir) begin cleaned_items = [] # 1. 删除 adaptive icon XML 目录 adaptive_dir = File.join(res_dir, "mipmap-anydpi-v26") if Dir.exist?(adaptive_dir) xml_files = Dir.glob(File.join(adaptive_dir, "*.xml")) FileUtils.rm_rf(adaptive_dir) cleaned_items << "adaptive XML(#{xml_files.size}个)" if xml_files.any? end # 2. 删除所有 mipmap 目录中的旧 icon 文件 old_png_count = 0 mipmap_dirs = Dir.glob(File.join(res_dir, "mipmap-*")) mipmap_dirs.each do |mipmap_dir| next unless File.directory?(mipmap_dir) old_files = [ 'app_icon.png', 'app_icon_round.png', 'ic_launcher_foreground.png', 'ic_launcher_background.png', 'ic_launcher.png', 'ic_launcher_round.png' ] old_files.each do |filename| file_path = File.join(mipmap_dir, filename) if File.exist?(file_path) File.delete(file_path) old_png_count += 1 end end end cleaned_items << "旧icon文件(#{old_png_count}个)" if old_png_count > 0 if cleaned_items.any? puts " ✓ 已清理: #{cleaned_items.join(', ')}" end return true rescue => e Funlog.instance.("清理旧 icon 失败: #{e.message}") return false end end |
.create_icon_for_density(icon_name: nil, new_icon_dir: nil, density: nil, size: nil) ⇒ Hash
创建单个密度的Android icon(同时生成方形和圆形命名)
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 |
# File 'lib/pindo/module/android/android_res_helper.rb', line 27 def self.create_icon_for_density(icon_name:nil, new_icon_dir:nil, density:nil, size:nil) unless File.exist?(icon_name) Funlog.instance.("文件不存在: #{icon_name}") return nil end begin density_dir = File.join(new_icon_dir, "mipmap-#{density}") FileUtils.mkdir_p(density_dir) result = {} # 生成两个文件:ic_launcher.png 和 ic_launcher_round.png # 注意:两个都是方形,不切圆角,只是文件名不同 ['ic_launcher.png', 'ic_launcher_round.png'].each do |filename| output_path = File.join(density_dir, filename) command = [ 'sips', '--matchTo', '/System/Library/ColorSync/Profiles/sRGB Profile.icc', '-z', size.to_s, size.to_s, icon_name, '--out', output_path ] Executable.capture_command('sips', command, capture: :out) unless File.exist?(output_path) Funlog.instance.("生成icon失败: #{output_path}") return nil end result[filename] = output_path end return result rescue => e Funlog.instance.("生成#{density}密度icon时出错: #{e.message}") return nil end end |
.create_icons(icon_name: nil, new_icon_dir: nil) ⇒ Hash
创建所有密度的Android icons
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 |
# File 'lib/pindo/module/android/android_res_helper.rb', line 73 def self.create_icons(icon_name:nil, new_icon_dir:nil) unless File.exist?(icon_name) Funlog.instance.("文件不存在: #{icon_name}") return nil end begin FileUtils.mkdir_p(new_icon_dir) rescue => e Funlog.instance.("创建输出目录失败: #{e.message}") return nil end all_icons = {} success_count = 0 ANDROID_ICON_DENSITIES.each do |density, size| icons = create_icon_for_density( icon_name: icon_name, new_icon_dir: new_icon_dir, density: density, size: size ) if icons all_icons[density] = icons success_count += 1 else Funlog.instance.("#{density}密度icon生成失败,跳过") end end # 如果所有密度都失败了,返回 nil return success_count > 0 ? all_icons : nil end |
.install_icon(proj_dir: nil, new_icon_dir: nil) ⇒ Boolean
安装Android icon到项目中(完全标准化方案)
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 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 |
# File 'lib/pindo/module/android/android_res_helper.rb', line 200 def self.install_icon(proj_dir:nil, new_icon_dir:nil) unless proj_dir && File.directory?(proj_dir) Funlog.instance.("项目目录不存在: #{proj_dir}") return false end unless new_icon_dir && File.directory?(new_icon_dir) Funlog.instance.("Icon目录不存在: #{new_icon_dir}") return false end begin # 1. 查找 res 目录(支持 launcher、app 和 unityLibrary) possible_res_dirs = [ File.join(proj_dir, "launcher/src/main/res"), File.join(proj_dir, "app/src/main/res"), File.join(proj_dir, "unityLibrary/src/main/res") ] res_dir = possible_res_dirs.find { |dir| File.directory?(dir) } # 如果没找到,创建默认目录 unless res_dir res_dir = File.join(proj_dir, "launcher/src/main/res") FileUtils.mkdir_p(res_dir) end # 2. 清理所有旧的 icon 资源 clean_old_icons(res_dir: res_dir) # 3. 查找并更新 AndroidManifest.xml manifest_paths = [ File.join(proj_dir, "launcher/src/main/AndroidManifest.xml"), File.join(proj_dir, "app/src/main/AndroidManifest.xml"), File.join(proj_dir, "src/main/AndroidManifest.xml") ] manifest_path = manifest_paths.find { |path| File.exist?(path) } if manifest_path update_manifest_to_standard(manifest_path: manifest_path) end # 4. 安装标准 icon 文件 success_count = 0 densities_installed = [] ANDROID_ICON_DENSITIES.keys.each do |density| source_dir = File.join(new_icon_dir, "mipmap-#{density}") target_dir = File.join(res_dir, "mipmap-#{density}") next unless File.directory?(source_dir) # 创建目标目录 FileUtils.mkdir_p(target_dir) unless File.directory?(target_dir) # 标准配置:只复制 ic_launcher.png 和 ic_launcher_round.png files_to_copy = [ { source: 'ic_launcher.png', target: 'ic_launcher.png' }, { source: 'ic_launcher_round.png', target: 'ic_launcher_round.png' } ] density_success = 0 files_to_copy.each do |file_map| source_file = File.join(source_dir, file_map[:source]) target_file = File.join(target_dir, file_map[:target]) if File.exist?(source_file) FileUtils.cp(source_file, target_file) success_count += 1 density_success += 1 else Funlog.instance.("源文件不存在: #{file_map[:source]}") end end densities_installed << density if density_success > 0 end if success_count > 0 puts " ✓ 已安装标准 icon: #{densities_installed.join(', ')} (共#{success_count}个文件)" end return success_count > 0 rescue => e Funlog.instance.("安装icon时出错: #{e.message}") puts e.backtrace return false end end |
.update_manifest_to_standard(manifest_path: nil) ⇒ Boolean
更新 AndroidManifest.xml 为标准配置
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 |
# File 'lib/pindo/module/android/android_res_helper.rb', line 167 def self.update_manifest_to_standard(manifest_path:nil) return false unless manifest_path && File.exist?(manifest_path) begin require 'nokogiri' content = File.read(manifest_path) doc = Nokogiri::XML(content) # 查找 <application> 标签 app_node = doc.at_xpath('//application') return false unless app_node # 设置标准 icon 配置 app_node['android:icon'] = '@mipmap/ic_launcher' app_node['android:roundIcon'] = '@mipmap/ic_launcher_round' # 保存文件 File.write(manifest_path, doc.to_xml) puts " ✓ AndroidManifest.xml 已更新为标准 icon 配置" return true rescue => e Funlog.instance.("更新 AndroidManifest.xml 失败: #{e.message}") return false end end |