iosxamarinxamarin.iosusbuidocumentpickerviewcontroller

How to read files of External Mass Storage Devices Without DocumentPicker? (iOS)


Just to give some context, there is an iOS app I'm building (in Xamarin) that requires the ability to fetch files (in an automatic way without having the user to navigate to the files and select them manually) that are stored on External Storage Devices (USB Sticks), and are connected (paired) to an iPhone/iPad.

Users connect a lighting cable to the iOS Devices, and plug their USB Sticks into this lighting cable. Here is an example of the cable that end users use to pair the USB Sticks with their iPhone/iPad, and the app then auto fetches these files from the USB Storage Devices.

enter image description here

The app then performs 2 functions:

  1. It listens to notifications, for when a usb stick is paired with the iOS Device.
  2. When it receives this notification, it then proceeds with querying the files on the USB Stick, and reads and processes the files. The app reads these files automatically and the user does not need to manually select these files

I've tried using External Accessory Framework, however that's only suitable for devices that you register with the MFi program. https://developer.apple.com/documentation/externalaccessory

Notifications Center never seems to work (the Notifications that handle when a Device gets Connected and Disconnected, the delegates never get called), and I've tried using the Microsoft Helpers.

https://learn.microsoft.com/en-us/dotnet/api/externalaccessory.eaaccessorymanager.notifications.observedidconnect?view=xamarin-ios-sdk-12

I've also tried some 3rd party libraries, but haven't found anything useful.

It doesn't look Apple has any Api Available to auto query and read the files, without having to use a DocumentPickerController. I know this is because of the App Sandbox, and I cannot directly access the Removable Storage Devices.

Now for my questions:

  1. Are there any 3rd party libraries anybody can recommend, that can help achieve most of the heavy lifting for this task? I'd prefer a library that's compatible with Xamarin, however if it's a native library (Swift or Objective-C Library, Cocoapods) I'm sure there is a binding I can use on nuget.
  2. Does anybody have any snippets, or documentation, or can point me in the right direction here (Please feel free to post Swift, or Objective-c solutions here if you like)? Where should I look, which Apple Framework (iOS SDK) is most suitable to deal with this situation. And to summarise, is what I'm asking for at all possible on iOS, without having to jailbreak, or get around the App Sandbox?

Update

So I've tried the solution that @Saamer suggested: Detect if USB is connected to iPhone device

Here is an example I wrote just to verify if the callback gets invoked, and the app can detect if a usb is plugged in.

CFNotificationCenter.Darwin.AddObserver("com.apple.mobile.lockdown.host_attached", null, (e, s) =>
        {
            MainThread.BeginInvokeOnMainThread(async () =>
            {
                var picker = await Xamarin.Essentials.FilePicker.PickAsync();
            });
    }, CFNotificationSuspensionBehavior.DeliverImmediately);

A file picker should immediately get invoked, and open up, once I plug the USB in, however this doesn't happen.

I'm happy for a solution right now which opens up a file picker, when the user plugs in a USB Device, and navigates to the root directory to start off with. So when the File Picker opens up the user should see this. Then they can select the files they want to transfer into the app.

enter image description here


Solution

    1. I thought you needed to jailbreak but it seems unlikely, a solution is possible for <iOS 12

    According to the Apple Docs

    You can use the Files app and other supported apps to access files stored on external devices, such as USB drives and SD cards, connected to your iPhone.

    1. Essentially you have to make your a "supported app". I have downloaded a free app called "Clockology" that I recommend downloading and playing with, which allows users to see data within the app as you can see below: Clockology app screenshots

    You generally use UIDocumentPickerViewController along with the right uttype to get the files from the Files apps or iCloud Drive, and you require activating the Key-value storage and iCloud Documents from iCloud entitlements capability. There's a lot of tutorials on UIDocumentPickerViewController usage, but you specifically want the capabilities that became available from iOS 13 onwards

    Entitlements

    This video from WWDC is the best example of getting to where you want. I also didn't find any 3rd party libraries that can help with this

    ——————-

    Edit: If the app does not need to be distributed through TestFlight or the App Store, you can use IOKit and distribute through AppCenter, as long as you have the UDIDs of all the devices you need the app installed on (up to 100?)