class Fastlane::Actions::ExtractAppInfoAction

Public Class Methods

author() click to toggle source
# File lib/fastlane/plugin/polidea/actions/extract_app_info.rb, line 207
def self.author
  "Piotrek Dubiel"
end
available_options() click to toggle source
# File lib/fastlane/plugin/polidea/actions/extract_app_info.rb, line 176
def self.available_options
  [
    FastlaneCore::ConfigItem.new(key: :ipa,
                                 env_name: "",
                                 description: ".ipa file to extract icon",
                                 optional: true,
                                 default_value: Actions.lane_context[SharedValues::IPA_OUTPUT_PATH]),
    FastlaneCore::ConfigItem.new(key: :apk,
                                 env_name: "",
                                 description: ".apk file to extract icon",
                                 optional: true,
                                 default_value: Actions.lane_context[SharedValues::GRADLE_APK_OUTPUT_PATH]),
    FastlaneCore::ConfigItem.new(key: :icon_output_path,
                                 env_name: "",
                                 description: "icon output path",
                                 optional: true,
                                 default_value: "./app_icon.png")
  ]
end
category() click to toggle source
# File lib/fastlane/plugin/polidea/actions/extract_app_info.rb, line 215
def self.category
  :project
end
description() click to toggle source
# File lib/fastlane/plugin/polidea/actions/extract_app_info.rb, line 172
def self.description
  "Extract information from .ipa/.apk"
end
extract_app_name(platform, config) click to toggle source
# File lib/fastlane/plugin/polidea/actions/extract_app_info.rb, line 68
def self.extract_app_name(platform, config)
  case platform
  when :ios
    info = FastlaneCore::IpaFileAnalyser.fetch_info_plist_file(config[:ipa])
    return info['CFBundleDisplayName'] || info['CFBundleName'], info['CFBundleIdentifier']
  when :android
    apk = Android::Apk.new(config[:apk])
    return apk.manifest.label, apk.manifest.package_name
  end
end
extract_binary_size(platform, config) click to toggle source
# File lib/fastlane/plugin/polidea/actions/extract_app_info.rb, line 88
def self.extract_binary_size(platform, config)
  case platform
  when :ios
    File.open(config[:ipa]).size
  when :android
    File.open(config[:apk]).size
  end
end
extract_icon(platform, config) click to toggle source
# File lib/fastlane/plugin/polidea/actions/extract_app_info.rb, line 79
def self.extract_icon(platform, config)
  case platform
  when :ios
    extract_icon_from_ipa(config[:ipa], config[:icon_output_path])
  when :android
    extract_icon_from_apk(config[:apk], config[:icon_output_path])
  end
end
extract_icon_from_apk(apk_file, icon_output_path) click to toggle source
# File lib/fastlane/plugin/polidea/actions/extract_app_info.rb, line 108
def self.extract_icon_from_apk(apk_file, icon_output_path)
  apk = Android::Apk.new(apk_file)
  icon = largest_android_icon(apk)
  return unless icon
  icon_file = File.open(icon_output_path, 'wb')
  icon_file.write icon[:data]
  icon_file
end
extract_icon_from_ipa(ipa_file, icon_output_path) click to toggle source
# File lib/fastlane/plugin/polidea/actions/extract_app_info.rb, line 136
def self.extract_icon_from_ipa(ipa_file, icon_output_path)
  info = FastlaneCore::IpaFileAnalyser.fetch_info_plist_file(ipa_file)
  icon_files = ipa_icon_files(info)
  return if icon_files.empty?
  icon_file_name = icon_files.sort.last
  Zip::File.open(ipa_file) do |zipfile|
    icon_file = self.largest_ios_icon(zipfile.glob("**/Payload/**/#{icon_file_name}*.png"))
    return nil unless icon_file
    tmp_path = "/tmp/app_icon.png"
    File.write(tmp_path, zipfile.read(icon_file))
    Actions.sh("xcrun -sdk iphoneos pngcrush -revert-iphone-optimizations #{tmp_path} #{icon_output_path}")
    File.delete(tmp_path)
  end
end
extract_version(platform, config) click to toggle source
# File lib/fastlane/plugin/polidea/actions/extract_app_info.rb, line 97
def self.extract_version(platform, config)
  case platform
  when :ios
    info = FastlaneCore::IpaFileAnalyser.fetch_info_plist_file(config[:ipa])
    return info['CFBundleShortVersionString'], info['CFBundleVersion'].to_i
  when :android
    apk = Android::Apk.new(config[:apk])
    return apk.manifest.version_name, apk.manifest.version_code
  end
end
ipa_icon_files(info) click to toggle source
# File lib/fastlane/plugin/polidea/actions/extract_app_info.rb, line 151
def self.ipa_icon_files(info)
  # try iPhone
  icons = info.dig('CFBundleIcons', 'CFBundlePrimaryIcon', 'CFBundleIconFiles')
  return icons unless icons.nil?
  # try iPad
  icons = info.dig('CFBundleIcons~ipad', 'CFBundlePrimaryIcon', 'CFBundleIconFiles')
  return icons unless icons.nil?
  []
end
is_supported?(platform) click to toggle source
# File lib/fastlane/plugin/polidea/actions/extract_app_info.rb, line 211
def self.is_supported?(platform)
  [:ios, :android].include? platform
end
largest_android_icon(apk) click to toggle source
# File lib/fastlane/plugin/polidea/actions/extract_app_info.rb, line 117
def self.largest_android_icon(apk)
  icons = apk.icon
  selected_icon = icons.max_by do |name, _|
    case name
    when /x*hdpi/
      name.count "x"
    when /mdpi/
      -1
    when %r{\/drawable\/}
      -2
    else
      -3
    end
  end
  { name: selected_icon[0], data: selected_icon[1] } if selected_icon
rescue
  nil
end
largest_ios_icon(icons) click to toggle source
# File lib/fastlane/plugin/polidea/actions/extract_app_info.rb, line 161
def self.largest_ios_icon(icons)
  icons.max_by do |file, _|
    case file.name
    when /@(\d+)x/
      $1.to_i
    else
      1
    end
  end
end
output() click to toggle source
# File lib/fastlane/plugin/polidea/actions/extract_app_info.rb, line 196
def self.output
  [
    ['APP_NAME', 'App name extracted from .ipa/.apk'],
    ['APP_IDENTIFIER', 'Bundle id or package name extracted from .ipa/.apk'],
    ['ICON_OUTPUT_PATH', 'Path to app icon extracted from .ipa/.apk'],
    ['BINARY_SIZE', 'Size of .ipa/.apk in bytes'],
    ['APP_VERSION', 'App version extracted from .ipa/.apk'],
    ['BUILD_NUMBER', 'Build number extracted from .ipa/.apk']
  ]
end
publish_shared_values(config) click to toggle source
# File lib/fastlane/plugin/polidea/actions/extract_app_info.rb, line 52
def self.publish_shared_values(config)
  config.each do |key, value|
    if value
      Actions.lane_context[key] = value
      ENV[key.to_s] = value.to_s
    else
      Actions.lane_context[key] = nil
      UI.important("Value for #{key} not found.")
    end
  end

  FastlaneCore::PrintTable.print_values(config: config,
                                     hide_keys: [],
                                         title: "Summary for extract_app_info")
end
run(config) click to toggle source
# File lib/fastlane/plugin/polidea/actions/extract_app_info.rb, line 17
def self.run(config)
  Fastlane::Polidea.session.action_launched("extract_app_info", config)

  platform = Actions.lane_context[Actions::SharedValues::PLATFORM_NAME].to_sym

  icon_output_path = config[:icon_output_path]

  validate(platform, config)

  app_name, app_identifier = extract_app_name(platform, config)
  app_icon = extract_icon(platform, config) if icon_output_path
  binary_size = extract_binary_size(platform, config)
  app_version, build_number = extract_version(platform, config)

  publish_shared_values(
    SharedValues::APP_NAME => app_name,
    SharedValues::APP_IDENTIFIER => app_identifier,
    SharedValues::ICON_OUTPUT_PATH => app_icon.nil? ? nil : icon_output_path,
    SharedValues::BINARY_SIZE => binary_size,
    SharedValues::APP_VERSION => app_version,
    SharedValues::BUILD_NUMBER => build_number
  )

  Fastlane::Polidea.session.action_completed("extract_app_info")
end
validate(platform, config) click to toggle source
# File lib/fastlane/plugin/polidea/actions/extract_app_info.rb, line 43
def self.validate(platform, config)
  case platform
  when :ios
    UI.user_error!("No IPA file path given, pass using `ipa: 'ipa path'`") unless config[:ipa].to_s.length > 0
  when :android
    UI.user_error!("No APK file path given, pass using `apk: 'apk path'`") unless config[:apk].to_s.length > 0
  end
end