Correct background mode for an app that must receive CoreMIDI while another app is frontmost

I am the developer of MIDIDeviceManager, an iOS and iPadOS application used by musicians to control external MIDI hardware during live performance. Before enabling any background execution mode, I would like to ask which architecture Apple intends for this type of application.

What the application does

The app organises the patches of a musician's MIDI instruments into Pads, Scenes and Setlists so they can be recalled during a performance. It sends MIDI to external hardware such as guitar processors, synthesisers and vocal processors, and it also receives incoming MIDI that triggers its own Scenes — typically from a Bluetooth foot controller, a wired MIDI controller, or another app on the same device.

Its purpose is to function as the software equivalent of a programmable hardware MIDI controller. It is not a lyrics app or an audio player, and it produces no audio.

The problem

During a performance, musicians commonly run more than one app. A typical setup is lyrics or chord charts displayed in one app while a Bluetooth foot controller recalls presets on a Line 6 Helix through MIDIDeviceManager.

This requires the app to keep receiving and processing incoming CoreMIDI events while another app is frontmost. Once iOS suspends the app, those events are no longer delivered and the foot controller stops working.

This affects iPhone as much as iPad. Several of my TestFlight users perform with iPhone alone, where the device sits on a stand and is not touched during a song.

What I have observed

I tested this directly on an iPhone 17 Pro Max. With two apps running simultaneously, an app legitimately using the audio background mode continued to receive and act on incoming CoreMIDI events from a Bluetooth foot controller while backgrounded. At the same moment, MIDIDeviceManager received nothing once iOS suspended it.

This suggests that, under certain circumstances, an app executing under an appropriate background mode may continue receiving CoreMIDI while backgrounded.

Background modes considered

audio — appears to provide the required behaviour, but my app produces no audio output. I do not wish to declare a background capability that does not accurately describe what the app does.

bluetooth-central — does not appear applicable, since Bluetooth MIDI connections are established through CoreMIDI and managed by the system MIDI server rather than by my own Core Bluetooth session.

I have not been able to identify any mode intended for continuous MIDI reception, so UIBackgroundModes is currently empty.

A previous rejection

An earlier submission did declare audio, and was rejected under Guideline 2.5.4 on 7 July 2026 (submission ID eab58179-8177-4d05-9c37-5e1006828a96):

"The app declares support for audio in the UIBackgroundModes key in the Info.plist but we are unable to locate any features that require persistent audio. Background audio is intended for use by apps that provide audible content to the user while in the background, such as music player, music creation, or streaming audio apps."

That assessment is correct — the app produces no audio, and I removed the key. But the functional requirement remains: the app needs to receive MIDI while another app is frontmost. I am asking here rather than resubmitting, because I would rather understand the intended architecture than guess again.

My questions

Which background mode, if any, is appropriate for an app whose purpose is to continue receiving and processing incoming CoreMIDI events while another app is frontmost? If background MIDI reception is supported, is CoreMIDI expected to continue delivering incoming MIDI to a backgrounded app, or is there a different recommended architecture for apps of this type?

If the answer is that no background mode applies and this capability is not available to apps of this kind, I would very much appreciate knowing that clearly. I can then document the limitation for my users and design accordingly rather than pursue an unsupported approach.

My objective is not to find a workaround, but to implement this the way Apple intends professional MIDI applications to work.

Thank you.

This is just a quick note to let you know that we’re not ignoring you. I’ve been discussing your issue with some colleagues. No obvious solution leapt out, but I haven’t quite given up yet. I expect to have an update for you later in the week.

Share and Enjoy

Quinn “The Eskimo!” @ Developer Technical Support @ Apple
let myEmail = "eskimo" + "1" + "@" + "apple.com"

Thank you for the note, and for the interest and care you've taken with this. Knowing you've discussed it with colleagues is genuinely reassuring — and useful in itself, since it tells me the question doesn't have an obvious answer I'd simply overlooked.

Let me be clearer about where this sits for me, because my original post understated it.

I've been treating Split View as the answer on iPad, but in practice it's a workaround. A musician on stage is reading lyrics or following backing tracks while MIDIDeviceManager sends Program Changes and SysEx to their instruments. Splitting the screen makes both apps harder to use at exactly the moment when legibility and hit targets matter most — dim light, mid-song, no second chances. On iPhone there's no Split View at all, so switching apps stops MIDI reception altogether.

What I'm after is the behaviour audio apps already have: continue receiving and sending CoreMIDI while another app is frontmost. I understand why audio is the wrong declaration — MIDI is a control protocol, not an audio stream, and my earlier submission declaring it was rightly rejected under 2.5.4. But the runtime need is the same one that mode exists to serve: real-time work for someone who is looking at something else.

I'll be honest that this matters more than a nice-to-have. The app is with beta testers now and I'm reluctant to release it publicly while a performer can lose MIDI control mid-song simply by glancing at their setlist. That's not a failure mode I want a musician discovering on stage.

So two questions, and I'd welcome either answer. Is there a supported architecture for this today that I've missed? And if not, would an enhancement request be the right way to raise it? I'd rather ask for the right thing through the right channel than keep bending an existing mode to fit.

Thanks again for the time you're giving this.

So two questions, and I'd welcome either answer. Is there a supported architecture for this today that I've missed? And if not, would an enhancement request be the right way to raise it? I'd rather ask for the right thing through the right channel than keep bending an existing mode to fit.

So, there are actually two different options that could be worth pursuing.

First off, on the audio background category side, the concept of what exactly it means to "play audio" is more complicated than just "the app directly plays audio to the user". That's clearly the most direct and obvious case, but I believe there have been cases where apps have been approved for the category when their involvement was less "direct“ - for example, because they're directly controlling/managing hardware that’s actively playing audio. I don't know how well that will apply for your case, but it's probably worth contacting App Review to discuss that with them in more detail.

In terms of API solutions, I think the best option would be BGContinuedProcessingTask which will allow your app to stay awake in the background for a considerable period of time (many minutes) and also provides a limited amount of interface access to that you can warn/inform the user if you've been in the background for "awhile" and need to foreground. Its WWDC 2025 introduction video has a good overview of what the API does and how to use it.

I will note that, in terms of the documentation and video, your use case is not a perfect fit. The API is primarily designed around finishing and displaying progress on more “fixed-length" work, which doesn't really match exactly what you’re describing. That's true; however, my understanding is that we're relatively flexible about this API’s usage (particularly compared to "audio"), as the background time is not unbounded and, more importantly, the system's UI means that the user is always aware that your app is using background time.

What is critical here is this requirement:

"In addition, your app needs to run the task only in response to someone’s action, such as tapping a button."

The key idea here is that these tasks need to be something the user specifically "wants" to be happening and has direct control of, NOT something that "spontaneously" happens without their interaction. However, keep in mind that this is specifically about the user’s control and understanding of what's going on, NOT about starting individual BGContinuedProcessingTasks. For example, an app like yours might have a prominent "Start Performance Session", with your app then using BGContinuedProcessingTask as needed to keep itself awake whenever a session was active. Again, the key here is that it needs to be obvious to the user why these tasks are occurring and how to stop them, NOT that EVERY individual task is directly tied to a specific user action.

Finally, returning to the issue of how the API “fits” your use case, I’d appreciate your filing a bug describing your particular use case (indeterminate continuation) and then posting the bug number back here. I obviously can’t talk about our future plans, but I do think this is something the API could better support without requiring a great deal of additional work or impact on the larger system.

__
Kevin Elliott
DTS Engineer, CoreOS/Hardware

Kevin, thank you — this is very helpful, and it has changed how I am approaching the problem. Having looked closely at both options, I think the audio category conversation is the one I should pursue, and I want to explain why BGContinuedProcessingTask does not fit rather than simply saying so.

Three reasons.

First, duration. A live performance runs two to three hours, sometimes longer with soundcheck. The documented window for continued processing is many minutes, not many hours. I recognise a musician could reasonably start a session per set rather than per gig, which narrows that gap — but the second point below applies regardless of how the session is divided.

Second, and more fundamentally, the progress model runs against this use case. The WWDC session states that the system expects these tasks to make measurable progress, and developers on these forums report tasks being marked stalled and expired after roughly thirty seconds without a progress update, with the system log naming the elapsed time since the last update. If that is accurate, it is decisive for me. A performance session has no progress to report. There is no unit of work and no fraction complete — the app is waiting on events that arrive when the musician plays, and between two songs there may be a minute of silence with nothing to update. The API would therefore expire my task not as an edge case but as its normal designed behaviour, because the defining property of the workload is the absence of measurable progress.

I would welcome your correction if I have that wrong, since the cadence figure comes from developer reports rather than documentation, and it is the load-bearing part of my reasoning.

Third, availability. iOS 26 and later excludes a significant part of my audience. Musicians very commonly dedicate an older iPad or iPhone to rig control — a deliberate choice rather than a reluctance to upgrade, because a dedicated device on a mic stand is more reliable than a phone that also takes calls. Gating this behind iOS 26 would mean the feature is absent on exactly the hardware most likely to be used for it.

On the audio category: your point about indirect involvement is the one I would like to explore with App Review. My app does not itself produce audio, but it controls hardware synthesisers, effects processors and vocal processors that are actively producing it throughout a performance. If the app stops receiving MIDI mid-set, the audible consequence is immediate — a patch change does not happen, or an effect does not switch, in front of an audience. The relationship to audio is not incidental to the app; it is the entire purpose of it.

I should be straightforward about something here. I did consider adding a metronome click to the app, which would have made it produce audio directly and qualify for the category without any argument. I decided against it. A metronome that exists only to satisfy a background mode is not a feature, it is a workaround wearing a feature's clothes, and I would rather ask for the category on the merits of what the app actually does than manufacture a technicality. I mention it because I think it illustrates the gap: the app can trivially become eligible by adding something musicians do not need, while remaining ineligible for doing the thing they do need.

I have filed the Feedback report you asked for, describing the indeterminate-continuation case: FB24176109. If continued processing were to support sessions of unbounded duration without progress semantics, it would suit this well — it is the current shape that does not fit, not the concept.

Thank you again for taking this to your colleagues. Knowing which door to knock on is worth a great deal.

A few points here:

First, duration. A live performance runs two to three hours, sometimes longer with soundcheck. The documented window for continued processing is many minutes, not many hours.

Strictly speaking, BGContinuedProcessingTask doesn't have any fixed time limit. There is a certain bound enforced by the fact progress needs to occur, but you don't have to report that frequently and the progress increment can be arbitrarily "fine" grained. It's certainly possible to continue a task for an hour+ and probably "days".

That doesn't really work on a device that's being used "normally", as the cumulative activity of a large number of apps, particularly apps creating their own tasks, will often force task termination. However, in the kind of "performance" scenario you're describing where the user is "flipping" between a small number of specific apps I'd expect it to work fine. The only reason it would fail is general resource contention (for example, the combination of apps requiring more memory than the device has) but that case would fail no matter what.

I recognise a musician could reasonably start a session per set rather than per gig, which narrows that gap — but the second point below applies regardless of how the session is divided.

This is exactly the kind of thinking I was warning about here:

Again, the key here is that it needs to be obvious to the user why these tasks are occurring and how to stop them, NOT that EVERY individual task is directly tied to a specific user action.

Nothing prevents your app from having a "Start Show" button and then producing tasks on a regular cadence or every time your app enters the background. Note that, architecturally, this is exactly what happens when the user kicks off a large collection of bulk downloads. And, yes, I'm aware that what I'm describing is different than what the WWDC presentation and our documentation describe. Both are specifically focused on its most direct use case and, in general, we don't want this API to turn into a generic API which every app is then using to extend its lifetime. However, the API itself can be used more broadly than that and I think that there are cases like yours where that non-conventional usage may be justified.

Lastly, I think it’s worth understanding that, in general, App Review is much concerned with how an API like BGContinuedProcessingTask than they are with a background category like "audio". The difference here is visibility— in theory both API can allow an app to run in the background "forever", but BGContinuedProcessingTask makes it pretty obvious if/when that's happening.

Second, and more fundamentally, the progress model runs against this use case. The WWDC session states that the system expects these tasks to make measurable progress, and developers on these forums report tasks being marked stalled and expired after roughly thirty seconds without a progress update, with the system log naming the elapsed time since the last update. If that is accurate, it is decisive for me. A performance session has no progress to report.

Yes. As I said, our UI here isn't a great fit for your use case and you'd need to report "fake" progress at a regular interval. That user experience isn't ideal, but it will work.

I would welcome your correction if I have that wrong, since the cadence figure comes from developer reports rather than documentation, and it is the load-bearing part of my reasoning.

The timing cadence is correct but I don't think it should prevent you from building on this API.

On the audio category: your point about indirect involvement is the one I would like to explore with App Review.

I should have included this link in my previous post; you can find the App Review contact options here.

I have filed the Feedback report you asked for, describing the indeterminate-continuation case: FB24176109.

Perfect, thank you.

If continued processing were to support sessions of unbounded duration without progress semantics, it would suit this well — it is the current shape that does not fit, not the concept.

As a general comment, my goal is to help you ship a product "now". You're absolutely right that the current API is not the ideal solution; however, it's the option that you can implement and ship today.

__
Kevin Elliott
DTS Engineer, CoreOS/Hardware

Correct background mode for an app that must receive CoreMIDI while another app is frontmost
 
 
Q