package info.varden.hauk.caching; import android.content.Context; import android.content.SharedPreferences; import java.util.ArrayList; import java.util.Iterator; import java.util.List; import info.varden.hauk.BuildConfig; import info.varden.hauk.Constants; import info.varden.hauk.struct.Session; import info.varden.hauk.struct.Share; import info.varden.hauk.utils.Log; import info.varden.hauk.utils.StringSerializer; /** * If the Hauk app crashes or shuts down, the app should give the option to resume any interrupted * shares. This class handles this functionality. * * @author Marius Lindvall */ public final class ResumableSessions { private final Context ctx; private final SharedPreferences prefs; public ResumableSessions(Context ctx) { this.ctx = ctx; this.prefs = ctx.getSharedPreferences(Constants.SHARED_PREFS_RESUMABLE, Context.MODE_PRIVATE); } /** * If the app crashed, or phone restarted, Hauk gives the option to resume interrupted shares. * This function checks if any incomplete shares are saved on the phone and asks the user if * they want to resume them. * * @param handler A handler that is called if there are shares available for resumption. */ public void tryResumeShare(ResumeHandler handler) { Log.i("Looking for resumable shares..."); //NON-NLS if (this.prefs.getBoolean(Constants.RESUME_AVAILABLE, false)) { Log.i("Resumable shares found"); //NON-NLS // Check if the app version that wrote the resumption data is the same as this session // to avoid deserialization errors due to incompatibilities. String writeVersion = this.prefs.getString(Constants.RESUME_CLIENT_VERSION, ""); if (writeVersion.equals(BuildConfig.VERSION_NAME)) { Log.i("Resumable shares are compatible with this version of Hauk"); //NON-NLS // Get session parameters. Session session = StringSerializer.deserialize(this.prefs.getString(Constants.RESUME_SESSION_PARAMS, null)); List<Share> shares = StringSerializer.deserialize(this.prefs.getString(Constants.RESUME_SHARE_PARAMS, null)); // Check that the session is still valid. boolean sessionValid = session != null && session.isActive(); boolean sharesAvailable = shares != null && !shares.isEmpty(); if (sessionValid && sharesAvailable) { Log.i("Stored session is valid and shares are available"); //NON-NLS handler.onSharesFetched(this.ctx, session, shares.toArray(new Share[0])); } else { Log.i("Stored share data is invalid"); //NON-NLS clearResumableSession(); } } else { Log.w("Resumption data incompatible, running=%s, stored=%s", BuildConfig.VERSION_NAME, writeVersion); //NON-NLS } } else { Log.i("No resumable shares found"); //NON-NLS } } /** * Saves session resumption data. This allows shares to be continued if the app crashes or is * otherwise closed. * * @param session The session to save resumption data for. */ public void setSessionResumable(Session session) { Log.i("Setting session %s resumable", session); //NON-NLS SharedPreferences.Editor editor = this.prefs.edit(); editor.putBoolean(Constants.RESUME_AVAILABLE, true); editor.putString(Constants.RESUME_CLIENT_VERSION, BuildConfig.VERSION_NAME); editor.putString(Constants.RESUME_SESSION_PARAMS, StringSerializer.serialize(session)); editor.apply(); } /** * Saves share resumption data. This allows the share to be continued if the app crashes or is * otherwise closed. * * @param share The share to save resumption data for. */ public void setShareResumable(Share share) { Log.i("Setting share %s resumable", share); //NON-NLS // Get the current list of resumable shares. ArrayList<Share> shares = StringSerializer.deserialize(this.prefs.getString(Constants.RESUME_SHARE_PARAMS, null)); if (shares == null) shares = new ArrayList<>(); // Add the share and save the updated list. shares.add(share); SharedPreferences.Editor editor = this.prefs.edit(); editor.putString(Constants.RESUME_SHARE_PARAMS, StringSerializer.serialize(shares)); editor.apply(); } /** * Removes a share from the list of resumable shares. * * @param shareID The ID of the share to remove. */ public void clearResumableShare(String shareID) { Log.i("Clearing resumable share %s", shareID); //NON-NLS // Get the current list of resumable shares. ArrayList<Share> shares = StringSerializer.deserialize(this.prefs.getString(Constants.RESUME_SHARE_PARAMS, null)); if (shares == null) return; // Remove the share and save the updated list. for (Iterator<Share> it = shares.iterator(); it.hasNext();) { if (it.next().getID().equals(shareID)) { it.remove(); } } SharedPreferences.Editor editor = this.prefs.edit(); editor.putString(Constants.RESUME_SHARE_PARAMS, StringSerializer.serialize(shares)); editor.apply(); } /** * Clears saved resumable session data. */ public void clearResumableSession() { Log.i("Clearing all resumption data"); //NON-NLS SharedPreferences.Editor editor = this.prefs.edit(); editor.clear(); editor.apply(); } }