diff -r 000000000000 -r 6474c204b198 mobile/android/base/sync/config/AccountPickler.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/mobile/android/base/sync/config/AccountPickler.java Wed Dec 31 06:09:35 2014 +0100 @@ -0,0 +1,182 @@ +/* This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ + +package org.mozilla.gecko.sync.config; + +import java.io.FileOutputStream; +import java.io.PrintStream; + +import org.mozilla.gecko.background.common.log.Logger; +import org.mozilla.gecko.sync.ExtendedJSONObject; +import org.mozilla.gecko.sync.Utils; +import org.mozilla.gecko.sync.setup.Constants; +import org.mozilla.gecko.sync.setup.SyncAccounts; +import org.mozilla.gecko.sync.setup.SyncAccounts.SyncAccountParameters; + +import android.accounts.Account; +import android.content.Context; + +/** + * Bug 768102: Android deletes Account objects when the Authenticator that owns + * the Account disappears. This happens when an App is installed to the SD card + * and the SD card is un-mounted or the device is rebooted. + *
+ * Bug 769745: Work around this by pickling the current Sync account data every + * sync. + *
+ * Bug 735842: Work around this by un-pickling when we check if Sync accounts + * exist (called from Fennec). + *
+ * Android just doesn't support installing Apps that define long-lived Services + * and/or own Account types onto the SD card. The documentation says not to do + * it. There are hordes of developers who want to do it, and have tried to + * register for almost every "package installation changed" broadcast intent + * that Android supports. They all explicitly state that the package that has + * changed does *not* receive the broadcast intent, thereby preventing an App + * from re-establishing its state. + *
+ * Reference. + *
+ * Quote: Your AbstractThreadedSyncAdapter and all its sync functionality + * will not work until external storage is remounted. + *
+ * Quote: Your running Service will be killed and will not be restarted + * when external storage is remounted. You can, however, register for the + * ACTION_EXTERNAL_APPLICATIONS_AVAILABLE broadcast Intent, which will notify + * your application when applications installed on external storage have become + * available to the system again. At which time, you can restart your Service. + *
+ * Problem: that intent doesn't work!
+ */
+public class AccountPickler {
+ public static final String LOG_TAG = "AccountPickler";
+
+ public static final long VERSION = 1;
+
+ /**
+ * Remove Sync account persisted to disk.
+ *
+ * @param context Android context.
+ * @param filename name of persisted pickle file; must not contain path separators.
+ * @return true
if given pickle existed and was successfully deleted.
+ */
+ public static boolean deletePickle(final Context context, final String filename) {
+ return context.deleteFile(filename);
+ }
+
+ /**
+ * Persist Sync account to disk as a JSON object.
+ *
+ * JSON object has keys: + *
Constants.JSON_KEY_ACCOUNT
: the Sync account's un-encoded username,
+ * like "test@mozilla.com".Constants.JSON_KEY_PASSWORD
: the Sync account's password;Constants.JSON_KEY_SERVER
: the Sync account's server;Constants.JSON_KEY_SYNCKEY
: the Sync account's sync key;Constants.JSON_KEY_CLUSTER
: the Sync account's cluster (may be null);Constants.JSON_KEY_CLIENT_NAME
: the Sync account's client name (may be null);Constants.JSON_KEY_CLIENT_GUID
: the Sync account's client GUID (may be null);Constants.JSON_KEY_SYNC_AUTOMATICALLY
: true if the Android Account is syncing automically;Constants.JSON_KEY_VERSION
: version of this file;Constants.JSON_KEY_TIMESTAMP
: when this file was written.