Hi all, I have started porting my plugins to iOS/iPad and I would like to keep my current desktop preset system.
As far as I understand, there are two ways to access the sandboxed area to save/load your own files.
Using App Group ID, something like:
juce::File::getContainerForSecurityApplicationGroupIdentifier ("group.audiothing");
in my case returns:
/private/var/mobile/Containers/Shared/AppGroup/691DFCB7-CA56-4BAB-8BE6-5BEE594B6EF9
While:
juce::File::getSpecialLocation (File::userDocumentsDirectory);
returns:
/var/mobile/Containers/Data/PluginKitPlugin/E0990E4E-A77D-4D32-8FFE-47404D75B78F/Documents
I am able to save presets in both locations, and they apparently end up in the same spot regardless of the method used. However, not matter what I try, I canāt access the files in any way.
Any clue on what should I do?
1 Like
Iām using:
presetsDirectory = File::getSpecialLocation(File::userApplicationDataDirectory)
.getChildFile("Application Support")
.getChildFile("MyCompany")
.getChildFile(appName)
.getChildFile("Presets");
I can access them fine in a standalone app, but havenāt tried as an AUv3 plugin yet.
1 Like
Thank you! So trying userApplicationDataDirectory
then I get this path:
/var/mobile/Containers/Data/PluginKitPlugin/1BEC12CE-C51A-4EF0-AE16-2B72973A5C22/Library/
But now I double-checked the path for the saved file and itās completely different from what I give to the FileChooser.
So, whatever path I give to the FileChooser (using each of the three methods outlined so far), it instead saves the file to:
/private/var/mobile/Containers/Shared/AppGroup/3BBD97CB-1852-4624-BC28-8FB5BDE9BC34/File Provider Storage/Filterjam/CustomPreset.atp
So yet another path, how am I supposed to get this path then? Or what should I provide to the FileChooser exactly?
This is what Iām testing right now:
File customPreset = File::getSpecialLocation (File::userApplicationDataDirectory)
.getChildFile ("AudioThing")
.getChildFile ("Filterjam")
.getChildFile ("Presets")
.getChildFile ("CustomPreset.atp"); // hardcoded just for this example
DBG ("customPreset: " << customPreset.getFullPathName());
// customPreset: /var/mobile/Containers/Data/PluginKitPlugin/60B27E2F-9F74-4672-B09B-AFBDE6109FCA/Library/AudioThing/Filterjam/Presets/CustomPreset.atp
fileChooser = std::make_unique<FileChooser> ("Save Preset", customPreset, "*.atp", true, false, this);
fileChooser->launchAsync (FileBrowserComponent::saveMode |
FileBrowserComponent::warnAboutOverwriting |
FileBrowserComponent::canSelectFiles,
[this](const FileChooser& fc)
{
File saveFile (fc.getResult());
DBG ("saveFile: " << saveFile.getFullPathName());
// saveFile: /private/var/mobile/Containers/Shared/AppGroup/3BBD97CB-1852-4624-BC28-8FB5BDE9BC34/File Provider Storage/Filterjam/CustomPreset.atp
});
So the path I provide to FileChooser and the path the FileChooser uses to save the file are different.
The result is the same for AUv3 and Standalone.
1 Like
Interestingā¦and odd.
For whatever reason, I chose to eliminate using a FileChooser when porting my plugin to iOS. Instead, Iām simplifying that so thereās no real file system view to the user. Iām just hardwiring several folders to ābanksā and just having the user pick a bank and a name and thatās it.
Ok, so bypassing the FileChooser works. So I can just prompt a small box to the user to get the preset name. Thatās ok I guessā¦but now the problem is, which path should I use?
To recap, there are 3 methods Iāve found so far:
juce::File::getContainerForSecurityApplicationGroupIdentifier ("group.audiothing");
juce::File::getSpecialLocation (File::userDocumentsDirectory);
juce::File::getSpecialLocation (File::userApplicationDataDirectory)
I think that if you need to share files among multiple apps, the first option is the way to go.
1 Like
Hmmm. I havenāt gotten that far yet.
Btw, Iām glad to see this documented somewhere. Not sure why, but as this is my first port to iOS, it still seems like the wild west for lots of small details to get right.
The App Group container is the right choice if you want user files to be seamlessly usable from both your app and AUv3.
However, if you have some factory presets or bundled content, you have to take care of copying these in the App Group container yourself, e.g. upon first launch.
2 Likes
Weāve recently ported a plugin to iOS and there is a requirement to use the same preset management system as we do on the Desktop. Iāve had some success using the App Group ID but I have seen this method fail on an iPad with an āoperation not permittedā error when attempting to load or save (XmlElement::writeTo). Iām not seeing the same problems if Iām running on the iOS simulator in Xcode, and can load and save (xml) presets without issue.
Has anybody else experienced this?