# Guideline 2.5.4 被拒：背景模式遭 Apple 退件

> Guideline 2.5.4：宣告了背景模式卻沒有功能使用它，Apple 就會退件。移除這個鍵，或向審查員展示聲音、位置或通話功能。

原始頁面：[Guideline 2.5.4 被拒：背景模式遭 Apple 退件](https://devoria.fr/zh-hant/blog/guideline-2-5-4-background-mode-rejected)
作者：[Mehdi Azizi](https://devoria.fr/zh-hant/mehdi-azizi)
發布日期：2026-11-04
內容最後修訂：2026-11-04


Guideline 2.5.4 規定背景模式只能用在它原本的用途：聲音、位置、VoIP 通話、完成任務、本機通知。當你的 Info.plist 宣告了其中一種模式，審查員卻找不到任何需要它的功能，就會被退件。**如果沒有東西用到，就移除這個鍵；否則就讓審查員在三十秒內看到這個功能。**

我用 Expo 發布自己的 iOS app。Solys 是我做的小遊戲鬧鐘，它宣告了 audio 模式：我曾經把它移除，後來又因為另一個原因加回去。這篇指南根據 Apple 的官方文字、其他開發者公開的退件案例，以及我自己的專案。想看所有退件原因的總覽，請讀[Apple 為什麼退件你的 app](https://devoria.fr/zh-hant/blog/apple-app-rejection-reasons-real-cases)。

## Guideline 2.5.4 說了什麼？

這條規則只有一句話，位於 [App Review Guidelines](https://developer.apple.com/app-store/review/guidelines/#2.5.4) 第 2 節「Performance」的 2.5「Software Requirements」：「Multitasking apps may only use background services for their intended purposes: VoIP, audio playback, location, task completion, local notifications, etc.」

白話來說：背景服務只能用在它存在的目的上。所以標題才會是「Guideline 2.5.4 - Performance - Software Requirements」。

預設情況下，app 進入背景後就會被暫停。想繼續執行，就要在 Info.plist 的 `UIBackgroundModes` 鍵裡宣告一個或多個模式。[Apple 關於背景模式的文件](https://developer.apple.com/documentation/xcode/configuring-background-execution-modes)要求謹慎使用，因為會耗電，有其他做法時應優先採用。**每個宣告的模式都是一個審查員可以驗證的承諾。**

## 背景模式與它們的預期用途

| 模式                | 鍵                    | 預期用途            |
| ------------------- | --------------------- | ------------------- |
| Audio、AirPlay、PiP | `audio`               | 背景中可聽見的聲音  |
| 位置                | `location`            | 持續定位            |
| VoIP                | `voip`                | 搭配 CallKit 的通話 |
| 背景擷取            | `fetch`               | 定期取得網路內容    |
| 背景處理            | `processing`          | 排程任務            |
| 遠端通知            | `remote-notification` | 推播新內容          |

這張表整理自 Apple 的頁面。在論壇上公開的退件案例中，最常出現的是 `audio`、`location` 和 `voip`。

## 2.5.4 退件訊息是什麼意思？

訊息會點名有問題的模式。以下是開發者在 Apple 論壇公開的兩個例子：

- **Audio**：「Your app still declares support for audio in the UIBackgroundModes key in your Info.plist but did not include features that require persistent audio.」接下來說明 `audio` 鍵是給在背景播放內容的 app 用的，例如音樂播放器。它提供兩條出路：加入這類內容，或移除這個鍵（[論壇討論串](https://developer.apple.com/forums/thread/95216)）。
- **位置**：在一個 [2024 年 12 月的討論串](https://developer.apple.com/forums/thread/771202)中，Apple 除了員工追蹤之外，找不到任何需要持續定位的功能，並表示光是這個用途並不恰當。

我的解讀是：**審查員不會讀你的程式碼，他找的是功能。**他必須能啟動這個功能、把 app 切到背景，然後確認它還在運作。

也有相反的情況。在一個 [2026 年 5 月的討論串](https://developer.apple.com/forums/thread/826849)裡，一款真的有用到 `audio` 模式的朗讀 app 被退了好幾次：審查員一直無法觸發聲音。另一位開發者在裡面寫說，他認為附上影片讓他的案子過關。這是個人經驗，不是 Apple 的規則。

## 你沒加這個鍵，它是從哪裡來的？

用 Expo 的話，是設定外掛（config plugin）在 prebuild 時填寫 Info.plist。**所以背景模式可能在你沒決定的情況下就進了你的二進位檔。**

### expo-audio 外掛的預設設定

[expo-audio 的文件](https://docs.expo.dev/versions/latest/sdk/audio/)寫得很清楚：`enableBackgroundPlayback` 選項預設為 `true`，在 iOS 上會加入 `audio` 模式。所以只要用簡寫形式 `"expo-audio"` 宣告外掛，就等於宣告了這個模式。

我在 TradaZen 第一次送審前重新檢查時就發現了這件事：只有前景的短介面音效，外掛卻是用簡寫宣告的。修正只要改 `app.json`：

```json
{
  "expo": {
    "plugins": [["expo-audio", { "enableBackgroundPlayback": false }]]
  }
}
```

其他套件也會用各自的方式加入模式。[expo-location](https://docs.expo.dev/versions/latest/sdk/location/) 的 `isIosBackgroundLocationEnabled` 選項只有在你啟用時才會加入 `location`。[expo-background-task](https://docs.expo.dev/versions/latest/sdk/background-task/) 則是一安裝，就會在 prebuild 時加入 `processing`。

### 保留舊鍵的 ios/ 資料夾

第二個陷阱，是我 2026 年 7 月在 Solys 上踩到的。我已經從 `app.json` 移除了 `audio`，但這個鍵還留在之前產生的 `ios/Solys/Info.plist` 裡。不加 `--clean` 的 prebuild 會修改這個專案而不是重建，外掛只會加入鍵，從來不會移除。本機建置就會把它帶進去。如果 `ios/` 被 git 忽略（我就是這樣），雲端的 EAS 建置會從全新的 prebuild 開始。

每次建置前，我都會檢查實際會送出去的內容：

```bash
npx expo config --type introspect --json | grep -o '"UIBackgroundModes":\[[^]]*\]'
npx expo prebuild --clean --platform ios
```

第一行列出 prebuild 會寫進 Info.plist 的模式。第二行會刪除 `ios/` 資料夾，為本機建置重建原生專案。在 Solys 上，第一行顯示 `"UIBackgroundModes":["audio"]`，在 TradaZen 上什麼都沒有：兩者都是我要的結果。

新增或移除模式會改動 Info.plist，也就是二進位檔：**需要新的建置，遠端更新不夠。**[EAS Update 的文件](https://docs.expo.dev/eas-update/introduction/)把這類變更歸在需要新二進位檔的類別，跟 [ITMS-90683](https://devoria.fr/zh-hant/blog/itms-90683-missing-purpose-string-expo) 一樣。

## Solys：有正當理由宣告 audio 模式

Solys 是鬧鐘，但 `audio` 模式不是用來讓鬧鐘響的：**鈴聲是透過 AlarmKit**，這是 Apple 從 iOS 26 開始提供的鬧鐘服務（[AlarmKit 文件](https://developer.apple.com/documentation/alarmkit)）。響鈴的是系統而不是 app，就算在靜音模式也一樣。

這個鍵的歷程如下，因為背後的思路比那一行設定更重要：

1. **2026 年 7 月底，我把它移除。**沒有任何東西在背景播放聲音：小遊戲的音效都在前景，鬧鐘也不依賴 app。
2. **兩天後，我把它加回來**，因為加了夜間聆聽功能。這個選項會用麥克風錄下你夜裡的聲音，並在 iPhone 上分析。螢幕鎖定時錄音必須持續，而 expo-audio 的文件指出，背景錄音選項同樣會加入 `audio` 模式。

理由的性質變了：**這個模式是用來錄音，不是播放。**app 裡看得到三道防線：

- 聆聽是預設關閉的選項，從設定或睡前儀式中開啟；
- 它有自己的同意畫面，符合 [規則 2.5.14](https://developer.apple.com/app-store/review/guidelines/#2.5.14) 對所有錄音的要求，而且資料完全不會離開手機；
- 麥克風會在鬧鐘響前十分鐘關閉，讓聆聽和鈴聲永遠不會互相干擾。

我不能保證審查員每次都會接受這個宣告。但每個元素是做什麼用的、在哪裡看得到，我都說得出來。

### 讓 app 保持清醒的鬧鐘

在 AlarmKit 出現之前，第三方鬧鐘 app 沒辦法像 Apple 的鬧鐘那樣響鈴。所以有些函式庫會讓 app 保持清醒：Flutter 套件 [alarm2](https://pub.dev/packages/alarm2) 的文件描述了一個一直跑到鬧鐘響起的靜音音訊播放器。但靜音的聲音根本聽不到。**從 iOS 26 起，AlarmKit 讓這種繞路變得沒必要。**

## 保留還是移除模式：判斷表

| 你的情況       | 該怎麼做                |
| -------------- | ----------------------- |
| 前景的短音效   | 移除 `audio`            |
| 音樂或有聲書   | 保留，並展示出來        |
| 長時間錄音     | 保留＋取得同意          |
| 鬧鐘或計時器   | AlarmKit（iOS 26）      |
| 偶爾需要位置   | 重大位置變更            |
| 不急的同步     | `fetch` 或 `processing` |
| 語音或視訊通話 | `voip` 搭配 CallKit     |

關於位置，Apple 的頁面提到重大位置變更服務可以取代 `location` 模式。

## 2.5 的其他條款：2.5.1 與 2.5.2

### 2.5.1：公開 API，框架用在該用的地方

「Apps may only use public APIs and must run on the currently shipping OS.」app 只能使用公開 API、要能在目前的系統版本上執行，並淘汰已棄用的東西。跟 2.5.4 一樣，每個框架都要用在它的預期用途上，並在描述中提到：HealthKit 用於健康，HomeKit 用於智慧家庭。如果某個函式庫呼叫了私有 API，被退件的是你的 app。

### 2.5.2：不能下載會改變 app 的程式碼

app 必須在自己的套件內自給自足。它不能「download, install, or execute code which introduces or changes features or functionality of the app」。只有教人寫程式的教育類 app 有有限的例外，而且程式碼必須完全可見、可由使用者修改。

用 Expo 的話，這牽涉到 EAS Update，它的文件提醒更新必須遵守 App Store 規則。**遠端更新只拿來修 bug，絕對不要用來推出審查員沒看過的功能。**跟審查有關的修正要走新的建置，就像我在 [guideline 2.1](https://devoria.fr/zh-hant/blog/app-store-guideline-2-1-rejection-fix) 指南裡說明的那樣。

## 怎麼回覆 2.5.4 退件？

對話在你 app 的 App Review 區塊進行，你在那裡[回覆 App Review 的訊息](https://developer.apple.com/help/app-store-connect/manage-submissions-to-app-review/reply-to-app-review-messages/)。分兩種情況：

- **模式沒有用處**：移除它、重新建置、檢查 introspection 結果，然後用兩句話回覆。
- **模式支撐真正的功能**：附上確切的操作路徑和一段短影片回覆，並在每個版本的審查備註中放入這段文字。

這是我會用的範本，請自行調整（如果你的 app 沒有鬧鐘，就刪掉鬧鐘那段）：

```text
Hello,

The "audio" background mode is used only by [feature], an
optional feature that [records / plays] audio while the
device is locked. It is off by default.

How to test:
1. Open [screen] and turn on [feature].
2. Accept the microphone permission if asked.
3. Tap [button], then lock the device.
   [What the reviewer will hear or see.]

Our alarm does not use this mode: it is scheduled with
AlarmKit and rings through the system.

Attached: a short screen recording of these steps.

Best regards,
```

## 送審前的 2.5.4 檢查清單

- Expo 的 introspection 只顯示你要的模式，而且每個模式對應的功能你都說得出來。
- 會預設加入模式的外掛（例如 expo-audio），都沒有用簡寫形式宣告。
- 本機的 `ios/` 資料夾沒有殘留舊鍵，或者你是從乾淨的 prebuild 編譯。
- 功能能快速觸發、不需要隱藏設定，審查備註也寫明每個模式的用途和測試方式。
- 所有錄音都要取得明確同意，並顯示可見的指示。權限請求的規則請看 [guideline 5.1.1](https://devoria.fr/zh-hant/blog/guideline-5-1-1-app-store-rejection-fix) 指南。
- 如果是鬧鐘，鈴聲要透過 AlarmKit，而不是由 app 播放聲音。

## 送出前檢查你的資料

[Review Kit](https://devoria.fr/zh-hant/kits/app-review) 收錄了我的送審前檢查清單、給審查員的備註範本，以及會檢查你專案的 Claude Code skills。想要真人幫你看，[跟我預約一小時](https://devoria.fr/zh-hant/coaching)：我們透過視訊一起看 Apple 的訊息和你的 Info.plist。完整流程請看[被 Apple 退件的 app](https://devoria.fr/zh-hant/expertise/app-rejected-by-apple) 頁面。

正在準備你的第一次上架嗎？[做免費診斷](https://devoria.fr/zh-hant/diagnostic)：它會幫你把步驟排好順序，並寄給你我的 Apple 防退件檢查清單。

沒有人能保證 Apple 會接受你的 app。但一個理由充分的背景模式，三十秒就能說清楚。

## 常見問題

### 「Guideline 2.5.4 - Performance - Software Requirements」是什麼意思？

這是 Apple 認為你 Info.plist 中的某個背景模式沒有用在預期用途時的退件標題。訊息會點名該模式，並建議你展示使用它的功能，或移除這個鍵。

### 2.5.4 退件後需要重新建置嗎？

如果你移除或修改了模式，需要：這個鍵在 Info.plist 裡，也就是在二進位檔裡。如果模式有正當理由，附上確切操作路徑和影片的回覆可能就夠了。

### 可以為了幾個介面音效保留 audio 模式嗎？

不行。在前景播放的短音效不需要它。用 Expo 的話，在 expo-audio 外掛中把 `enableBackgroundPlayback` 設為 `false`。

### 鬧鐘 app 需要 audio 模式嗎？

如果它使用 iOS 26 起提供的 AlarmKit，響鈴就不需要：播放鬧鐘的是系統。在 Solys 上，`audio` 模式是用於夜間聆聽，在螢幕鎖定時錄音。

### 我什麼都沒宣告，為什麼 Apple 引用 2.5.4？

可能是某個外掛幫你宣告了：expo-audio 預設會加入 `audio` 模式，舊的 `ios/` 資料夾也可能保留你已從設定中移除的鍵。用 `npx expo config --type introspect` 檢查。


## 你的專案

[Review Kit](https://devoria.fr/zh-hant/kits/app-review)：我的 App Store 審查檢查清單、我被 Apple 退件後的修正、Google Play 檢查清單，以及三個 Claude Code skill。$1,749。

[iOS & Android Kit](https://devoria.fr/zh-hant/kits/ios)：用 Claude Code 打造你的 iPhone 和 Android App：我自己 App 的起始程式碼、上架商店的完整流程，以及所有套件。$3,599。

[診斷：你離自己的 iPhone App 還差什麼](https://devoria.fr/zh-hant/diagnostic)：7 個問題，60 秒：找出真正卡住你發布 iPhone App 的原因，拿到你的 4 步驟路線，以及最適合你的套件。
