iOS AUv3 download error

Hi All,

I’m trying to port some code to iOS and I am running into an issue with downloadToFile(). The download starts without issue and appears to get to completion but this code always outputs “Download failed with code: -1” (the file never actually gets written to but the data appears to be downloaded). This code works flawlessly on MacOS. Anyone know what I’m doing wrong? Is there some extra permission required for download task to actually save?

    static void download(juce::String url, juce::String fileName, bool &isDownloaded, bool &downloadError)
    {
#if JUCE_IOS
        auto downloadFolderLocation = juce::File::getContainerForSecurityApplicationGroupIdentifier(APP_GROUP_ID).getChildFile("Downloads");
#else
        auto downloadFolderLocation = juce::File(juce::File::getSpecialLocation(juce::File::userHomeDirectory).getChildFile("Downloads"));
#endif
        
        juce::URL download(url);
        juce::File fileToWrite(downloadFolderLocation.getChildFile(fileName));
        
        juce::URL::DownloadTaskOptions downloadOptions;
#if JUCE_IOS
        downloadOptions = downloadOptions.withSharedContainer(APP_GROUP_ID);
#endif
        
        std::unique_ptr<juce::URL::DownloadTask> taskProgress = download.downloadToFile(fileToWrite, downloadOptions);
        if (taskProgress)
        {
            while (taskProgress->isFinished() == false)
            {
                juce::Thread::sleep(100);
                std::cout << "Downloading Files:" <<  taskProgress->getLengthDownloaded() / (float) taskProgress->getTotalLength() * 100.0 << "%" << std::endl;
            }
            bool error = taskProgress->hadError();
            if (error == false)
            {
                isDownloaded = true;
            }
            else
            {
                std::cout << "Download failed with code: " << taskProgress->statusCode() << std::endl;
                downloadError = true;
                fileToWrite.deleteFile();
            }
        }
        else
        {
            downloadError = true;
            fileToWrite.deleteFile();
        }
    }

The docs for getContainerForSecurityApplicationGroupIdentifier mention that you need to pass one of the app group IDs from your entitlements file. To get this set up in the Projucer:

  • Make sure you have configured signing properly - add a developer team ID in the main iOS exporter options, and a code-signing identity to each of the debug/release configurations
  • In the iOS exporter options, set the “App Groups Capability” option to “enabled”
  • Also in the iOS exporter options, add an ID to the “App Group ID” field

The app group ID that you pick needs to be registered with Apple. You can do so following the instructions here.

All of these steps should work with CMake too, but you’ll need to use the CMake API docs in the repo to locate the relevant settings.

Hi reuk,

Thanks for getting back to me. All of that is setup. Turns out that the file is actually being downloaded and saved but it is always returning that it has an error. Not sure why?

In juce_Network_mac didWriteData gets called followed by didFinishDownloadingToURL. After this didCompleteWithError and didBecomeInvalidWithError both get called with a nil NSError.

Not sure how safe it is to ignore this error… In testing it is working and I don’t know why due to the nil errors. For my purposes I am trying to unzip immediately after so can use that success/fail to determine but doesn’t explain the above error.

edit: I should note that getContainerForSecurityApplicationGroupIdentifier is used elsewhere in the app without issue so I doubt the issue is related to that.

Scratch that, it isn’t downloading after deleting and reinstalling the app. Must have succeeded once for the file to be there :thinking:

Edit: it downloads without error if the directory is created before downloading - if the directory doesn’t exist then it fails.