2

I am using the Google Backup API for SharedPreferences as described here:

http://developer.android.com/guide/topics/data/backup.html#RequestingRestore

When using bmgr, as described here: http://developer.android.com/tools/help/bmgr.html

I do get the log messages for onRestore an onBackup methods, but in onRestore I get this line:

06-06 11:24:16.546: D/backup_data(24615): SKIP_PADDING FAILED at line 332

The only reference for it is here: https://github.com/comex/frash/blob/master/utils/utils/BackupData.cpp

And no input is read.

My Helper class:

public class NoteBackupAgent extends BackupAgentHelper {

    public static final Object[] DATA_LOCK = new Object[0];
    private static final String PREFS_BACKUP_KEY = Const.ENTRY_PREFS;

    @Override
    public void onBackup(ParcelFileDescriptor oldState, BackupDataOutput data,
            ParcelFileDescriptor newState) throws IOException {

        Log.d(toString(), "########### onBackup() " + oldState.getStatSize());

        synchronized (DATA_LOCK) {
            super.onBackup(oldState, data, newState);
        }
    }

    @Override
    public void onCreate() {
        SharedPreferencesBackupHelper preferencesHelper = new SharedPreferencesBackupHelper(this,
                getPackageName() + "_preferences");
        Toast.makeText(getApplicationContext(), "onCreate", Toast.LENGTH_LONG).show();
        addHelper(PREFS_BACKUP_KEY, preferencesHelper);

    }

    @Override
    public void onRestore(BackupDataInput data, int appVersionCode, ParcelFileDescriptor newState)
            throws IOException {

        synchronized (DATA_LOCK) {
            //super.onRestore(data, appVersionCode, newState);

            // There should be only one entity, but the safest
            // way to consume it is using a while loop
            StringBuilder total = new StringBuilder();

            while (data.readNextHeader()) {
                String key = data.getKey();
                int dataSize = data.getDataSize();

                // If the key is ours (for saving top score). Note this key was used when
                // we wrote the backup entity header
                if (PREFS_BACKUP_KEY.equals(key)) {
                    // Create an input stream for the BackupDataInput
                    byte[] dataBuf = new byte[dataSize];
                    data.readEntityData(dataBuf, 0, dataSize);
                    ByteArrayInputStream baStream = new ByteArrayInputStream(dataBuf);
                    DataInputStream in = new DataInputStream(baStream);

                    BufferedReader r = new BufferedReader(new InputStreamReader(in));

                    String line;
                    while ((line = r.readLine()) != null) {
                        total.append(line);
                    }
                    Log.d(toString(), "########## data " + total);
                } else {
                    data.skipEntityData();
                }
            }

            Log.d(toString(), "########## onRestore()" + total.toString());
        }
    }

}
Demonick
  • 2,116
  • 3
  • 30
  • 40
  • No, no further info either – Demonick Jan 07 '15 at 17:06
  • have you find more about this in some point? or any alternatives? – carlosavoy Apr 28 '16 at 07:49
  • @CarloLópezScutaro did not find a solution – Demonick Apr 28 '16 at 08:03
  • @Demonick are those preferences you using some Base64 encoding? I think this may be the reason for this to fail in my case. When I switch to vanila sharedPreferences things work out of the box. In more detail: our encryption on sharedPreferences was setting an encoding of the values with Base64.encodeToString(input, Base64.NO_PADDING | Base64.NO_WRAP), and this seem to break the backup-agent – carlosavoy Apr 28 '16 at 08:37
  • 1
    @carlosavoy Hi, I'm very new to all this. How would I check if I'm using Base64 encoding? How would I switch to vanilla sharedPreferences? Thanks for any help you can offer :-) – AndyCr15 Nov 19 '18 at 15:53

1 Answers1

1

In our case the solution was preventing enforcing Base64 encodings on the values stored in our shared preferences. As you mentoined @Demonick, https://github.com/comex/frash/blob/master/utils/utils/BackupData.cpp is the cause of the error, BackupDataReader::skip_padding() is using Base32 encoding for paddings.

Conclusion is: Prevent using Base64.encodeToString(input, Base64.NO_PADDING) for writing shared preferences.

carlosavoy
  • 99
  • 4
  • 1
    Nice find, will help for future reference. – Demonick Apr 28 '16 at 17:17
  • So what, we can't encode what we want in sharedPrefs, or by FileBackupHelper? They can't handle BaseN encodings? That is really bad in such a case... – JohnyTex Feb 25 '22 at 09:21
  • I get the same error when restoring a simple sharedPrefs with a boolean in it. Restore works however.... – JohnyTex Feb 25 '22 at 13:55
  • I suspect this is a stray error message from BackupData.cpp on reading end-of byte stream. Could be a coincidence you didn't get it anymore, when you thought you fixed it. – JohnyTex Feb 25 '22 at 16:02