Detect SD Card

Both Photos and Lightroom are able to detect when a card reader has been plugged into an iPhone or iPad and a card exists with the correct DCIM format (from a digital camera).

I have been unable to find the API that allows an application to do this (except using the standard file import function and making the user navigate to the card).

ChatGPT tells me that Photos and Lightroom use a private API that is not made available to normal developers.

Does anyone know if this is true - or if not then how to detect that a card is present using Swift?

Answered by DTS Engineer in 886696022

I have been unable to find the API that allows an application to do this (except using the standard file import function and making the user navigate to the card).

Have you tried using the ImageCapture framework?

ChatGPT tells me that Photos and Lightroom use a private API that is not made available to normal developers.

God bless ChatGPT...

I was curious enough that I decided it to poke at this myself. The summary is that:

  • It's sure it's private.

  • If you ask if it's REALLY sure, then yes, it's REALLY sure it's private API on iOS.

  • If you ask it if it's REALLY, REALLY sure and to please provide sources for that information...

...it confesses that ImageCaptureCore is public API and has been since iOS 13.

__
Kevin Elliott
DTS Engineer, CoreOS/Hardware

Accepted Answer

I have been unable to find the API that allows an application to do this (except using the standard file import function and making the user navigate to the card).

Have you tried using the ImageCapture framework?

ChatGPT tells me that Photos and Lightroom use a private API that is not made available to normal developers.

God bless ChatGPT...

I was curious enough that I decided it to poke at this myself. The summary is that:

  • It's sure it's private.

  • If you ask if it's REALLY sure, then yes, it's REALLY sure it's private API on iOS.

  • If you ask it if it's REALLY, REALLY sure and to please provide sources for that information...

...it confesses that ImageCaptureCore is public API and has been since iOS 13.

__
Kevin Elliott
DTS Engineer, CoreOS/Hardware

Thanks very much for the response. Yes I considered using the ImageCapture framework but it seems to be designed for communicating with cameras and scanners rather than SD card readers. Is this incorrect?

Does the Photos app use the ImageCapture framework for importing images from USB attached SD cards?

Thanks very much for the response. Yes I considered using the ImageCapture framework but it seems to be designed for communicating with cameras and scanners rather than SD card areaders. Is this incorrect?

Yes, that's incorrect.

More specifically, the "spec" that camera's actually implement is a actually just a formal specification for the file system (a FAT variant), directory hierarchy ("DCIM" and it's descendants), and naming conventions used by cameras. If you're curious, it goes by the rather charming name "Design rule for Camera File system" on Wikipedia.

In any case, that means that there's no difference between what the systems see when a camera is directly attached or that same SD card is directly attached through an SD card reader. Both show up as a FAT variant file system with a particular layout, which is what the ImageCapture framework is designed to interpret[1].

Does the Photos app use the ImageCapture framework for importing images from USB attached SD cards?

We generally don't talk about how our apps are implemented and I'm not sure why that matter but, yes, I believe it does.

[1] ImageCapture also support PTP (Picture Transfer Protocol), but that's not relevant to SD cards.

__
Kevin Elliott
DTS Engineer, CoreOS/Hardware

Thanks - are you aware of any sample Swift code that could help me in accessing the card reader? The documentation is more geared towards camera access.

Thanks - are you aware of any sample Swift code that could help me in accessing the card reader?

Have you actually tried using the framework yet? What problem have you run into?

I think you’re assuming this is much more complicated than it actually is. Jumping back to what I said here:

"In any case, that means that there's no difference between what the systems see when a camera is directly attached or that same SD card is directly attached through an SD card reader."

That statement is quite literal. The ImageCapture doesn't actually see "cameras" and "SD Cards" as two different kinds of devices— both of them are just "DCIM volumes". In both cases, you'll just get an ICCameraDevice.

The documentation is more geared towards camera access.

Well, sort of, but that's really only because the name "ICCameraDevice" sounds much more specific than it actually is. It supports SD cards and always has, because that's exactly how many cameras present themselves to the system.

__
Kevin Elliott
DTS Engineer, CoreOS/Hardware

This is as far as I have got with ImageCaptureCore - attempting the simplest possible case to detect the card - running on an iPhone from Xcode it crashes. I have also tried with the ICDeviceBrowserDelegate directly on the DeviceProbe class but get the same result.

import Foundation
import ImageCaptureCore

@objcMembers
final class CameraBrowserDelegate: NSObject, ICDeviceBrowserDelegate {
  func deviceBrowser(_ browser: ICDeviceBrowser,
                     didAdd device: ICDevice,
                     moreComing: Bool) {
    print("Did add device: \(device)")
  }

  func deviceBrowser(_ browser: ICDeviceBrowser,
                     didRemove device: ICDevice,
                     moreGoing: Bool) {
    print("Did remove device: \(device)")
  }
}

final class DeviceProbe: NSObject {

  private let browser = ICDeviceBrowser()
  private let delegate = CameraBrowserDelegate()

  override init() {
    super.init()
    browser.delegate = delegate
    browser.browsedDeviceTypeMask = ICDeviceTypeMask(
      rawValue: ICDeviceTypeMask.camera.rawValue
    )!
    print("Starting device browser...")
    browser.start()   // <-- crash occurs here
  }
}

I now have everything working - thanks for your help - I'll Accept your first response. Thanks again for your patience.

I now have everything working - thanks for your help - I'll accept your first response.

If you don't mind answering, what went wrong? Were you not holding a reference to "DeviceProbe" (so you'd crash when the browser tried to call your delegate) or was it something else?

Thanks again for your patience.

You're very welcome and I'm glad to hear everything is working!

__
Kevin Elliott
DTS Engineer, CoreOS/Hardware

Yes - it was my lack of familiarity with the communication between a SwiftUI application and this type of framework.

Its a shame its so slow.

It overcomes many of the drawbacks of using native SwiftUI functionality but its orders of magnitude slower.

Detect SD Card
 
 
Q