6

Been testing the new Android 6 auto backup/restore function, and run into a problem with my app crashing immediately after a restore. Further investigation revealed that the Application.onCreate() initialization method was not being called before the main Activity.onCreate() method. This strikes me as a likely bug in the new autorestore logic. But I thought I would ask for advice here before reporting it as an official bug.

The sequence of events I go through is

  1. Run the app, always open a main activity window.
  2. Force a backup of app data by entering

    adb shell bmgr fullbackup net.anei.cadpage

  3. Use the app manager to force close the app and to clear all app and cache data
  4. Restore app information with

    adb shell bmgr restore

  5. Manually launch the app

Resulting logs show that the Activity.onCreate() method is called before the Application.onCreate() is. The app crashes because some critical initialization was not performed by the Application.onCreate() method.

Is there something obvious that I am missing???

FWIW, launching the app a second time after the crash works perfectly.

kencorbin
  • 1,958
  • 1
  • 20
  • 18

1 Answers1

3

It's actually intentional, though intrusive.

For full-data backup and restore operations, the package is launched with a base class Application instance, not your manifest-declared subclass. This is because, unfortunately, many apps open files or databases via Application subclasses, and this blocks the ability of the backup machinery to correctly read/write the underlying files. Similarly, your app's content providers are not automatically instantiated for full-data backup/restore operations. The app process is then destroyed following the operation, because of course your app cannot continue to run normally without its expected Application subclass or content providers.

You also don't say exactly what command you're using to perform a test restore, but I suspect you're using the bmgr command with this syntax:

adb shell bmgr restore PACKAGE

This doesn't do what you expect. In particular, it invokes the code path that happens when your app calls BackupManager.requestRestore(observer). In this specific code path, the app is NOT shut down following the restore operation, because the app has asked to observe the operation itself. This means that you're left with the app process still running but with a base class Application. It's a power-user API that is pretty much only safe when the app uses the original key/value backup API. You need to test instead using the other bmgr syntax:

adb shell bmgr restore TOKEN PACKAGE

where TOKEN is the identifier for which dataset should be used. At least on the most recent versions of the OS you can see the current and ancestral dataset tokens in the output of adb shell dumpsys backup.

This all needs to be better documented and made less surprising.

Subclassing Application is generally discouraged; this is one reason. Try to use your own lazy-init statics instead of subclassing Application.

Jing Li
  • 14,547
  • 7
  • 57
  • 69
ctate
  • 1,379
  • 10
  • 11
  • What is the expected behaviour when installing the app using "Automatic restore"? From some cursory testing it appears that the behaviour on Android 7 is as described above - the app will be launched with a base class Application and then the process is destroyed and relaunched normally once the restore is complete. On Android 6.0 however, the process is not shut down, leaving the app running with the base class Application. – user3615737 Nov 24 '16 at 16:00
  • 1
    It's possible that there is a bug in Android 6 such that it fails to kill the base-Application process instance after the restore is performed? It's also possible that it is an OEM-specific bug, of course; in general try to reproduce things on Nexus/Pixel devices as well as other OEM's devices when possible. – ctate Nov 28 '16 at 21:00
  • I've seen this happen on a Nexus 5 running Android 6.0. It works correctly on a Pixel C running Android 7.0 – user3615737 Dec 01 '16 at 12:37