Cannot restore an adb backup due to a tarball with a broken header


Question

I have two devices that have Android 5.0.2 and 6.0.1 respectively. I would like to migrate some non-cloud apps from the device with the older Android version to the new one using adb. The backing up command is simple:



adb backup -apk -f foo.bar.baz.ab foo.bar.baz


Now, after connecting the device with the newer Android version, the following command is expected to work:



adb restore foo.bar.baz.ab


Unfortunately it isn't. As usual, the restoring process fails silently just reporting that the restoring process is ended. Actually nothing really happens. Here are the logs:



adb logcat -s BackupManagerService



08-27 01:02:44.100 1300 2300 I BackupManagerService: Beginning full restore...

08-27 01:02:44.100 1300 2300 D BackupManagerService: Starting restore confirmation UI, token=1956031088

08-27 01:02:44.120 1300 2300 D BackupManagerService: Waiting for full restore completion...

08-27 01:02:45.650 1300 2450 D BackupManagerService: acknowledgeFullBackupOrRestore : token=1956031088 allow=true

08-27 01:02:45.660 1300 18181 I BackupManagerService: --- Performing full-dataset restore ---

08-27 01:02:45.680 1300 18181 I BackupManagerService: Package foo.bar.baz not installed; requiring apk in dataset

08-27 01:02:45.680 1300 18181 D BackupManagerService: APK file; installing

08-27 01:02:45.680 1300 18181 D BackupManagerService: Installing from backup: foo.bar.baz

08-27 01:02:45.690 1300 18181 E BackupManagerService: Unable to transcribe restored apk for install

08-27 01:02:45.690 1300 18181 E BackupManagerService: Parse error in header: Invalid number in header: 'я╛В' for radix 8

08-27 01:02:45.710 1300 18181 W BackupManagerService: io exception on restore socket read

08-27 01:02:45.710 1300 18181 W BackupManagerService: java.io.IOException: Invalid number in header: 'я╛В' for radix 8

08-27 01:02:45.710 1300 18181 W BackupManagerService: at com.android.server.backup.BackupManagerService$PerformAdbRestoreTask.extractRadix(BackupManagerService.java:7380)

08-27 01:02:45.710 1300 18181 W BackupManagerService: at com.android.server.backup.BackupManagerService$PerformAdbRestoreTask.readTarHeaders(BackupManagerService.java:7179)

08-27 01:02:45.710 1300 18181 W BackupManagerService: at com.android.server.backup.BackupManagerService$PerformAdbRestoreTask.restoreOneFile(BackupManagerService.java:6396)

08-27 01:02:45.710 1300 18181 W BackupManagerService: at com.android.server.backup.BackupManagerService$PerformAdbRestoreTask.run(BackupManagerService.java:6254)

08-27 01:02:45.710 1300 18181 W BackupManagerService: at java.lang.Thread.run(Thread.java:818)

08-27 01:02:45.710 1300 2300 I BackupManagerService: Full restore processing complete.

08-27 01:02:45.720 1300 18181 D BackupManagerService: Full restore pass complete.




It looks somewhat strange that the same backup format cannot be restored on a newer device. I've also tried to repack the underlying tarball using nelenkov/android-backup-extractor preserving the same file order (tar cvf ... -T files.lst) hoping that the broken header gets repaired. No luck.



What does cause such a backup/restore behavior and how do I resolve the issue to migrate the application from the older device to the newer one? Any help is highly appreciated and thanks in advance.




  • Android Debug Bridge version 1.0.31

  • LG Optimus E975, Android 5.0.2, CyanogenMod 12-2015...

  • Samsung Galaxy S5, Android 6.0.2, flashed to a newer Sprint stock firmware (initially Android 5.0.x earlier)


Answer

After a whole day of various experiments with another tools like TitaniumBackup (neither worked nice, TB was only able to restore APKs, not data) I've figured out that specifying the -apk key was the problem. Simply omitting the flag during a backup operation makes it fully restorable.



So my new backup/restore plan became as follows:




  • device 1: backup data only

  • device 2: backup APK+data retaining the APK only later (requires nelenkov/android-backup-exractor by Nikolay Elenkov; can be easily built using JDK 1.8.x and Gradle 2.7 (couldn't build it using Gradle 2.7+ and Gradle 3.0+) with simple gradle command)

  • device 2: restore the APK using adb install

  • device 2: restore the data using adb restore



Here are the scripts:



backup.sh





#!/bin/bash

set -e

PACKAGE=$1

if [ -z "$PACKAGE" ]; then
echo no package specified
exit
fi

echo ">>> Backing up $PACKAGE data..."
adb backup -f "$PACKAGE".DATA.ab $PACKAGE

echo ">>> Backing up $PACKAGE APK..."
adb backup -apk -f "$PACKAGE".APK.ab $PACKAGE

echo ">>> Extracting APK..."
java -jar abe-all.jar unpack "$PACKAGE".APK.ab "$PACKAGE".APK.ab.tar
rm "$PACKAGE".APK.ab
APK_FILENAME=$(basename $(tar tf "$PACKAGE".APK.ab.tar | grep '^apps/'"$PACKAGE"'/a/'))
tar xvf "$PACKAGE".APK.ab.tar -C ./ "apps/$PACKAGE/a/$APK_FILENAME" --strip-components=3
mv "$APK_FILENAME" "$PACKAGE".apk
rm "$PACKAGE".APK.ab.tar

echo
echo "*************"
echo "*** Done ***"
echo "*************"


This script requires a package name as the input parameter and stores an APK and its data as foo.bar.apk and foo.bar.DATA.ab respectively. I also implemented it as a twice-backup script (a device asks for making a backup two times) because I didn't want to re-pack underlying tarballs preserving the original file order just making sure that the DATA.ab file is in its original state.



restore.sh





#!/bin/bash

set -e

PACKAGE=$1

if [ -z "$PACKAGE" ]; then
echo no package specified
exit
fi

echo ">>> Installing $PACKAGE APK..."
adb install -r $PACKAGE.apk

echo ">>> Restoring $PACKAGE data..."
adb restore $PACKAGE.DATA.ab

echo
echo "*************"
echo "*** Done ***"
echo "*************"


This script simply installs an APK on a target device and restores its data. The only input parameter is the application package name.



So the overall backup/restore process is:




  • Connect device #1

  • Execute backup.sh passing an application package name

  • Click "Backup..." on the device #1 (one will be asked two times for the data and APK+data backups respectively)

  • Repeat the previous two steps for other packages if necessary

  • Disconnect the device #1 and connect the device #2

  • Execute restore.sh passing an application package name

  • Click "Restore..." on the device #2 once asked

  • Repeat the previous two steps for other packages if necessary


Topics


2D Engines   3D Engines   9-Patch   Action Bars   Activities   ADB   Advertisements   Analytics   Animations   ANR   AOP   API   APK   APT   Architecture   Audio   Autocomplete   Background Processing   Backward Compatibility   Badges   Bar Codes   Benchmarking   Bitmaps   Bluetooth   Blur Effects   Bread Crumbs   BRMS   Browser Extensions   Build Systems   Bundles   Buttons   Caching   Camera   Canvas   Cards   Carousels   Changelog   Checkboxes   Cloud Storages   Color Analysis   Color Pickers   Colors   Comet/Push   Compass Sensors   Conferences   Content Providers   Continuous Integration   Crash Reports   Credit Cards   Credits   CSV   Curl/Flip   Data Binding   Data Generators   Data Structures   Database   Database Browsers   Date &   Debugging   Decompilers   Deep Links   Dependency Injections   Design   Design Patterns   Dex   Dialogs   Distributed Computing   Distribution Platforms   Download Managers   Drawables   Emoji   Emulators   EPUB   Equalizers &   Event Buses   Exception Handling   Face Recognition   Feedback &   File System   File/Directory   Fingerprint   Floating Action   Fonts   Forms   Fragments   FRP   FSM   Functional Programming   Gamepads   Games   Geocaching   Gestures   GIF   Glow Pad   Gradle Plugins   Graphics   Grid Views   Highlighting   HTML   HTTP Mocking   Icons   IDE   IDE Plugins   Image Croppers   Image Loaders   Image Pickers   Image Processing   Image Views   Instrumentation   Intents   Job Schedulers   JSON   Keyboard   Kotlin   Layouts   Library Demos   List View   List Views   Localization   Location   Lock Patterns   Logcat   Logging   Mails   Maps   Markdown   Mathematics   Maven Plugins   MBaaS   Media   Menus   Messaging   MIME   Mobile Web   Native Image   Navigation   NDK   Networking   NFC   NoSQL   Number Pickers   OAuth   Object Mocking   OCR Engines   OpenGL   ORM   Other Pickers   Parallax List   Parcelables   Particle Systems   Password Inputs   PDF   Permissions   Physics Engines   Platforms   Plugin Frameworks   Preferences   Progress Indicators   ProGuard   Properties   Protocol Buffer   Pull To   Purchases   Push/Pull   QR Codes   Quick Return   Radio Buttons   Range Bars   Ratings   Recycler Views   Resources   REST   Ripple Effects   RSS   Screenshots   Scripting   Scroll Views   SDK   Search Inputs   Security   Sensors   Services   Showcase Views   Signatures   Sliding Panels   Snackbars   SOAP   Social Networks   Spannable   Spinners   Splash Screens   SSH   Static Analysis   Status Bars   Styling   SVG   System   Tags   Task Managers   TDD &   Template Engines   Testing   Testing Tools   Text Formatting   Text Views   Text Watchers   Text-to   Toasts   Toolkits For   Tools   Tooltips   Trainings   TV   Twitter   Updaters   USB   User Stories   Utils   Validation   Video   View Adapters   View Pagers   Views   Watch Face   Wearable Data   Wearables   Weather   Web Tools   Web Views   WebRTC   WebSockets   Wheel Widgets   Wi-Fi   Widgets   Windows   Wizards   XML   XMPP   YAML   ZIP Codes