class FastlaneCore::DeviceManager

Public Class Methods

all(requested_os_type = "") click to toggle source
# File lib/fastlane_core/device_manager.rb, line 7
def all(requested_os_type = "")
  return connected_devices(requested_os_type) + simulators(requested_os_type)
end
connected_devices(requested_os_type) click to toggle source
# File lib/fastlane_core/device_manager.rb, line 51
def connected_devices(requested_os_type)
  UI.verbose("Fetching available connected devices")

  device_types = if requested_os_type == "tvOS"
                   ["AppleTV"]
                 elsif requested_os_type == "iOS"
                   ["iPhone", "iPad", "iPod"]
                 else
                   []
                 end

  devices = [] # Return early if no supported devices are being searched for
  if device_types.count == 0
    return devices
  end

  usb_devices_output = ''
  Open3.popen3("system_profiler SPUSBDataType -xml") do |stdin, stdout, stderr, wait_thr|
    usb_devices_output = stdout.read
  end

  device_uuids = []
  result = Plist.parse_xml(usb_devices_output)
  result[0]['_items'].each do |host_controller| # loop just incase the host system has more then 1 controller
    host_controller['_items'].each do |usb_device|
      is_supported_device = device_types.any? { |device_type| usb_device['_name'] == device_type }
      if is_supported_device && usb_device['serial_num'].length == 40
        device_uuids.push(usb_device['serial_num'])
      end
    end
  end

  if device_uuids.count > 0 # instruments takes a little while to return so skip it if we have no devices
    instruments_devices_output = ''
    Open3.popen3("instruments -s devices") do |stdin, stdout, stderr, wait_thr|
      instruments_devices_output = stdout.read
    end

    instruments_devices_output.split(/\n/).each do |instruments_device|
      device_uuids.each do |device_uuid|
        match = instruments_device.match(/(.+) \(([0-9.]+)\) \[([0-9a-f]+)\]?/)
        if match && match[3] == device_uuid
          devices << Device.new(name: match[1], udid: match[3], os_type: requested_os_type, os_version: match[2], state: "Booted", is_simulator: false)
          UI.verbose("USB Device Found - \"" + match[1] + "\" (" + match[2] + ") UUID:" + match[3])
        end
      end
    end
  end

  return devices
end
simulators(requested_os_type = "") click to toggle source
# File lib/fastlane_core/device_manager.rb, line 11
def simulators(requested_os_type = "")
  UI.verbose("Fetching available simulator devices")

  @devices = []
  os_type = 'unknown'
  os_version = 'unknown'
  output = ''
  Open3.popen3('xcrun simctl list devices') do |stdin, stdout, stderr, wait_thr|
    output = stdout.read
  end

  unless output.include?("== Devices ==")
    UI.error("xcrun simctl CLI broken, run `xcrun simctl list devices` and make sure it works")
    UI.user_error!("xcrun simctl not working.")
  end

  output.split(/\n/).each do |line|
    next if line =~ /^== /
    if line =~ /^-- /
      (os_type, os_version) = line.gsub(/-- (.*) --/, '\1').split
    else
      # iPad 2 (0EDE6AFC-3767-425A-9658-AAA30A60F212) (Shutdown)
      # iPad Air 2 (4F3B8059-03FD-4D72-99C0-6E9BBEE2A9CE) (Shutdown) (unavailable, device type profile not found)
      if line.include?("inch)")
        # For Xcode 8, where sometimes we have the # of inches in ()
        # iPad Pro (12.9 inch) (CEF11EB3-79DF-43CB-896A-0F33916C8BDE) (Shutdown)
        match = line.match(/\s+([^\(]+ \(.*inch\)) \(([-0-9A-F]+)\) \(([^\(]+)\)(.*unavailable.*)?/)
      else
        match = line.match(/\s+([^\(]+) \(([-0-9A-F]+)\) \(([^\(]+)\)(.*unavailable.*)?/)
      end

      if match && !match[4] && (os_type == requested_os_type || requested_os_type == "")
        @devices << Device.new(name: match[1], os_type: os_type, os_version: os_version, udid: match[2], state: match[3], is_simulator: true)
      end
    end
  end

  return @devices
end