为什么备份相关的过程可能导致应用程序的onCreate不执行? [英] Why backup related process might cause Application's onCreate is not executed?
问题描述
通常具有Application
类如下
public class WeNoteApplication extends MultiDexApplication {
public static WeNoteApplication instance() {
return me;
}
@Override
public void onCreate() {
super.onCreate();
me = this;
在正常情况下,总是在入口点Activity
的onCreate之前调用Application
的onCreate
.
During normal circumstance, Application
's onCreate
will always be called before entry point Activity
's onCreate.
public class MainActivity extends AppCompatActivity {
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
// Normally, it will NOT be null.
android.util.Log.i("CHEOK", "WeNoteApplication -> " + WeNoteApplication.instance());
但是,如果我在应用启动时运行以下命令
However, if I run the following command while the app is launched
c:\yocto>adb shell bmgr restore com.yocto.wenote
restoreStarting: 1 packages
onUpdate: 0 = com.yocto.wenote
restoreFinished: 0
done
该应用程序将关闭.如果是,我点击应用程序图标以再次启动.这就是发生的情况
The app will be closed. If, I tap on the app icon to launch again. This is what happens
-
Application
的onCreate
未执行! -
Activity
的onCreate
被执行,而WeNoteApplication.instance()
是null
Application
'sonCreate
is not executed!Activity
'sonCreate
is executed, andWeNoteApplication.instance()
isnull
我看一些Google的Android源代码(例如WorkManager
)
I look at some Google's Android source code (WorkManager
for instance)
https://github.com/googlecodelabs/android-workmanager/issues/80
他们在评论中指出
// 1. The app is performing an auto-backup. Prior to O, JobScheduler could erroneously
// try to send commands to JobService in this state (b/32180780). Since neither
// Application#onCreate nor ContentProviders have run,...
似乎,如果涉及到备份相关的过程,则Application
的onCreate
将不会执行!
It seems that, if backup related process is involved, Application
's onCreate
will not be executed!
为什么会这样呢?这种行为曾经在某些地方被记录过吗?
Why it is so? Is this behavior ever documented some where?
https://issuetracker.google.com/issues/138423608
https://github.com/yccheok/AutoBackup-bug
推荐答案
您可以使用此替代方法来绕过您的问题.
You can bypass your issue with this workaround.
其背后的想法是创建一个自定义BackupAgent
来接收onRestoreFinished
事件的通知,然后终止您的进程,因此,下次您打开该应用程序时,系统将创建您的自定义Application类.
The idea behind this is to create a custom BackupAgent
to receive notification of onRestoreFinished
event and then kill your process, so the next time you will open the app the system will create your custom Application class.
通常使用自定义BackupAgent
强制您实现用于键值备份的抽象方法onBackup
和onRestore
.幸运的是,如果您在清单中指定android:fullBackupOnly
,则系统将改为使用基于文件的自动备份,如
Usually using a custom BackupAgent
force you to implement the abstract methods onBackup
and onRestore
, which are used for key-value backup. Luckily if you specify android:fullBackupOnly
in the manifest, the system will use the file-based Auto Backup instead, as explained here.
首先,创建自定义BackupAgent
:
package com.yocto.cheok;
import android.app.ActivityManager;
import android.app.backup.BackupAgent;
import android.app.backup.BackupDataInput;
import android.app.backup.BackupDataOutput;
import android.content.Context;
import android.os.ParcelFileDescriptor;
import android.os.Process;
import java.util.List;
public class CustomBackupAgent extends BackupAgent {
private Boolean isRestoreFinished = false;
@Override
public void onBackup(ParcelFileDescriptor oldState, BackupDataOutput data, ParcelFileDescriptor newState) {
//NO-OP - abstract method
}
@Override
public void onRestore(BackupDataInput data, int appVersionCode, ParcelFileDescriptor newState) {
//NO-OP - abstract method
}
@Override
public void onRestoreFinished() {
super.onRestoreFinished();
isRestoreFinished = true;
}
@Override
public void onDestroy() {
super.onDestroy();
if (isRestoreFinished) {
ActivityManager activityManager = (ActivityManager) getSystemService(Context.ACTIVITY_SERVICE);
if (activityManager != null) {
final List<ActivityManager.RunningAppProcessInfo> runningServices = activityManager.getRunningAppProcesses();
if (runningServices != null &&
runningServices.size() > 0 &&
runningServices.get(0).processName.equals("com.yocto.cheok")
) {
Process.killProcess(runningServices.get(0).pid);
}
}
}
}
}
然后将android:backupAgent="com.yocto.cheok.CustomBackupAgent"
和android:fullBackupOnly="true"
添加到Android清单中:
then add android:backupAgent="com.yocto.cheok.CustomBackupAgent"
and android:fullBackupOnly="true"
to the Android manifest:
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="com.yocto.cheok">
<application
android:name="com.yocto.cheok.CheokApplication"
android:allowBackup="true"
android:backupAgent="com.yocto.cheok.CustomBackupAgent"
android:fullBackupContent="@xml/my_backup_rules"
android:fullBackupOnly="true"
android:icon="@mipmap/ic_launcher"
android:label="@string/app_name"
android:roundIcon="@mipmap/ic_launcher_round"
android:supportsRtl="true"
android:theme="@style/AppTheme">
<activity android:name="com.yocto.cheok.MainActivity">
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>
</application>
</manifest>
下次还原后,您将在应用程序中午餐,您将获得:
Next time you will lunch the app after a restore you will get:
2019-07-28 22:25:33.528 6956-6956/com.yocto.cheok I/CHEOK: CheokApplication onCreate
2019-07-28 22:25:33.642 6956-6956/com.yocto.cheok I/CHEOK: In MainActivity, CheokApplication = com.yocto.cheok.CheokApplication@7b28a29
这篇关于为什么备份相关的过程可能导致应用程序的onCreate不执行?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!