The usual cause of this is inducing a manual restore "the wrong way." This is very poorly documented, I'm afraid, but there are different ways of invoking "bmgr restore", one of which will cause exactly the problem you describe.
(The problem, specifically, is that full-data backup/restore operations currently require that the app be launched with neither its content providers nor any app-defined Application subclass instantiated; instead, you run with a base-class Application instance. Trying to cast back to your declared subclass throws ClassCastException as you might imagine.)
In the normal course of things, your app is killed following restore. HOWEVER, if you trigger the restore like this:
adb shell bmgr restore PACKAGE
this does not happen. That particular invocation syntax runs a "my app wants to restore its data 'live' right now; do not kill me before or after" code path, the one that you get via BackupManager.requestRestore()
. In this code path the app is intentionally not killed following restore. It's an artifact of the time when key/value was the only backup/restore paradigm, and in that paradigm there are no such Application subclass issues etc.
You need to make sure that when you trigger a restore via bmgr, you are using the full syntax:
adb shell bmgr restore TOKEN PACKAGE
This syntax invokes the complete restore-at-install code path, the one that will tear down your app following the restore specifically to avoid trying subsequent execution with a base-class Application.
'TOKEN' is the identifier of the dataset containing the data you wish to restore. If you are using the local debugging transport, then TOKEN is always "1". If you are using cloud backup, then it will be the device's own current backup dataset identifier if there is one, or the ancestral dataset if the device has not generated one itself. You can see these in the output of
adb shell dumpsys backup | egrep 'Current:|Ancestral:'
The dataset's identifying TOKEN is the hex string given there.