Android数据备份:带有BackupAgentHelper的动态文件列表

时间:2014-03-13 21:04:32

标签: android file service backup

我想备份我的内部文件。这些是由我的应用程序创建的:随机数量的文件和随机名称。像data1.xml,data7,xml,data13.xml,....

所以我没有任何固定的文件列表。

当MyBackupAgentHelper :: onCreate在onBackup()之前运行时,我可以通过查询文件getApplicationContext()。fileList();

轻松提供文件名。
public class MyBackupAgentHelper extends BackupAgentHelper 
{
  @Override
  public void onCreate() 
  {
    String[] files  = getApplicationContext().fileList();
    FileBackupHelper helper = new FileBackupHelper(this, files );
    addHelper(FILES_BACKUP_KEY, helper);    
  }
...

但是,如果onRestore准备好在卸载/重新安装后运行,我就无法在onCreate中提供文件名,因为这次getApplicationContext()。fileList()显然返回空列表。

所以没有恢复:(

有没有办法恢复所有备份的文件而不指定文件名?只是说,"做到这一切"。

如果没有,我如何在这种情况下使用数据备份?

由于

3 个答案:

答案 0 :(得分:3)

我遇到了同样的问题。令人沮丧的是因为FileBackupHelper几乎完全符合我们的要求。

如果你在这里查看FileBackupHelper的restoreEntity函数的代码

https://android.googlesource.com/platform/frameworks/base.git/+/android-4.2.2_r1/core/java/android/app/backup/FileBackupHelper.java

public void restoreEntity(BackupDataInputStream data) {
    if (DEBUG) Log.d(TAG, "got entity '" + data.getKey() + "' size=" + data.size());
    String key = data.getKey();
    if (isKeyInList(key, mFiles)) {
        File f = new File(mFilesDir, key);
        writeFile(f, data);
    }
}

...您可以看到文件没有被写入的唯一原因是因为它们不在您传递给FileBackupHelper构造函数的列表中。

我的第一个解决方案是覆盖 isKeyInList 以始终返回true。这实际上是有效的,但它让我觉得奇怪,因为isKeyInList有默认保护,我的FileBackupHelper子类不在同一个包中。事实证明,这是一种dalvik vm错误允许这样,所以我不想依赖它(参见Android method with default (package) visibility overriding (shouldn't work, but does - why?)

但后来我意识到我可以抓住我传递给FileBackupHelper构造函数的文件数组,然后将第一个元素更改为始终是要创建的文件的名称。这样就可以在列表中找到它。

class MyFileBackupHelper extends FileBackupHelper
{
    String[] mMyFiles;
    MyFileBackupHelper(Context context, String... files)
    {
        super(context,files);
        mMyFiles = files;
    }

/*  boolean isKeyInList(String key, String[] list) 
    {       
        return true;
    }   */

    public void restoreEntity(BackupDataInputStream data) 
    {
        mMyFiles[0] = data.getKey();
        super.restoreEntity(data);
    }    
}

当然,这也依赖于FileBackupHelper保持相同的实现,它不会复制Files列表。我不确定为什么他们为防止恢复任意文件而遇到这么多麻烦,也许他们会在以后试图阻止这个解决方案。但就目前而言,我称之为好!

哦,是的,使我的解决方案工作的一个额外细节是,您需要确保在您恢复时列表中始终有一个文件。这样总会有一个数组元素0来替换。这就是我在BackupAgent中所做的事情

public class MyBackupAgent extends BackupAgentHelper 
{   
    public void AddFileHelper(String files[])
    {
        FileBackupHelper aHelper = new MyFileBackupHelper(this,files);
        addHelper("userfiles", aHelper);        
    }

    @Override
    public void onBackup(ParcelFileDescriptor oldState, BackupDataOutput data, ParcelFileDescriptor newState) throws IOException
    {
        String[] anArray = GetAllUserFiles(); // I'm not including this function for brevity
        AddFileHelper(anArray);
        super.onBackup(oldState, data, newState);       
    }

    @Override
    public void onRestore(BackupDataInput data, int appVersionCode, ParcelFileDescriptor newState) throws IOException
    {
        AddFileHelper(new String[] { "filename" } );
        super.onRestore(data, appVersionCode, newState);
    }
}

所以你看到我不依赖于onCreate()。相反,我将正确的文件放在onBackup的列表中,我只是在onRestore的列表中放入一个文件名。然后,每次调用父restoreEntity之前,MyFileBackupHelper都会替换该列表中的数组元素0。希望谷歌会让这个解决方案继续在他们的库的未来版本中工作,因为它似乎是一个很好的功能!

答案 1 :(得分:0)

编辑:您无法备份文件夹 - 您需要单独列出文件助手中的文件以备份这些文件。

答案 2 :(得分:0)

我意识到这个问题已经很老了,但是我遇到了一个类似的问题(希望从文件夹中备份任意文件集),而我的解决方案是将所有文件放入一个文件中。压缩文件,然后让FileBackupHelper备份该压缩文件。对于onRestore,恢复.zip文件后,我将文件解压缩回去。这可能不是最佳解决方案,但它似乎对我有用。