Repository navigation
Fix playback stopping when Android backs up the app - #6205
Conversation
|
Claude finished @geekygecko's task in 47s —— View job The manifest change should stop the post-backup SIGKILL on Android 16+. The catch is that the same property also turns off restricted mode for restore. Restore then runs alongside a fully initialised app that holds Room and Blocking
|
| <!-- Stops Android 16+ killing the app (and interrupting playback) after a full backup --> | ||
| <property | ||
| android:name="android.app.backup.PROPERTY_USE_RESTRICTED_BACKUP_MODE" |
There was a problem hiding this comment.
On Android 16+, a user restoring to a new phone can end up with their restored podcasts and settings overwritten or reset, because restore now runs inside the full app process.
This property turns off restricted mode for restore as well as backup. That means PocketCastsApplication.onCreate runs first: Hilt init, Room opening and migrating pocketcasts, and Settings loading au.com.shiftyjelly.pocketcasts_preferences.xml into the SharedPreferences cache. Then the transport replaces those files underneath it. Because the process is no longer killed on unbind (the shouldKillAppOnUnbind path you cite), it keeps running with an open Room connection to the old file and a stale prefs cache. The next apply() writes the pre-restore prefs back over the restored file, and DB writes go to the replaced inode. Step 6 of the test plan probably won't catch this, because the restore usually runs before anything in the app touches prefs or the DB.
Fix: keep the backup benefit but make restore safe. Add a minimal android:backupAgent with android:fullBackupOnly="true" (it stays a full backup with the same rules) and end the process in onRestoreFinished() (exitProcess(0)) so the next launch reads the restored files. Then test restore with the app already running, e.g. bmgr restore <token> au.com.shiftyjelly.pocketcasts while it's in the foreground.
There was a problem hiding this comment.
I completed the restore successfully in my testing, and everything worked as expected.
Project manifest changes for appThe following changes in the --- ./build/reports/diff_manifest/app/release/base_manifest.txt 2026-10-22 01:56:27.893594891 +0000
+++ ./build/reports/diff_manifest/app/release/head_manifest.txt 2026-10-22 01:56:59.132372442 +0000
@@ -100,6 +100,12 @@
android:supportsRtl="false"
android:theme="@style/ThemeDark"
android:usesCleartextTraffic="true" >
+
+ <!-- Stops Android 16+ killing the app (and interrupting playback) after a full backup -->
+ <property
+ android:name="android.app.backup.PROPERTY_USE_RESTRICTED_BACKUP_MODE"
+ android:value="false" />
+
<meta-data
android:name="com.google.android.gms.car.application"
android:resource="@xml/automotive_app_desc" />Go to https://buildkite.com/automattic/pocket-casts-android/builds/20313/canvas?sid=01a16150-2e85-4af9-8df3-23dc798f75e0, click on the |
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
|
Claude finished @geekygecko's task in 17s —— View job The only commit since the last review adds the CHANGELOG entry, so there's nothing new to review. The restore concern is still open. Step 6 runs a restore on a fresh install, before the app has opened Room or loaded Blocking
|
|
Claude finished @geekygecko's task in 14s —— View job The only new commit ( Blocking
|
|
Claude finished @sztomek's task in 14s —— View job The only new commit ( Blocking
|
|
Claude finished @geekygecko's task in 13s —— View job The only new commit ( Blocking
|
Description
On Android 16 and newer, playback no longer stops when the phone runs its automatic backup of Pocket Casts in the background. I managed to repeat this issue using the
adbbackupnowcommand. This could be why alot of people's episodes stop playing.A user reported playback stopping 10 to 20 minutes into a long sleep timer. Their bugreport showed Google's backup transport starting a full-data backup of the app mid-playback, then
BackupManagerServicelogging "Killing agent host process" and SIGKILLing our process, foreground playback service and all. Android restarted the service, but nothing resumed playback, and the in-memory sleep timer was lost. The earlier incidents in the report have the same exit signature, as does PCDROID-555.Android only kills the app after a backup when the backup ran in "restricted mode". Full backups used restricted mode by default, but Android 16 added the
PROPERTY_USE_RESTRICTED_BACKUP_MODEapplication property. Setting it tofalseruns the backup inside our normal process and skips the kill on unbind (seeBackupAgentConnectionManager.shouldKillAppOnUnbindin AOSP).android:backupInForeground="false"is also set explicitly. It's already the default, and it only defers the system's scheduled full-backup job. Backups requested throughrequestBackup()(Google Play services,bmgr backupnow) skip that check, which is why the property is the actual fix.Things reviewers should know:
releasebuild type enables backup, so this only changes release builds.Applicationstartup while Android replaces the database and preferences files. That could overwrite restored data, so restore needs testing before release (step 6 below).Fixes #6204
Linear: https://linear.app/a8c/issue/PCDROID-831/playback-ends-before-end-of-sleep-timer-sporadically
Testing Instructions
Use a release build on an Android 16+ device with backup enabled (
adb shell bmgr enabled).adb shell bmgr backupnow au.com.shiftyjelly.pocketcasts.mainto see playback stop and the process get killed.backupnowagain.Checklist
./gradlew spotlessApplyto automatically apply formatting/linting)modules/services/localization/src/main/res/values/strings.xml