向后兼容的BackupAgent

Eri*_*Kok 6 reflection android backwards-compatibility android-backup-service

我正在考虑使用自Android 2.2以来可用的新备份API,但需要保持向后兼容性(准确地说是1.5).

文档说明:

备份服务和必须使用的API仅在运行API Level 8(Android 2.2)或更高版本的设备上可用,因此您还应将android:minSdkVersion属性设置为"8".但是,如果在应用程序中实现正确的向后兼容性,则可以为运行API级别8或更高级别的设备支持此功能,同时保持与旧设备兼容.

我确实targetSdkVersion使用级别3 构建了8 级minSdkVersion并尝试使用包装类(使用反射)来克服如果实现扩展不存在的类的类,应用程序将无法运行的问题.

问题在于:由于我们自己没有对BackupHelper班级进行实际调用,因此如果班级确实存在,我们就无法提前检查.(正如使用checkAvailable()方法在Android向后兼容性文档中所解释的那样.)因此,将实例化类并将其强制转换为BackupAgent.但是,由于我们使用反射,它实际上不会覆盖BackupAgent,并且在请求备份时在运行时发生异常:

java.lang.RuntimeException: Unable to create BackupAgent org.transdroid.service.BackupAgent: java.lang.ClassCastException: org.transdroid.service.BackupAgent
Run Code Online (Sandbox Code Playgroud)

以下是我向后兼容的方法BackupAgent:http://code.google.com/p/transdroid/source/browse/#svn/trunk/src/org/transdroid/service其中BackupAgent.java是'常规'BackupAgentHelper -extending类和BackupAgentHelperWrapper是基于反射的包装类.

有人成功实现了BackupAgent向后兼容性吗?

Mik*_*ryn 10

作为替代方案,您可以使用纯反射与BackupManager通信:

public void scheduleBackup() {
    Log.d(TAG, "Scheduling backup");
    try {
        Class managerClass = Class.forName("android.app.backup.BackupManager");
        Constructor managerConstructor = managerClass.getConstructor(Context.class);
        Object manager = managerConstructor.newInstance(context);
        Method m = managerClass.getMethod("dataChanged");
        m.invoke(manager);
        Log.d(TAG, "Backup requested");
    } catch(ClassNotFoundException e) {
        Log.d(TAG, "No backup manager found");
    } catch(Throwable t) {
        Log.d(TAG, "Scheduling backup failed " + t);
        t.printStackTrace();
    }
}
Run Code Online (Sandbox Code Playgroud)

将android:backupAgent直接指向v2.2类; 它永远不会加载到v2.2之前的VM上,因此不存在任何链接问题.


Pet*_*rdk 7

我不明白你为什么遇到这个问题.

我有同样的问题:我想用支持1.5(API 3)的应用程序支持备份.

创建我的BackupAgentHelper类没有问题,因为该类永远不会从我自己的代码中调用,而是从BackupManager系统本身调用.因此我不需要包装它,我不明白为什么你应该这样做:

 public class MyBackupAgentHelper extends BackupAgentHelper {
 @override onCreate()
 { 
       \\do something usefull
 }
Run Code Online (Sandbox Code Playgroud)

但是,您确实希望运行备份,为此需要在BackupManager.dataChanged()数据发生更改时调用,并且您希望通知系统备份它(使用您的BackupAgentBackupAgentHelper).

您需要包装该类,因为您从应用程序代码中调用它.


public class WrapBackupManager {
private BackupManager wrappedInstance;

static 
{
    try
    {
        Class.forName("android.app.backup.BackupManager");
    }
    catch (Exception e)
    {
        throw new RuntimeException(e);
    }
}
public static void checkAvailable() {}

public void dataChanged()
{
    wrappedInstance.dataChanged();
}

public WrapBackupManager(Context context)
{
    wrappedInstance = new BackupManager(context);
}

}
Run Code Online (Sandbox Code Playgroud)

然后,在更改首选项或保存某些数据时,可以从代码中调用它.我的应用中的一些代码:


private static Boolean backupManagerAvailable = null;

    private static void postCommitAction() {


        if (backupManagerAvailable == null) {
            try {
                WrapBackupManager.checkAvailable();
                backupManagerAvailable = true;
            } catch (Throwable t) {
                backupManagerAvailable = false;
            }
        }

        if (backupManagerAvailable == true) {
            Log.d("Fretter", "Backup Manager available, using it now.");
            WrapBackupManager wrapBackupManager = new WrapBackupManager(
                    FretterApplication.getApplication());
            wrapBackupManager.dataChanged();
        } else {
            Log.d("Fretter", "Backup Manager not available, not using it now.");
        }
Run Code Online (Sandbox Code Playgroud)

所以,希望这对你有用!

(如果adb shell bmgr run每次想要模拟实际系统启动的backupprocess时都要调用它,那么在重新安装应用程序时应该正确备份和恢复.)